Merging upstream version 2.11.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
6f6d3e85f8
commit
0f2367f2fa
533 changed files with 9033 additions and 4835 deletions
553
plugins/dapustor/dapustor-nvme.c
Normal file
553
plugins/dapustor/dapustor-nvme.c
Normal file
|
@ -0,0 +1,553 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "nvme.h"
|
||||
#include "libnvme.h"
|
||||
#include "plugin.h"
|
||||
#include "nvme-print.h"
|
||||
|
||||
#include "util/suffix.h"
|
||||
|
||||
#define CREATE_CMD
|
||||
#include "dapustor-nvme.h"
|
||||
|
||||
struct __packed nvme_additional_smart_log_item {
|
||||
__u8 key;
|
||||
__u8 _kp[2];
|
||||
__u8 norm;
|
||||
__u8 _np;
|
||||
union __packed {
|
||||
__u8 raw[6];
|
||||
struct __packed wear_level {
|
||||
__le16 min;
|
||||
__le16 max;
|
||||
__le16 avg;
|
||||
} wear_level;
|
||||
struct __packed thermal_throttle {
|
||||
__u8 pct;
|
||||
__u32 count;
|
||||
} thermal_throttle;
|
||||
struct __packed temperature {
|
||||
__le16 max;
|
||||
__le16 min;
|
||||
__le16 cur;
|
||||
} temperature;
|
||||
struct __packed power_consumption {
|
||||
__le16 max;
|
||||
__le16 min;
|
||||
__le16 avg;
|
||||
} power_consumption;
|
||||
struct __packed thermal_throttle_time {
|
||||
__u8 sts;
|
||||
__u32 time;
|
||||
__u8 rsv;
|
||||
} thermal_throttle_time;
|
||||
};
|
||||
__u8 _rp;
|
||||
};
|
||||
|
||||
struct nvme_additional_smart_log {
|
||||
struct nvme_additional_smart_log_item program_fail_cnt;
|
||||
struct nvme_additional_smart_log_item erase_fail_cnt;
|
||||
struct nvme_additional_smart_log_item wear_leveling_cnt;
|
||||
struct nvme_additional_smart_log_item e2e_err_cnt;
|
||||
struct nvme_additional_smart_log_item crc_err_cnt;
|
||||
struct nvme_additional_smart_log_item timed_workload_media_wear;
|
||||
struct nvme_additional_smart_log_item timed_workload_host_reads;
|
||||
struct nvme_additional_smart_log_item timed_workload_timer;
|
||||
struct nvme_additional_smart_log_item thermal_throttle_status;
|
||||
struct nvme_additional_smart_log_item retry_buffer_overflow_cnt;
|
||||
struct nvme_additional_smart_log_item pll_lock_loss_cnt;
|
||||
struct nvme_additional_smart_log_item nand_bytes_written;
|
||||
struct nvme_additional_smart_log_item host_bytes_written;
|
||||
};
|
||||
|
||||
struct nvme_extended_additional_smart_log {
|
||||
struct nvme_additional_smart_log_item sys_area_life_remain;
|
||||
struct nvme_additional_smart_log_item nand_bytes_read;
|
||||
struct nvme_additional_smart_log_item temperature;
|
||||
struct nvme_additional_smart_log_item power_consumption;
|
||||
struct nvme_additional_smart_log_item power_on_temperature;
|
||||
struct nvme_additional_smart_log_item power_loss_protection;
|
||||
struct nvme_additional_smart_log_item read_fail_count;
|
||||
struct nvme_additional_smart_log_item thermal_throttle_time;
|
||||
struct nvme_additional_smart_log_item flash_error_media_count;
|
||||
struct nvme_additional_smart_log_item lifetime_write_amplification;
|
||||
struct nvme_additional_smart_log_item firmware_update_count;
|
||||
struct nvme_additional_smart_log_item dram_cecc_count;
|
||||
struct nvme_additional_smart_log_item dram_uecc_count;
|
||||
struct nvme_additional_smart_log_item xor_pass_count;
|
||||
struct nvme_additional_smart_log_item xor_fail_count;
|
||||
struct nvme_additional_smart_log_item xor_invoked_count;
|
||||
struct nvme_additional_smart_log_item inflight_read_io_cmd;
|
||||
struct nvme_additional_smart_log_item temp_since_born;
|
||||
struct nvme_additional_smart_log_item temp_since_bootup;
|
||||
struct nvme_additional_smart_log_item inflight_write_io_cmd;
|
||||
};
|
||||
|
||||
static void show_dapustor_add_smart_log_jsn(struct nvme_additional_smart_log *smart,
|
||||
struct json_object *dev_stats)
|
||||
{
|
||||
struct json_object *entry_stats, *multi;
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->program_fail_cnt.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->program_fail_cnt.raw));
|
||||
json_object_add_value_object(dev_stats, "program_fail_count", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->erase_fail_cnt.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->erase_fail_cnt.raw));
|
||||
json_object_add_value_object(dev_stats, "erase_fail_count", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->wear_leveling_cnt.norm);
|
||||
multi = json_create_object();
|
||||
json_object_add_value_int(multi, "min",
|
||||
le16_to_cpu(smart->wear_leveling_cnt.wear_level.min));
|
||||
json_object_add_value_int(multi, "max",
|
||||
le16_to_cpu(smart->wear_leveling_cnt.wear_level.max));
|
||||
json_object_add_value_int(multi, "avg",
|
||||
le16_to_cpu(smart->wear_leveling_cnt.wear_level.avg));
|
||||
json_object_add_value_object(entry_stats, "raw", multi);
|
||||
json_object_add_value_object(dev_stats, "wear_leveling", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->e2e_err_cnt.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->e2e_err_cnt.raw));
|
||||
json_object_add_value_object(dev_stats, "end_to_end_error_detection_count", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->crc_err_cnt.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->crc_err_cnt.raw));
|
||||
json_object_add_value_object(dev_stats, "crc_error_count", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->timed_workload_media_wear.norm);
|
||||
json_object_add_value_float(entry_stats, "raw",
|
||||
((long double)int48_to_long(smart->timed_workload_media_wear.raw)) / 1024);
|
||||
json_object_add_value_object(dev_stats, "timed_workload_media_wear", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->timed_workload_host_reads.norm);
|
||||
json_object_add_value_int(entry_stats, "raw",
|
||||
int48_to_long(smart->timed_workload_host_reads.raw));
|
||||
json_object_add_value_object(dev_stats, "timed_workload_host_reads", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->timed_workload_timer.norm);
|
||||
json_object_add_value_int(entry_stats, "raw",
|
||||
int48_to_long(smart->timed_workload_timer.raw));
|
||||
json_object_add_value_object(dev_stats, "timed_workload_timer", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->thermal_throttle_status.norm);
|
||||
multi = json_create_object();
|
||||
json_object_add_value_int(multi, "pct",
|
||||
smart->thermal_throttle_status.thermal_throttle.pct);
|
||||
json_object_add_value_int(multi, "cnt",
|
||||
smart->thermal_throttle_status.thermal_throttle.count);
|
||||
json_object_add_value_object(entry_stats, "raw", multi);
|
||||
json_object_add_value_object(dev_stats, "thermal_throttle_status", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->retry_buffer_overflow_cnt.norm);
|
||||
json_object_add_value_int(entry_stats, "raw",
|
||||
int48_to_long(smart->retry_buffer_overflow_cnt.raw));
|
||||
json_object_add_value_object(dev_stats, "retry_buffer_overflow_count", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->pll_lock_loss_cnt.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->pll_lock_loss_cnt.raw));
|
||||
json_object_add_value_object(dev_stats, "pll_lock_loss_count", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->nand_bytes_written.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->nand_bytes_written.raw));
|
||||
json_object_add_value_object(dev_stats, "nand_bytes_written", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->host_bytes_written.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->host_bytes_written.raw));
|
||||
json_object_add_value_object(dev_stats, "host_bytes_written", entry_stats);
|
||||
}
|
||||
|
||||
static void show_dapustor_ext_add_smart_log_jsn(struct nvme_extended_additional_smart_log *smart,
|
||||
struct json_object *dev_stats)
|
||||
{
|
||||
struct json_object *entry_stats, *multi;
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->sys_area_life_remain.norm);
|
||||
json_object_add_value_int(entry_stats, "raw",
|
||||
int48_to_long(smart->sys_area_life_remain.raw));
|
||||
json_object_add_value_object(dev_stats, "system_area_life_remaining", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->nand_bytes_read.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->nand_bytes_read.raw));
|
||||
json_object_add_value_object(dev_stats, "nand_bytes_read", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->temperature.norm);
|
||||
multi = json_create_object();
|
||||
json_object_add_value_int(multi, "min", le16_to_cpu(smart->temperature.temperature.min));
|
||||
json_object_add_value_int(multi, "max", le16_to_cpu(smart->temperature.temperature.max));
|
||||
json_object_add_value_int(multi, "cur", le16_to_cpu(smart->temperature.temperature.cur));
|
||||
json_object_add_value_object(entry_stats, "raw", multi);
|
||||
json_object_add_value_object(dev_stats, "temperature", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->power_consumption.norm);
|
||||
multi = json_create_object();
|
||||
json_object_add_value_int(multi, "min",
|
||||
le16_to_cpu(smart->power_consumption.power_consumption.min));
|
||||
json_object_add_value_int(multi, "max",
|
||||
le16_to_cpu(smart->power_consumption.power_consumption.max));
|
||||
json_object_add_value_int(multi, "avg",
|
||||
le16_to_cpu(smart->power_consumption.power_consumption.avg));
|
||||
json_object_add_value_object(entry_stats, "raw", multi);
|
||||
json_object_add_value_object(dev_stats, "power_consumption", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->power_on_temperature.norm);
|
||||
multi = json_create_object();
|
||||
json_object_add_value_int(multi, "min",
|
||||
le16_to_cpu(smart->power_on_temperature.temperature.min));
|
||||
json_object_add_value_int(multi, "max",
|
||||
le16_to_cpu(smart->power_on_temperature.temperature.max));
|
||||
json_object_add_value_int(multi, "cur",
|
||||
le16_to_cpu(smart->power_on_temperature.temperature.cur));
|
||||
json_object_add_value_object(entry_stats, "raw", multi);
|
||||
json_object_add_value_object(dev_stats, "power_on_temperature", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->power_loss_protection.norm);
|
||||
json_object_add_value_int(entry_stats, "raw",
|
||||
int48_to_long(smart->power_loss_protection.raw));
|
||||
json_object_add_value_object(dev_stats, "power_loss_protection", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->read_fail_count.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->read_fail_count.raw));
|
||||
json_object_add_value_object(dev_stats, "read_fail_count", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->thermal_throttle_time.norm);
|
||||
json_object_add_value_int(entry_stats, "raw",
|
||||
int48_to_long(smart->thermal_throttle_time.raw));
|
||||
json_object_add_value_object(dev_stats, "thermal_throttle_time", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->flash_error_media_count.norm);
|
||||
json_object_add_value_int(entry_stats, "raw",
|
||||
int48_to_long(smart->flash_error_media_count.raw));
|
||||
json_object_add_value_object(dev_stats, "flash_error_media_count", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized",
|
||||
smart->lifetime_write_amplification.norm);
|
||||
json_object_add_value_int(entry_stats, "raw",
|
||||
int48_to_long(smart->lifetime_write_amplification.raw));
|
||||
json_object_add_value_object(dev_stats, "lifetime_write_amplification", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->firmware_update_count.norm);
|
||||
json_object_add_value_int(entry_stats, "raw",
|
||||
int48_to_long(smart->firmware_update_count.raw));
|
||||
json_object_add_value_object(dev_stats, "firmware_update_count", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->dram_cecc_count.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->dram_cecc_count.raw));
|
||||
json_object_add_value_object(dev_stats, "dram_cecc_count", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->dram_uecc_count.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->dram_uecc_count.raw));
|
||||
json_object_add_value_object(dev_stats, "dram_uecc_count", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->xor_pass_count.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->xor_pass_count.raw));
|
||||
json_object_add_value_object(dev_stats, "xor_pass_count", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->xor_fail_count.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->xor_fail_count.raw));
|
||||
json_object_add_value_object(dev_stats, "xor_fail_count", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->xor_invoked_count.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->xor_invoked_count.raw));
|
||||
json_object_add_value_object(dev_stats, "xor_invoked_count", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->inflight_read_io_cmd.norm);
|
||||
json_object_add_value_int(entry_stats, "raw",
|
||||
int48_to_long(smart->inflight_read_io_cmd.raw));
|
||||
json_object_add_value_object(dev_stats, "inflight_read_io_cmd", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->temp_since_born.norm);
|
||||
multi = json_create_object();
|
||||
json_object_add_value_int(multi, "min",
|
||||
le16_to_cpu(smart->temp_since_born.temperature.min));
|
||||
json_object_add_value_int(multi, "max",
|
||||
le16_to_cpu(smart->temp_since_born.temperature.max));
|
||||
json_object_add_value_int(multi, "cur",
|
||||
le16_to_cpu(smart->temp_since_born.temperature.cur));
|
||||
json_object_add_value_object(entry_stats, "raw", multi);
|
||||
json_object_add_value_object(dev_stats, "temp_since_born", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->temp_since_bootup.norm);
|
||||
multi = json_create_object();
|
||||
json_object_add_value_int(multi, "min",
|
||||
le16_to_cpu(smart->temp_since_bootup.temperature.min));
|
||||
json_object_add_value_int(multi, "max",
|
||||
le16_to_cpu(smart->temp_since_bootup.temperature.max));
|
||||
json_object_add_value_int(multi, "cur",
|
||||
le16_to_cpu(smart->temp_since_bootup.temperature.cur));
|
||||
json_object_add_value_object(entry_stats, "raw", multi);
|
||||
json_object_add_value_object(dev_stats, "temp_since_bootup", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->inflight_write_io_cmd.norm);
|
||||
json_object_add_value_int(entry_stats, "raw",
|
||||
int48_to_long(smart->inflight_write_io_cmd.raw));
|
||||
json_object_add_value_object(dev_stats, "inflight_write_io_cmd", entry_stats);
|
||||
}
|
||||
|
||||
static void show_dapustor_smart_log_jsn(struct nvme_additional_smart_log *smart,
|
||||
struct nvme_extended_additional_smart_log *ext_smart,
|
||||
unsigned int nsid, const char *devname, bool has_ext)
|
||||
{
|
||||
struct json_object *root, *dev_stats;
|
||||
|
||||
root = json_create_object();
|
||||
json_object_add_value_string(root, "Intel Smart log", devname);
|
||||
|
||||
dev_stats = json_create_object();
|
||||
show_dapustor_add_smart_log_jsn(smart, dev_stats);
|
||||
if (has_ext)
|
||||
show_dapustor_ext_add_smart_log_jsn(ext_smart, dev_stats);
|
||||
json_object_add_value_object(root, "Device stats", dev_stats);
|
||||
|
||||
json_print_object(root, NULL);
|
||||
json_free_object(root);
|
||||
}
|
||||
|
||||
static void show_dapustor_add_smart_log(struct nvme_additional_smart_log *smart)
|
||||
{
|
||||
printf("program_fail_count : %3d%% %"PRIu64"\n",
|
||||
smart->program_fail_cnt.norm,
|
||||
int48_to_long(smart->program_fail_cnt.raw));
|
||||
printf("erase_fail_count : %3d%% %"PRIu64"\n",
|
||||
smart->erase_fail_cnt.norm,
|
||||
int48_to_long(smart->erase_fail_cnt.raw));
|
||||
printf("wear_leveling : %3d%% min: %u, max: %u, avg: %u\n",
|
||||
smart->wear_leveling_cnt.norm,
|
||||
le16_to_cpu(smart->wear_leveling_cnt.wear_level.min),
|
||||
le16_to_cpu(smart->wear_leveling_cnt.wear_level.max),
|
||||
le16_to_cpu(smart->wear_leveling_cnt.wear_level.avg));
|
||||
printf("end_to_end_error_detection_count: %3d%% %"PRIu64"\n",
|
||||
smart->e2e_err_cnt.norm,
|
||||
int48_to_long(smart->e2e_err_cnt.raw));
|
||||
printf("crc_error_count : %3d%% %"PRIu64"\n",
|
||||
smart->crc_err_cnt.norm,
|
||||
int48_to_long(smart->crc_err_cnt.raw));
|
||||
printf("timed_workload_media_wear : %3d%% %.3f%%\n",
|
||||
smart->timed_workload_media_wear.norm,
|
||||
((float)int48_to_long(smart->timed_workload_media_wear.raw)) / 1024);
|
||||
printf("timed_workload_host_reads : %3d%% %"PRIu64"%%\n",
|
||||
smart->timed_workload_host_reads.norm,
|
||||
int48_to_long(smart->timed_workload_host_reads.raw));
|
||||
printf("timed_workload_timer : %3d%% %"PRIu64" min\n",
|
||||
smart->timed_workload_timer.norm,
|
||||
int48_to_long(smart->timed_workload_timer.raw));
|
||||
printf("thermal_throttle_status : %3d%% %u%%, cnt: %u\n",
|
||||
smart->thermal_throttle_status.norm,
|
||||
smart->thermal_throttle_status.thermal_throttle.pct,
|
||||
smart->thermal_throttle_status.thermal_throttle.count);
|
||||
printf("retry_buffer_overflow_count : %3d%% %"PRIu64"\n",
|
||||
smart->retry_buffer_overflow_cnt.norm,
|
||||
int48_to_long(smart->retry_buffer_overflow_cnt.raw));
|
||||
printf("pll_lock_loss_count : %3d%% %"PRIu64"\n",
|
||||
smart->pll_lock_loss_cnt.norm,
|
||||
int48_to_long(smart->pll_lock_loss_cnt.raw));
|
||||
printf("nand_bytes_written : %3d%% sectors: %"PRIu64"\n",
|
||||
smart->nand_bytes_written.norm,
|
||||
int48_to_long(smart->nand_bytes_written.raw));
|
||||
printf("host_bytes_written : %3d%% sectors: %"PRIu64"\n",
|
||||
smart->host_bytes_written.norm,
|
||||
int48_to_long(smart->host_bytes_written.raw));
|
||||
}
|
||||
|
||||
static void show_dapustor_ext_add_smart_log(struct nvme_extended_additional_smart_log *smart)
|
||||
{
|
||||
printf("system_area_life_remaining : %3d%% %"PRIu64"\n",
|
||||
smart->sys_area_life_remain.norm,
|
||||
int48_to_long(smart->sys_area_life_remain.raw));
|
||||
printf("nand_bytes_read : %3d%% %"PRIu64"\n",
|
||||
smart->nand_bytes_read.norm,
|
||||
int48_to_long(smart->nand_bytes_read.raw));
|
||||
printf("temperature : %3d%% min: %u, max: %u, cur: %u\n",
|
||||
smart->temperature.norm,
|
||||
le16_to_cpu(smart->temperature.temperature.min),
|
||||
le16_to_cpu(smart->temperature.temperature.max),
|
||||
le16_to_cpu(smart->temperature.temperature.cur));
|
||||
printf("power_consumption : %3d%% min: %u, max: %u, avg: %u\n",
|
||||
smart->power_consumption.norm,
|
||||
le16_to_cpu(smart->power_consumption.power_consumption.min),
|
||||
le16_to_cpu(smart->power_consumption.power_consumption.max),
|
||||
le16_to_cpu(smart->power_consumption.power_consumption.avg));
|
||||
printf("power_on_temperature : %3d%% min: %u, max: %u, cur: %u\n",
|
||||
smart->power_on_temperature.norm,
|
||||
le16_to_cpu(smart->power_on_temperature.temperature.min),
|
||||
le16_to_cpu(smart->power_on_temperature.temperature.max),
|
||||
le16_to_cpu(smart->power_on_temperature.temperature.cur));
|
||||
printf("power_loss_protection : %3d%% %"PRIu64"\n",
|
||||
smart->power_loss_protection.norm,
|
||||
int48_to_long(smart->power_loss_protection.raw));
|
||||
printf("read_fail_count : %3d%% %"PRIu64"\n",
|
||||
smart->read_fail_count.norm,
|
||||
int48_to_long(smart->read_fail_count.raw));
|
||||
printf("thermal_throttle_time : %3d%% %"PRIu64"\n",
|
||||
smart->thermal_throttle_time.norm,
|
||||
int48_to_long(smart->thermal_throttle_time.raw));
|
||||
printf("flash_error_media_count : %3d%% %"PRIu64"\n",
|
||||
smart->flash_error_media_count.norm,
|
||||
int48_to_long(smart->flash_error_media_count.raw));
|
||||
printf("lifetime_write_amplification : %3d%% %"PRIu64"\n",
|
||||
smart->lifetime_write_amplification.norm,
|
||||
int48_to_long(smart->lifetime_write_amplification.raw));
|
||||
printf("firmware_update_count : %3d%% %"PRIu64"\n",
|
||||
smart->firmware_update_count.norm,
|
||||
int48_to_long(smart->firmware_update_count.raw));
|
||||
printf("dram_cecc_count : %3d%% %"PRIu64"\n",
|
||||
smart->dram_cecc_count.norm,
|
||||
int48_to_long(smart->dram_cecc_count.raw));
|
||||
printf("dram_uecc_count : %3d%% %"PRIu64"\n",
|
||||
smart->dram_uecc_count.norm,
|
||||
int48_to_long(smart->dram_uecc_count.raw));
|
||||
printf("xor_pass_count : %3d%% %"PRIu64"\n",
|
||||
smart->xor_pass_count.norm,
|
||||
int48_to_long(smart->xor_pass_count.raw));
|
||||
printf("xor_fail_count : %3d%% %"PRIu64"\n",
|
||||
smart->xor_fail_count.norm,
|
||||
int48_to_long(smart->xor_fail_count.raw));
|
||||
printf("xor_invoked_count : %3d%% %"PRIu64"\n",
|
||||
smart->xor_invoked_count.norm,
|
||||
int48_to_long(smart->xor_invoked_count.raw));
|
||||
printf("inflight_read_io_cmd : %3d%% %"PRIu64"\n",
|
||||
smart->inflight_read_io_cmd.norm,
|
||||
int48_to_long(smart->inflight_read_io_cmd.raw));
|
||||
printf("temp_since_born : %3d%% min: %u, max: %u, cur: %u\n",
|
||||
smart->temp_since_born.norm,
|
||||
le16_to_cpu(smart->temp_since_born.temperature.min),
|
||||
le16_to_cpu(smart->temp_since_born.temperature.max),
|
||||
le16_to_cpu(smart->temp_since_born.temperature.cur));
|
||||
printf("temp_since_bootup : %3d%% min: %u, max: %u, cur: %u\n",
|
||||
smart->temp_since_bootup.norm,
|
||||
le16_to_cpu(smart->temp_since_bootup.temperature.min),
|
||||
le16_to_cpu(smart->temp_since_bootup.temperature.max),
|
||||
le16_to_cpu(smart->temp_since_bootup.temperature.cur));
|
||||
printf("inflight_write_io_cmd : %3d%% %"PRIu64"\n",
|
||||
smart->inflight_write_io_cmd.norm,
|
||||
int48_to_long(smart->inflight_write_io_cmd.raw));
|
||||
}
|
||||
|
||||
static void show_dapustor_smart_log(struct nvme_additional_smart_log *smart,
|
||||
struct nvme_extended_additional_smart_log *ext_smart,
|
||||
unsigned int nsid, const char *devname, bool has_ext)
|
||||
{
|
||||
printf("Additional Smart Log for NVME device:%s namespace-id:%x\n",
|
||||
devname, nsid);
|
||||
printf("key normalized raw\n");
|
||||
show_dapustor_add_smart_log(smart);
|
||||
if (has_ext)
|
||||
show_dapustor_ext_add_smart_log(ext_smart);
|
||||
}
|
||||
|
||||
static int dapustor_additional_smart_log_data(
|
||||
int dev_fd,
|
||||
struct nvme_additional_smart_log *smart_log,
|
||||
struct nvme_extended_additional_smart_log *ext_smart_log,
|
||||
bool *has_ext)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = nvme_get_log_simple(dev_fd, 0xca, sizeof(*smart_log), smart_log);
|
||||
if (err) {
|
||||
nvme_show_status(err);
|
||||
return err;
|
||||
}
|
||||
err = nvme_get_log_simple(dev_fd, 0xcb, sizeof(*ext_smart_log), ext_smart_log);
|
||||
*has_ext = !err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dapustor_additional_smart_log(int argc, char **argv, struct command *cmd,
|
||||
struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "Get DapuStor vendor specific additional smart log, and show it.";
|
||||
const char *namespace = "(optional) desired namespace";
|
||||
const char *raw = "Dump output in binary format";
|
||||
const char *json = "Dump output in json format";
|
||||
|
||||
struct nvme_additional_smart_log smart_log;
|
||||
struct nvme_extended_additional_smart_log ext_smart_log;
|
||||
struct nvme_dev *dev;
|
||||
int err;
|
||||
bool has_ext = false;
|
||||
|
||||
struct config {
|
||||
uint32_t namespace_id;
|
||||
bool raw_binary;
|
||||
bool json;
|
||||
};
|
||||
|
||||
struct config cfg = {
|
||||
.namespace_id = NVME_NSID_ALL,
|
||||
};
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace),
|
||||
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
|
||||
OPT_FLAG("json", 'j', &cfg.json, json),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = dapustor_additional_smart_log_data(dev_fd(dev), &smart_log, &ext_smart_log, &has_ext);
|
||||
if (!err) {
|
||||
if (cfg.json)
|
||||
show_dapustor_smart_log_jsn(&smart_log, &ext_smart_log,
|
||||
cfg.namespace_id, dev->name, has_ext);
|
||||
else if (!cfg.raw_binary)
|
||||
show_dapustor_smart_log(&smart_log, &ext_smart_log,
|
||||
cfg.namespace_id, dev->name, has_ext);
|
||||
else {
|
||||
d_raw((unsigned char *)&smart_log, sizeof(smart_log));
|
||||
if (has_ext)
|
||||
d_raw((unsigned char *)&ext_smart_log, sizeof(ext_smart_log));
|
||||
}
|
||||
}
|
||||
dev_close(dev);
|
||||
return err;
|
||||
}
|
18
plugins/dapustor/dapustor-nvme.h
Normal file
18
plugins/dapustor/dapustor-nvme.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#undef CMD_INC_FILE
|
||||
#define CMD_INC_FILE plugins/dapustor/dapustor-nvme
|
||||
|
||||
#if !defined(DAPUSTOR_NVME) || defined(CMD_HEADER_MULTI_READ)
|
||||
#define DAPUSTOR_NVME
|
||||
|
||||
#include "cmd.h"
|
||||
|
||||
PLUGIN(NAME("dapustor", "DapuStor vendor specific extensions", NVME_VERSION),
|
||||
COMMAND_LIST(
|
||||
ENTRY("smart-log-add", "Retrieve DapuStor SMART Log, show it", dapustor_additional_smart_log)
|
||||
)
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
#include "define_cmd.h"
|
|
@ -57,7 +57,7 @@ static int fdp_configs(int argc, char **argv, struct command *cmd,
|
|||
return err;
|
||||
|
||||
err = validate_output_format(cfg.output_format, &flags);
|
||||
if (flags < 0)
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
if (cfg.raw_binary)
|
||||
|
@ -138,7 +138,7 @@ static int fdp_usage(int argc, char **argv, struct command *cmd, struct plugin *
|
|||
return err;
|
||||
|
||||
err = validate_output_format(cfg.output_format, &flags);
|
||||
if (flags < 0)
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
if (cfg.raw_binary)
|
||||
|
@ -209,7 +209,7 @@ static int fdp_stats(int argc, char **argv, struct command *cmd, struct plugin *
|
|||
return err;
|
||||
|
||||
err = validate_output_format(cfg.output_format, &flags);
|
||||
if (flags < 0)
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
if (cfg.raw_binary)
|
||||
|
@ -270,7 +270,7 @@ static int fdp_events(int argc, char **argv, struct command *cmd, struct plugin
|
|||
return err;
|
||||
|
||||
err = validate_output_format(cfg.output_format, &flags);
|
||||
if (flags < 0)
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
if (cfg.raw_binary)
|
||||
|
@ -329,7 +329,7 @@ static int fdp_status(int argc, char **argv, struct command *cmd, struct plugin
|
|||
return err;
|
||||
|
||||
err = validate_output_format(cfg.output_format, &flags);
|
||||
if (flags < 0)
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
if (cfg.raw_binary)
|
||||
|
|
|
@ -16,128 +16,6 @@
|
|||
#define CREATE_CMD
|
||||
#include "innogrit-nvme.h"
|
||||
|
||||
static int innogrit_smart_log_additional(int argc, char **argv,
|
||||
struct command *command,
|
||||
struct plugin *plugin)
|
||||
{
|
||||
struct nvme_smart_log smart_log = { 0 };
|
||||
struct vsc_smart_log *pvsc_smart = (struct vsc_smart_log *)smart_log.rsvd232;
|
||||
const char *desc = "Retrieve additional SMART log for the given device ";
|
||||
const char *namespace = "(optional) desired namespace";
|
||||
struct nvme_dev *dev;
|
||||
int err, i, iindex;
|
||||
|
||||
struct config {
|
||||
__u32 namespace_id;
|
||||
};
|
||||
|
||||
struct config cfg = {
|
||||
.namespace_id = NVME_NSID_ALL,
|
||||
};
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
nvme_get_log_smart(dev_fd(dev), cfg.namespace_id, false, &smart_log);
|
||||
nvme_show_smart_log(&smart_log, cfg.namespace_id, dev->name, NORMAL);
|
||||
|
||||
printf("DW0[0-1] Defect Cnt : %u\n", pvsc_smart->defect_cnt);
|
||||
printf("DW0[2-3] Slc Spb Cnt : %u\n", pvsc_smart->slc_spb_cnt);
|
||||
printf("DW1 Slc Total Ec Cnt : %u\n", pvsc_smart->slc_total_ec_cnt);
|
||||
printf("DW2 Slc Max Ec Cnt : %u\n", pvsc_smart->slc_max_ec_cnt);
|
||||
printf("DW3 Slc Min Ec Cnt : %u\n", pvsc_smart->slc_min_ec_cnt);
|
||||
printf("DW4 Slc Avg Ec Cnt : %u\n", pvsc_smart->slc_avg_ec_cnt);
|
||||
printf("DW5 Total Ec Cnt : %u\n", pvsc_smart->total_ec_cnt);
|
||||
printf("DW6 Max Ec Cnt : %u\n", pvsc_smart->max_ec_cnt);
|
||||
printf("DW7 Min Ec Cnt : %u\n", pvsc_smart->min_ec_cnt);
|
||||
printf("DW8 Avg Ec Cnt : %u\n", pvsc_smart->avg_ec_cnt);
|
||||
printf("DW9 Mrd Rr Good Cnt : %u\n", pvsc_smart->mrd_rr_good_cnt);
|
||||
printf("DW10 Ard Rr Good Cnt : %u\n", pvsc_smart->ard_rr_good_cnt);
|
||||
printf("DW11 Preset Cnt : %u\n", pvsc_smart->preset_cnt);
|
||||
printf("DW12 Nvme Reset Cnt : %u\n", pvsc_smart->nvme_reset_cnt);
|
||||
printf("DW13 Low Pwr Cnt : %u\n", pvsc_smart->low_pwr_cnt);
|
||||
printf("DW14 Wa : %u\n", pvsc_smart->wa);
|
||||
printf("DW15 Ps3 Entry Cnt : %u\n", pvsc_smart->ps3_entry_cnt);
|
||||
printf("DW16[0] highest_temp[0] : %u\n", pvsc_smart->highest_temp[0]);
|
||||
printf("DW16[1] highest_temp[1] : %u\n", pvsc_smart->highest_temp[1]);
|
||||
printf("DW16[2] highest_temp[2] : %u\n", pvsc_smart->highest_temp[2]);
|
||||
printf("DW16[3] highest_temp[3] : %u\n", pvsc_smart->highest_temp[3]);
|
||||
printf("DW17 weight_ec : %u\n", pvsc_smart->weight_ec);
|
||||
printf("DW18 slc_cap_mb : %u\n", pvsc_smart->slc_cap_mb);
|
||||
printf("DW19-20 nand_page_write_cnt : %llu\n", pvsc_smart->nand_page_write_cnt);
|
||||
printf("DW21 program_error_cnt : %u\n", pvsc_smart->program_error_cnt);
|
||||
printf("DW22 erase_error_cnt : %u\n", pvsc_smart->erase_error_cnt);
|
||||
printf("DW23[0] flash_type : %u\n", pvsc_smart->flash_type);
|
||||
printf("DW24 hs_crc_err_cnt : %u\n", pvsc_smart->hs_crc_err_cnt);
|
||||
printf("DW25 ddr_ecc_err_cnt : %u\n", pvsc_smart->ddr_ecc_err_cnt);
|
||||
iindex = 26;
|
||||
for (i = 0; i < (sizeof(pvsc_smart->reserved3)/4); i++) {
|
||||
if (pvsc_smart->reserved3[i] != 0)
|
||||
printf("DW%-37d : %u\n", iindex, pvsc_smart->reserved3[i]);
|
||||
iindex++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sort_eventlog_fn(const void *a, const void *b)
|
||||
{
|
||||
const struct eventlog_addindex *l = a;
|
||||
const struct eventlog_addindex *r = b;
|
||||
int rc;
|
||||
|
||||
if (l->ms > r->ms) {
|
||||
rc = 1;
|
||||
} else if (l->ms < r->ms) {
|
||||
rc = -1;
|
||||
} else {
|
||||
if (l->iindex < r->iindex)
|
||||
rc = -1;
|
||||
else
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void sort_eventlog(struct eventlog *data16ksrc, unsigned int icount)
|
||||
{
|
||||
struct eventlog_addindex peventlogadd[512];
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < icount; i++) {
|
||||
memcpy(&peventlogadd[i], &data16ksrc[i], sizeof(struct eventlog));
|
||||
peventlogadd[i].iindex = i;
|
||||
}
|
||||
|
||||
qsort(peventlogadd, icount, sizeof(struct eventlog_addindex), sort_eventlog_fn);
|
||||
|
||||
for (i = 0; i < icount; i++)
|
||||
memcpy(&data16ksrc[i], &peventlogadd[i], sizeof(struct eventlog));
|
||||
}
|
||||
|
||||
static unsigned char setfilecontent(char *filenamea, unsigned char *buffer,
|
||||
unsigned int buffersize)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
int rc;
|
||||
|
||||
if (buffersize == 0)
|
||||
return true;
|
||||
fp = fopen(filenamea, "a+");
|
||||
rc = fwrite(buffer, 1, buffersize, fp);
|
||||
fclose(fp);
|
||||
if (rc != buffersize)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int nvme_vucmd(int fd, unsigned char opcode, unsigned int cdw12,
|
||||
unsigned int cdw13, unsigned int cdw14,
|
||||
unsigned int cdw15, char *data, int data_len)
|
||||
|
@ -158,34 +36,155 @@ static int nvme_vucmd(int fd, unsigned char opcode, unsigned int cdw12,
|
|||
return nvme_submit_admin_passthru(fd, &cmd, NULL);
|
||||
}
|
||||
|
||||
static int innogrit_vsc_geteventlog(int argc, char **argv,
|
||||
int getlogpage(struct nvme_dev *dev, unsigned char ilogid, unsigned char ilsp,
|
||||
char *data, int data_len, unsigned int *result)
|
||||
{
|
||||
struct nvme_get_log_args args = {
|
||||
.args_size = sizeof(args),
|
||||
.fd = dev_fd(dev),
|
||||
.lid = ilogid,
|
||||
.nsid = 0xffffffff,
|
||||
.lpo = 0,
|
||||
.lsp = ilsp,
|
||||
.lsi = 0,
|
||||
.rae = true,
|
||||
.uuidx = 0,
|
||||
.csi = NVME_CSI_NVM,
|
||||
.ot = false,
|
||||
.len = data_len,
|
||||
.log = (void *)data,
|
||||
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
|
||||
.result = result,
|
||||
};
|
||||
return nvme_get_log(&args);
|
||||
}
|
||||
|
||||
int getvsctype(struct nvme_dev *dev)
|
||||
{
|
||||
unsigned char ilogid;
|
||||
char data[4096];
|
||||
struct drvinfo_t *pdrvinfo = (struct drvinfo_t *)data;
|
||||
|
||||
memset(data, 0, 4096);
|
||||
// pdrvinfo by getlogpage
|
||||
for (ilogid = 0xe1; ilogid < 0xe2; ilogid++) {
|
||||
getlogpage(dev, ilogid, 0, data, 4096, NULL);
|
||||
if (pdrvinfo->signature == 0x5A)
|
||||
return 1;
|
||||
}
|
||||
|
||||
//pdrvinfo by vucmd
|
||||
nvme_vucmd(dev_fd(dev), 0xfe, 0x82, 0X03, 0x00, 0, (char *)data, 4096);
|
||||
if (pdrvinfo->signature == 0x5A)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getvsc_eventlog(struct nvme_dev *dev, FILE *fp)
|
||||
{
|
||||
char data[4096];
|
||||
unsigned int errcnt, rxlen, start_flag;
|
||||
unsigned long long end_flag;
|
||||
struct evlg_flush_hdr *pevlog = (struct evlg_flush_hdr *)data;
|
||||
int ret = -1;
|
||||
int ivsctype = getvsctype(dev);
|
||||
|
||||
start_flag = 0;
|
||||
rxlen = 0;
|
||||
errcnt = 0;
|
||||
|
||||
while (1) {
|
||||
memset(data, 0, 4096);
|
||||
if (ivsctype == 0) {
|
||||
ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET_EVENT_LOG, 0, 0,
|
||||
(SRB_SIGNATURE >> 32),
|
||||
(SRB_SIGNATURE & 0xFFFFFFFF),
|
||||
(char *)data, 4096);
|
||||
} else {
|
||||
ret = nvme_vucmd(dev_fd(dev), NVME_VSC_TYPE1_GET, 0x60, 0,
|
||||
0, 0, (char *)data, 4096);
|
||||
}
|
||||
|
||||
if (ret == -1) {
|
||||
printf("(error)\n");
|
||||
return IG_ERROR;
|
||||
}
|
||||
|
||||
if (pevlog->signature == EVLOG_SIG) {
|
||||
errcnt = 0;
|
||||
} else {
|
||||
errcnt++;
|
||||
if (errcnt > 16) {
|
||||
printf("(invalid data error)\n");
|
||||
return IG_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (start_flag == 1) {
|
||||
end_flag = *(unsigned long long *)&data[4096 - 32];
|
||||
if (end_flag == 0xffffffff00000000)
|
||||
break;
|
||||
fwrite(data, 1, 4096, fp);
|
||||
rxlen += 4096;
|
||||
printf("\rget eventlog : %d.%d MB ", rxlen / SIZE_MB,
|
||||
(rxlen % SIZE_MB) * 100 / SIZE_MB);
|
||||
} else if (errcnt == 0) {
|
||||
printf("get eventlog by vsc command\n");
|
||||
start_flag = 1;
|
||||
fwrite(data, 1, 4096, fp);
|
||||
rxlen += 4096;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
return IG_SUCCESS;
|
||||
}
|
||||
|
||||
int getlogpage_eventlog(struct nvme_dev *dev, FILE *fp)
|
||||
{
|
||||
unsigned int i, result, total_size;
|
||||
char data[4096];
|
||||
int ret = 0;
|
||||
|
||||
result = 0;
|
||||
ret = getlogpage(dev, 0xcb, 0x01, data, 4096, NULL);
|
||||
if (ret)
|
||||
return IG_UNSUPPORT;
|
||||
|
||||
ret = getlogpage(dev, 0xcb, 0x02, data, 4096, &result);
|
||||
if ((ret) || (result == 0))
|
||||
return IG_UNSUPPORT;
|
||||
|
||||
total_size = result * 4096;
|
||||
printf("total eventlog : %d.%d MB\n", total_size / SIZE_MB,
|
||||
(total_size % SIZE_MB) * 100 / SIZE_MB);
|
||||
for (i = 0; i <= total_size; i += 4096) {
|
||||
ret = getlogpage(dev, 0xcb, 0x00, data, 4096, NULL);
|
||||
printf("\rget eventlog : %d.%d MB ", i / SIZE_MB,
|
||||
(i % SIZE_MB) * 100 / SIZE_MB);
|
||||
if (ret) {
|
||||
printf("(error)\n");
|
||||
return IG_ERROR;
|
||||
}
|
||||
fwrite(data, 1, 4096, fp);
|
||||
}
|
||||
printf("\n");
|
||||
return IG_SUCCESS;
|
||||
}
|
||||
|
||||
static int innogrit_geteventlog(int argc, char **argv,
|
||||
struct command *command,
|
||||
struct plugin *plugin)
|
||||
{
|
||||
time_t timep;
|
||||
struct tm *logtime;
|
||||
int icount, ioffset16k, iblock, ivsctype;
|
||||
char currentdir[128], filename[512];
|
||||
unsigned char data[4096], data16k[SIZE_16K], zerob[32];
|
||||
unsigned int *pcheckdata;
|
||||
unsigned int isize, icheck_stopvalue, iend;
|
||||
unsigned char bSortLog = false, bget_nextlog = true;
|
||||
struct evlg_flush_hdr *pevlog = (struct evlg_flush_hdr *)data;
|
||||
const char *desc = "Recrieve event log for the given device ";
|
||||
const char *clean_opt = "(optional) 1 for clean event log";
|
||||
struct nvme_dev *dev;
|
||||
FILE *fp = NULL;
|
||||
int ret = -1;
|
||||
|
||||
struct config {
|
||||
__u32 clean_flg;
|
||||
};
|
||||
|
||||
struct config cfg = {
|
||||
.clean_flg = 0,
|
||||
};
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_UINT("clean_flg", 'c', &cfg.clean_flg, clean_opt),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
|
@ -193,120 +192,25 @@ static int innogrit_vsc_geteventlog(int argc, char **argv,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
if (getcwd(currentdir, 128) == NULL)
|
||||
return -1;
|
||||
|
||||
ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x82, 0x03, 0x00, 0x00, (char *)data, 4096);
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
|
||||
if (data[0] == 0x5A)
|
||||
ivsctype = 1;
|
||||
else
|
||||
ivsctype = 0;
|
||||
|
||||
time(&timep);
|
||||
logtime = localtime(&timep);
|
||||
sprintf(filename, "%s/eventlog_%02d%02d-%02d%02d%02d.elog", currentdir, logtime->tm_mon+1,
|
||||
logtime->tm_mday, logtime->tm_hour, logtime->tm_min, logtime->tm_sec);
|
||||
sprintf(filename, "%s/eventlog_%02d%02d-%02d%02d%02d.eraw", currentdir,
|
||||
logtime->tm_mon+1, logtime->tm_mday, logtime->tm_hour, logtime->tm_min,
|
||||
logtime->tm_sec);
|
||||
printf("output eventlog file : %s\n", filename);
|
||||
|
||||
iblock = 0;
|
||||
ioffset16k = 0;
|
||||
memset(data16k, 0, SIZE_16K);
|
||||
memset(zerob, 0, 32);
|
||||
|
||||
icount = 0;
|
||||
while (bget_nextlog) {
|
||||
if (icount % 100 == 0) {
|
||||
printf("\rWait for Dump EventLog " XCLEAN_LINE);
|
||||
fflush(stdout);
|
||||
icount = 0;
|
||||
} else if (icount % 5 == 0) {
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
}
|
||||
icount++;
|
||||
|
||||
memset(data, 0, 4096);
|
||||
if (ivsctype == 1)
|
||||
ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x60, 0x00, 0x00, 0x00, (char *)data,
|
||||
4096);
|
||||
else
|
||||
ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET_EVENT_LOG, 0, 0,
|
||||
(SRB_SIGNATURE >> 32),
|
||||
(SRB_SIGNATURE & 0xFFFFFFFF),
|
||||
(char *)data, 4096);
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
|
||||
pcheckdata = (unsigned int *)&data[4096 - 32];
|
||||
icheck_stopvalue = pcheckdata[1];
|
||||
|
||||
if (icheck_stopvalue == 0xFFFFFFFF) {
|
||||
isize = pcheckdata[0];
|
||||
if (isize == 0) {
|
||||
/* Finish Log */
|
||||
bget_nextlog = false;
|
||||
} else if (bSortLog) {
|
||||
/* No Full 4K Package */
|
||||
for (iend = 0; iend < isize - 32; iend += sizeof(struct eventlog)) {
|
||||
if (memcmp(&data[iend], zerob, sizeof(struct eventlog)) != 0) {
|
||||
memcpy(&data16k[ioffset16k], &data[iend], sizeof(struct eventlog));
|
||||
ioffset16k += sizeof(struct eventlog);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setfilecontent(filename, data, isize);
|
||||
}
|
||||
} else {
|
||||
/* Full 4K Package */
|
||||
if ((pevlog->signature == EVLOG_SIG) && (pevlog->log_type == 1))
|
||||
bSortLog = true;
|
||||
|
||||
if (bSortLog) {
|
||||
for (iend = 0; iend < SIZE_4K; iend += sizeof(struct eventlog)) {
|
||||
if (memcmp(&data[iend], zerob, sizeof(struct eventlog)) != 0) {
|
||||
memcpy(&data16k[ioffset16k], &data[iend], sizeof(struct eventlog));
|
||||
ioffset16k += sizeof(struct eventlog);
|
||||
}
|
||||
}
|
||||
|
||||
iblock++;
|
||||
if (iblock == 4) {
|
||||
sort_eventlog((struct eventlog *)(data16k + sizeof(struct evlg_flush_hdr)),
|
||||
(ioffset16k - sizeof(struct evlg_flush_hdr))/sizeof(struct eventlog));
|
||||
setfilecontent(filename, data16k, ioffset16k);
|
||||
ioffset16k = 0;
|
||||
iblock = 0;
|
||||
memset(data16k, 0, SIZE_16K);
|
||||
}
|
||||
} else {
|
||||
setfilecontent(filename, data, SIZE_4K);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (bSortLog) {
|
||||
if (ioffset16k > 0) {
|
||||
sort_eventlog((struct eventlog *)(data16k + sizeof(struct evlg_flush_hdr)),
|
||||
(ioffset16k - sizeof(struct evlg_flush_hdr))/sizeof(struct eventlog));
|
||||
setfilecontent(filename, data16k, ioffset16k);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\r" XCLEAN_LINE "Dump eventLog finish to %s\n", filename);
|
||||
chmod(filename, 0666);
|
||||
|
||||
if (cfg.clean_flg == 1) {
|
||||
printf("Clean eventlog\n");
|
||||
nvme_vucmd(dev_fd(dev), NVME_VSC_CLEAN_EVENT_LOG, 0, 0,
|
||||
(SRB_SIGNATURE >> 32),
|
||||
(SRB_SIGNATURE & 0xFFFFFFFF), (char *)NULL, 0);
|
||||
}
|
||||
fp = fopen(filename, "a+");
|
||||
getvsctype(dev);
|
||||
ret = getlogpage_eventlog(dev, fp);
|
||||
if (ret == IG_UNSUPPORT)
|
||||
ret = getvsc_eventlog(dev, fp);
|
||||
|
||||
fclose(fp);
|
||||
dev_close(dev);
|
||||
chmod(filename, 0666);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -318,13 +222,14 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command,
|
|||
struct tm *logtime;
|
||||
char currentdir[128], filename[512], fname[128];
|
||||
unsigned int itotal, icur, ivsctype;
|
||||
unsigned char data[4096];
|
||||
char data[4096];
|
||||
struct cdumpinfo cdumpinfo;
|
||||
unsigned char busevsc = false;
|
||||
unsigned int ipackcount, ipackindex;
|
||||
char fwvera[32];
|
||||
const char *desc = "Recrieve cdump data for the given device ";
|
||||
struct nvme_dev *dev;
|
||||
FILE *fp = NULL;
|
||||
int ret = -1;
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
|
@ -335,50 +240,48 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ivsctype = getvsctype(dev);
|
||||
|
||||
if (getcwd(currentdir, 128) == NULL)
|
||||
return -1;
|
||||
|
||||
time(&timep);
|
||||
logtime = localtime(&timep);
|
||||
|
||||
ivsctype = 0;
|
||||
ipackindex = 0;
|
||||
memset(data, 0, 4096);
|
||||
|
||||
ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x82, 0x03, 0x00, 0x00, (char *)data, 4096);
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
|
||||
if (data[0] == 0x5A) {
|
||||
ivsctype = 1;
|
||||
ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x82, 0x08, 0x00, 0x00, (char *)data, 4096);
|
||||
} else {
|
||||
ivsctype = 0;
|
||||
if (ivsctype == 0) {
|
||||
ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET, VSC_FN_GET_CDUMP, 0x00,
|
||||
(SRB_SIGNATURE >> 32), (SRB_SIGNATURE & 0xFFFFFFFF),
|
||||
(char *)data, 4096);
|
||||
(SRB_SIGNATURE >> 32), (SRB_SIGNATURE & 0xFFFFFFFF),
|
||||
(char *)data, 4096);
|
||||
} else {
|
||||
ret = nvme_vucmd(dev_fd(dev), NVME_VSC_TYPE1_GET, 0x82, 0x00,
|
||||
0, 0, (char *)data, 4096);
|
||||
}
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
|
||||
memcpy(&cdumpinfo, &data[3072], sizeof(cdumpinfo));
|
||||
if (cdumpinfo.sig == 0x5a5b5c5d) {
|
||||
busevsc = true;
|
||||
ipackcount = cdumpinfo.ipackcount;
|
||||
if (ipackcount == 0) {
|
||||
itotal = 0;
|
||||
} else {
|
||||
itotal = cdumpinfo.cdumppack[ipackindex].ilenth;
|
||||
memset(fwvera, 0, sizeof(fwvera));
|
||||
memcpy(fwvera, cdumpinfo.cdumppack[ipackindex].fwver, 8);
|
||||
sprintf(fname, "cdump_%02d%02d-%02d%02d%02d_%d_%s.cdp", logtime->tm_mon+1,
|
||||
logtime->tm_mday, logtime->tm_hour, logtime->tm_min, logtime->tm_sec,
|
||||
ipackindex, fwvera);
|
||||
sprintf(filename, "%s/%s", currentdir, fname);
|
||||
if (ret == 0) {
|
||||
memcpy(&cdumpinfo, &data[3072], sizeof(cdumpinfo));
|
||||
if (cdumpinfo.sig == 0x5a5b5c5d) {
|
||||
busevsc = true;
|
||||
ipackcount = cdumpinfo.ipackcount;
|
||||
if (ipackcount == 0) {
|
||||
itotal = 0;
|
||||
} else {
|
||||
itotal = cdumpinfo.cdumppack[ipackindex].ilenth;
|
||||
memset(fwvera, 0, sizeof(fwvera));
|
||||
memcpy(fwvera, cdumpinfo.cdumppack[ipackindex].fwver, 8);
|
||||
sprintf(fname, "cdump_%02d%02d-%02d%02d%02d_%d_%s.cdp",
|
||||
logtime->tm_mon+1, logtime->tm_mday, logtime->tm_hour,
|
||||
logtime->tm_min, logtime->tm_sec, ipackindex, fwvera);
|
||||
sprintf(filename, "%s/%s", currentdir, fname);
|
||||
if (fp != NULL)
|
||||
fclose(fp);
|
||||
fp = fopen(filename, "a+");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (busevsc == false) {
|
||||
memset(data, 0, 4096);
|
||||
ret = nvme_get_nsid_log(dev_fd(dev), true, 0x07,
|
||||
|
@ -389,9 +292,12 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command,
|
|||
|
||||
ipackcount = 1;
|
||||
memcpy(&itotal, &data[4092], 4);
|
||||
sprintf(fname, "cdump_%02d%02d-%02d%02d%02d.cdp", logtime->tm_mon+1, logtime->tm_mday,
|
||||
logtime->tm_hour, logtime->tm_min, logtime->tm_sec);
|
||||
sprintf(fname, "cdump_%02d%02d-%02d%02d%02d.cdp", logtime->tm_mon+1,
|
||||
logtime->tm_mday, logtime->tm_hour, logtime->tm_min, logtime->tm_sec);
|
||||
sprintf(filename, "%s/%s", currentdir, fname);
|
||||
if (fp != NULL)
|
||||
fclose(fp);
|
||||
fp = fopen(filename, "a+");
|
||||
}
|
||||
|
||||
if (itotal == 0) {
|
||||
|
@ -402,17 +308,20 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command,
|
|||
while (ipackindex < ipackcount) {
|
||||
memset(data, 0, 4096);
|
||||
strcpy((char *)data, "cdumpstart");
|
||||
setfilecontent(filename, data, strlen((char *)data));
|
||||
fwrite(data, 1, strlen((char *)data), fp);
|
||||
for (icur = 0; icur < itotal; icur += 4096) {
|
||||
memset(data, 0, 4096);
|
||||
if (busevsc) {
|
||||
if (ivsctype == 1)
|
||||
ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x82, 0x08, 0x00, 0x00,
|
||||
(char *)data, 4096);
|
||||
else
|
||||
ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET, VSC_FN_GET_CDUMP, 0x00,
|
||||
(SRB_SIGNATURE >> 32), (SRB_SIGNATURE & 0xFFFFFFFF),
|
||||
(char *)data, 4096);
|
||||
if (ivsctype == 0) {
|
||||
ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET,
|
||||
VSC_FN_GET_CDUMP, 0x00,
|
||||
(SRB_SIGNATURE >> 32),
|
||||
(SRB_SIGNATURE & 0xFFFFFFFF),
|
||||
(char *)data, 4096);
|
||||
} else {
|
||||
ret = nvme_vucmd(dev_fd(dev), NVME_VSC_TYPE1_GET,
|
||||
0x82, 0x00, 0, 0, (char *)data, 4096);
|
||||
}
|
||||
} else {
|
||||
ret = nvme_get_nsid_log(dev_fd(dev), true,
|
||||
0x07,
|
||||
|
@ -421,25 +330,27 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command,
|
|||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
setfilecontent(filename, data, 4096);
|
||||
|
||||
fwrite(data, 1, 4096, fp);
|
||||
printf("\rWait for dump data %d%%" XCLEAN_LINE, ((icur+4096) * 100/itotal));
|
||||
}
|
||||
memset(data, 0, 4096);
|
||||
strcpy((char *)data, "cdumpend");
|
||||
setfilecontent(filename, data, strlen((char *)data));
|
||||
fwrite(data, 1, strlen((char *)data), fp);
|
||||
printf("\r%s\n", fname);
|
||||
ipackindex++;
|
||||
if (ipackindex != ipackcount) {
|
||||
memset(data, 0, 4096);
|
||||
if (busevsc) {
|
||||
if (ivsctype == 1)
|
||||
ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x82, 0x08, 0x00, 0x00,
|
||||
(char *)data, 4096);
|
||||
else
|
||||
ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET, VSC_FN_GET_CDUMP, 0x00,
|
||||
(SRB_SIGNATURE >> 32), (SRB_SIGNATURE & 0xFFFFFFFF),
|
||||
(char *)data, 4096);
|
||||
if (ivsctype == 0) {
|
||||
ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET,
|
||||
VSC_FN_GET_CDUMP, 0x00,
|
||||
(SRB_SIGNATURE >> 32),
|
||||
(SRB_SIGNATURE & 0xFFFFFFFF),
|
||||
(char *)data, 4096);
|
||||
} else {
|
||||
ret = nvme_vucmd(dev_fd(dev), NVME_VSC_TYPE1_GET,
|
||||
0x82, 0x00, 0, 0, (char *)data, 4096);
|
||||
}
|
||||
} else {
|
||||
ret = nvme_get_nsid_log(dev_fd(dev), true,
|
||||
0x07,
|
||||
|
@ -455,12 +366,16 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command,
|
|||
sprintf(fname, "cdump_%02d%02d-%02d%02d%02d_%d_%s.cdp", logtime->tm_mon+1,
|
||||
logtime->tm_mday, logtime->tm_hour, logtime->tm_min, logtime->tm_sec,
|
||||
ipackindex, fwvera);
|
||||
sprintf(filename, "%s/%s", currentdir, fname);
|
||||
if (fp != NULL)
|
||||
fclose(fp);
|
||||
fp = fopen(filename, "a+");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
dev_close(dev);
|
||||
if (fp != NULL)
|
||||
fclose(fp);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
|
||||
PLUGIN(NAME("innogrit", "innogrit vendor specific extensions", NVME_VERSION),
|
||||
COMMAND_LIST(
|
||||
ENTRY("smart-log-add", "Retrieve innogrit SMART Log, show it", innogrit_smart_log_additional)
|
||||
ENTRY("get-eventlog", "get event log", innogrit_vsc_geteventlog)
|
||||
ENTRY("get-eventlog", "get event log", innogrit_geteventlog)
|
||||
ENTRY("get-cdump", "get cdump data", innogrit_vsc_getcdump)
|
||||
)
|
||||
);
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#define SIZE_4K 4096
|
||||
#define SIZE_16K 16384
|
||||
#define IG_SUCCESS (0)
|
||||
#define IG_UNSUPPORT (-1)
|
||||
#define IG_ERROR (-2)
|
||||
|
||||
#define NVME_VSC_GET_EVENT_LOG 0xC2
|
||||
#define NVME_VSC_CLEAN_EVENT_LOG 0xD8
|
||||
#define NVME_VSC_GET 0xE6
|
||||
#define VSC_FN_GET_CDUMP 0x08
|
||||
#define EVLOG_SIG 0x65766C67
|
||||
#define IGVSC_SIG 0x69677673
|
||||
#define SRB_SIGNATURE 0x544952474F4E4E49ULL
|
||||
#define XCLEAN_LINE "\033[K"
|
||||
#define NVME_VSC_GET_EVENT_LOG 0xC2
|
||||
#define NVME_VSC_GET 0xE6
|
||||
#define NVME_VSC_TYPE1_GET 0xFE
|
||||
#define VSC_FN_GET_CDUMP 0x08
|
||||
#define IGVSC_SIG 0x69677673
|
||||
#define EVLOG_SIG 0x65766C67
|
||||
#define SRB_SIGNATURE 0x544952474F4E4E49ULL
|
||||
|
||||
#define XCLEAN_LINE "\033[K"
|
||||
#define SIZE_MB 0x100000
|
||||
|
||||
struct evlg_flush_hdr {
|
||||
unsigned int signature;
|
||||
|
@ -27,46 +30,34 @@ struct eventlog {
|
|||
unsigned int param[7];
|
||||
};
|
||||
|
||||
struct eventlog_addindex {
|
||||
unsigned int ms;
|
||||
unsigned int param[7];
|
||||
unsigned int iindex;
|
||||
struct drvinfo_t {
|
||||
unsigned char signature;
|
||||
unsigned char fw_base;
|
||||
unsigned short socid;
|
||||
unsigned char soc_ver[4];
|
||||
unsigned char loader_version[8];
|
||||
unsigned char nand_devids[6];
|
||||
unsigned char ddr_type;
|
||||
unsigned char ddr_size;
|
||||
unsigned char rsvd1[8];
|
||||
unsigned char origin_fw_name[8];
|
||||
unsigned long long nand_type;
|
||||
unsigned int board_type[5];
|
||||
unsigned short soc_type;
|
||||
unsigned char build_mode;
|
||||
unsigned char rsvd2;
|
||||
unsigned int ftl_build_num;
|
||||
unsigned short soc_reg;
|
||||
unsigned char rsvd3[2];
|
||||
unsigned int cur_cpu_clk;
|
||||
unsigned int cur_nf_clk;
|
||||
unsigned char nand_geo[4];
|
||||
unsigned int fw_d2h_info_bit;
|
||||
unsigned int spi_flash_id;
|
||||
unsigned char rom_version[8];
|
||||
unsigned char rsvd4[404];
|
||||
};
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
struct vsc_smart_log {
|
||||
unsigned short defect_cnt;
|
||||
unsigned short slc_spb_cnt;
|
||||
unsigned int slc_total_ec_cnt;
|
||||
unsigned int slc_max_ec_cnt;
|
||||
unsigned int slc_min_ec_cnt;
|
||||
unsigned int slc_avg_ec_cnt;
|
||||
unsigned int total_ec_cnt;
|
||||
unsigned int max_ec_cnt;
|
||||
unsigned int min_ec_cnt;
|
||||
unsigned int avg_ec_cnt;
|
||||
unsigned int mrd_rr_good_cnt;
|
||||
unsigned int ard_rr_good_cnt;
|
||||
unsigned int preset_cnt;
|
||||
unsigned int nvme_reset_cnt;
|
||||
unsigned int low_pwr_cnt;
|
||||
unsigned int wa;
|
||||
unsigned int ps3_entry_cnt;
|
||||
unsigned char highest_temp[4];
|
||||
unsigned int weight_ec;
|
||||
unsigned int slc_cap_mb;
|
||||
unsigned long long nand_page_write_cnt;
|
||||
unsigned int program_error_cnt;
|
||||
unsigned int erase_error_cnt;
|
||||
unsigned char flash_type;
|
||||
unsigned char reserved2[3];
|
||||
unsigned int hs_crc_err_cnt;
|
||||
unsigned int ddr_ecc_err_cnt;
|
||||
unsigned int reserved3[44];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct cdump_pack {
|
||||
unsigned int ilenth;
|
||||
char fwver[8];
|
||||
|
|
|
@ -1521,7 +1521,7 @@ static void smart_log_add_v3_print(struct smart_log_add_item_10 *item, int item_
|
|||
[0xab] = {0, "program_fail_count" },
|
||||
[0xac] = {1, "erase_fail_count" },
|
||||
[0xad] = {2, "wear_leveling_count" },
|
||||
[0xb8] = {3, "ext_e2e_err_count" },
|
||||
[0xdf] = {3, "ext_e2e_err_count" },
|
||||
[0xc7] = {4, "crc_err_count" },
|
||||
[0xf4] = {5, "nand_bytes_written" },
|
||||
[0xf5] = {6, "host_bytes_written" },
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
if json_c_dep.found()
|
||||
sources += [
|
||||
'plugins/amzn/amzn-nvme.c',
|
||||
'plugins/dapustor/dapustor-nvme.c',
|
||||
'plugins/dell/dell-nvme.c',
|
||||
'plugins/dera/dera-nvme.c',
|
||||
'plugins/fdp/fdp.c',
|
||||
|
@ -29,8 +30,9 @@ if json_c_dep.found()
|
|||
'plugins/ssstc/ssstc-nvme.c',
|
||||
]
|
||||
subdir('solidigm')
|
||||
subdir('ocp')
|
||||
if conf.get('HAVE_SED_OPAL') != 0
|
||||
subdir('sed')
|
||||
endif
|
||||
endif
|
||||
|
||||
subdir('ocp')
|
||||
|
|
|
@ -251,23 +251,24 @@ static void netapp_ontapdevice_json(struct json_object *devices, char *devname,
|
|||
json_array_add_value_object(devices, device_attrs);
|
||||
}
|
||||
|
||||
static void netapp_smdevices_print(struct smdevice_info *devices, int count, int format)
|
||||
static void netapp_smdevices_print_regular(struct smdevice_info *devices,
|
||||
int count, int format, const char *devname)
|
||||
{
|
||||
struct json_object *root = NULL;
|
||||
struct json_object *json_devices = NULL;
|
||||
int i, slta;
|
||||
char array_label[ARRAY_LABEL_LEN / 2 + 1];
|
||||
char volume_label[VOLUME_LABEL_LEN / 2 + 1];
|
||||
char nguid_str[33];
|
||||
__u8 lba_index;
|
||||
|
||||
char *formatstr = NULL;
|
||||
char basestr[] =
|
||||
"%s, Array Name %s, Volume Name %s, NSID %d, Volume ID %s, Controller %c, Access State %s, %s\n";
|
||||
char columnstr[] = "%-16s %-30s %-30s %4d %32s %c %-12s %9s\n";
|
||||
char *formatstr = basestr; /* default to "normal" output format */
|
||||
__u8 lba_index;
|
||||
|
||||
if (format == NCOLUMN) {
|
||||
/* for column output, change output string and print column headers */
|
||||
formatstr = columnstr;
|
||||
if (format == NNORMAL)
|
||||
formatstr = basestr;
|
||||
else if (format == NCOLUMN) {
|
||||
/* change output string and print column headers */
|
||||
printf("%-16s %-30s %-30s %-4s %-32s %-4s %-12s %-9s\n",
|
||||
"Device", "Array Name", "Volume Name", "NSID",
|
||||
"Volume ID", "Ctrl", "Access State", " Size");
|
||||
|
@ -276,48 +277,194 @@ static void netapp_smdevices_print(struct smdevice_info *devices, int count, int
|
|||
"------------------------------", "----",
|
||||
"--------------------------------", "----",
|
||||
"------------", "---------");
|
||||
} else if (format == NJSON) {
|
||||
/* prepare for json output */
|
||||
root = json_create_object();
|
||||
json_devices = json_create_array();
|
||||
formatstr = columnstr;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (devname && !strcmp(devname, basename(devices[i].dev))) {
|
||||
/* found the device, fetch info for that alone */
|
||||
nvme_id_ns_flbas_to_lbaf_inuse(devices[i].ns.flbas,
|
||||
&lba_index);
|
||||
unsigned long long lba = 1ULL <<
|
||||
devices[i].ns.lbaf[lba_index].ds;
|
||||
double nsze = le64_to_cpu(devices[i].ns.nsze) * lba;
|
||||
const char *s_suffix = suffix_si_get(&nsze);
|
||||
char size[128];
|
||||
|
||||
sprintf(size, "%.2f%sB", nsze, s_suffix);
|
||||
netapp_convert_string(array_label,
|
||||
(char *)&devices[i].ctrl.vs[20],
|
||||
ARRAY_LABEL_LEN / 2);
|
||||
slta = devices[i].ctrl.vs[0] & 0x1;
|
||||
netapp_convert_string(volume_label,
|
||||
(char *)devices[i].ns.vs,
|
||||
VOLUME_LABEL_LEN / 2);
|
||||
netapp_nguid_to_str(nguid_str, devices[i].ns.nguid);
|
||||
|
||||
printf(formatstr, devices[i].dev, array_label,
|
||||
volume_label, devices[i].nsid,
|
||||
nguid_str,
|
||||
slta ? 'A' : 'B', "unknown", size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
/* fetch info for all devices */
|
||||
nvme_id_ns_flbas_to_lbaf_inuse(devices[i].ns.flbas, &lba_index);
|
||||
unsigned long long lba = 1ULL << devices[i].ns.lbaf[lba_index].ds;
|
||||
unsigned long long lba = 1ULL <<
|
||||
devices[i].ns.lbaf[lba_index].ds;
|
||||
double nsze = le64_to_cpu(devices[i].ns.nsze) * lba;
|
||||
const char *s_suffix = suffix_si_get(&nsze);
|
||||
char size[128];
|
||||
|
||||
sprintf(size, "%.2f%sB", nsze, s_suffix);
|
||||
netapp_convert_string(array_label, (char *)&devices[i].ctrl.vs[20],
|
||||
ARRAY_LABEL_LEN / 2);
|
||||
netapp_convert_string(array_label,
|
||||
(char *)&devices[i].ctrl.vs[20],
|
||||
ARRAY_LABEL_LEN / 2);
|
||||
slta = devices[i].ctrl.vs[0] & 0x1;
|
||||
netapp_convert_string(volume_label, (char *)devices[i].ns.vs,
|
||||
VOLUME_LABEL_LEN / 2);
|
||||
VOLUME_LABEL_LEN / 2);
|
||||
netapp_nguid_to_str(nguid_str, devices[i].ns.nguid);
|
||||
if (format == NJSON)
|
||||
netapp_smdevice_json(json_devices, devices[i].dev,
|
||||
array_label, volume_label, devices[i].nsid,
|
||||
nguid_str, slta ? "A" : "B", "unknown", size,
|
||||
lba, le64_to_cpu(devices[i].ns.nsze));
|
||||
else
|
||||
printf(formatstr, devices[i].dev, array_label,
|
||||
|
||||
printf(formatstr, devices[i].dev, array_label,
|
||||
volume_label, devices[i].nsid, nguid_str,
|
||||
slta ? 'A' : 'B', "unknown", size);
|
||||
}
|
||||
}
|
||||
|
||||
if (format == NJSON) {
|
||||
/* complete the json output */
|
||||
json_object_add_value_array(root, "SMdevices", json_devices);
|
||||
json_print_object(root, NULL);
|
||||
printf("\n");
|
||||
json_free_object(root);
|
||||
static void netapp_smdevices_print_json(struct smdevice_info *devices,
|
||||
int count, const char *devname)
|
||||
{
|
||||
struct json_object *root = NULL;
|
||||
struct json_object *json_devices = NULL;
|
||||
int i, slta;
|
||||
char array_label[ARRAY_LABEL_LEN / 2 + 1];
|
||||
char volume_label[VOLUME_LABEL_LEN / 2 + 1];
|
||||
char nguid_str[33];
|
||||
__u8 lba_index;
|
||||
|
||||
/* prepare for the json output */
|
||||
root = json_create_object();
|
||||
json_devices = json_create_array();
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (devname && !strcmp(devname, basename(devices[i].dev))) {
|
||||
/* found the device, fetch info for that alone */
|
||||
nvme_id_ns_flbas_to_lbaf_inuse(devices[i].ns.flbas,
|
||||
&lba_index);
|
||||
unsigned long long lba = 1ULL <<
|
||||
devices[i].ns.lbaf[lba_index].ds;
|
||||
double nsze = le64_to_cpu(devices[i].ns.nsze) * lba;
|
||||
const char *s_suffix = suffix_si_get(&nsze);
|
||||
char size[128];
|
||||
|
||||
sprintf(size, "%.2f%sB", nsze, s_suffix);
|
||||
netapp_convert_string(array_label,
|
||||
(char *)&devices[i].ctrl.vs[20],
|
||||
ARRAY_LABEL_LEN / 2);
|
||||
slta = devices[i].ctrl.vs[0] & 0x1;
|
||||
netapp_convert_string(volume_label,
|
||||
(char *)devices[i].ns.vs,
|
||||
VOLUME_LABEL_LEN / 2);
|
||||
netapp_nguid_to_str(nguid_str, devices[i].ns.nguid);
|
||||
netapp_smdevice_json(json_devices, devices[i].dev,
|
||||
array_label, volume_label,
|
||||
devices[i].nsid, nguid_str,
|
||||
slta ? "A" : "B", "unknown", size, lba,
|
||||
le64_to_cpu(devices[i].ns.nsze));
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
/* fetch info for all devices */
|
||||
nvme_id_ns_flbas_to_lbaf_inuse(devices[i].ns.flbas, &lba_index);
|
||||
unsigned long long lba = 1ULL <<
|
||||
devices[i].ns.lbaf[lba_index].ds;
|
||||
double nsze = le64_to_cpu(devices[i].ns.nsze) * lba;
|
||||
const char *s_suffix = suffix_si_get(&nsze);
|
||||
char size[128];
|
||||
|
||||
sprintf(size, "%.2f%sB", nsze, s_suffix);
|
||||
netapp_convert_string(array_label,
|
||||
(char *)&devices[i].ctrl.vs[20],
|
||||
ARRAY_LABEL_LEN / 2);
|
||||
slta = devices[i].ctrl.vs[0] & 0x1;
|
||||
netapp_convert_string(volume_label,
|
||||
(char *)devices[i].ns.vs,
|
||||
VOLUME_LABEL_LEN / 2);
|
||||
netapp_nguid_to_str(nguid_str, devices[i].ns.nguid);
|
||||
netapp_smdevice_json(json_devices, devices[i].dev,
|
||||
array_label, volume_label, devices[i].nsid,
|
||||
nguid_str, slta ? "A" : "B", "unknown",
|
||||
size, lba, le64_to_cpu(devices[i].ns.nsze));
|
||||
}
|
||||
|
||||
out:
|
||||
/* complete the json output */
|
||||
json_object_add_value_array(root, "SMdevices", json_devices);
|
||||
json_print_object(root, NULL);
|
||||
printf("\n");
|
||||
json_free_object(root);
|
||||
}
|
||||
|
||||
static void netapp_ontapdevices_print_regular(struct ontapdevice_info *devices,
|
||||
int count, int format, const char *devname)
|
||||
{
|
||||
char vsname[ONTAP_LABEL_LEN] = " ";
|
||||
char nspath[ONTAP_NS_PATHLEN] = " ";
|
||||
unsigned long long lba;
|
||||
char size[128];
|
||||
char uuid_str[37] = " ";
|
||||
int i;
|
||||
|
||||
char *formatstr = NULL;
|
||||
char basestr[] =
|
||||
"%s, Vserver %s, Namespace Path %s, NSID %d, UUID %s, %s\n";
|
||||
char columnstr[] = "%-16s %-25s %-50s %-4d %-38s %-9s\n";
|
||||
|
||||
if (format == NNORMAL)
|
||||
formatstr = basestr;
|
||||
else if (format == NCOLUMN) {
|
||||
printf("%-16s %-25s %-50s %-4s %-38s %-9s\n",
|
||||
"Device", "Vserver", "Namespace Path",
|
||||
"NSID", "UUID", "Size");
|
||||
printf("%-16s %-25s %-50s %-4s %-38s %-9s\n",
|
||||
"----------------", "-------------------------",
|
||||
"--------------------------------------------------",
|
||||
"----", "--------------------------------------",
|
||||
"---------");
|
||||
formatstr = columnstr;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (devname && !strcmp(devname, basename(devices[i].dev))) {
|
||||
/* found the device, fetch and print for that alone */
|
||||
netapp_get_ns_size(size, &lba, &devices[i].ns);
|
||||
nvme_uuid_to_string(devices[i].uuid, uuid_str);
|
||||
netapp_get_ontap_labels(vsname, nspath,
|
||||
devices[i].log_data);
|
||||
|
||||
printf(formatstr, devices[i].dev, vsname, nspath,
|
||||
devices[i].nsid, uuid_str, size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
/* fetch info and print for all devices */
|
||||
netapp_get_ns_size(size, &lba, &devices[i].ns);
|
||||
nvme_uuid_to_string(devices[i].uuid, uuid_str);
|
||||
netapp_get_ontap_labels(vsname, nspath, devices[i].log_data);
|
||||
|
||||
printf(formatstr, devices[i].dev, vsname, nspath,
|
||||
devices[i].nsid, uuid_str, size);
|
||||
}
|
||||
}
|
||||
|
||||
static void netapp_ontapdevices_print(struct ontapdevice_info *devices,
|
||||
int count, int format)
|
||||
static void netapp_ontapdevices_print_json(struct ontapdevice_info *devices,
|
||||
int count, const char *devname)
|
||||
{
|
||||
struct json_object *root = NULL;
|
||||
struct json_object *json_devices = NULL;
|
||||
|
@ -328,52 +475,43 @@ static void netapp_ontapdevices_print(struct ontapdevice_info *devices,
|
|||
char uuid_str[37] = " ";
|
||||
int i;
|
||||
|
||||
char basestr[] = "%s, Vserver %s, Namespace Path %s, NSID %d, UUID %s, %s\n";
|
||||
char columnstr[] = "%-16s %-25s %-50s %-4d %-38s %-9s\n";
|
||||
|
||||
/* default to 'normal' output format */
|
||||
char *formatstr = basestr;
|
||||
|
||||
if (format == NCOLUMN) {
|
||||
/* change output string and print column headers */
|
||||
formatstr = columnstr;
|
||||
printf("%-16s %-25s %-50s %-4s %-38s %-9s\n",
|
||||
"Device", "Vserver", "Namespace Path",
|
||||
"NSID", "UUID", "Size");
|
||||
printf("%-16s %-25s %-50s %-4s %-38s %-9s\n",
|
||||
"----------------", "-------------------------",
|
||||
"--------------------------------------------------",
|
||||
"----", "--------------------------------------",
|
||||
"---------");
|
||||
} else if (format == NJSON) {
|
||||
/* prepare for json output */
|
||||
root = json_create_object();
|
||||
json_devices = json_create_array();
|
||||
}
|
||||
/* prepare for the json output */
|
||||
root = json_create_object();
|
||||
json_devices = json_create_array();
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (devname && !strcmp(devname, basename(devices[i].dev))) {
|
||||
/* found the device, fetch info for that alone */
|
||||
netapp_get_ns_size(size, &lba, &devices[i].ns);
|
||||
nvme_uuid_to_string(devices[i].uuid, uuid_str);
|
||||
netapp_get_ontap_labels(vsname, nspath, devices[i].log_data);
|
||||
|
||||
netapp_get_ns_size(size, &lba, &devices[i].ns);
|
||||
nvme_uuid_to_string(devices[i].uuid, uuid_str);
|
||||
netapp_get_ontap_labels(vsname, nspath, devices[i].log_data);
|
||||
|
||||
if (format == NJSON) {
|
||||
netapp_ontapdevice_json(json_devices, devices[i].dev,
|
||||
vsname, nspath, devices[i].nsid,
|
||||
uuid_str, size, lba,
|
||||
le64_to_cpu(devices[i].ns.nsze));
|
||||
} else
|
||||
printf(formatstr, devices[i].dev, vsname, nspath,
|
||||
devices[i].nsid, uuid_str, size);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (format == NJSON) {
|
||||
/* complete the json output */
|
||||
json_object_add_value_array(root, "ONTAPdevices", json_devices);
|
||||
json_print_object(root, NULL);
|
||||
printf("\n");
|
||||
json_free_object(root);
|
||||
for (i = 0; i < count; i++) {
|
||||
/* fetch info for all devices */
|
||||
netapp_get_ns_size(size, &lba, &devices[i].ns);
|
||||
nvme_uuid_to_string(devices[i].uuid, uuid_str);
|
||||
netapp_get_ontap_labels(vsname, nspath, devices[i].log_data);
|
||||
|
||||
netapp_ontapdevice_json(json_devices, devices[i].dev,
|
||||
vsname, nspath, devices[i].nsid,
|
||||
uuid_str, size, lba,
|
||||
le64_to_cpu(devices[i].ns.nsze));
|
||||
}
|
||||
|
||||
out:
|
||||
/* complete the json output */
|
||||
json_object_add_value_array(root, "ONTAPdevices", json_devices);
|
||||
json_print_object(root, NULL);
|
||||
printf("\n");
|
||||
json_free_object(root);
|
||||
}
|
||||
|
||||
static int nvme_get_ontap_c2_log(int fd, __u32 nsid, void *buf, __u32 buflen)
|
||||
|
@ -470,6 +608,8 @@ static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item,
|
|||
return 0;
|
||||
}
|
||||
|
||||
memset(nsdescs, 0, 0x1000);
|
||||
|
||||
err = nvme_identify_ns_descs(fd, item->nsid, nsdescs);
|
||||
if (err) {
|
||||
fprintf(stderr, "Unable to identify namespace descriptor for %s (%s)\n",
|
||||
|
@ -540,6 +680,7 @@ static int netapp_smdevices(int argc, char **argv, struct command *command,
|
|||
int num, i, fd, ret, fmt;
|
||||
struct smdevice_info *smdevices;
|
||||
char path[264];
|
||||
char *devname = NULL;
|
||||
int num_smdevices = 0;
|
||||
|
||||
struct config {
|
||||
|
@ -571,6 +712,18 @@ static int netapp_smdevices(int argc, char **argv, struct command *command,
|
|||
return num;
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
devname = basename(argv[optind++]);
|
||||
|
||||
if (devname) {
|
||||
int subsys_num, nsid;
|
||||
|
||||
if (sscanf(devname, "nvme%dn%d", &subsys_num, &nsid) != 2) {
|
||||
fprintf(stderr, "Invalid device name %s\n", devname);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
smdevices = calloc(num, sizeof(*smdevices));
|
||||
if (!smdevices) {
|
||||
fprintf(stderr, "Unable to allocate memory for devices.\n");
|
||||
|
@ -592,8 +745,15 @@ static int netapp_smdevices(int argc, char **argv, struct command *command,
|
|||
close(fd);
|
||||
}
|
||||
|
||||
if (num_smdevices)
|
||||
netapp_smdevices_print(smdevices, num_smdevices, fmt);
|
||||
if (num_smdevices) {
|
||||
if (fmt == NNORMAL || fmt == NCOLUMN)
|
||||
netapp_smdevices_print_regular(smdevices,
|
||||
num_smdevices, fmt, devname);
|
||||
else if (fmt == NJSON)
|
||||
netapp_smdevices_print_json(smdevices,
|
||||
num_smdevices, devname);
|
||||
} else
|
||||
fprintf(stderr, "No smdevices detected\n");
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
free(devices[i]);
|
||||
|
@ -611,6 +771,7 @@ static int netapp_ontapdevices(int argc, char **argv, struct command *command,
|
|||
int num, i, fd, ret, fmt;
|
||||
struct ontapdevice_info *ontapdevices;
|
||||
char path[264];
|
||||
char *devname = NULL;
|
||||
int num_ontapdevices = 0;
|
||||
|
||||
struct config {
|
||||
|
@ -636,6 +797,18 @@ static int netapp_ontapdevices(int argc, char **argv, struct command *command,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
devname = basename(argv[optind++]);
|
||||
|
||||
if (devname) {
|
||||
int subsys_num, nsid;
|
||||
|
||||
if (sscanf(devname, "nvme%dn%d", &subsys_num, &nsid) != 2) {
|
||||
fprintf(stderr, "Invalid device name %s\n", devname);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
num = scandir(dev_path, &devices, netapp_nvme_filter, alphasort);
|
||||
if (num <= 0) {
|
||||
fprintf(stderr, "No NVMe devices detected.\n");
|
||||
|
@ -664,8 +837,15 @@ static int netapp_ontapdevices(int argc, char **argv, struct command *command,
|
|||
close(fd);
|
||||
}
|
||||
|
||||
if (num_ontapdevices)
|
||||
netapp_ontapdevices_print(ontapdevices, num_ontapdevices, fmt);
|
||||
if (num_ontapdevices) {
|
||||
if (fmt == NNORMAL || fmt == NCOLUMN)
|
||||
netapp_ontapdevices_print_regular(ontapdevices,
|
||||
num_ontapdevices, fmt, devname);
|
||||
else if (fmt == NJSON)
|
||||
netapp_ontapdevices_print_json(ontapdevices,
|
||||
num_ontapdevices, devname);
|
||||
} else
|
||||
fprintf(stderr, "No ontapdevices detected\n");
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
free(devices[i]);
|
||||
|
|
|
@ -5,5 +5,14 @@ sources += [
|
|||
'plugins/ocp/ocp-smart-extended-log.c',
|
||||
'plugins/ocp/ocp-fw-activation-history.c',
|
||||
'plugins/ocp/ocp-telemetry-decode.c',
|
||||
'plugins/ocp/ocp-hardware-component-log.c',
|
||||
'plugins/ocp/ocp-print.c',
|
||||
'plugins/ocp/ocp-print-stdout.c',
|
||||
'plugins/ocp/ocp-print-binary.c',
|
||||
]
|
||||
|
||||
if json_c_dep.found()
|
||||
sources += [
|
||||
'plugins/ocp/ocp-print-json.c',
|
||||
]
|
||||
endif
|
||||
|
|
|
@ -14,135 +14,15 @@
|
|||
#include "nvme-print.h"
|
||||
|
||||
#include "ocp-utils.h"
|
||||
#include "ocp-print.h"
|
||||
|
||||
static const unsigned char ocp_fw_activation_history_guid[16] = {
|
||||
static const unsigned char ocp_fw_activation_history_guid[GUID_LEN] = {
|
||||
0x6D, 0x79, 0x9a, 0x76,
|
||||
0xb4, 0xda, 0xf6, 0xa3,
|
||||
0xe2, 0x4d, 0xb2, 0x8a,
|
||||
0xac, 0xf3, 0x1c, 0xd1
|
||||
};
|
||||
|
||||
struct __packed fw_activation_history_entry {
|
||||
__u8 ver_num;
|
||||
__u8 entry_length;
|
||||
__u16 reserved1;
|
||||
__u16 activation_count;
|
||||
__u64 timestamp;
|
||||
__u64 reserved2;
|
||||
__u64 power_cycle_count;
|
||||
char previous_fw[8];
|
||||
char new_fw[8];
|
||||
__u8 slot_number;
|
||||
__u8 commit_action;
|
||||
__u16 result;
|
||||
__u8 reserved3[14];
|
||||
};
|
||||
|
||||
struct __packed fw_activation_history {
|
||||
__u8 log_id;
|
||||
__u8 reserved1[3];
|
||||
__u32 valid_entries;
|
||||
struct fw_activation_history_entry entries[20];
|
||||
__u8 reserved2[2790];
|
||||
__u16 log_page_version;
|
||||
__u64 log_page_guid[2];
|
||||
};
|
||||
|
||||
static void ocp_fw_activation_history_normal(const struct fw_activation_history *fw_history)
|
||||
{
|
||||
printf("Firmware History Log:\n");
|
||||
|
||||
printf(" %-26s%d\n", "log identifier:", fw_history->log_id);
|
||||
printf(" %-26s%d\n", "valid entries:", le32_to_cpu(fw_history->valid_entries));
|
||||
|
||||
printf(" entries:\n");
|
||||
|
||||
for (int index = 0; index < fw_history->valid_entries; index++) {
|
||||
const struct fw_activation_history_entry *entry = &fw_history->entries[index];
|
||||
|
||||
printf(" entry[%d]:\n", le32_to_cpu(index));
|
||||
printf(" %-22s%d\n", "version number:", entry->ver_num);
|
||||
printf(" %-22s%d\n", "entry length:", entry->entry_length);
|
||||
printf(" %-22s%d\n", "activation count:",
|
||||
le16_to_cpu(entry->activation_count));
|
||||
printf(" %-22s%"PRIu64"\n", "timestamp:",
|
||||
(0x0000FFFFFFFFFFFF & le64_to_cpu(entry->timestamp)));
|
||||
printf(" %-22s%"PRIu64"\n", "power cycle count:",
|
||||
le64_to_cpu(entry->power_cycle_count));
|
||||
printf(" %-22s%.*s\n", "previous firmware:", (int)sizeof(entry->previous_fw),
|
||||
entry->previous_fw);
|
||||
printf(" %-22s%.*s\n", "new firmware:", (int)sizeof(entry->new_fw),
|
||||
entry->new_fw);
|
||||
printf(" %-22s%d\n", "slot number:", entry->slot_number);
|
||||
printf(" %-22s%d\n", "commit action type:", entry->commit_action);
|
||||
printf(" %-22s%d\n", "result:", le16_to_cpu(entry->result));
|
||||
}
|
||||
|
||||
printf(" %-26s%d\n", "log page version:",
|
||||
le16_to_cpu(fw_history->log_page_version));
|
||||
|
||||
printf(" %-26s0x%"PRIx64"%"PRIx64"\n", "log page guid:",
|
||||
le64_to_cpu(fw_history->log_page_guid[1]),
|
||||
le64_to_cpu(fw_history->log_page_guid[0]));
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void ocp_fw_activation_history_json(const struct fw_activation_history *fw_history)
|
||||
{
|
||||
struct json_object *root = json_create_object();
|
||||
|
||||
json_object_add_value_uint(root, "log identifier", fw_history->log_id);
|
||||
json_object_add_value_uint(root, "valid entries", le32_to_cpu(fw_history->valid_entries));
|
||||
|
||||
struct json_object *entries = json_create_array();
|
||||
|
||||
for (int index = 0; index < fw_history->valid_entries; index++) {
|
||||
const struct fw_activation_history_entry *entry = &fw_history->entries[index];
|
||||
struct json_object *entry_obj = json_create_object();
|
||||
|
||||
json_object_add_value_uint(entry_obj, "version number", entry->ver_num);
|
||||
json_object_add_value_uint(entry_obj, "entry length", entry->entry_length);
|
||||
json_object_add_value_uint(entry_obj, "activation count",
|
||||
le16_to_cpu(entry->activation_count));
|
||||
json_object_add_value_uint64(entry_obj, "timestamp",
|
||||
(0x0000FFFFFFFFFFFF & le64_to_cpu(entry->timestamp)));
|
||||
json_object_add_value_uint(entry_obj, "power cycle count",
|
||||
le64_to_cpu(entry->power_cycle_count));
|
||||
|
||||
struct json_object *fw = json_object_new_string_len(entry->previous_fw,
|
||||
sizeof(entry->previous_fw));
|
||||
|
||||
json_object_add_value_object(entry_obj, "previous firmware", fw);
|
||||
|
||||
fw = json_object_new_string_len(entry->new_fw, sizeof(entry->new_fw));
|
||||
|
||||
json_object_add_value_object(entry_obj, "new firmware", fw);
|
||||
json_object_add_value_uint(entry_obj, "slot number", entry->slot_number);
|
||||
json_object_add_value_uint(entry_obj, "commit action type", entry->commit_action);
|
||||
json_object_add_value_uint(entry_obj, "result", le16_to_cpu(entry->result));
|
||||
|
||||
json_array_add_value_object(entries, entry_obj);
|
||||
}
|
||||
|
||||
json_object_add_value_array(root, "entries", entries);
|
||||
|
||||
json_object_add_value_uint(root, "log page version",
|
||||
le16_to_cpu(fw_history->log_page_version));
|
||||
|
||||
char guid[2 * sizeof(fw_history->log_page_guid) + 3] = { 0 };
|
||||
|
||||
sprintf(guid, "0x%"PRIx64"%"PRIx64"",
|
||||
le64_to_cpu(fw_history->log_page_guid[1]),
|
||||
le64_to_cpu(fw_history->log_page_guid[0]));
|
||||
json_object_add_value_string(root, "log page guid", guid);
|
||||
|
||||
json_print_object(root, NULL);
|
||||
json_free_object(root);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int ocp_fw_activation_history_log(int argc, char **argv, struct command *cmd,
|
||||
struct plugin *plugin)
|
||||
{
|
||||
|
@ -215,10 +95,7 @@ int ocp_fw_activation_history_log(int argc, char **argv, struct command *cmd,
|
|||
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);
|
||||
ocp_fw_act_history(&fw_history, print_flag);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
*
|
||||
* Authors: karl.dedow@solidigm.com
|
||||
*/
|
||||
#include "common.h"
|
||||
#include "linux/types.h"
|
||||
|
||||
#ifndef OCP_FIRMWARE_ACTIVATION_HISTORY_H
|
||||
#define OCP_FIRMWARE_ACTIVATION_HISTORY_H
|
||||
|
@ -11,7 +13,33 @@
|
|||
struct command;
|
||||
struct plugin;
|
||||
|
||||
int ocp_fw_activation_history_log(int argc, char **argv,
|
||||
struct command *cmd, struct plugin *plugin);
|
||||
struct __packed fw_activation_history_entry {
|
||||
__u8 ver_num;
|
||||
__u8 entry_length;
|
||||
__le16 reserved1;
|
||||
__le16 activation_count;
|
||||
__le64 timestamp;
|
||||
__le64 reserved2;
|
||||
__le64 power_cycle_count;
|
||||
char previous_fw[8];
|
||||
char new_fw[8];
|
||||
__u8 slot_number;
|
||||
__u8 commit_action;
|
||||
__le16 result;
|
||||
__u8 reserved3[14];
|
||||
};
|
||||
|
||||
struct __packed fw_activation_history {
|
||||
__u8 log_id;
|
||||
__u8 reserved1[3];
|
||||
__le32 valid_entries;
|
||||
struct fw_activation_history_entry entries[20];
|
||||
__u8 reserved2[2790];
|
||||
__le16 log_page_version;
|
||||
__le64 log_page_guid[2];
|
||||
};
|
||||
|
||||
int ocp_fw_activation_history_log(int argc, char **argv, struct command *cmd,
|
||||
struct plugin *plugin);
|
||||
|
||||
#endif
|
||||
|
|
288
plugins/ocp/ocp-hardware-component-log.c
Normal file
288
plugins/ocp/ocp-hardware-component-log.c
Normal file
|
@ -0,0 +1,288 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2024
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "util/types.h"
|
||||
#include "util/logging.h"
|
||||
#include "nvme-print.h"
|
||||
#include "ocp-hardware-component-log.h"
|
||||
#include "ocp-print.h"
|
||||
|
||||
//#define HWCOMP_DUMMY
|
||||
|
||||
#define print_info_array(...) \
|
||||
do { \
|
||||
if (log_level >= LOG_INFO) \
|
||||
print_array(__VA_ARGS__); \
|
||||
} while (false)
|
||||
|
||||
#define print_info_error(...) \
|
||||
do { \
|
||||
if (log_level >= LOG_INFO) \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
} while (false)
|
||||
|
||||
#ifdef HWCOMP_DUMMY
|
||||
static __u8 hwcomp_dummy[] = {
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xdc, 0x57, 0x0f, 0x9f, 0xb9, 0x31, 0x6b, 0xb7,
|
||||
0xd0, 0x4e, 0xcd, 0x30, 0x1f, 0x82, 0xb6, 0xbc,
|
||||
0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
|
||||
};
|
||||
#endif /* HWCOMP_DUMMY */
|
||||
|
||||
const char *hwcomp_id_to_string(__u32 id)
|
||||
{
|
||||
switch (id) {
|
||||
case HWCOMP_ID_ASIC:
|
||||
return "Controller ASIC component";
|
||||
case HWCOMP_ID_NAND:
|
||||
return "NAND Component";
|
||||
case HWCOMP_ID_DRAM:
|
||||
return "DRAM Component";
|
||||
case HWCOMP_ID_PMIC:
|
||||
return "PMIC Component";
|
||||
case HWCOMP_ID_PCB:
|
||||
return "PCB Component";
|
||||
case HWCOMP_ID_CAP:
|
||||
return "capacitor component";
|
||||
case HWCOMP_ID_REG:
|
||||
return "registor component";
|
||||
case HWCOMP_ID_CASE:
|
||||
return "case component";
|
||||
case HWCOMP_ID_SN:
|
||||
return "Device Serial Number";
|
||||
case HWCOMP_ID_COUNTRY:
|
||||
return "Country of Origin";
|
||||
case HWCOMP_ID_HW_REV:
|
||||
return "Global Device Hardware Revision";
|
||||
case HWCOMP_ID_VENDOR ... HWCOMP_ID_MAX:
|
||||
return "Vendor Unique Component";
|
||||
case HWCOMP_ID_RSVD:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return "Reserved";
|
||||
}
|
||||
|
||||
static int get_hwcomp_log_data(struct nvme_dev *dev, struct hwcomp_log *log)
|
||||
{
|
||||
int ret = 0;
|
||||
size_t desc_offset = offsetof(struct hwcomp_log, desc);
|
||||
struct nvme_get_log_args args = {
|
||||
.lpo = desc_offset,
|
||||
.args_size = sizeof(args),
|
||||
.fd = dev_fd(dev),
|
||||
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
|
||||
.lid = LID_HWCOMP,
|
||||
.nsid = NVME_NSID_ALL,
|
||||
};
|
||||
|
||||
#ifdef HWCOMP_DUMMY
|
||||
memcpy(log, hwcomp_dummy, desc_offset);
|
||||
#else /* HWCOMP_DUMMY */
|
||||
ret = nvme_get_log_simple(dev_fd(dev), LID_HWCOMP, desc_offset, log);
|
||||
if (ret) {
|
||||
print_info_error("error: ocp: failed to get log simple (hwcomp: %02X, ret: %d)\n",
|
||||
LID_HWCOMP, ret);
|
||||
return ret;
|
||||
}
|
||||
#endif /* HWCOMP_DUMMY */
|
||||
|
||||
print_info("id: %02Xh\n", LID_HWCOMP);
|
||||
print_info("version: %04Xh\n", log->ver);
|
||||
print_info_array("guid", log->guid, ARRAY_SIZE(log->guid));
|
||||
print_info("size: %s\n", uint128_t_to_string(le128_to_cpu(log->size)));
|
||||
|
||||
args.len = uint128_t_to_double(le128_to_cpu(log->size)) * sizeof(__le32);
|
||||
log->desc = calloc(1, args.len);
|
||||
if (!log->desc) {
|
||||
fprintf(stderr, "error: ocp: calloc: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
args.log = log->desc,
|
||||
|
||||
#ifdef HWCOMP_DUMMY
|
||||
memcpy(log->desc, &hwcomp_dummy[desc_offset], args.len);
|
||||
#else /* HWCOMP_DUMMY */
|
||||
ret = nvme_get_log_page(dev_fd(dev), NVME_LOG_PAGE_PDU_SIZE, &args);
|
||||
if (ret) {
|
||||
print_info_error("error: ocp: failed to get log page (hwcomp: %02X, ret: %d)\n",
|
||||
LID_HWCOMP, ret);
|
||||
return ret;
|
||||
}
|
||||
#endif /* HWCOMP_DUMMY */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_hwcomp_log(struct nvme_dev *dev, __u32 id, bool list)
|
||||
{
|
||||
_cleanup_free_ __u8 *desc = NULL;
|
||||
|
||||
int ret;
|
||||
nvme_print_flags_t fmt;
|
||||
struct hwcomp_log log = {
|
||||
.desc = (struct hwcomp_desc *)desc,
|
||||
};
|
||||
|
||||
ret = validate_output_format(nvme_cfg.output_format, &fmt);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "error: ocp: invalid output format\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = get_hwcomp_log_data(dev, &log);
|
||||
if (ret) {
|
||||
print_info_error("error: ocp: failed get hwcomp log: %02X data, ret: %d\n",
|
||||
LID_HWCOMP, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ocp_show_hwcomp_log(&log, id, list, fmt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ocp_hwcomp_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
_cleanup_nvme_dev_ struct nvme_dev *dev = NULL;
|
||||
int ret = 0;
|
||||
const char *desc = "retrieve hardware component log";
|
||||
struct config {
|
||||
__u64 id;
|
||||
bool list;
|
||||
} cfg = { 0 };
|
||||
const char *id_desc = "component identifier";
|
||||
const char *list_desc = "list component descriptions";
|
||||
|
||||
OPT_VALS(id) = {
|
||||
VAL_LONG("asic", HWCOMP_ID_ASIC),
|
||||
VAL_LONG("nand", HWCOMP_ID_NAND),
|
||||
VAL_LONG("dram", HWCOMP_ID_DRAM),
|
||||
VAL_LONG("pmic", HWCOMP_ID_PMIC),
|
||||
VAL_LONG("pcb", HWCOMP_ID_PCB),
|
||||
VAL_LONG("cap", HWCOMP_ID_CAP),
|
||||
VAL_LONG("reg", HWCOMP_ID_REG),
|
||||
VAL_LONG("case", HWCOMP_ID_CASE),
|
||||
VAL_LONG("sn", HWCOMP_ID_SN),
|
||||
VAL_LONG("country", HWCOMP_ID_COUNTRY),
|
||||
VAL_LONG("hw-rev", HWCOMP_ID_HW_REV),
|
||||
VAL_LONG("vendor", HWCOMP_ID_VENDOR),
|
||||
VAL_END()
|
||||
};
|
||||
|
||||
NVME_ARGS(opts, OPT_LONG("comp-id", 'i', &cfg.id, id_desc, id),
|
||||
OPT_FLAG("list", 'l', &cfg.list, list_desc));
|
||||
|
||||
ret = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = get_hwcomp_log(dev, cfg.id, cfg.list);
|
||||
if (ret)
|
||||
fprintf(stderr, "error: ocp: failed to get hwcomp log: %02X, ret: %d\n", LID_HWCOMP,
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
64
plugins/ocp/ocp-hardware-component-log.h
Normal file
64
plugins/ocp/ocp-hardware-component-log.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (c) 2024
|
||||
*/
|
||||
#include "cmd.h"
|
||||
#include "common.h"
|
||||
#include "ocp-nvme.h"
|
||||
|
||||
#ifndef OCP_HARDWARE_COMPONENT_LOG_H
|
||||
#define OCP_HARDWARE_COMPONENT_LOG_H
|
||||
|
||||
#define LID_HWCOMP 0xc6
|
||||
#define HWCOMP_RSVD2_LEN 14
|
||||
#define HWCOMP_SIZE_LEN 16
|
||||
#define HWCOMP_RSVD48_LEN 16
|
||||
|
||||
struct __packed hwcomp_desc {
|
||||
__le64 date_lot_size;
|
||||
__le64 add_info_size;
|
||||
__le32 id;
|
||||
__le64 mfg;
|
||||
__le64 rev;
|
||||
__le64 mfg_code;
|
||||
};
|
||||
|
||||
struct __packed hwcomp_log {
|
||||
__le16 ver;
|
||||
__u8 rsvd2[HWCOMP_RSVD2_LEN];
|
||||
__u8 guid[GUID_LEN];
|
||||
__u8 size[HWCOMP_SIZE_LEN];
|
||||
__u8 rsvd48[HWCOMP_RSVD48_LEN];
|
||||
struct hwcomp_desc *desc;
|
||||
};
|
||||
|
||||
struct hwcomp_desc_entry {
|
||||
struct hwcomp_desc *desc;
|
||||
__u64 date_lot_size;
|
||||
__u8 *date_lot_code;
|
||||
__u64 add_info_size;
|
||||
__u8 *add_info;
|
||||
__u64 desc_size;
|
||||
};
|
||||
|
||||
enum hwcomp_id {
|
||||
HWCOMP_ID_RSVD,
|
||||
HWCOMP_ID_ASIC,
|
||||
HWCOMP_ID_NAND,
|
||||
HWCOMP_ID_DRAM,
|
||||
HWCOMP_ID_PMIC,
|
||||
HWCOMP_ID_PCB,
|
||||
HWCOMP_ID_CAP,
|
||||
HWCOMP_ID_REG,
|
||||
HWCOMP_ID_CASE,
|
||||
HWCOMP_ID_SN,
|
||||
HWCOMP_ID_COUNTRY,
|
||||
HWCOMP_ID_HW_REV,
|
||||
HWCOMP_ID_VENDOR = 0x8000,
|
||||
HWCOMP_ID_MAX = 0xffff,
|
||||
};
|
||||
|
||||
int ocp_hwcomp_log(int argc, char **argv, struct command *cmd, struct plugin *plugin);
|
||||
const char *hwcomp_id_to_string(__u32 id);
|
||||
|
||||
#endif /* OCP_HARDWARE_COMPONENT_LOG_H */
|
File diff suppressed because it is too large
Load diff
|
@ -11,7 +11,7 @@
|
|||
#if !defined(OCP_NVME) || defined(CMD_HEADER_MULTI_READ)
|
||||
#define OCP_NVME
|
||||
|
||||
#define OCP_PLUGIN_VERSION "2.9.0"
|
||||
#define OCP_PLUGIN_VERSION "2.9.2"
|
||||
#include "cmd.h"
|
||||
|
||||
PLUGIN(NAME("ocp", "OCP cloud SSD extensions", OCP_PLUGIN_VERSION),
|
||||
|
@ -38,9 +38,207 @@ PLUGIN(NAME("ocp", "OCP cloud SSD extensions", OCP_PLUGIN_VERSION),
|
|||
ENTRY("tcg-configuration-log", "Retrieve TCG Configuration Log Page", ocp_tcg_configuration_log)
|
||||
ENTRY("get-error-injection", "Return set of error injection", get_error_injection)
|
||||
ENTRY("set-error-injection", "Inject error conditions", set_error_injection)
|
||||
ENTRY("get-enable-ieee1667-silo", "return set of enable IEEE1667 silo",
|
||||
get_enable_ieee1667_silo)
|
||||
ENTRY("hardware-component-log", "retrieve hardware component log", hwcomp_log)
|
||||
)
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
#include "define_cmd.h"
|
||||
|
||||
#ifndef OCP_NVME_H
|
||||
#define OCP_NVME_H
|
||||
struct __packed ssd_latency_monitor_log {
|
||||
__u8 feature_status; /* 0x00 */
|
||||
__u8 rsvd1; /* 0x01 */
|
||||
__le16 active_bucket_timer; /* 0x02 */
|
||||
__le16 active_bucket_timer_threshold; /* 0x04 */
|
||||
__u8 active_threshold_a; /* 0x06 */
|
||||
__u8 active_threshold_b; /* 0x07 */
|
||||
__u8 active_threshold_c; /* 0x08 */
|
||||
__u8 active_threshold_d; /* 0x09 */
|
||||
__le16 active_latency_config; /* 0x0A */
|
||||
__u8 active_latency_min_window; /* 0x0C */
|
||||
__u8 rsvd2[0x13]; /* 0x0D */
|
||||
|
||||
__le32 active_bucket_counter[4][4]; /* 0x20 - 0x5F */
|
||||
__le64 active_latency_timestamp[4][3]; /* 0x60 - 0xBF */
|
||||
__le16 active_measured_latency[4][3]; /* 0xC0 - 0xD7 */
|
||||
__le16 active_latency_stamp_units; /* 0xD8 */
|
||||
__u8 rsvd3[0x16]; /* 0xDA */
|
||||
|
||||
__le32 static_bucket_counter[4][4]; /* 0x0F0 - 0x12F */
|
||||
__le64 static_latency_timestamp[4][3]; /* 0x130 - 0x18F */
|
||||
__le16 static_measured_latency[4][3]; /* 0x190 - 0x1A7 */
|
||||
__le16 static_latency_stamp_units; /* 0x1A8 */
|
||||
__u8 rsvd4[0x16]; /* 0x1AA */
|
||||
|
||||
__le16 debug_log_trigger_enable; /* 0x1C0 */
|
||||
__le16 debug_log_measured_latency; /* 0x1C2 */
|
||||
__le64 debug_log_latency_stamp; /* 0x1C4 */
|
||||
__le16 debug_log_ptr; /* 0x1CC */
|
||||
__le16 debug_log_counter_trigger; /* 0x1CE */
|
||||
__u8 debug_log_stamp_units; /* 0x1D0 */
|
||||
__u8 rsvd5[0x1D]; /* 0x1D1 */
|
||||
|
||||
__le16 log_page_version; /* 0x1EE */
|
||||
__u8 log_page_guid[0x10]; /* 0x1F0 */
|
||||
};
|
||||
|
||||
#define GUID_LEN 16
|
||||
|
||||
#define C3_ACTIVE_BUCKET_TIMER_INCREMENT 5
|
||||
#define C3_ACTIVE_THRESHOLD_INCREMENT 5
|
||||
#define C3_MINIMUM_WINDOW_INCREMENT 100
|
||||
#define C3_BUCKET_NUM 4
|
||||
|
||||
#define READ 3
|
||||
#define WRITE 2
|
||||
#define TRIM 1
|
||||
|
||||
#define C5_NUM_UNSUPPORTED_REQ_ENTRIES 253
|
||||
|
||||
/*
|
||||
* struct unsupported_requirement_log - unsupported requirement list
|
||||
* @unsupported_count: Number of Unsupported Requirement IDs
|
||||
* @rsvd1: Reserved
|
||||
* @unsupported_req_list: Unsupported Requirements lists up to 253.
|
||||
* @rsvd2: Reserved
|
||||
* @log_page_version: indicates the version of the mapping this log page uses.
|
||||
* Shall be set to 0001h
|
||||
* @log_page_guid: Shall be set to C7BB98B7D0324863BB2C23990E9C722Fh.
|
||||
*/
|
||||
struct __packed unsupported_requirement_log {
|
||||
__le16 unsupported_count;
|
||||
__u8 rsvd1[14];
|
||||
__u8 unsupported_req_list[C5_NUM_UNSUPPORTED_REQ_ENTRIES][16];
|
||||
__u8 rsvd2[14];
|
||||
__le16 log_page_version;
|
||||
__u8 log_page_guid[GUID_LEN];
|
||||
};
|
||||
|
||||
#define C1_PREV_PANIC_IDS_LENGTH 4
|
||||
|
||||
/**
|
||||
* struct ocp_error_recovery_log_page - Error Recovery Log Page
|
||||
* @panic_reset_wait_time: Panic Reset Wait Time
|
||||
* @panic_reset_action: Panic Reset Action
|
||||
* @device_recover_action_1: Device Recovery Action 1
|
||||
* @panic_id: Panic ID
|
||||
* @device_capabilities: Device Capabilities
|
||||
* @vendor_specific_recovery_opcode: Vendor Specific Recovery Opcode
|
||||
* @reserved: Reserved
|
||||
* @vendor_specific_command_cdw12: Vendor Specific Command CDW12
|
||||
* @vendor_specific_command_cdw13: Vendor Specific Command CDW13
|
||||
* @vendor_specific_command_timeout: Vendor Specific Command Timeout
|
||||
* @device_recover_action_2: Device Recovery Action 2
|
||||
* @device_recover_action_2_timeout: Device Recovery Action 2 Timeout
|
||||
* @panic_count: Panic Count
|
||||
* @prev_panic_id: Previous Panic IDs
|
||||
* @reserved2: Reserved
|
||||
* @log_page_version: Log Page Version
|
||||
* @log_page_guid: Log Page GUID
|
||||
*/
|
||||
struct __packed ocp_error_recovery_log_page {
|
||||
__le16 panic_reset_wait_time; /* 2 bytes - 0x00 - 0x01 */
|
||||
__u8 panic_reset_action; /* 1 byte - 0x02 */
|
||||
__u8 device_recover_action_1; /* 1 byte - 0x03 */
|
||||
__le64 panic_id; /* 8 bytes - 0x04 - 0x0B */
|
||||
__le32 device_capabilities; /* 4 bytes - 0x0C - 0x0F */
|
||||
__u8 vendor_specific_recovery_opcode; /* 1 byte - 0x10 */
|
||||
__u8 reserved[0x3]; /* 3 bytes - 0x11 - 0x13 */
|
||||
__le32 vendor_specific_command_cdw12; /* 4 bytes - 0x14 - 0x17 */
|
||||
__le32 vendor_specific_command_cdw13; /* 4 bytes - 0x18 - 0x1B */
|
||||
__u8 vendor_specific_command_timeout; /* 1 byte - 0x1C */
|
||||
__u8 device_recover_action_2; /* 1 byte - 0x1D */
|
||||
__u8 device_recover_action_2_timeout; /* 1 byte - 0x1E */
|
||||
__u8 panic_count; /* 1 byte - 0x1F */
|
||||
__le64 prev_panic_id[C1_PREV_PANIC_IDS_LENGTH]; /* 32 bytes - 0x20 - 0x3F */
|
||||
__u8 reserved2[0x1ae]; /* 430 bytes - 0x40 - 0x1ED */
|
||||
__le16 log_page_version; /* 2 bytes - 0x1EE - 0x1EF */
|
||||
__u8 log_page_guid[GUID_LEN]; /* 16 bytes - 0x1F0 - 0x1FF */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ocp_device_capabilities_log_page - Device Capability Log page
|
||||
* @pcie_exp_port: PCI Express Ports
|
||||
* @oob_management_support: OOB Management Support
|
||||
* @wz_cmd_support: Write Zeroes Command Support
|
||||
* @sanitize_cmd_support: Sanitize Command Support
|
||||
* @dsm_cmd_support: Dataset Management Command Support
|
||||
* @wu_cmd_support: Write Uncorrectable Command Support
|
||||
* @fused_operation_support: Fused Operation Support
|
||||
* @min_valid_dssd_pwr_state: Minimum Valid DSSD Power State
|
||||
* @dssd_pwr_state_desc: DSSD Power State Descriptors
|
||||
* @vendor_specific_command_timeout: Vendor Specific Command Timeout
|
||||
* @reserved: Reserved
|
||||
* @log_page_version: Log Page Version
|
||||
* @log_page_guid: Log Page GUID
|
||||
*/
|
||||
struct __packed ocp_device_capabilities_log_page {
|
||||
__le16 pcie_exp_port;
|
||||
__le16 oob_management_support;
|
||||
__le16 wz_cmd_support;
|
||||
__le16 sanitize_cmd_support;
|
||||
__le16 dsm_cmd_support;
|
||||
__le16 wu_cmd_support;
|
||||
__le16 fused_operation_support;
|
||||
__le16 min_valid_dssd_pwr_state;
|
||||
__u8 dssd_pwr_state_desc[128];
|
||||
__u8 reserved[3934];
|
||||
__le16 log_page_version;
|
||||
__u8 log_page_guid[GUID_LEN];
|
||||
};
|
||||
|
||||
/*
|
||||
* struct tcg_configuration_log - TCG Configuration Log Page Structure
|
||||
* @state: state
|
||||
* @rsvd1: Reserved1
|
||||
* @locking_sp_act_count: Locking SP Activation Count
|
||||
* @type_rev_count: Tper Revert Count
|
||||
* @locking_sp_rev_count: Locking SP Revert Count.
|
||||
* @no_of_locking_obj: Number of Locking Objects
|
||||
* @no_of_single_um_locking_obj: Number of Single User Mode Locking Objects
|
||||
* @no_of_range_prov_locking_obj: Number of Range Provisioned Locking Objects
|
||||
* @no_of_ns_prov_locking_obj: Number of Namespace Provisioned Locking Objects
|
||||
* @no_of_read_lock_locking_obj: Number of Read Locked Locking Objects
|
||||
* @no_of_write_lock_locking_obj: Number of Write Locked Locking Objects
|
||||
* @no_of_read_unlock_locking_obj: Number of Read Unlocked Locking Objects
|
||||
* @no_of_read_unlock_locking_obj: Number of Write Unlocked Locking Objects
|
||||
* @rsvd2: Reserved2
|
||||
* @sid_auth_try_count: SID Authentication Try Count
|
||||
* @sid_auth_try_limit: SID Authentication Try Limit
|
||||
* @pro_tcg_rc: Programmatic TCG Reset Count
|
||||
* @pro_rlc: Programmatic Reset Lock Count
|
||||
* @tcg_ec: TCG Error Count
|
||||
* @rsvd3: Reserved3
|
||||
* @log_page_version: Log Page Version
|
||||
*/
|
||||
struct __packed tcg_configuration_log {
|
||||
__u8 state;
|
||||
__u8 rsvd1[3];
|
||||
__u8 locking_sp_act_count;
|
||||
__u8 type_rev_count;
|
||||
__u8 locking_sp_rev_count;
|
||||
__u8 no_of_locking_obj;
|
||||
__u8 no_of_single_um_locking_obj;
|
||||
__u8 no_of_range_prov_locking_obj;
|
||||
__u8 no_of_ns_prov_locking_obj;
|
||||
__u8 no_of_read_lock_locking_obj;
|
||||
__u8 no_of_write_lock_locking_obj;
|
||||
__u8 no_of_read_unlock_locking_obj;
|
||||
__u8 no_of_write_unlock_locking_obj;
|
||||
__u8 rsvd2;
|
||||
__le32 sid_auth_try_count;
|
||||
__le32 sid_auth_try_limit;
|
||||
__le32 pro_tcg_rc;
|
||||
__le32 pro_rlc;
|
||||
__le32 tcg_ec;
|
||||
__u8 rsvd3[458];
|
||||
__le16 log_page_version;
|
||||
__u8 log_page_guid[GUID_LEN];
|
||||
|
||||
};
|
||||
#endif /* OCP_NVME_H */
|
||||
|
|
54
plugins/ocp/ocp-print-binary.c
Normal file
54
plugins/ocp/ocp-print-binary.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "util/types.h"
|
||||
#include "nvme-print.h"
|
||||
#include "ocp-print.h"
|
||||
#include "ocp-hardware-component-log.h"
|
||||
|
||||
static void binary_hwcomp_log(struct hwcomp_log *log, __u32 id, bool list)
|
||||
{
|
||||
long double desc_len = uint128_t_to_double(le128_to_cpu(log->size)) * sizeof(__le32);
|
||||
|
||||
d_raw((unsigned char *)log, offsetof(struct hwcomp_log, desc) + desc_len);
|
||||
}
|
||||
|
||||
static void binary_c5_log(struct nvme_dev *dev, struct unsupported_requirement_log *log_data)
|
||||
{
|
||||
d_raw((unsigned char *)log_data, sizeof(*log_data));
|
||||
}
|
||||
|
||||
static void binary_c1_log(struct ocp_error_recovery_log_page *log_data)
|
||||
{
|
||||
d_raw((unsigned char *)log_data, sizeof(*log_data));
|
||||
}
|
||||
|
||||
static void binary_c4_log(struct ocp_device_capabilities_log_page *log_data)
|
||||
{
|
||||
d_raw((unsigned char *)log_data, sizeof(*log_data));
|
||||
}
|
||||
|
||||
static void binary_c9_log(struct telemetry_str_log_format *log_data, __u8 *log_data_buf,
|
||||
int total_log_page_size)
|
||||
{
|
||||
d_raw((unsigned char *)log_data_buf, total_log_page_size);
|
||||
}
|
||||
|
||||
static void binary_c7_log(struct nvme_dev *dev, struct tcg_configuration_log *log_data)
|
||||
{
|
||||
d_raw((unsigned char *)log_data, sizeof(*log_data));
|
||||
}
|
||||
|
||||
static struct ocp_print_ops binary_print_ops = {
|
||||
.hwcomp_log = binary_hwcomp_log,
|
||||
.c5_log = binary_c5_log,
|
||||
.c1_log = binary_c1_log,
|
||||
.c4_log = binary_c4_log,
|
||||
.c9_log = binary_c9_log,
|
||||
.c7_log = binary_c7_log,
|
||||
};
|
||||
|
||||
struct ocp_print_ops *ocp_get_binary_print_ops(nvme_print_flags_t flags)
|
||||
{
|
||||
binary_print_ops.flags = flags;
|
||||
return &binary_print_ops;
|
||||
}
|
851
plugins/ocp/ocp-print-json.c
Normal file
851
plugins/ocp/ocp-print-json.c
Normal file
|
@ -0,0 +1,851 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#include "util/types.h"
|
||||
#include "common.h"
|
||||
#include "nvme-print.h"
|
||||
#include "ocp-print.h"
|
||||
#include "ocp-hardware-component-log.h"
|
||||
#include "ocp-fw-activation-history.h"
|
||||
#include "ocp-smart-extended-log.h"
|
||||
#include "ocp-telemetry-decode.h"
|
||||
#include "ocp-nvme.h"
|
||||
|
||||
static void print_hwcomp_desc_json(struct hwcomp_desc_entry *e, struct json_object *r)
|
||||
{
|
||||
obj_add_str(r, "Description", hwcomp_id_to_string(le32_to_cpu(e->desc->id)));
|
||||
obj_add_nprix64(r, "Date/Lot Size", e->date_lot_size);
|
||||
obj_add_nprix64(r, "Additional Information Size", e->add_info_size);
|
||||
obj_add_uint_0nx(r, "Identifier", le32_to_cpu(e->desc->id), 8);
|
||||
obj_add_0nprix64(r, "Manufacture", le64_to_cpu(e->desc->mfg), 16);
|
||||
obj_add_0nprix64(r, "Revision", le64_to_cpu(e->desc->rev), 16);
|
||||
obj_add_0nprix64(r, "Manufacture Code", le64_to_cpu(e->desc->mfg_code), 16);
|
||||
obj_add_byte_array(r, "Date/Lot Code", e->date_lot_code, e->date_lot_size);
|
||||
obj_add_byte_array(r, "Additional Information", e->add_info, e->add_info_size);
|
||||
}
|
||||
|
||||
static void print_hwcomp_desc_list_json(struct json_object *r, struct hwcomp_desc_entry *e,
|
||||
bool list, int num)
|
||||
{
|
||||
_cleanup_free_ char *k = NULL;
|
||||
|
||||
if (asprintf(&k, "Component %d", num) < 0)
|
||||
return;
|
||||
|
||||
if (list) {
|
||||
obj_add_str(r, k, hwcomp_id_to_string(le32_to_cpu(e->desc->id)));
|
||||
return;
|
||||
}
|
||||
|
||||
print_hwcomp_desc_json(e, obj_create_array_obj(r, k));
|
||||
}
|
||||
|
||||
static void print_hwcomp_descs_json(struct hwcomp_desc *desc, long double log_size, __u32 id,
|
||||
bool list, struct json_object *r)
|
||||
{
|
||||
size_t date_lot_code_offset = sizeof(struct hwcomp_desc);
|
||||
struct hwcomp_desc_entry e = { desc };
|
||||
int num = 1;
|
||||
|
||||
while (log_size > 0) {
|
||||
e.date_lot_size = le64_to_cpu(e.desc->date_lot_size) * sizeof(__le32);
|
||||
e.date_lot_code = e.date_lot_size ?
|
||||
(__u8 *)e.desc + date_lot_code_offset : NULL;
|
||||
e.add_info_size = le64_to_cpu(e.desc->add_info_size) * sizeof(__le32);
|
||||
e.add_info = e.add_info_size ? e.date_lot_code ?
|
||||
e.date_lot_code + e.date_lot_size :
|
||||
(__u8 *)e.desc + date_lot_code_offset : NULL;
|
||||
if (!id || id == le32_to_cpu(e.desc->id))
|
||||
print_hwcomp_desc_list_json(r, &e, list, num++);
|
||||
e.desc_size = date_lot_code_offset + e.date_lot_size + e.add_info_size;
|
||||
e.desc = (struct hwcomp_desc *)((__u8 *)e.desc + e.desc_size);
|
||||
log_size -= e.desc_size;
|
||||
}
|
||||
}
|
||||
|
||||
static void json_hwcomp_log(struct hwcomp_log *log, __u32 id, bool list)
|
||||
{
|
||||
struct json_object *r = json_create_object();
|
||||
|
||||
long double log_size = uint128_t_to_double(le128_to_cpu(log->size)) * sizeof(__le32);
|
||||
|
||||
obj_add_uint_02x(r, "Log Identifier", LID_HWCOMP);
|
||||
obj_add_uint_0x(r, "Log Page Version", le16_to_cpu(log->ver));
|
||||
obj_add_byte_array(r, "Reserved2", log->rsvd2, ARRAY_SIZE(log->rsvd2));
|
||||
obj_add_byte_array(r, "Log page GUID", log->guid, ARRAY_SIZE(log->guid));
|
||||
obj_add_nprix64(r, "Hardware Component Log Size", (unsigned long long)log_size);
|
||||
obj_add_byte_array(r, "Reserved48", log->rsvd48, ARRAY_SIZE(log->rsvd48));
|
||||
print_hwcomp_descs_json(log->desc, log_size, id, list,
|
||||
obj_create_array_obj(r, "Component Descriptions"));
|
||||
|
||||
json_print(r);
|
||||
}
|
||||
|
||||
static void json_fw_activation_history(const struct fw_activation_history *fw_history)
|
||||
{
|
||||
struct json_object *root = json_create_object();
|
||||
|
||||
json_object_add_value_uint(root, "log identifier", fw_history->log_id);
|
||||
json_object_add_value_uint(root, "valid entries", le32_to_cpu(fw_history->valid_entries));
|
||||
|
||||
struct json_object *entries = json_create_array();
|
||||
|
||||
for (int index = 0; index < le32_to_cpu(fw_history->valid_entries); index++) {
|
||||
const struct fw_activation_history_entry *entry = &fw_history->entries[index];
|
||||
struct json_object *entry_obj = json_create_object();
|
||||
|
||||
json_object_add_value_uint(entry_obj, "version number", entry->ver_num);
|
||||
json_object_add_value_uint(entry_obj, "entry length", entry->entry_length);
|
||||
json_object_add_value_uint(entry_obj, "activation count",
|
||||
le16_to_cpu(entry->activation_count));
|
||||
json_object_add_value_uint64(entry_obj, "timestamp",
|
||||
(0x0000FFFFFFFFFFFF & le64_to_cpu(entry->timestamp)));
|
||||
json_object_add_value_uint(entry_obj, "power cycle count",
|
||||
le64_to_cpu(entry->power_cycle_count));
|
||||
|
||||
struct json_object *fw = json_object_new_string_len(entry->previous_fw,
|
||||
sizeof(entry->previous_fw));
|
||||
|
||||
json_object_add_value_object(entry_obj, "previous firmware", fw);
|
||||
|
||||
fw = json_object_new_string_len(entry->new_fw, sizeof(entry->new_fw));
|
||||
|
||||
json_object_add_value_object(entry_obj, "new firmware", fw);
|
||||
json_object_add_value_uint(entry_obj, "slot number", entry->slot_number);
|
||||
json_object_add_value_uint(entry_obj, "commit action type", entry->commit_action);
|
||||
json_object_add_value_uint(entry_obj, "result", le16_to_cpu(entry->result));
|
||||
|
||||
json_array_add_value_object(entries, entry_obj);
|
||||
}
|
||||
|
||||
json_object_add_value_array(root, "entries", entries);
|
||||
|
||||
json_object_add_value_uint(root, "log page version",
|
||||
le16_to_cpu(fw_history->log_page_version));
|
||||
|
||||
char guid[2 * sizeof(fw_history->log_page_guid) + 3] = { 0 };
|
||||
|
||||
sprintf(guid, "0x%"PRIx64"%"PRIx64"",
|
||||
le64_to_cpu(fw_history->log_page_guid[1]),
|
||||
le64_to_cpu(fw_history->log_page_guid[0]));
|
||||
json_object_add_value_string(root, "log page guid", guid);
|
||||
|
||||
json_print_object(root, NULL);
|
||||
json_free_object(root);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void json_smart_extended_log(void *data)
|
||||
{
|
||||
struct json_object *root;
|
||||
struct json_object *pmuw;
|
||||
struct json_object *pmur;
|
||||
uint16_t smart_log_ver = 0;
|
||||
__u8 *log_data = data;
|
||||
char guid[40];
|
||||
|
||||
root = json_create_object();
|
||||
pmuw = json_create_object();
|
||||
pmur = json_create_object();
|
||||
|
||||
json_object_add_value_uint64(pmuw, "hi",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW + 8] & 0xFFFFFFFFFFFFFFFF));
|
||||
json_object_add_value_uint64(pmuw, "lo",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF));
|
||||
json_object_add_value_object(root, "Physical media units written", pmuw);
|
||||
json_object_add_value_uint64(pmur, "hi",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR + 8] & 0xFFFFFFFFFFFFFFFF));
|
||||
json_object_add_value_uint64(pmur, "lo",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF));
|
||||
json_object_add_value_object(root, "Physical media units read", pmur);
|
||||
json_object_add_value_uint64(root, "Bad user nand blocks - Raw",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF));
|
||||
json_object_add_value_uint(root, "Bad user nand blocks - Normalized",
|
||||
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN]));
|
||||
json_object_add_value_uint64(root, "Bad system nand blocks - Raw",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF));
|
||||
json_object_add_value_uint(root, "Bad system nand blocks - Normalized",
|
||||
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN]));
|
||||
json_object_add_value_uint64(root, "XOR recovery count",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC]));
|
||||
json_object_add_value_uint64(root, "Uncorrectable read error count",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC]));
|
||||
json_object_add_value_uint64(root, "Soft ecc error count",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC]));
|
||||
json_object_add_value_uint(root, "End to end detected errors",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC]));
|
||||
json_object_add_value_uint(root, "End to end corrected errors",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE]));
|
||||
json_object_add_value_uint(root, "System data percent used",
|
||||
(__u8)log_data[SCAO_SDPU]);
|
||||
json_object_add_value_uint64(root, "Refresh counts",
|
||||
(uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC]) & 0x00FFFFFFFFFFFFFF));
|
||||
json_object_add_value_uint(root, "Max User data erase counts",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC]));
|
||||
json_object_add_value_uint(root, "Min User data erase counts",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC]));
|
||||
json_object_add_value_uint(root, "Number of Thermal throttling events",
|
||||
(__u8)log_data[SCAO_NTTE]);
|
||||
json_object_add_value_uint(root, "Current throttling status",
|
||||
(__u8)log_data[SCAO_CTS]);
|
||||
json_object_add_value_uint64(root, "PCIe correctable error count",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC]));
|
||||
json_object_add_value_uint(root, "Incomplete shutdowns",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS]));
|
||||
json_object_add_value_uint(root, "Percent free blocks",
|
||||
(__u8)log_data[SCAO_PFB]);
|
||||
json_object_add_value_uint(root, "Capacitor health",
|
||||
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH]));
|
||||
json_object_add_value_uint64(root, "Unaligned I/O",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO]));
|
||||
json_object_add_value_uint64(root, "Security Version Number",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN]));
|
||||
json_object_add_value_uint64(root, "NUSE - Namespace utilization",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE]));
|
||||
json_object_add_value_uint128(root, "PLP start count",
|
||||
le128_to_cpu(&log_data[SCAO_PSC]));
|
||||
json_object_add_value_uint128(root, "Endurance estimate",
|
||||
le128_to_cpu(&log_data[SCAO_EEST]));
|
||||
smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]);
|
||||
|
||||
json_object_add_value_uint(root, "Log page version", smart_log_ver);
|
||||
|
||||
memset((void *)guid, 0, 40);
|
||||
sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]),
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG]));
|
||||
json_object_add_value_string(root, "Log page GUID", guid);
|
||||
|
||||
switch (smart_log_ver) {
|
||||
case 0 ... 1:
|
||||
break;
|
||||
default:
|
||||
case 4:
|
||||
json_object_add_value_uint(root, "NVMe Command Set Errata Version",
|
||||
(__u8)log_data[SCAO_NCSEV]);
|
||||
json_object_add_value_uint(root, "Lowest Permitted Firmware Revision",
|
||||
le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC]));
|
||||
fallthrough;
|
||||
case 2 ... 3:
|
||||
json_object_add_value_uint(root, "Errata Version Field",
|
||||
(__u8)log_data[SCAO_EVF]);
|
||||
json_object_add_value_uint(root, "Point Version Field",
|
||||
le16_to_cpu(*(uint16_t *)&log_data[SCAO_PVF]));
|
||||
json_object_add_value_uint(root, "Minor Version Field",
|
||||
le16_to_cpu(*(uint16_t *)&log_data[SCAO_MIVF]));
|
||||
json_object_add_value_uint(root, "Major Version Field",
|
||||
(__u8)log_data[SCAO_MAVF]);
|
||||
json_object_add_value_uint(root, "NVMe Base Errata Version",
|
||||
(__u8)log_data[SCAO_NBEV]);
|
||||
json_object_add_value_uint(root, "PCIe Link Retraining Count",
|
||||
le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC]));
|
||||
json_object_add_value_uint(root, "Power State Change Count",
|
||||
le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC]));
|
||||
}
|
||||
json_print_object(root, NULL);
|
||||
printf("\n");
|
||||
json_free_object(root);
|
||||
}
|
||||
|
||||
static void json_telemetry_log(struct ocp_telemetry_parse_options *options)
|
||||
{
|
||||
print_ocp_telemetry_json(options);
|
||||
}
|
||||
|
||||
static void json_c3_log(struct nvme_dev *dev, struct ssd_latency_monitor_log *log_data)
|
||||
{
|
||||
struct json_object *root;
|
||||
char ts_buf[128];
|
||||
char buf[128];
|
||||
int i, j;
|
||||
char *operation[3] = {"Trim", "Write", "Read"};
|
||||
|
||||
root = json_create_object();
|
||||
|
||||
json_object_add_value_uint(root, "Feature Status",
|
||||
log_data->feature_status);
|
||||
json_object_add_value_uint(root, "Active Bucket Timer",
|
||||
C3_ACTIVE_BUCKET_TIMER_INCREMENT *
|
||||
le16_to_cpu(log_data->active_bucket_timer));
|
||||
json_object_add_value_uint(root, "Active Bucket Timer Threshold",
|
||||
C3_ACTIVE_BUCKET_TIMER_INCREMENT *
|
||||
le16_to_cpu(log_data->active_bucket_timer_threshold));
|
||||
json_object_add_value_uint(root, "Active Threshold A",
|
||||
C3_ACTIVE_THRESHOLD_INCREMENT *
|
||||
le16_to_cpu(log_data->active_threshold_a + 1));
|
||||
json_object_add_value_uint(root, "Active Threshold B",
|
||||
C3_ACTIVE_THRESHOLD_INCREMENT *
|
||||
le16_to_cpu(log_data->active_threshold_b + 1));
|
||||
json_object_add_value_uint(root, "Active Threshold C",
|
||||
C3_ACTIVE_THRESHOLD_INCREMENT *
|
||||
le16_to_cpu(log_data->active_threshold_c + 1));
|
||||
json_object_add_value_uint(root, "Active Threshold D",
|
||||
C3_ACTIVE_THRESHOLD_INCREMENT *
|
||||
le16_to_cpu(log_data->active_threshold_d + 1));
|
||||
json_object_add_value_uint(root, "Active Latency Configuration",
|
||||
le16_to_cpu(log_data->active_latency_config));
|
||||
json_object_add_value_uint(root, "Active Latency Minimum Window",
|
||||
C3_MINIMUM_WINDOW_INCREMENT *
|
||||
le16_to_cpu(log_data->active_latency_min_window));
|
||||
|
||||
for (i = 0; i < C3_BUCKET_NUM; i++) {
|
||||
struct json_object *bucket;
|
||||
|
||||
bucket = json_create_object();
|
||||
sprintf(buf, "Active Bucket Counter: Bucket %d", i);
|
||||
for (j = 2; j >= 0; j--) {
|
||||
json_object_add_value_uint(bucket, operation[j],
|
||||
le32_to_cpu(log_data->active_bucket_counter[i][j+1]));
|
||||
}
|
||||
json_object_add_value_object(root, buf, bucket);
|
||||
}
|
||||
|
||||
for (i = 0; i < C3_BUCKET_NUM; i++) {
|
||||
struct json_object *bucket;
|
||||
|
||||
bucket = json_create_object();
|
||||
sprintf(buf, "Active Latency Time Stamp: Bucket %d", i);
|
||||
for (j = 2; j >= 0; j--) {
|
||||
if (le64_to_cpu(log_data->active_latency_timestamp[3-i][j]) == -1) {
|
||||
json_object_add_value_string(bucket, operation[j], "NA");
|
||||
} else {
|
||||
convert_ts(le64_to_cpu(log_data->active_latency_timestamp[3-i][j]),
|
||||
ts_buf);
|
||||
json_object_add_value_string(bucket, operation[j], ts_buf);
|
||||
}
|
||||
}
|
||||
json_object_add_value_object(root, buf, bucket);
|
||||
}
|
||||
|
||||
for (i = 0; i < C3_BUCKET_NUM; i++) {
|
||||
struct json_object *bucket;
|
||||
|
||||
bucket = json_create_object();
|
||||
sprintf(buf, "Active Measured Latency: Bucket %d", i);
|
||||
for (j = 2; j >= 0; j--) {
|
||||
json_object_add_value_uint(bucket, operation[j],
|
||||
le16_to_cpu(log_data->active_measured_latency[3-i][j]));
|
||||
}
|
||||
json_object_add_value_object(root, buf, bucket);
|
||||
}
|
||||
|
||||
json_object_add_value_uint(root, "Active Latency Stamp Units",
|
||||
le16_to_cpu(log_data->active_latency_stamp_units));
|
||||
|
||||
for (i = 0; i < C3_BUCKET_NUM; i++) {
|
||||
struct json_object *bucket;
|
||||
|
||||
bucket = json_create_object();
|
||||
sprintf(buf, "Static Bucket Counter: Bucket %d", i);
|
||||
for (j = 2; j >= 0; j--) {
|
||||
json_object_add_value_uint(bucket, operation[j],
|
||||
le32_to_cpu(log_data->static_bucket_counter[i][j+1]));
|
||||
}
|
||||
json_object_add_value_object(root, buf, bucket);
|
||||
}
|
||||
|
||||
for (i = 0; i < C3_BUCKET_NUM; i++) {
|
||||
struct json_object *bucket;
|
||||
|
||||
bucket = json_create_object();
|
||||
sprintf(buf, "Static Latency Time Stamp: Bucket %d", i);
|
||||
for (j = 2; j >= 0; j--) {
|
||||
if (le64_to_cpu(log_data->static_latency_timestamp[3-i][j]) == -1) {
|
||||
json_object_add_value_string(bucket, operation[j], "NA");
|
||||
} else {
|
||||
convert_ts(le64_to_cpu(log_data->static_latency_timestamp[3-i][j]),
|
||||
ts_buf);
|
||||
json_object_add_value_string(bucket, operation[j], ts_buf);
|
||||
}
|
||||
}
|
||||
json_object_add_value_object(root, buf, bucket);
|
||||
}
|
||||
|
||||
for (i = 0; i < C3_BUCKET_NUM; i++) {
|
||||
struct json_object *bucket;
|
||||
|
||||
bucket = json_create_object();
|
||||
sprintf(buf, "Static Measured Latency: Bucket %d", i);
|
||||
for (j = 2; j >= 0; j--) {
|
||||
json_object_add_value_uint(bucket, operation[j],
|
||||
le16_to_cpu(log_data->static_measured_latency[3-i][j]));
|
||||
}
|
||||
json_object_add_value_object(root, buf, bucket);
|
||||
}
|
||||
|
||||
json_object_add_value_uint(root, "Static Latency Stamp Units",
|
||||
le16_to_cpu(log_data->static_latency_stamp_units));
|
||||
json_object_add_value_uint(root, "Debug Log Trigger Enable",
|
||||
le16_to_cpu(log_data->debug_log_trigger_enable));
|
||||
json_object_add_value_uint(root, "Debug Log Measured Latency",
|
||||
le16_to_cpu(log_data->debug_log_measured_latency));
|
||||
if (le64_to_cpu(log_data->debug_log_latency_stamp) == -1) {
|
||||
json_object_add_value_string(root, "Debug Log Latency Time Stamp", "NA");
|
||||
} else {
|
||||
convert_ts(le64_to_cpu(log_data->debug_log_latency_stamp), ts_buf);
|
||||
json_object_add_value_string(root, "Debug Log Latency Time Stamp", ts_buf);
|
||||
}
|
||||
json_object_add_value_uint(root, "Debug Log Pointer",
|
||||
le16_to_cpu(log_data->debug_log_ptr));
|
||||
json_object_add_value_uint(root, "Debug Counter Trigger Source",
|
||||
le16_to_cpu(log_data->debug_log_counter_trigger));
|
||||
json_object_add_value_uint(root, "Debug Log Stamp Units",
|
||||
le16_to_cpu(log_data->debug_log_stamp_units));
|
||||
json_object_add_value_uint(root, "Log Page Version",
|
||||
le16_to_cpu(log_data->log_page_version));
|
||||
|
||||
char guid[(GUID_LEN * 2) + 1];
|
||||
char *ptr = &guid[0];
|
||||
|
||||
for (i = GUID_LEN - 1; i >= 0; i--)
|
||||
ptr += sprintf(ptr, "%02X", log_data->log_page_guid[i]);
|
||||
|
||||
json_object_add_value_string(root, "Log Page GUID", guid);
|
||||
|
||||
json_print_object(root, NULL);
|
||||
printf("\n");
|
||||
|
||||
json_free_object(root);
|
||||
}
|
||||
|
||||
static void json_c5_log(struct nvme_dev *dev, struct unsupported_requirement_log *log_data)
|
||||
{
|
||||
int j;
|
||||
struct json_object *root;
|
||||
char unsup_req_list_str[40];
|
||||
char guid_buf[GUID_LEN];
|
||||
char *guid = guid_buf;
|
||||
|
||||
root = json_create_object();
|
||||
|
||||
json_object_add_value_int(root, "Number Unsupported Req IDs",
|
||||
le16_to_cpu(log_data->unsupported_count));
|
||||
|
||||
memset((void *)unsup_req_list_str, 0, 40);
|
||||
for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) {
|
||||
sprintf((char *)unsup_req_list_str, "Unsupported Requirement List %d", j);
|
||||
json_object_add_value_string(root, unsup_req_list_str,
|
||||
(char *)log_data->unsupported_req_list[j]);
|
||||
}
|
||||
|
||||
json_object_add_value_int(root, "Log Page Version",
|
||||
le16_to_cpu(log_data->log_page_version));
|
||||
|
||||
memset((void *)guid, 0, GUID_LEN);
|
||||
for (j = GUID_LEN - 1; j >= 0; j--)
|
||||
guid += sprintf(guid, "%02x", log_data->log_page_guid[j]);
|
||||
json_object_add_value_string(root, "Log page GUID", guid_buf);
|
||||
|
||||
json_print_object(root, NULL);
|
||||
printf("\n");
|
||||
|
||||
json_free_object(root);
|
||||
}
|
||||
|
||||
static void json_c1_log(struct ocp_error_recovery_log_page *log_data)
|
||||
{
|
||||
struct json_object *root;
|
||||
|
||||
root = json_create_object();
|
||||
char guid[64];
|
||||
|
||||
json_object_add_value_int(root, "Panic Reset Wait Time",
|
||||
le16_to_cpu(log_data->panic_reset_wait_time));
|
||||
json_object_add_value_int(root, "Panic Reset Action", log_data->panic_reset_action);
|
||||
json_object_add_value_int(root, "Device Recovery Action 1",
|
||||
log_data->device_recover_action_1);
|
||||
json_object_add_value_int(root, "Panic ID", le32_to_cpu(log_data->panic_id));
|
||||
json_object_add_value_int(root, "Device Capabilities",
|
||||
le32_to_cpu(log_data->device_capabilities));
|
||||
json_object_add_value_int(root, "Vendor Specific Recovery Opcode",
|
||||
log_data->vendor_specific_recovery_opcode);
|
||||
json_object_add_value_int(root, "Vendor Specific Command CDW12",
|
||||
le32_to_cpu(log_data->vendor_specific_command_cdw12));
|
||||
json_object_add_value_int(root, "Vendor Specific Command CDW13",
|
||||
le32_to_cpu(log_data->vendor_specific_command_cdw13));
|
||||
json_object_add_value_int(root, "Vendor Specific Command Timeout",
|
||||
log_data->vendor_specific_command_timeout);
|
||||
json_object_add_value_int(root, "Device Recovery Action 2",
|
||||
log_data->device_recover_action_2);
|
||||
json_object_add_value_int(root, "Device Recovery Action 2 Timeout",
|
||||
log_data->device_recover_action_2_timeout);
|
||||
json_object_add_value_int(root, "Log Page Version",
|
||||
le16_to_cpu(log_data->log_page_version));
|
||||
|
||||
memset((void *)guid, 0, 64);
|
||||
sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]),
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0]));
|
||||
json_object_add_value_string(root, "Log page GUID", guid);
|
||||
|
||||
json_print_object(root, NULL);
|
||||
printf("\n");
|
||||
json_free_object(root);
|
||||
}
|
||||
|
||||
static void json_c4_log(struct ocp_device_capabilities_log_page *log_data)
|
||||
{
|
||||
struct json_object *root = json_create_object();
|
||||
char guid[64];
|
||||
int i;
|
||||
|
||||
json_object_add_value_int(root, "PCI Express Ports", le16_to_cpu(log_data->pcie_exp_port));
|
||||
json_object_add_value_int(root, "OOB Management Support",
|
||||
le16_to_cpu(log_data->oob_management_support));
|
||||
json_object_add_value_int(root, "Write Zeroes Command Support",
|
||||
le16_to_cpu(log_data->wz_cmd_support));
|
||||
json_object_add_value_int(root, "Sanitize Command Support",
|
||||
le16_to_cpu(log_data->sanitize_cmd_support));
|
||||
json_object_add_value_int(root, "Dataset Management Command Support",
|
||||
le16_to_cpu(log_data->dsm_cmd_support));
|
||||
json_object_add_value_int(root, "Write Uncorrectable Command Support",
|
||||
le16_to_cpu(log_data->wu_cmd_support));
|
||||
json_object_add_value_int(root, "Fused Operation Support",
|
||||
le16_to_cpu(log_data->fused_operation_support));
|
||||
json_object_add_value_int(root, "Minimum Valid DSSD Power State",
|
||||
le16_to_cpu(log_data->min_valid_dssd_pwr_state));
|
||||
for (i = 0; i <= 127; i++)
|
||||
json_object_add_value_int(root, "DSSD Power State Descriptors",
|
||||
log_data->dssd_pwr_state_desc[i]);
|
||||
json_object_add_value_int(root, "Log Page Version",
|
||||
le16_to_cpu(log_data->log_page_version));
|
||||
|
||||
memset((void *)guid, 0, 64);
|
||||
sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]),
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0]));
|
||||
json_object_add_value_string(root, "Log page GUID", guid);
|
||||
|
||||
json_print_object(root, NULL);
|
||||
printf("\n");
|
||||
json_free_object(root);
|
||||
}
|
||||
|
||||
static void json_c9_log(struct telemetry_str_log_format *log_data, __u8 *log_data_buf,
|
||||
int total_log_page_size)
|
||||
{
|
||||
struct json_object *root = json_create_object();
|
||||
char res_arr[48];
|
||||
char *res = res_arr;
|
||||
char guid_buf[GUID_LEN];
|
||||
char *guid = guid_buf;
|
||||
char fifo_arr[16];
|
||||
char *fifo = fifo_arr;
|
||||
char buf[128];
|
||||
//calculating the index value for array
|
||||
__le64 stat_id_index = (log_data->sitsz * 4) / 16;
|
||||
__le64 eve_id_index = (log_data->estsz * 4) / 16;
|
||||
__le64 vu_eve_index = (log_data->vu_eve_st_sz * 4) / 16;
|
||||
__le64 ascii_table_index = (log_data->asctsz * 4);
|
||||
//Calculating the offset for dynamic fields.
|
||||
__le64 stat_id_str_table_ofst = log_data->sits * 4;
|
||||
__le64 event_str_table_ofst = log_data->ests * 4;
|
||||
__le64 vu_event_str_table_ofst = log_data->vu_eve_sts * 4;
|
||||
__le64 ascii_table_ofst = log_data->ascts * 4;
|
||||
struct statistics_id_str_table_entry stat_id_str_table_arr[stat_id_index];
|
||||
struct event_id_str_table_entry event_id_str_table_arr[eve_id_index];
|
||||
struct vu_event_id_str_table_entry vu_event_id_str_table_arr[vu_eve_index];
|
||||
__u8 ascii_table_info_arr[ascii_table_index];
|
||||
char ascii_buf[ascii_table_index];
|
||||
char *ascii = ascii_buf;
|
||||
int j;
|
||||
|
||||
json_object_add_value_int(root, "Log Page Version",
|
||||
le16_to_cpu(log_data->log_page_version));
|
||||
|
||||
memset((__u8 *)res, 0, 15);
|
||||
for (j = 0; j < 15; j++)
|
||||
res += sprintf(res, "%d", log_data->reserved1[j]);
|
||||
json_object_add_value_string(root, "Reserved", res_arr);
|
||||
|
||||
memset((void *)guid, 0, GUID_LEN);
|
||||
for (j = GUID_LEN - 1; j >= 0; j--)
|
||||
guid += sprintf(guid, "%02x", log_data->log_page_guid[j]);
|
||||
json_object_add_value_string(root, "Log page GUID", guid_buf);
|
||||
|
||||
json_object_add_value_int(root, "Telemetry String Log Size", le64_to_cpu(log_data->sls));
|
||||
|
||||
memset((__u8 *)res, 0, 24);
|
||||
for (j = 0; j < 24; j++)
|
||||
res += sprintf(res, "%d", log_data->reserved2[j]);
|
||||
json_object_add_value_string(root, "Reserved", res_arr);
|
||||
|
||||
json_object_add_value_int(root, "Statistics Identifier String Table Start",
|
||||
le64_to_cpu(log_data->sits));
|
||||
json_object_add_value_int(root, "Event String Table Start", le64_to_cpu(log_data->ests));
|
||||
json_object_add_value_int(root, "Event String Table Size", le64_to_cpu(log_data->estsz));
|
||||
json_object_add_value_int(root, "VU Event String Table Start",
|
||||
le64_to_cpu(log_data->vu_eve_sts));
|
||||
json_object_add_value_int(root, "VU Event String Table Size",
|
||||
le64_to_cpu(log_data->vu_eve_st_sz));
|
||||
json_object_add_value_int(root, "ASCII Table Start",
|
||||
le64_to_cpu(log_data->ascts));
|
||||
json_object_add_value_int(root, "ASCII Table Size",
|
||||
le64_to_cpu(log_data->asctsz));
|
||||
|
||||
memset((void *)fifo, 0, 16);
|
||||
for (j = 0; j < 16; j++)
|
||||
fifo += sprintf(fifo, "%c", log_data->fifo1[j]);
|
||||
json_object_add_value_string(root, "FIFO 1 ASCII String", fifo_arr);
|
||||
|
||||
memset((void *)fifo, 0, 16);
|
||||
for (j = 0; j < 16; j++)
|
||||
fifo += sprintf(fifo, "%c", log_data->fifo2[j]);
|
||||
json_object_add_value_string(root, "FIFO 2 ASCII String", fifo_arr);
|
||||
|
||||
memset((void *)fifo, 0, 16);
|
||||
for (j = 0; j < 16; j++)
|
||||
fifo += sprintf(fifo, "%c", log_data->fifo3[j]);
|
||||
json_object_add_value_string(root, "FIFO 3 ASCII String", fifo_arr);
|
||||
|
||||
memset((void *)fifo, 0, 16);
|
||||
for (j = 0; j < 16; j++)
|
||||
fifo += sprintf(fifo, "%c", log_data->fifo4[j]);
|
||||
json_object_add_value_string(root, "FIFO 4 ASCII String", fifo_arr);
|
||||
|
||||
memset((void *)fifo, 0, 16);
|
||||
for (j = 0; j < 16; j++)
|
||||
fifo += sprintf(fifo, "%c", log_data->fifo5[j]);
|
||||
json_object_add_value_string(root, "FIFO 5 ASCII String", fifo_arr);
|
||||
|
||||
memset((void *)fifo, 0, 16);
|
||||
for (j = 0; j < 16; j++)
|
||||
fifo += sprintf(fifo, "%c", log_data->fifo6[j]);
|
||||
json_object_add_value_string(root, "FIFO 6 ASCII String", fifo_arr);
|
||||
|
||||
memset((void *)fifo, 0, 16);
|
||||
for (j = 0; j < 16; j++)
|
||||
fifo += sprintf(fifo, "%c", log_data->fifo7[j]);
|
||||
json_object_add_value_string(root, "FIFO 7 ASCII String", fifo_arr);
|
||||
|
||||
memset((void *)fifo, 0, 16);
|
||||
for (j = 0; j < 16; j++)
|
||||
fifo += sprintf(fifo, "%c", log_data->fifo8[j]);
|
||||
json_object_add_value_string(root, "FIFO 8 ASCII String", fifo_arr);
|
||||
|
||||
memset((void *)fifo, 0, 16);
|
||||
for (j = 0; j < 16; j++)
|
||||
fifo += sprintf(fifo, "%c", log_data->fifo9[j]);
|
||||
json_object_add_value_string(root, "FIFO 9 ASCII String", fifo_arr);
|
||||
|
||||
memset((void *)fifo, 0, 16);
|
||||
for (j = 0; j < 16; j++)
|
||||
fifo += sprintf(fifo, "%c", log_data->fifo10[j]);
|
||||
json_object_add_value_string(root, "FIFO 10 ASCII String", fifo_arr);
|
||||
|
||||
memset((void *)fifo, 0, 16);
|
||||
for (j = 0; j < 16; j++)
|
||||
fifo += sprintf(fifo, "%c", log_data->fifo11[j]);
|
||||
json_object_add_value_string(root, "FIFO 11 ASCII String", fifo_arr);
|
||||
|
||||
memset((void *)fifo, 0, 16);
|
||||
for (j = 0; j < 16; j++)
|
||||
fifo += sprintf(fifo, "%c", log_data->fifo12[j]);
|
||||
json_object_add_value_string(root, "FIFO 12 ASCII String", fifo_arr);
|
||||
|
||||
memset((void *)fifo, 0, 16);
|
||||
for (j = 0; j < 16; j++)
|
||||
fifo += sprintf(fifo, "%c", log_data->fifo13[j]);
|
||||
json_object_add_value_string(root, "FIFO 13 ASCII String", fifo_arr);
|
||||
|
||||
memset((void *)fifo, 0, 16);
|
||||
for (j = 0; j < 16; j++)
|
||||
fifo += sprintf(fifo, "%c", log_data->fifo14[j]);
|
||||
json_object_add_value_string(root, "FIFO 14 ASCII String", fifo_arr);
|
||||
|
||||
memset((void *)fifo, 0, 16);
|
||||
for (j = 0; j < 16; j++)
|
||||
fifo += sprintf(fifo, "%c", log_data->fifo15[j]);
|
||||
json_object_add_value_string(root, "FIFO 15 ASCII String", fifo_arr);
|
||||
|
||||
memset((void *)fifo, 0, 16);
|
||||
for (j = 0; j < 16; j++)
|
||||
fifo += sprintf(fifo, "%c", log_data->fifo16[j]);
|
||||
json_object_add_value_string(root, "FIFO 16 ASCII String", fifo_arr);
|
||||
|
||||
memset((__u8 *)res, 0, 48);
|
||||
for (j = 0; j < 48; j++)
|
||||
res += sprintf(res, "%d", log_data->reserved3[j]);
|
||||
json_object_add_value_string(root, "Reserved", res_arr);
|
||||
|
||||
if (log_data->sitsz != 0) {
|
||||
|
||||
memcpy(stat_id_str_table_arr,
|
||||
(__u8 *)log_data_buf + stat_id_str_table_ofst,
|
||||
(log_data->sitsz * 4));
|
||||
struct json_object *stat_table = json_create_object();
|
||||
|
||||
for (j = 0; j < stat_id_index; j++) {
|
||||
struct json_object *entry = json_create_object();
|
||||
|
||||
json_object_add_value_uint(entry, "Vendor Specific Statistic Identifier",
|
||||
le16_to_cpu(stat_id_str_table_arr[j].vs_si));
|
||||
json_object_add_value_uint(entry, "Reserved",
|
||||
le64_to_cpu(stat_id_str_table_arr[j].reserved1));
|
||||
json_object_add_value_uint(entry, "ASCII ID Length",
|
||||
le64_to_cpu(stat_id_str_table_arr[j].ascii_id_len));
|
||||
json_object_add_value_uint(entry, "ASCII ID offset",
|
||||
le64_to_cpu(stat_id_str_table_arr[j].ascii_id_ofst));
|
||||
json_object_add_value_uint(entry, "Reserved2",
|
||||
le64_to_cpu(stat_id_str_table_arr[j].reserved2));
|
||||
sprintf(buf, "Statistics Identifier String Table %d", j);
|
||||
json_object_add_value_object(stat_table, buf, entry);
|
||||
}
|
||||
|
||||
json_object_add_value_object(root,
|
||||
"Statistics Identifier String Table", stat_table);
|
||||
}
|
||||
|
||||
if (log_data->estsz != 0) {
|
||||
struct json_object *eve_table = json_create_object();
|
||||
|
||||
memcpy(event_id_str_table_arr,
|
||||
(__u8 *)log_data_buf + event_str_table_ofst,
|
||||
(log_data->estsz * 4));
|
||||
for (j = 0; j < eve_id_index; j++) {
|
||||
struct json_object *entry = json_create_object();
|
||||
|
||||
json_object_add_value_int(entry, "Debug Event Class",
|
||||
le16_to_cpu(event_id_str_table_arr[j].deb_eve_class));
|
||||
json_object_add_value_int(entry, "Event Identifier",
|
||||
le16_to_cpu(event_id_str_table_arr[j].ei));
|
||||
json_object_add_value_int(entry, "ASCII ID Length",
|
||||
le64_to_cpu(event_id_str_table_arr[j].ascii_id_len));
|
||||
json_object_add_value_int(entry, "ASCII ID offset",
|
||||
le64_to_cpu(event_id_str_table_arr[j].ascii_id_ofst));
|
||||
json_object_add_value_int(entry, "Reserved",
|
||||
le64_to_cpu(event_id_str_table_arr[j].reserved2));
|
||||
sprintf(buf, "Event Identifier String Table Entry %d", j);
|
||||
json_object_add_value_object(eve_table, buf, entry);
|
||||
}
|
||||
json_object_add_value_object(root,
|
||||
"Event Identifier String Table Entry",
|
||||
eve_table);
|
||||
}
|
||||
|
||||
if (log_data->vu_eve_st_sz != 0) {
|
||||
struct json_object *vu_eve_table = json_create_object();
|
||||
|
||||
memcpy(vu_event_id_str_table_arr,
|
||||
(__u8 *)log_data_buf + vu_event_str_table_ofst,
|
||||
(log_data->vu_eve_st_sz * 4));
|
||||
for (j = 0; j < vu_eve_index; j++) {
|
||||
struct json_object *entry = json_create_object();
|
||||
|
||||
json_object_add_value_int(entry, "Debug Event Class",
|
||||
le16_to_cpu(vu_event_id_str_table_arr[j].deb_eve_class));
|
||||
json_object_add_value_int(entry, "VU Event Identifier",
|
||||
le16_to_cpu(vu_event_id_str_table_arr[j].vu_ei));
|
||||
json_object_add_value_int(entry, "ASCII ID Length",
|
||||
le64_to_cpu(vu_event_id_str_table_arr[j].ascii_id_len));
|
||||
json_object_add_value_int(entry, "ASCII ID offset",
|
||||
le64_to_cpu(vu_event_id_str_table_arr[j].ascii_id_ofst));
|
||||
json_object_add_value_int(entry, "Reserved",
|
||||
le64_to_cpu(vu_event_id_str_table_arr[j].reserved));
|
||||
sprintf(buf, "VU Event Identifier String Table Entry %d", j);
|
||||
json_object_add_value_object(vu_eve_table, buf, entry);
|
||||
}
|
||||
json_object_add_value_object(root,
|
||||
"VU Event Identifier String Table Entry",
|
||||
vu_eve_table);
|
||||
}
|
||||
|
||||
if (log_data->asctsz != 0) {
|
||||
memcpy(ascii_table_info_arr,
|
||||
(__u8 *)log_data_buf + ascii_table_ofst,
|
||||
(log_data->asctsz * 4));
|
||||
memset((void *)ascii, 0, ascii_table_index);
|
||||
for (j = 0; j < ascii_table_index; j++)
|
||||
ascii += sprintf(ascii, "%c", ascii_table_info_arr[j]);
|
||||
json_object_add_value_string(root, "ASCII Table", ascii_buf);
|
||||
}
|
||||
|
||||
json_print_object(root, NULL);
|
||||
printf("\n");
|
||||
json_free_object(root);
|
||||
}
|
||||
|
||||
static void json_c7_log(struct nvme_dev *dev, struct tcg_configuration_log *log_data)
|
||||
{
|
||||
int j;
|
||||
struct json_object *root;
|
||||
char guid_buf[GUID_LEN];
|
||||
char *guid = guid_buf;
|
||||
char res_arr[458];
|
||||
char *res = res_arr;
|
||||
|
||||
root = json_create_object();
|
||||
|
||||
json_object_add_value_int(root, "State", log_data->state);
|
||||
memset((__u8 *)res, 0, 3);
|
||||
for (j = 0; j < 3; j++)
|
||||
res += sprintf(res, "%d", log_data->rsvd1[j]);
|
||||
json_object_add_value_string(root, "Reserved1", res_arr);
|
||||
json_object_add_value_int(root, "Locking SP Activation Count",
|
||||
log_data->locking_sp_act_count);
|
||||
json_object_add_value_int(root, "Tper Revert Count",
|
||||
log_data->locking_sp_rev_count);
|
||||
json_object_add_value_int(root, "Number of Locking Objects",
|
||||
log_data->no_of_locking_obj);
|
||||
json_object_add_value_int(root, "Number of Single User Mode Locking Objects",
|
||||
log_data->no_of_single_um_locking_obj);
|
||||
json_object_add_value_int(root, "Number of Range Provisioned Locking Objects",
|
||||
log_data->no_of_range_prov_locking_obj);
|
||||
json_object_add_value_int(root, "Number of Namespace Provisioned Locking Objects",
|
||||
log_data->no_of_ns_prov_locking_obj);
|
||||
json_object_add_value_int(root, "Number of Read Locked Locking Objects",
|
||||
log_data->no_of_read_lock_locking_obj);
|
||||
json_object_add_value_int(root, "Number of Write Locked Locking Objects",
|
||||
log_data->no_of_write_lock_locking_obj);
|
||||
json_object_add_value_int(root, "Number of Read Unlocked Locking Objects",
|
||||
log_data->no_of_read_unlock_locking_obj);
|
||||
json_object_add_value_int(root, "Number of Write Unlocked Locking Objects",
|
||||
log_data->no_of_write_unlock_locking_obj);
|
||||
json_object_add_value_int(root, "Reserved2", log_data->rsvd2);
|
||||
|
||||
json_object_add_value_int(root, "SID Authentication Try Count",
|
||||
le32_to_cpu(log_data->sid_auth_try_count));
|
||||
json_object_add_value_int(root, "SID Authentication Try Limit",
|
||||
le32_to_cpu(log_data->sid_auth_try_limit));
|
||||
json_object_add_value_int(root, "Programmatic TCG Reset Count",
|
||||
le32_to_cpu(log_data->pro_tcg_rc));
|
||||
json_object_add_value_int(root, "Programmatic Reset Lock Count",
|
||||
le32_to_cpu(log_data->pro_rlc));
|
||||
json_object_add_value_int(root, "TCG Error Count", le32_to_cpu(log_data->tcg_ec));
|
||||
|
||||
memset((__u8 *)res, 0, 458);
|
||||
for (j = 0; j < 458; j++)
|
||||
res += sprintf(res, "%d", log_data->rsvd3[j]);
|
||||
json_object_add_value_string(root, "Reserved3", res_arr);
|
||||
|
||||
json_object_add_value_int(root, "Log Page Version",
|
||||
le16_to_cpu(log_data->log_page_version));
|
||||
|
||||
memset((void *)guid, 0, GUID_LEN);
|
||||
for (j = GUID_LEN - 1; j >= 0; j--)
|
||||
guid += sprintf(guid, "%02x", log_data->log_page_guid[j]);
|
||||
json_object_add_value_string(root, "Log page GUID", guid_buf);
|
||||
|
||||
json_print_object(root, NULL);
|
||||
printf("\n");
|
||||
|
||||
json_free_object(root);
|
||||
}
|
||||
|
||||
static struct ocp_print_ops json_print_ops = {
|
||||
.hwcomp_log = json_hwcomp_log,
|
||||
.fw_act_history = json_fw_activation_history,
|
||||
.smart_extended_log = json_smart_extended_log,
|
||||
.telemetry_log = json_telemetry_log,
|
||||
.c3_log = json_c3_log,
|
||||
.c5_log = json_c5_log,
|
||||
.c1_log = json_c1_log,
|
||||
.c4_log = json_c4_log,
|
||||
.c9_log = json_c9_log,
|
||||
.c7_log = json_c7_log,
|
||||
};
|
||||
|
||||
struct ocp_print_ops *ocp_get_json_print_ops(nvme_print_flags_t flags)
|
||||
{
|
||||
json_print_ops.flags = flags;
|
||||
return &json_print_ops;
|
||||
}
|
710
plugins/ocp/ocp-print-stdout.c
Normal file
710
plugins/ocp/ocp-print-stdout.c
Normal file
|
@ -0,0 +1,710 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#include "util/types.h"
|
||||
#include "common.h"
|
||||
#include "nvme-print.h"
|
||||
#include "ocp-print.h"
|
||||
#include "ocp-hardware-component-log.h"
|
||||
#include "ocp-fw-activation-history.h"
|
||||
#include "ocp-smart-extended-log.h"
|
||||
#include "ocp-telemetry-decode.h"
|
||||
#include "ocp-nvme.h"
|
||||
|
||||
static void print_hwcomp_desc(struct hwcomp_desc_entry *e, bool list, int num)
|
||||
{
|
||||
printf(" Component %d: %s\n", num, hwcomp_id_to_string(le32_to_cpu(e->desc->id)));
|
||||
|
||||
if (list)
|
||||
return;
|
||||
|
||||
printf(" Date/Lot Size: 0x%"PRIx64"\n", (uint64_t)e->date_lot_size);
|
||||
printf(" Additional Information Size: 0x%"PRIx64"\n", (uint64_t)e->add_info_size);
|
||||
printf(" Identifier: 0x%08x\n", le32_to_cpu(e->desc->id));
|
||||
printf(" Manufacture: 0x%016"PRIx64"\n", le64_to_cpu(e->desc->mfg));
|
||||
printf(" Revision: 0x%016"PRIx64"\n", le64_to_cpu(e->desc->rev));
|
||||
printf(" Manufacture Code: 0x%016"PRIx64"\n", le64_to_cpu(e->desc->mfg_code));
|
||||
print_array(" Date/Lot Code", e->date_lot_code, e->date_lot_size);
|
||||
print_array(" Additional Information", e->add_info, e->add_info_size);
|
||||
}
|
||||
|
||||
static void stdout_hwcomp_log(struct hwcomp_log *log, __u32 id, bool list)
|
||||
{
|
||||
size_t date_lot_code_offset = sizeof(struct hwcomp_desc);
|
||||
int num = 1;
|
||||
struct hwcomp_desc_entry e = { log->desc };
|
||||
|
||||
long double log_size = uint128_t_to_double(le128_to_cpu(log->size)) * sizeof(__le32);
|
||||
|
||||
printf("Log Identifier: 0x%02xh\n", LID_HWCOMP);
|
||||
printf("Log Page Version: 0x%x\n", le16_to_cpu(log->ver));
|
||||
print_array("Reserved2", log->rsvd2, ARRAY_SIZE(log->rsvd2));
|
||||
print_array("Log page GUID", log->guid, ARRAY_SIZE(log->guid));
|
||||
printf("Hardware Component Log Size: 0x%"PRIx64"\n", (uint64_t)log_size);
|
||||
print_array("Reserved48", log->rsvd48, ARRAY_SIZE(log->rsvd48));
|
||||
printf("Component Descriptions\n");
|
||||
while (log_size > 0) {
|
||||
e.date_lot_size = le64_to_cpu(e.desc->date_lot_size) * sizeof(__le32);
|
||||
e.date_lot_code = e.date_lot_size ? (__u8 *)e.desc + date_lot_code_offset : NULL;
|
||||
e.add_info_size = le64_to_cpu(e.desc->add_info_size) * sizeof(__le32);
|
||||
e.add_info = e.add_info_size ? e.date_lot_code ? e.date_lot_code + e.date_lot_size :
|
||||
(__u8 *)e.desc + date_lot_code_offset : NULL;
|
||||
if (!id || id == le32_to_cpu(e.desc->id))
|
||||
print_hwcomp_desc(&e, list, num++);
|
||||
e.desc_size = date_lot_code_offset + e.date_lot_size + e.add_info_size;
|
||||
e.desc = (struct hwcomp_desc *)((__u8 *)e.desc + e.desc_size);
|
||||
log_size -= e.desc_size;
|
||||
}
|
||||
}
|
||||
|
||||
static void stdout_fw_activation_history(const struct fw_activation_history *fw_history)
|
||||
{
|
||||
printf("Firmware History Log:\n");
|
||||
|
||||
printf(" %-26s%d\n", "log identifier:", fw_history->log_id);
|
||||
printf(" %-26s%d\n", "valid entries:", le32_to_cpu(fw_history->valid_entries));
|
||||
|
||||
printf(" entries:\n");
|
||||
|
||||
for (int index = 0; index < le32_to_cpu(fw_history->valid_entries); index++) {
|
||||
const struct fw_activation_history_entry *entry = &fw_history->entries[index];
|
||||
|
||||
printf(" entry[%d]:\n", index);
|
||||
printf(" %-22s%d\n", "version number:", entry->ver_num);
|
||||
printf(" %-22s%d\n", "entry length:", entry->entry_length);
|
||||
printf(" %-22s%d\n", "activation count:",
|
||||
le16_to_cpu(entry->activation_count));
|
||||
printf(" %-22s%"PRIu64"\n", "timestamp:",
|
||||
(0x0000FFFFFFFFFFFF & le64_to_cpu(entry->timestamp)));
|
||||
printf(" %-22s%"PRIu64"\n", "power cycle count:",
|
||||
le64_to_cpu(entry->power_cycle_count));
|
||||
printf(" %-22s%.*s\n", "previous firmware:", (int)sizeof(entry->previous_fw),
|
||||
entry->previous_fw);
|
||||
printf(" %-22s%.*s\n", "new firmware:", (int)sizeof(entry->new_fw),
|
||||
entry->new_fw);
|
||||
printf(" %-22s%d\n", "slot number:", entry->slot_number);
|
||||
printf(" %-22s%d\n", "commit action type:", entry->commit_action);
|
||||
printf(" %-22s%d\n", "result:", le16_to_cpu(entry->result));
|
||||
}
|
||||
|
||||
printf(" %-26s%d\n", "log page version:",
|
||||
le16_to_cpu(fw_history->log_page_version));
|
||||
|
||||
printf(" %-26s0x%"PRIx64"%"PRIx64"\n", "log page guid:",
|
||||
le64_to_cpu(fw_history->log_page_guid[1]),
|
||||
le64_to_cpu(fw_history->log_page_guid[0]));
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void stdout_smart_extended_log(void *data)
|
||||
{
|
||||
uint16_t smart_log_ver = 0;
|
||||
__u8 *log_data = data;
|
||||
|
||||
printf("SMART Cloud Attributes :-\n");
|
||||
|
||||
printf(" Physical media units written - %"PRIu64" %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW + 8] & 0xFFFFFFFFFFFFFFFF),
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF));
|
||||
printf(" Physical media units read - %"PRIu64" %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR + 8] & 0xFFFFFFFFFFFFFFFF),
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF));
|
||||
printf(" Bad user nand blocks - Raw %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF));
|
||||
printf(" Bad user nand blocks - Normalized %d\n",
|
||||
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN]));
|
||||
printf(" Bad system nand blocks - Raw %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF));
|
||||
printf(" Bad system nand blocks - Normalized %d\n",
|
||||
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN]));
|
||||
printf(" XOR recovery count %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC]));
|
||||
printf(" Uncorrectable read error count %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC]));
|
||||
printf(" Soft ecc error count %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC]));
|
||||
printf(" End to end detected errors %"PRIu32"\n",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC]));
|
||||
printf(" End to end corrected errors %"PRIu32"\n",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE]));
|
||||
printf(" System data percent used %d\n",
|
||||
(__u8)log_data[SCAO_SDPU]);
|
||||
printf(" Refresh counts %"PRIu64"\n",
|
||||
(uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC]) & 0x00FFFFFFFFFFFFFF));
|
||||
printf(" Max User data erase counts %"PRIu32"\n",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC]));
|
||||
printf(" Min User data erase counts %"PRIu32"\n",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC]));
|
||||
printf(" Number of Thermal throttling events %d\n",
|
||||
(__u8)log_data[SCAO_NTTE]);
|
||||
printf(" Current throttling status 0x%x\n",
|
||||
(__u8)log_data[SCAO_CTS]);
|
||||
printf(" PCIe correctable error count %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC]));
|
||||
printf(" Incomplete shutdowns %"PRIu32"\n",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS]));
|
||||
printf(" Percent free blocks %d\n",
|
||||
(__u8)log_data[SCAO_PFB]);
|
||||
printf(" Capacitor health %"PRIu16"\n",
|
||||
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH]));
|
||||
printf(" NVMe base errata version %c\n",
|
||||
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH]));
|
||||
printf(" NVMe command set errata version %c\n",
|
||||
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH]));
|
||||
printf(" Unaligned I/O %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO]));
|
||||
printf(" Security Version Number %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN]));
|
||||
printf(" NUSE - Namespace utilization %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE]));
|
||||
printf(" PLP start count %s\n",
|
||||
uint128_t_to_string(le128_to_cpu(&log_data[SCAO_PSC])));
|
||||
printf(" Endurance estimate %s\n",
|
||||
uint128_t_to_string(le128_to_cpu(&log_data[SCAO_EEST])));
|
||||
smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]);
|
||||
printf(" Log page version %"PRIu16"\n", smart_log_ver);
|
||||
printf(" Log page GUID 0x");
|
||||
printf("%"PRIx64"%"PRIx64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]),
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG]));
|
||||
switch (smart_log_ver) {
|
||||
case 0 ... 1:
|
||||
break;
|
||||
default:
|
||||
case 4:
|
||||
printf(" NVMe Command Set Errata Version %d\n",
|
||||
(__u8)log_data[SCAO_NCSEV]);
|
||||
printf(" Lowest Permitted Firmware Revision %"PRIu64"\n",
|
||||
le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC]));
|
||||
fallthrough;
|
||||
case 2 ... 3:
|
||||
printf(" Errata Version Field %d\n",
|
||||
(__u8)log_data[SCAO_EVF]);
|
||||
printf(" Point Version Field %"PRIu16"\n",
|
||||
le16_to_cpu(*(uint16_t *)&log_data[SCAO_PVF]));
|
||||
printf(" Minor Version Field %"PRIu16"\n",
|
||||
le16_to_cpu(*(uint16_t *)&log_data[SCAO_MIVF]));
|
||||
printf(" Major Version Field %d\n",
|
||||
(__u8)log_data[SCAO_MAVF]);
|
||||
printf(" NVMe Base Errata Version %d\n",
|
||||
(__u8)log_data[SCAO_NBEV]);
|
||||
printf(" PCIe Link Retraining Count %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC]));
|
||||
printf(" Power State Change Count %"PRIu64"\n",
|
||||
le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC]));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void stdout_telemetry_log(struct ocp_telemetry_parse_options *options)
|
||||
{
|
||||
#ifdef CONFIG_JSONC
|
||||
print_ocp_telemetry_normal(options);
|
||||
#endif /* CONFIG_JSONC */
|
||||
}
|
||||
|
||||
static void stdout_c3_log(struct nvme_dev *dev, struct ssd_latency_monitor_log *log_data)
|
||||
{
|
||||
char ts_buf[128];
|
||||
int i, j;
|
||||
|
||||
printf("-Latency Monitor/C3 Log Page Data-\n");
|
||||
printf(" Controller : %s\n", dev->name);
|
||||
printf(" Feature Status 0x%x\n",
|
||||
log_data->feature_status);
|
||||
printf(" Active Bucket Timer %d min\n",
|
||||
C3_ACTIVE_BUCKET_TIMER_INCREMENT *
|
||||
le16_to_cpu(log_data->active_bucket_timer));
|
||||
printf(" Active Bucket Timer Threshold %d min\n",
|
||||
C3_ACTIVE_BUCKET_TIMER_INCREMENT *
|
||||
le16_to_cpu(log_data->active_bucket_timer_threshold));
|
||||
printf(" Active Threshold A %d ms\n",
|
||||
C3_ACTIVE_THRESHOLD_INCREMENT *
|
||||
le16_to_cpu(log_data->active_threshold_a+1));
|
||||
printf(" Active Threshold B %d ms\n",
|
||||
C3_ACTIVE_THRESHOLD_INCREMENT *
|
||||
le16_to_cpu(log_data->active_threshold_b+1));
|
||||
printf(" Active Threshold C %d ms\n",
|
||||
C3_ACTIVE_THRESHOLD_INCREMENT *
|
||||
le16_to_cpu(log_data->active_threshold_c+1));
|
||||
printf(" Active Threshold D %d ms\n",
|
||||
C3_ACTIVE_THRESHOLD_INCREMENT *
|
||||
le16_to_cpu(log_data->active_threshold_d+1));
|
||||
printf(" Active Latency Configuration 0x%x\n",
|
||||
le16_to_cpu(log_data->active_latency_config));
|
||||
printf(" Active Latency Minimum Window %d ms\n",
|
||||
C3_MINIMUM_WINDOW_INCREMENT *
|
||||
le16_to_cpu(log_data->active_latency_min_window));
|
||||
printf(" Active Latency Stamp Units %d\n",
|
||||
le16_to_cpu(log_data->active_latency_stamp_units));
|
||||
printf(" Static Latency Stamp Units %d\n",
|
||||
le16_to_cpu(log_data->static_latency_stamp_units));
|
||||
printf(" Debug Log Trigger Enable %d\n",
|
||||
le16_to_cpu(log_data->debug_log_trigger_enable));
|
||||
printf(" Debug Log Measured Latency %d\n",
|
||||
le16_to_cpu(log_data->debug_log_measured_latency));
|
||||
if (le64_to_cpu(log_data->debug_log_latency_stamp) == -1) {
|
||||
printf(" Debug Log Latency Time Stamp N/A\n");
|
||||
} else {
|
||||
convert_ts(le64_to_cpu(log_data->debug_log_latency_stamp), ts_buf);
|
||||
printf(" Debug Log Latency Time Stamp %s\n", ts_buf);
|
||||
}
|
||||
printf(" Debug Log Pointer %d\n",
|
||||
le16_to_cpu(log_data->debug_log_ptr));
|
||||
printf(" Debug Counter Trigger Source %d\n",
|
||||
le16_to_cpu(log_data->debug_log_counter_trigger));
|
||||
printf(" Debug Log Stamp Units %d\n",
|
||||
le16_to_cpu(log_data->debug_log_stamp_units));
|
||||
printf(" Log Page Version %d\n",
|
||||
le16_to_cpu(log_data->log_page_version));
|
||||
|
||||
char guid[(GUID_LEN * 2) + 1];
|
||||
char *ptr = &guid[0];
|
||||
|
||||
for (i = GUID_LEN - 1; i >= 0; i--)
|
||||
ptr += sprintf(ptr, "%02X", log_data->log_page_guid[i]);
|
||||
|
||||
printf(" Log Page GUID %s\n", guid);
|
||||
printf("\n");
|
||||
|
||||
printf("%64s%92s%119s\n", "Read", "Write", "Deallocate/Trim");
|
||||
for (i = 0; i < C3_BUCKET_NUM; i++) {
|
||||
printf(" Active Bucket Counter: Bucket %d %27d %27d %27d\n",
|
||||
i,
|
||||
le32_to_cpu(log_data->active_bucket_counter[i][READ]),
|
||||
le32_to_cpu(log_data->active_bucket_counter[i][WRITE]),
|
||||
le32_to_cpu(log_data->active_bucket_counter[i][TRIM]));
|
||||
}
|
||||
|
||||
for (i = 0; i < C3_BUCKET_NUM; i++) {
|
||||
printf(" Active Latency Time Stamp: Bucket %d ", i);
|
||||
for (j = 2; j >= 0; j--) {
|
||||
if (le64_to_cpu(log_data->active_latency_timestamp[3-i][j]) == -1) {
|
||||
printf(" N/A ");
|
||||
} else {
|
||||
convert_ts(le64_to_cpu(log_data->active_latency_timestamp[3-i][j]),
|
||||
ts_buf);
|
||||
printf("%s ", ts_buf);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < C3_BUCKET_NUM; i++) {
|
||||
printf(" Active Measured Latency: Bucket %d %27d ms %27d ms %27d ms\n",
|
||||
i,
|
||||
le16_to_cpu(log_data->active_measured_latency[3-i][READ-1]),
|
||||
le16_to_cpu(log_data->active_measured_latency[3-i][WRITE-1]),
|
||||
le16_to_cpu(log_data->active_measured_latency[3-i][TRIM-1]));
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
for (i = 0; i < C3_BUCKET_NUM; i++) {
|
||||
printf(" Static Bucket Counter: Bucket %d %27d %27d %27d\n",
|
||||
i,
|
||||
le32_to_cpu(log_data->static_bucket_counter[i][READ]),
|
||||
le32_to_cpu(log_data->static_bucket_counter[i][WRITE]),
|
||||
le32_to_cpu(log_data->static_bucket_counter[i][TRIM]));
|
||||
}
|
||||
|
||||
for (i = 0; i < C3_BUCKET_NUM; i++) {
|
||||
printf(" Static Latency Time Stamp: Bucket %d ", i);
|
||||
for (j = 2; j >= 0; j--) {
|
||||
if (le64_to_cpu(log_data->static_latency_timestamp[3-i][j]) == -1) {
|
||||
printf(" N/A ");
|
||||
} else {
|
||||
convert_ts(le64_to_cpu(log_data->static_latency_timestamp[3-i][j]),
|
||||
ts_buf);
|
||||
printf("%s ", ts_buf);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < C3_BUCKET_NUM; i++) {
|
||||
printf(" Static Measured Latency: Bucket %d %27d ms %27d ms %27d ms\n",
|
||||
i,
|
||||
le16_to_cpu(log_data->static_measured_latency[3-i][READ-1]),
|
||||
le16_to_cpu(log_data->static_measured_latency[3-i][WRITE-1]),
|
||||
le16_to_cpu(log_data->static_measured_latency[3-i][TRIM-1]));
|
||||
}
|
||||
}
|
||||
|
||||
static void stdout_c5_log(struct nvme_dev *dev, struct unsupported_requirement_log *log_data)
|
||||
{
|
||||
int j;
|
||||
|
||||
printf("Unsupported Requirement-C5 Log Page Data-\n");
|
||||
|
||||
printf(" Number Unsupported Req IDs : 0x%x\n",
|
||||
le16_to_cpu(log_data->unsupported_count));
|
||||
|
||||
for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++)
|
||||
printf(" Unsupported Requirement List %d : %s\n", j,
|
||||
log_data->unsupported_req_list[j]);
|
||||
|
||||
printf(" Log Page Version : 0x%x\n",
|
||||
le16_to_cpu(log_data->log_page_version));
|
||||
printf(" Log page GUID : 0x");
|
||||
for (j = GUID_LEN - 1; j >= 0; j--)
|
||||
printf("%02x", log_data->log_page_guid[j]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void stdout_c1_log(struct ocp_error_recovery_log_page *log_data)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf(" Error Recovery/C1 Log Page Data\n");
|
||||
printf(" Panic Reset Wait Time : 0x%x\n",
|
||||
le16_to_cpu(log_data->panic_reset_wait_time));
|
||||
printf(" Panic Reset Action : 0x%x\n", log_data->panic_reset_action);
|
||||
printf(" Device Recovery Action 1 : 0x%x\n", log_data->device_recover_action_1);
|
||||
printf(" Panic ID : 0x%x\n", le32_to_cpu(log_data->panic_id));
|
||||
printf(" Device Capabilities : 0x%x\n",
|
||||
le32_to_cpu(log_data->device_capabilities));
|
||||
printf(" Vendor Specific Recovery Opcode : 0x%x\n",
|
||||
log_data->vendor_specific_recovery_opcode);
|
||||
printf(" Vendor Specific Command CDW12 : 0x%x\n",
|
||||
le32_to_cpu(log_data->vendor_specific_command_cdw12));
|
||||
printf(" Vendor Specific Command CDW13 : 0x%x\n",
|
||||
le32_to_cpu(log_data->vendor_specific_command_cdw13));
|
||||
printf(" Vendor Specific Command Timeout : 0x%x\n",
|
||||
log_data->vendor_specific_command_timeout);
|
||||
printf(" Device Recovery Action 2 : 0x%x\n",
|
||||
log_data->device_recover_action_2);
|
||||
printf(" Device Recovery Action 2 Timeout : 0x%x\n",
|
||||
log_data->device_recover_action_2_timeout);
|
||||
printf(" Panic Count : 0x%x\n", log_data->panic_count);
|
||||
printf(" Previous Panic IDs:");
|
||||
for (i = 0; i < C1_PREV_PANIC_IDS_LENGTH; i++)
|
||||
printf("%s Panic ID N-%d : 0x%"PRIx64"\n", i ? " " : "", i + 1,
|
||||
le64_to_cpu(log_data->prev_panic_id[i]));
|
||||
printf(" Log Page Version : 0x%x\n",
|
||||
le16_to_cpu(log_data->log_page_version));
|
||||
printf(" Log page GUID : 0x");
|
||||
for (i = GUID_LEN - 1; i >= 0; i--)
|
||||
printf("%02x", log_data->log_page_guid[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void stdout_c4_log(struct ocp_device_capabilities_log_page *log_data)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf(" Device Capability/C4 Log Page Data\n");
|
||||
printf(" PCI Express Ports : 0x%x\n",
|
||||
le16_to_cpu(log_data->pcie_exp_port));
|
||||
printf(" OOB Management Support : 0x%x\n",
|
||||
le16_to_cpu(log_data->oob_management_support));
|
||||
printf(" Write Zeroes Command Support : 0x%x\n",
|
||||
le16_to_cpu(log_data->wz_cmd_support));
|
||||
printf(" Sanitize Command Support : 0x%x\n",
|
||||
le16_to_cpu(log_data->sanitize_cmd_support));
|
||||
printf(" Dataset Management Command Support : 0x%x\n",
|
||||
le16_to_cpu(log_data->dsm_cmd_support));
|
||||
printf(" Write Uncorrectable Command Support : 0x%x\n",
|
||||
le16_to_cpu(log_data->wu_cmd_support));
|
||||
printf(" Fused Operation Support : 0x%x\n",
|
||||
le16_to_cpu(log_data->fused_operation_support));
|
||||
printf(" Minimum Valid DSSD Power State : 0x%x\n",
|
||||
le16_to_cpu(log_data->min_valid_dssd_pwr_state));
|
||||
printf(" DSSD Power State Descriptors : 0x");
|
||||
for (i = 0; i <= 127; i++)
|
||||
printf("%x", log_data->dssd_pwr_state_desc[i]);
|
||||
printf("\n");
|
||||
printf(" Log Page Version : 0x%x\n",
|
||||
le16_to_cpu(log_data->log_page_version));
|
||||
printf(" Log page GUID : 0x");
|
||||
for (i = GUID_LEN - 1; i >= 0; i--)
|
||||
printf("%02x", log_data->log_page_guid[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void stdout_c9_log(struct telemetry_str_log_format *log_data, __u8 *log_data_buf,
|
||||
int total_log_page_size)
|
||||
{
|
||||
//calculating the index value for array
|
||||
__le64 stat_id_index = (log_data->sitsz * 4) / 16;
|
||||
__le64 eve_id_index = (log_data->estsz * 4) / 16;
|
||||
__le64 vu_eve_index = (log_data->vu_eve_st_sz * 4) / 16;
|
||||
__le64 ascii_table_index = (log_data->asctsz * 4);
|
||||
//Calculating the offset for dynamic fields.
|
||||
__le64 stat_id_str_table_ofst = log_data->sits * 4;
|
||||
__le64 event_str_table_ofst = log_data->ests * 4;
|
||||
__le64 vu_event_str_table_ofst = log_data->vu_eve_sts * 4;
|
||||
__le64 ascii_table_ofst = log_data->ascts * 4;
|
||||
struct statistics_id_str_table_entry stat_id_str_table_arr[stat_id_index];
|
||||
struct event_id_str_table_entry event_id_str_table_arr[eve_id_index];
|
||||
struct vu_event_id_str_table_entry vu_event_id_str_table_arr[vu_eve_index];
|
||||
int j;
|
||||
|
||||
printf(" Log Page Version : 0x%x\n",
|
||||
log_data->log_page_version);
|
||||
|
||||
printf(" Reserved : ");
|
||||
for (j = 0; j < 15; j++)
|
||||
printf("%d", log_data->reserved1[j]);
|
||||
printf("\n");
|
||||
|
||||
printf(" Log page GUID : 0x");
|
||||
for (j = GUID_LEN - 1; j >= 0; j--)
|
||||
printf("%02x", log_data->log_page_guid[j]);
|
||||
printf("\n");
|
||||
|
||||
printf(" Telemetry String Log Size : 0x%"PRIx64"\n",
|
||||
le64_to_cpu(log_data->sls));
|
||||
|
||||
printf(" Reserved : ");
|
||||
for (j = 0; j < 24; j++)
|
||||
printf("%d", log_data->reserved2[j]);
|
||||
printf("\n");
|
||||
|
||||
printf(" Statistics Identifier String Table Start : 0x%"PRIx64"\n",
|
||||
le64_to_cpu(log_data->sits));
|
||||
printf(" Statistics Identifier String Table Size : 0x%"PRIx64"\n",
|
||||
le64_to_cpu(log_data->sitsz));
|
||||
printf(" Event String Table Start : 0x%"PRIx64"\n",
|
||||
le64_to_cpu(log_data->ests));
|
||||
printf(" Event String Table Size : 0x%"PRIx64"\n",
|
||||
le64_to_cpu(log_data->estsz));
|
||||
printf(" VU Event String Table Start : 0x%"PRIx64"\n",
|
||||
le64_to_cpu(log_data->vu_eve_sts));
|
||||
printf(" VU Event String Table Size : 0x%"PRIx64"\n",
|
||||
le64_to_cpu(log_data->vu_eve_st_sz));
|
||||
printf(" ASCII Table Start : 0x%"PRIx64"\n",
|
||||
le64_to_cpu(log_data->ascts));
|
||||
printf(" ASCII Table Size : 0x%"PRIx64"\n",
|
||||
le64_to_cpu(log_data->asctsz));
|
||||
|
||||
printf(" FIFO 1 ASCII String\n");
|
||||
printf(" index value ascii_val\n");
|
||||
for (j = 0; j < 16; j++)
|
||||
printf(" %d %d %c\n", j, log_data->fifo1[j],
|
||||
log_data->fifo1[j]);
|
||||
|
||||
printf(" FIFO 2 ASCII String\n");
|
||||
printf(" index value ascii_val\n");
|
||||
for (j = 0; j < 16; j++)
|
||||
printf(" %d %d %c\n", j, log_data->fifo2[j],
|
||||
log_data->fifo2[j]);
|
||||
|
||||
printf(" FIFO 3 ASCII String\n");
|
||||
printf(" index value ascii_val\n");
|
||||
for (j = 0; j < 16; j++)
|
||||
printf(" %d %d %c\n", j, log_data->fifo3[j],
|
||||
log_data->fifo3[j]);
|
||||
|
||||
printf(" FIFO 4 ASCII String\n");
|
||||
printf(" index value ascii_val\n");
|
||||
for (j = 0; j < 16; j++)
|
||||
printf(" %d %d %c\n", j, log_data->fifo4[j], log_data->fifo4[j]);
|
||||
|
||||
printf(" FIFO 5 ASCII String\n");
|
||||
printf(" index value ascii_val\n");
|
||||
for (j = 0; j < 16; j++)
|
||||
printf(" %d %d %c\n", j, log_data->fifo5[j], log_data->fifo5[j]);
|
||||
|
||||
printf(" FIFO 6 ASCII String\n");
|
||||
printf(" index value ascii_val\n");
|
||||
for (j = 0; j < 16; j++)
|
||||
printf(" %d %d %c\n", j, log_data->fifo6[j], log_data->fifo6[j]);
|
||||
|
||||
printf(" FIFO 7 ASCII String\n");
|
||||
printf(" index value ascii_val\n");
|
||||
for (j = 0; j < 16; j++)
|
||||
printf(" %d %d %c\n", j, log_data->fifo7[j], log_data->fifo7[j]);
|
||||
|
||||
printf(" FIFO 8 ASCII String\n");
|
||||
printf(" index value ascii_val\n");
|
||||
for (j = 0; j < 16; j++)
|
||||
printf(" %d %d %c\n", j, log_data->fifo8[j], log_data->fifo8[j]);
|
||||
|
||||
printf(" FIFO 9 ASCII String\n");
|
||||
printf(" index value ascii_val\n");
|
||||
for (j = 0; j < 16; j++)
|
||||
printf(" %d %d %c\n", j, log_data->fifo9[j], log_data->fifo9[j]);
|
||||
|
||||
printf(" FIFO 10 ASCII String\n");
|
||||
printf(" index value ascii_val\n");
|
||||
for (j = 0; j < 16; j++)
|
||||
printf(" %d %d %c\n", j, log_data->fifo10[j], log_data->fifo10[j]);
|
||||
|
||||
printf(" FIFO 11 ASCII String\n");
|
||||
printf(" index value ascii_val\n");
|
||||
for (j = 0; j < 16; j++)
|
||||
printf(" %d %d %c\n", j, log_data->fifo11[j], log_data->fifo11[j]);
|
||||
|
||||
printf(" FIFO 12 ASCII String\n");
|
||||
printf(" index value ascii_val\n");
|
||||
for (j = 0; j < 16; j++)
|
||||
printf(" %d %d %c\n", j, log_data->fifo12[j], log_data->fifo12[j]);
|
||||
|
||||
printf(" FIFO 13 ASCII String\n");
|
||||
printf(" index value ascii_val\n");
|
||||
for (j = 0; j < 16; j++)
|
||||
printf(" %d %d %c\n", j, log_data->fifo13[j], log_data->fifo13[j]);
|
||||
|
||||
printf(" FIFO 14 ASCII String\n");
|
||||
printf(" index value ascii_val\n");
|
||||
for (j = 0; j < 16; j++)
|
||||
printf(" %d %d %c\n", j, log_data->fifo14[j], log_data->fifo14[j]);
|
||||
|
||||
printf(" FIFO 15 ASCII String\n");
|
||||
printf(" index value ascii_val\n");
|
||||
for (j = 0; j < 16; j++)
|
||||
printf(" %d %d %c\n", j, log_data->fifo15[j], log_data->fifo16[j]);
|
||||
|
||||
printf(" FIFO 16 ASCII String\n");
|
||||
printf(" index value ascii_val\n");
|
||||
for (j = 0; j < 16; j++)
|
||||
printf(" %d %d %c\n", j, log_data->fifo16[j], log_data->fifo16[j]);
|
||||
|
||||
printf(" Reserved : ");
|
||||
for (j = 0; j < 48; j++)
|
||||
printf("%d", log_data->reserved3[j]);
|
||||
printf("\n");
|
||||
|
||||
if (log_data->sitsz != 0) {
|
||||
memcpy(stat_id_str_table_arr, (__u8 *)log_data_buf + stat_id_str_table_ofst,
|
||||
(log_data->sitsz * 4));
|
||||
printf(" Statistics Identifier String Table\n");
|
||||
for (j = 0; j < stat_id_index; j++) {
|
||||
printf(" Vendor Specific Statistic Identifier : 0x%x\n",
|
||||
le16_to_cpu(stat_id_str_table_arr[j].vs_si));
|
||||
printf(" Reserved : 0x%x\n",
|
||||
stat_id_str_table_arr[j].reserved1);
|
||||
printf(" ASCII ID Length : 0x%x\n",
|
||||
stat_id_str_table_arr[j].ascii_id_len);
|
||||
printf(" ASCII ID offset : 0x%"PRIx64"\n",
|
||||
le64_to_cpu(stat_id_str_table_arr[j].ascii_id_ofst));
|
||||
printf(" Reserved : 0x%x\n",
|
||||
stat_id_str_table_arr[j].reserved2);
|
||||
}
|
||||
}
|
||||
|
||||
if (log_data->estsz != 0) {
|
||||
memcpy(event_id_str_table_arr, (__u8 *)log_data_buf + event_str_table_ofst,
|
||||
(log_data->estsz * 4));
|
||||
printf(" Event Identifier String Table Entry\n");
|
||||
for (j = 0; j < eve_id_index; j++) {
|
||||
printf(" Debug Event Class : 0x%x\n",
|
||||
event_id_str_table_arr[j].deb_eve_class);
|
||||
printf(" Event Identifier : 0x%x\n",
|
||||
le16_to_cpu(event_id_str_table_arr[j].ei));
|
||||
printf(" ASCII ID Length : 0x%x\n",
|
||||
event_id_str_table_arr[j].ascii_id_len);
|
||||
printf(" ASCII ID offset : 0x%"PRIx64"\n",
|
||||
le64_to_cpu(event_id_str_table_arr[j].ascii_id_ofst));
|
||||
printf(" Reserved : 0x%x\n",
|
||||
event_id_str_table_arr[j].reserved2);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (log_data->vu_eve_st_sz != 0) {
|
||||
memcpy(vu_event_id_str_table_arr, (__u8 *)log_data_buf + vu_event_str_table_ofst,
|
||||
(log_data->vu_eve_st_sz * 4));
|
||||
printf(" VU Event Identifier String Table Entry\n");
|
||||
for (j = 0; j < vu_eve_index; j++) {
|
||||
printf(" Debug Event Class : 0x%x\n",
|
||||
vu_event_id_str_table_arr[j].deb_eve_class);
|
||||
printf(" VU Event Identifier : 0x%x\n",
|
||||
le16_to_cpu(vu_event_id_str_table_arr[j].vu_ei));
|
||||
printf(" ASCII ID Length : 0x%x\n",
|
||||
vu_event_id_str_table_arr[j].ascii_id_len);
|
||||
printf(" ASCII ID offset : 0x%"PRIx64"\n",
|
||||
le64_to_cpu(vu_event_id_str_table_arr[j].ascii_id_ofst));
|
||||
printf(" Reserved : 0x%x\n",
|
||||
vu_event_id_str_table_arr[j].reserved);
|
||||
}
|
||||
}
|
||||
|
||||
if (log_data->asctsz != 0) {
|
||||
printf(" ASCII Table\n");
|
||||
printf(" Byte Data_Byte ASCII_Character\n");
|
||||
for (j = 0; j < ascii_table_index; j++)
|
||||
printf(" %"PRIu64" %d %c\n",
|
||||
le64_to_cpu(ascii_table_ofst + j),
|
||||
log_data_buf[ascii_table_ofst + j],
|
||||
(char)log_data_buf[ascii_table_ofst + j]);
|
||||
}
|
||||
}
|
||||
|
||||
static void stdout_c7_log(struct nvme_dev *dev, struct tcg_configuration_log *log_data)
|
||||
{
|
||||
int j;
|
||||
|
||||
printf("TCG Configuration C7 Log Page Data-\n");
|
||||
|
||||
printf(" State : 0x%x\n",
|
||||
log_data->state);
|
||||
printf(" Reserved1 : 0x");
|
||||
for (j = 0; j < 3; j++)
|
||||
printf("%d", log_data->rsvd1[j]);
|
||||
printf("\n");
|
||||
printf(" Locking SP Activation Count : 0x%x\n",
|
||||
log_data->locking_sp_act_count);
|
||||
printf(" Tper Revert Count : 0x%x\n",
|
||||
log_data->type_rev_count);
|
||||
printf(" Locking SP Revert Count : 0x%x\n",
|
||||
log_data->locking_sp_rev_count);
|
||||
printf(" Number of Locking Objects : 0x%x\n",
|
||||
log_data->no_of_locking_obj);
|
||||
printf(" Number of Single User Mode Locking Objects : 0x%x\n",
|
||||
log_data->no_of_single_um_locking_obj);
|
||||
printf(" Number of Range Provisioned Locking Objects : 0x%x\n",
|
||||
log_data->no_of_range_prov_locking_obj);
|
||||
printf(" Number of Namespace Provisioned Locking Objects : 0x%x\n",
|
||||
log_data->no_of_ns_prov_locking_obj);
|
||||
printf(" Number of Read Locked Locking Objects : 0x%x\n",
|
||||
log_data->no_of_read_lock_locking_obj);
|
||||
printf(" Number of Write Locked Locking Objects : 0x%x\n",
|
||||
log_data->no_of_write_lock_locking_obj);
|
||||
printf(" Number of Read Unlocked Locking Objects : 0x%x\n",
|
||||
log_data->no_of_read_unlock_locking_obj);
|
||||
printf(" Number of Write Unlocked Locking Objects : 0x%x\n",
|
||||
log_data->no_of_write_unlock_locking_obj);
|
||||
printf(" Reserved2 : 0x%x\n",
|
||||
log_data->rsvd2);
|
||||
|
||||
printf(" SID Authentication Try Count : 0x%x\n",
|
||||
le32_to_cpu(log_data->sid_auth_try_count));
|
||||
printf(" SID Authentication Try Limit : 0x%x\n",
|
||||
le32_to_cpu(log_data->sid_auth_try_limit));
|
||||
printf(" Programmatic TCG Reset Count : 0x%x\n",
|
||||
le32_to_cpu(log_data->pro_tcg_rc));
|
||||
printf(" Programmatic Reset Lock Count : 0x%x\n",
|
||||
le32_to_cpu(log_data->pro_rlc));
|
||||
printf(" TCG Error Count : 0x%x\n",
|
||||
le32_to_cpu(log_data->tcg_ec));
|
||||
|
||||
printf(" Reserved3 : 0x");
|
||||
for (j = 0; j < 458; j++)
|
||||
printf("%d", log_data->rsvd3[j]);
|
||||
printf("\n");
|
||||
|
||||
printf(" Log Page Version : 0x%x\n",
|
||||
le16_to_cpu(log_data->log_page_version));
|
||||
printf(" Log page GUID : 0x");
|
||||
for (j = GUID_LEN - 1; j >= 0; j--)
|
||||
printf("%02x", log_data->log_page_guid[j]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static struct ocp_print_ops stdout_print_ops = {
|
||||
.hwcomp_log = stdout_hwcomp_log,
|
||||
.fw_act_history = stdout_fw_activation_history,
|
||||
.smart_extended_log = stdout_smart_extended_log,
|
||||
.telemetry_log = stdout_telemetry_log,
|
||||
.c3_log = stdout_c3_log,
|
||||
.c5_log = stdout_c5_log,
|
||||
.c1_log = stdout_c1_log,
|
||||
.c4_log = stdout_c4_log,
|
||||
.c9_log = stdout_c9_log,
|
||||
.c7_log = stdout_c7_log,
|
||||
};
|
||||
|
||||
struct ocp_print_ops *ocp_get_stdout_print_ops(nvme_print_flags_t flags)
|
||||
{
|
||||
stdout_print_ops.flags = flags;
|
||||
return &stdout_print_ops;
|
||||
}
|
81
plugins/ocp/ocp-print.c
Normal file
81
plugins/ocp/ocp-print.c
Normal file
|
@ -0,0 +1,81 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#include "nvme-print.h"
|
||||
#include "ocp-print.h"
|
||||
#include "ocp-hardware-component-log.h"
|
||||
|
||||
#define ocp_print(name, flags, ...) \
|
||||
do { \
|
||||
struct ocp_print_ops *ops = ocp_print_ops(flags); \
|
||||
if (ops && ops->name) \
|
||||
ops->name(__VA_ARGS__); \
|
||||
else \
|
||||
fprintf(stderr, "unhandled output format\n"); \
|
||||
} while (false)
|
||||
|
||||
static struct ocp_print_ops *ocp_print_ops(nvme_print_flags_t flags)
|
||||
{
|
||||
struct ocp_print_ops *ops = NULL;
|
||||
|
||||
if (flags & JSON || nvme_is_output_format_json())
|
||||
ops = ocp_get_json_print_ops(flags);
|
||||
else if (flags & BINARY)
|
||||
ops = ocp_get_binary_print_ops(flags);
|
||||
else
|
||||
ops = ocp_get_stdout_print_ops(flags);
|
||||
|
||||
return ops;
|
||||
}
|
||||
|
||||
void ocp_show_hwcomp_log(struct hwcomp_log *log, __u32 id, bool list, nvme_print_flags_t flags)
|
||||
{
|
||||
ocp_print(hwcomp_log, flags, log, id, list);
|
||||
}
|
||||
|
||||
void ocp_fw_act_history(const struct fw_activation_history *fw_history, nvme_print_flags_t flags)
|
||||
{
|
||||
ocp_print(fw_act_history, flags, fw_history);
|
||||
}
|
||||
|
||||
void ocp_smart_extended_log(void *data, nvme_print_flags_t flags)
|
||||
{
|
||||
ocp_print(smart_extended_log, flags, data);
|
||||
}
|
||||
|
||||
void ocp_show_telemetry_log(struct ocp_telemetry_parse_options *options, nvme_print_flags_t flags)
|
||||
{
|
||||
ocp_print(telemetry_log, flags, options);
|
||||
}
|
||||
|
||||
void ocp_c3_log(struct nvme_dev *dev, struct ssd_latency_monitor_log *log_data,
|
||||
nvme_print_flags_t flags)
|
||||
{
|
||||
ocp_print(c3_log, flags, dev, log_data);
|
||||
}
|
||||
|
||||
void ocp_c5_log(struct nvme_dev *dev, struct unsupported_requirement_log *log_data,
|
||||
nvme_print_flags_t flags)
|
||||
{
|
||||
ocp_print(c5_log, flags, dev, log_data);
|
||||
}
|
||||
|
||||
void ocp_c1_log(struct ocp_error_recovery_log_page *log_data, nvme_print_flags_t flags)
|
||||
{
|
||||
ocp_print(c1_log, flags, log_data);
|
||||
}
|
||||
|
||||
void ocp_c4_log(struct ocp_device_capabilities_log_page *log_data, nvme_print_flags_t flags)
|
||||
{
|
||||
ocp_print(c4_log, flags, log_data);
|
||||
}
|
||||
|
||||
void ocp_c9_log(struct telemetry_str_log_format *log_data, __u8 *log_data_buf,
|
||||
int total_log_page_size, nvme_print_flags_t flags)
|
||||
{
|
||||
ocp_print(c9_log, flags, log_data, log_data_buf, total_log_page_size);
|
||||
}
|
||||
|
||||
void ocp_c7_log(struct nvme_dev *dev, struct tcg_configuration_log *log_data,
|
||||
nvme_print_flags_t flags)
|
||||
{
|
||||
ocp_print(c7_log, flags, dev, log_data);
|
||||
}
|
51
plugins/ocp/ocp-print.h
Normal file
51
plugins/ocp/ocp-print.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#ifndef OCP_PRINT_H
|
||||
#define OCP_PRINT_H
|
||||
|
||||
#include "ocp-hardware-component-log.h"
|
||||
#include "ocp-fw-activation-history.h"
|
||||
#include "ocp-telemetry-decode.h"
|
||||
#include "ocp-nvme.h"
|
||||
|
||||
struct ocp_print_ops {
|
||||
void (*hwcomp_log)(struct hwcomp_log *log, __u32 id, bool list);
|
||||
void (*fw_act_history)(const struct fw_activation_history *fw_history);
|
||||
void (*smart_extended_log)(void *data);
|
||||
void (*telemetry_log)(struct ocp_telemetry_parse_options *options);
|
||||
void (*c3_log)(struct nvme_dev *dev, struct ssd_latency_monitor_log *log_data);
|
||||
void (*c5_log)(struct nvme_dev *dev, struct unsupported_requirement_log *log_data);
|
||||
void (*c1_log)(struct ocp_error_recovery_log_page *log_data);
|
||||
void (*c4_log)(struct ocp_device_capabilities_log_page *log_data);
|
||||
void (*c9_log)(struct telemetry_str_log_format *log_data, __u8 *log_data_buf,
|
||||
int total_log_page_size);
|
||||
void (*c7_log)(struct nvme_dev *dev, struct tcg_configuration_log *log_data);
|
||||
nvme_print_flags_t flags;
|
||||
};
|
||||
|
||||
struct ocp_print_ops *ocp_get_stdout_print_ops(nvme_print_flags_t flags);
|
||||
struct ocp_print_ops *ocp_get_binary_print_ops(nvme_print_flags_t flags);
|
||||
|
||||
#ifdef CONFIG_JSONC
|
||||
struct ocp_print_ops *ocp_get_json_print_ops(nvme_print_flags_t flags);
|
||||
#else /* !CONFIG_JSONC */
|
||||
static inline struct ocp_print_ops *ocp_get_json_print_ops(nvme_print_flags_t flags)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /* !CONFIG_JSONC */
|
||||
|
||||
void ocp_show_hwcomp_log(struct hwcomp_log *log, __u32 id, bool list, nvme_print_flags_t flags);
|
||||
void ocp_fw_act_history(const struct fw_activation_history *fw_history, nvme_print_flags_t flags);
|
||||
void ocp_smart_extended_log(void *data, nvme_print_flags_t flags);
|
||||
void ocp_show_telemetry_log(struct ocp_telemetry_parse_options *options, nvme_print_flags_t flags);
|
||||
void ocp_c3_log(struct nvme_dev *dev, struct ssd_latency_monitor_log *log_data,
|
||||
nvme_print_flags_t flags);
|
||||
void ocp_c5_log(struct nvme_dev *dev, struct unsupported_requirement_log *log_data,
|
||||
nvme_print_flags_t flags);
|
||||
void ocp_c1_log(struct ocp_error_recovery_log_page *log_data, nvme_print_flags_t flags);
|
||||
void ocp_c4_log(struct ocp_device_capabilities_log_page *log_data, nvme_print_flags_t flags);
|
||||
void ocp_c9_log(struct telemetry_str_log_format *log_data, __u8 *log_data_buf,
|
||||
int total_log_page_size, nvme_print_flags_t flags);
|
||||
void ocp_c7_log(struct nvme_dev *dev, struct tcg_configuration_log *log_data,
|
||||
nvme_print_flags_t flags);
|
||||
#endif /* OCP_PRINT_H */
|
|
@ -13,243 +13,19 @@
|
|||
|
||||
#include "common.h"
|
||||
#include "nvme-print.h"
|
||||
#include "ocp-print.h"
|
||||
|
||||
/* C0 SCAO Log Page */
|
||||
#define C0_SMART_CLOUD_ATTR_LEN 0x200
|
||||
#define C0_SMART_CLOUD_ATTR_OPCODE 0xC0
|
||||
#define C0_GUID_LENGTH 16
|
||||
|
||||
static __u8 scao_guid[C0_GUID_LENGTH] = {
|
||||
static __u8 scao_guid[GUID_LEN] = {
|
||||
0xC5, 0xAF, 0x10, 0x28,
|
||||
0xEA, 0xBF, 0xF2, 0xA4,
|
||||
0x9C, 0x4F, 0x6F, 0x7C,
|
||||
0xC9, 0x14, 0xD5, 0xAF
|
||||
};
|
||||
|
||||
enum {
|
||||
SCAO_PMUW = 0, /* Physical media units written */
|
||||
SCAO_PMUR = 16, /* Physical media units read */
|
||||
SCAO_BUNBR = 32, /* Bad user nand blocks raw */
|
||||
SCAO_BUNBN = 38, /* Bad user nand blocks normalized */
|
||||
SCAO_BSNBR = 40, /* Bad system nand blocks raw */
|
||||
SCAO_BSNBN = 46, /* Bad system nand blocks normalized */
|
||||
SCAO_XRC = 48, /* XOR recovery count */
|
||||
SCAO_UREC = 56, /* Uncorrectable read error count */
|
||||
SCAO_SEEC = 64, /* Soft ecc error count */
|
||||
SCAO_EEDC = 72, /* End to end detected errors */
|
||||
SCAO_EECE = 76, /* End to end corrected errors */
|
||||
SCAO_SDPU = 80, /* System data percent used */
|
||||
SCAO_RFSC = 81, /* Refresh counts */
|
||||
SCAO_MXUDEC = 88, /* Max User data erase counts */
|
||||
SCAO_MNUDEC = 92, /* Min User data erase counts */
|
||||
SCAO_NTTE = 96, /* Number of Thermal throttling events */
|
||||
SCAO_CTS = 97, /* Current throttling status */
|
||||
SCAO_EVF = 98, /* Errata Version Field */
|
||||
SCAO_PVF = 99, /* Point Version Field */
|
||||
SCAO_MIVF = 101, /* Minor Version Field */
|
||||
SCAO_MAVF = 103, /* Major Version Field */
|
||||
SCAO_PCEC = 104, /* PCIe correctable error count */
|
||||
SCAO_ICS = 112, /* Incomplete shutdowns */
|
||||
SCAO_PFB = 120, /* Percent free blocks */
|
||||
SCAO_CPH = 128, /* Capacitor health */
|
||||
SCAO_NEV = 130, /* NVMe Errata Version */
|
||||
SCAO_UIO = 136, /* Unaligned I/O */
|
||||
SCAO_SVN = 144, /* Security Version Number */
|
||||
SCAO_NUSE = 152, /* NUSE - Namespace utilization */
|
||||
SCAO_PSC = 160, /* PLP start count */
|
||||
SCAO_EEST = 176, /* Endurance estimate */
|
||||
SCAO_PLRC = 192, /* PCIe Link Retraining Count */
|
||||
SCAO_PSCC = 200, /* Power State Change Count */
|
||||
SCAO_LPV = 494, /* Log page version */
|
||||
SCAO_LPG = 496, /* Log page GUID */
|
||||
};
|
||||
|
||||
static void ocp_print_C0_log_normal(void *data)
|
||||
{
|
||||
uint16_t smart_log_ver = 0;
|
||||
__u8 *log_data = data;
|
||||
|
||||
printf("SMART Cloud Attributes :-\n");
|
||||
|
||||
printf(" Physical media units written - %"PRIu64" %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW + 8] & 0xFFFFFFFFFFFFFFFF),
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF));
|
||||
printf(" Physical media units read - %"PRIu64" %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR + 8] & 0xFFFFFFFFFFFFFFFF),
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF));
|
||||
printf(" Bad user nand blocks - Raw %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF));
|
||||
printf(" Bad user nand blocks - Normalized %d\n",
|
||||
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN]));
|
||||
printf(" Bad system nand blocks - Raw %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF));
|
||||
printf(" Bad system nand blocks - Normalized %d\n",
|
||||
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN]));
|
||||
printf(" XOR recovery count %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC]));
|
||||
printf(" Uncorrectable read error count %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC]));
|
||||
printf(" Soft ecc error count %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC]));
|
||||
printf(" End to end detected errors %"PRIu32"\n",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC]));
|
||||
printf(" End to end corrected errors %"PRIu32"\n",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE]));
|
||||
printf(" System data percent used %d\n",
|
||||
(__u8)log_data[SCAO_SDPU]);
|
||||
printf(" Refresh counts %"PRIu64"\n",
|
||||
(uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC]) & 0x00FFFFFFFFFFFFFF));
|
||||
printf(" Max User data erase counts %"PRIu32"\n",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC]));
|
||||
printf(" Min User data erase counts %"PRIu32"\n",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC]));
|
||||
printf(" Number of Thermal throttling events %d\n",
|
||||
(__u8)log_data[SCAO_NTTE]);
|
||||
printf(" Current throttling status 0x%x\n",
|
||||
(__u8)log_data[SCAO_CTS]);
|
||||
printf(" PCIe correctable error count %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC]));
|
||||
printf(" Incomplete shutdowns %"PRIu32"\n",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS]));
|
||||
printf(" Percent free blocks %d\n",
|
||||
(__u8)log_data[SCAO_PFB]);
|
||||
printf(" Capacitor health %"PRIu16"\n",
|
||||
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH]));
|
||||
printf(" Unaligned I/O %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO]));
|
||||
printf(" Security Version Number %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN]));
|
||||
printf(" NUSE - Namespace utilization %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE]));
|
||||
printf(" PLP start count %s\n",
|
||||
uint128_t_to_string(le128_to_cpu(&log_data[SCAO_PSC])));
|
||||
printf(" Endurance estimate %s\n",
|
||||
uint128_t_to_string(le128_to_cpu(&log_data[SCAO_EEST])));
|
||||
smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]);
|
||||
printf(" Log page version %"PRIu16"\n", smart_log_ver);
|
||||
printf(" Log page GUID 0x");
|
||||
printf("%"PRIx64"%"PRIx64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]),
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG]));
|
||||
if (smart_log_ver > 2) {
|
||||
printf(" Errata Version Field %d\n",
|
||||
(__u8)log_data[SCAO_EVF]);
|
||||
printf(" Point Version Field %"PRIu16"\n",
|
||||
le16_to_cpu(*(uint16_t *)&log_data[SCAO_PVF]));
|
||||
printf(" Minor Version Field %"PRIu16"\n",
|
||||
le16_to_cpu(*(uint16_t *)&log_data[SCAO_MIVF]));
|
||||
printf(" Major Version Field %d\n",
|
||||
(__u8)log_data[SCAO_MAVF]);
|
||||
printf(" NVMe Errata Version %d\n",
|
||||
(__u8)log_data[SCAO_NEV]);
|
||||
printf(" PCIe Link Retraining Count %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC]));
|
||||
printf(" Power State Change Count %"PRIu64"\n",
|
||||
le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC]));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void ocp_print_C0_log_json(void *data)
|
||||
{
|
||||
struct json_object *root;
|
||||
struct json_object *pmuw;
|
||||
struct json_object *pmur;
|
||||
uint16_t smart_log_ver = 0;
|
||||
__u8 *log_data = data;
|
||||
char guid[40];
|
||||
|
||||
root = json_create_object();
|
||||
pmuw = json_create_object();
|
||||
pmur = json_create_object();
|
||||
|
||||
json_object_add_value_uint64(pmuw, "hi",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW + 8] & 0xFFFFFFFFFFFFFFFF));
|
||||
json_object_add_value_uint64(pmuw, "lo",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF));
|
||||
json_object_add_value_object(root, "Physical media units written", pmuw);
|
||||
json_object_add_value_uint64(pmur, "hi",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR + 8] & 0xFFFFFFFFFFFFFFFF));
|
||||
json_object_add_value_uint64(pmur, "lo",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF));
|
||||
json_object_add_value_object(root, "Physical media units read", pmur);
|
||||
json_object_add_value_uint64(root, "Bad user nand blocks - Raw",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF));
|
||||
json_object_add_value_uint(root, "Bad user nand blocks - Normalized",
|
||||
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN]));
|
||||
json_object_add_value_uint64(root, "Bad system nand blocks - Raw",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF));
|
||||
json_object_add_value_uint(root, "Bad system nand blocks - Normalized",
|
||||
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN]));
|
||||
json_object_add_value_uint64(root, "XOR recovery count",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC]));
|
||||
json_object_add_value_uint64(root, "Uncorrectable read error count",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC]));
|
||||
json_object_add_value_uint64(root, "Soft ecc error count",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC]));
|
||||
json_object_add_value_uint(root, "End to end detected errors",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC]));
|
||||
json_object_add_value_uint(root, "End to end corrected errors",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE]));
|
||||
json_object_add_value_uint(root, "System data percent used",
|
||||
(__u8)log_data[SCAO_SDPU]);
|
||||
json_object_add_value_uint64(root, "Refresh counts",
|
||||
(uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC]) & 0x00FFFFFFFFFFFFFF));
|
||||
json_object_add_value_uint(root, "Max User data erase counts",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC]));
|
||||
json_object_add_value_uint(root, "Min User data erase counts",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC]));
|
||||
json_object_add_value_uint(root, "Number of Thermal throttling events",
|
||||
(__u8)log_data[SCAO_NTTE]);
|
||||
json_object_add_value_uint(root, "Current throttling status",
|
||||
(__u8)log_data[SCAO_CTS]);
|
||||
json_object_add_value_uint64(root, "PCIe correctable error count",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC]));
|
||||
json_object_add_value_uint(root, "Incomplete shutdowns",
|
||||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS]));
|
||||
json_object_add_value_uint(root, "Percent free blocks",
|
||||
(__u8)log_data[SCAO_PFB]);
|
||||
json_object_add_value_uint(root, "Capacitor health",
|
||||
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH]));
|
||||
json_object_add_value_uint64(root, "Unaligned I/O",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO]));
|
||||
json_object_add_value_uint64(root, "Security Version Number",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN]));
|
||||
json_object_add_value_uint64(root, "NUSE - Namespace utilization",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE]));
|
||||
json_object_add_value_uint128(root, "PLP start count",
|
||||
le128_to_cpu(&log_data[SCAO_PSC]));
|
||||
json_object_add_value_uint128(root, "Endurance estimate",
|
||||
le128_to_cpu(&log_data[SCAO_EEST]));
|
||||
smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]);
|
||||
|
||||
json_object_add_value_uint(root, "Log page version", smart_log_ver);
|
||||
|
||||
memset((void *)guid, 0, 40);
|
||||
sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]),
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG]));
|
||||
json_object_add_value_string(root, "Log page GUID", guid);
|
||||
|
||||
if (smart_log_ver > 2) {
|
||||
json_object_add_value_uint(root, "Errata Version Field",
|
||||
(__u8)log_data[SCAO_EVF]);
|
||||
json_object_add_value_uint(root, "Point Version Field",
|
||||
le16_to_cpu(*(uint16_t *)&log_data[SCAO_PVF]));
|
||||
json_object_add_value_uint(root, "Minor Version Field",
|
||||
le16_to_cpu(*(uint16_t *)&log_data[SCAO_MIVF]));
|
||||
json_object_add_value_uint(root, "Major Version Field",
|
||||
(__u8)log_data[SCAO_MAVF]);
|
||||
json_object_add_value_uint(root, "NVMe Errata Version",
|
||||
(__u8)log_data[SCAO_NEV]);
|
||||
json_object_add_value_uint(root, "PCIe Link Retraining Count",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC]));
|
||||
json_object_add_value_uint(root, "Power State Change Count",
|
||||
le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC]));
|
||||
}
|
||||
json_print_object(root, NULL);
|
||||
printf("\n");
|
||||
json_free_object(root);
|
||||
}
|
||||
|
||||
static int get_c0_log_page(int fd, char *format)
|
||||
{
|
||||
nvme_print_flags_t fmt;
|
||||
|
@ -300,16 +76,7 @@ static int get_c0_log_page(int fd, char *format)
|
|||
}
|
||||
|
||||
/* print the data */
|
||||
switch (fmt) {
|
||||
case NORMAL:
|
||||
ocp_print_C0_log_normal(data);
|
||||
break;
|
||||
case JSON:
|
||||
ocp_print_C0_log_json(data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ocp_smart_extended_log(data, fmt);
|
||||
} else {
|
||||
fprintf(stderr, "ERROR : OCP : Unable to read C0 data from buffer\n");
|
||||
}
|
||||
|
|
|
@ -12,6 +12,46 @@
|
|||
struct command;
|
||||
struct plugin;
|
||||
|
||||
enum {
|
||||
SCAO_PMUW = 0, /* Physical media units written */
|
||||
SCAO_PMUR = 16, /* Physical media units read */
|
||||
SCAO_BUNBR = 32, /* Bad user nand blocks raw */
|
||||
SCAO_BUNBN = 38, /* Bad user nand blocks normalized */
|
||||
SCAO_BSNBR = 40, /* Bad system nand blocks raw */
|
||||
SCAO_BSNBN = 46, /* Bad system nand blocks normalized */
|
||||
SCAO_XRC = 48, /* XOR recovery count */
|
||||
SCAO_UREC = 56, /* Uncorrectable read error count */
|
||||
SCAO_SEEC = 64, /* Soft ecc error count */
|
||||
SCAO_EEDC = 72, /* End to end detected errors */
|
||||
SCAO_EECE = 76, /* End to end corrected errors */
|
||||
SCAO_SDPU = 80, /* System data percent used */
|
||||
SCAO_RFSC = 81, /* Refresh counts */
|
||||
SCAO_MXUDEC = 88, /* Max User data erase counts */
|
||||
SCAO_MNUDEC = 92, /* Min User data erase counts */
|
||||
SCAO_NTTE = 96, /* Number of Thermal throttling events */
|
||||
SCAO_CTS = 97, /* Current throttling status */
|
||||
SCAO_EVF = 98, /* Errata Version Field */
|
||||
SCAO_PVF = 99, /* Point Version Field */
|
||||
SCAO_MIVF = 101, /* Minor Version Field */
|
||||
SCAO_MAVF = 103, /* Major Version Field */
|
||||
SCAO_PCEC = 104, /* PCIe correctable error count */
|
||||
SCAO_ICS = 112, /* Incomplete shutdowns */
|
||||
SCAO_PFB = 120, /* Percent free blocks */
|
||||
SCAO_CPH = 128, /* Capacitor health */
|
||||
SCAO_NBEV = 130, /* NVMe Base Errata Version */
|
||||
SCAO_NCSEV = 131, /* NVMe Command Set Errata Version */
|
||||
SCAO_UIO = 136, /* Unaligned I/O */
|
||||
SCAO_SVN = 144, /* Security Version Number */
|
||||
SCAO_NUSE = 152, /* NUSE - Namespace utilization */
|
||||
SCAO_PSC = 160, /* PLP start count */
|
||||
SCAO_EEST = 176, /* Endurance estimate */
|
||||
SCAO_PLRC = 192, /* PCIe Link Retraining Count */
|
||||
SCAO_PSCC = 200, /* Power State Change Count */
|
||||
SCAO_LPFR = 208, /* Lowest Permitted Firmware Revision */
|
||||
SCAO_LPV = 494, /* Log page version */
|
||||
SCAO_LPG = 496, /* Log page GUID */
|
||||
};
|
||||
|
||||
int ocp_smart_add_log(int argc, char **argv, struct command *cmd,
|
||||
struct plugin *plugin);
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ void print_telemetry_fifo_event(__u8 class_type,
|
|||
if (class_type) {
|
||||
class_str = telemetry_event_class_to_string(class_type);
|
||||
printf("Event Class : %s\n", class_str);
|
||||
printf(" Size : 0x%02x\n", size);
|
||||
}
|
||||
|
||||
switch (class_type) {
|
||||
|
@ -75,9 +76,8 @@ void print_telemetry_fifo_event(__u8 class_type,
|
|||
(int)((le64_to_cpu(timestamp%3600)/60)),
|
||||
(int)(le64_to_cpu(timestamp%60)));
|
||||
|
||||
printf(" Event ID : 0x%02x %s\n", id, telemetry_ts_event_to_string(id));
|
||||
printf(" Event ID : 0x%04x %s\n", id, telemetry_ts_event_to_string(id));
|
||||
printf(" Timestamp : %s\n", time_str);
|
||||
printf(" Size : %d\n", size);
|
||||
if (size > 8) {
|
||||
printf(" VU Data : 0x");
|
||||
for (j = 8; j < size; j++)
|
||||
|
@ -87,7 +87,7 @@ void print_telemetry_fifo_event(__u8 class_type,
|
|||
break;
|
||||
|
||||
case TELEMETRY_PCIE_CLASS:
|
||||
printf(" Event ID : 0x%02x %s\n",
|
||||
printf(" Event ID : 0x%04x %s\n",
|
||||
id, telemetry_pcie_event_id_to_string(id));
|
||||
printf(" State : 0x%02x %s\n",
|
||||
data[0], telemetry_pcie_state_data_to_string(data[0]));
|
||||
|
@ -104,7 +104,7 @@ void print_telemetry_fifo_event(__u8 class_type,
|
|||
break;
|
||||
|
||||
case TELEMETRY_NVME_CLASS:
|
||||
printf(" Event ID : 0x%02x %s\n",
|
||||
printf(" Event ID : 0x%04x %s\n",
|
||||
id, telemetry_nvme_event_id_to_string(id));
|
||||
if ((id == ADMIN_QUEUE_NONZERO_STATUS) ||
|
||||
(id == IO_QUEUE_NONZERO_STATUS)) {
|
||||
|
@ -128,46 +128,46 @@ void print_telemetry_fifo_event(__u8 class_type,
|
|||
le32_to_cpu(csts_reg_data));
|
||||
}
|
||||
if (size > 8)
|
||||
print_vu_event_data(size, (__u8 *)&data[8]);
|
||||
print_vu_event_data((size-8), (__u8 *)&data[8]);
|
||||
break;
|
||||
|
||||
case TELEMETRY_RESET_CLASS:
|
||||
printf(" Event ID : 0x%02x %s\n",
|
||||
printf(" Event ID : 0x%04x %s\n",
|
||||
id, telemetry_reset_event_id_to_string(id));
|
||||
if (size)
|
||||
print_vu_event_data(size, data);
|
||||
break;
|
||||
|
||||
case TELEMETRY_BOOT_SEQ_CLASS:
|
||||
printf(" Event ID : 0x%02x %s\n",
|
||||
printf(" Event ID : 0x%04x %s\n",
|
||||
id, telemetry_boot_seq_event_id_to_string(id));
|
||||
if (size)
|
||||
print_vu_event_data(size, data);
|
||||
break;
|
||||
|
||||
case TELEMETRY_FW_ASSERT_CLASS:
|
||||
printf(" Event ID : 0x%02x %s\n",
|
||||
printf(" Event ID : 0x%04x %s\n",
|
||||
id, telemetry_fw_assert_event_id_to_string(id));
|
||||
if (size)
|
||||
print_vu_event_data(size, data);
|
||||
break;
|
||||
|
||||
case TELEMETRY_TEMPERATURE_CLASS:
|
||||
printf(" Event ID : 0x%02x %s\n",
|
||||
printf(" Event ID : 0x%04x %s\n",
|
||||
id, telemetry_temperature_event_id_to_string(id));
|
||||
if (size)
|
||||
print_vu_event_data(size, data);
|
||||
break;
|
||||
|
||||
case TELEMETRY_MEDIA_DBG_CLASS:
|
||||
printf(" Event ID : 0x%02x %s\n",
|
||||
printf(" Event ID : 0x%04x %s\n",
|
||||
id, telemetry_media_debug_event_id_to_string(id));
|
||||
if (size)
|
||||
print_vu_event_data(size, data);
|
||||
break;
|
||||
|
||||
case TELEMETRY_MEDIA_WEAR_CLASS:
|
||||
printf(" Event ID : 0x%02x %s\n",
|
||||
printf(" Event ID : 0x%04x %s\n",
|
||||
id, telemetry_media_debug_event_id_to_string(id));
|
||||
__u32 host_tb_written = *(__u32 *)&data[0];
|
||||
__u32 media_tb_written = *(__u32 *)&data[4];
|
||||
|
@ -181,7 +181,7 @@ void print_telemetry_fifo_event(__u8 class_type,
|
|||
le16_to_cpu(media_tb_erased));
|
||||
|
||||
if (size > 12)
|
||||
print_vu_event_data(size, (__u8 *)&data[12]);
|
||||
print_vu_event_data((size-12), (__u8 *)&data[12]);
|
||||
break;
|
||||
|
||||
case TELEMETRY_STAT_SNAPSHOT_CLASS:
|
||||
|
@ -280,7 +280,7 @@ struct request_data ocp_header_in_da1[] = {
|
|||
{ "Minor Version", 2 },
|
||||
{ "Reserved1", 4 },
|
||||
{ "Timestamp", 8 },
|
||||
{ "Log page GUID", 16 },
|
||||
{ "Log page GUID", GUID_LEN },
|
||||
{ "Number Telemetry Profiles Supported", 1 },
|
||||
{ "Telemetry Profile Selected", 1 },
|
||||
{ "Reserved2", 6 },
|
||||
|
@ -419,9 +419,10 @@ struct request_data smart_extended[] = {
|
|||
{ "Lowest Permitted Firmware Revision", 8 },
|
||||
{ "Reserved4", 278 },
|
||||
{ "Log Page Version", 2 },
|
||||
{ "Log page GUID", 16 }
|
||||
{ "Log page GUID", GUID_LEN }
|
||||
};
|
||||
|
||||
#ifdef CONFIG_JSONC
|
||||
void json_add_formatted_u32_str(struct json_object *pobject, const char *msg, unsigned int pdata)
|
||||
{
|
||||
char data_str[70] = { 0 };
|
||||
|
@ -443,6 +444,7 @@ void json_add_formatted_var_size_str(struct json_object *pobject, const char *ms
|
|||
|
||||
json_object_add_value_string(pobject, msg, description_str);
|
||||
}
|
||||
#endif /* CONFIG_JSONC */
|
||||
|
||||
int get_telemetry_das_offset_and_size(
|
||||
struct nvme_ocp_telemetry_common_header *ptelemetry_common_header,
|
||||
|
@ -636,49 +638,67 @@ int parse_ocp_telemetry_string_log(int event_fifo_num, int identifier, int debug
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_JSONC
|
||||
void parse_time_stamp_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
|
||||
struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
|
||||
struct json_object *pevent_fifos_object, FILE *fp)
|
||||
{
|
||||
struct nvme_ocp_time_stamp_dbg_evt_class_format *ptime_stamp_event =
|
||||
(struct nvme_ocp_time_stamp_dbg_evt_class_format *) pevent_specific_data;
|
||||
|
||||
int vu_event_id = (int)ptime_stamp_event->vu_event_identifier;
|
||||
|
||||
unsigned int data_size = ((pevent_descriptor->event_data_size * SIZE_OF_DWORD)-
|
||||
sizeof(struct nvme_ocp_time_stamp_dbg_evt_class_format));
|
||||
|
||||
__u8 *pdata = (__u8 *)ptime_stamp_event +
|
||||
sizeof(struct nvme_ocp_time_stamp_dbg_evt_class_format);
|
||||
|
||||
struct nvme_ocp_common_dbg_evt_class_vu_data *ptime_stamp_event_vu_data = NULL;
|
||||
__u16 vu_event_id = 0;
|
||||
__u8 *pdata = NULL;
|
||||
char description_str[256] = "";
|
||||
unsigned int vu_data_size = 0;
|
||||
bool vu_data_present = false;
|
||||
|
||||
parse_ocp_telemetry_string_log(0, ptime_stamp_event->vu_event_identifier,
|
||||
pevent_descriptor->debug_event_class_type,
|
||||
VU_EVENT_STRING, description_str);
|
||||
if ((pevent_descriptor->event_data_size * SIZE_OF_DWORD) >
|
||||
sizeof(struct nvme_ocp_time_stamp_dbg_evt_class_format)) {
|
||||
vu_data_present = true;
|
||||
vu_data_size =
|
||||
((pevent_descriptor->event_data_size * SIZE_OF_DWORD) -
|
||||
(sizeof(struct nvme_ocp_time_stamp_dbg_evt_class_format) +
|
||||
SIZE_OF_VU_EVENT_ID));
|
||||
|
||||
ptime_stamp_event_vu_data =
|
||||
(struct nvme_ocp_common_dbg_evt_class_vu_data *)((__u64)ptime_stamp_event +
|
||||
sizeof(struct nvme_ocp_time_stamp_dbg_evt_class_format));
|
||||
vu_event_id = le16_to_cpu(ptime_stamp_event_vu_data->vu_event_identifier);
|
||||
pdata = (__u8 *)&(ptime_stamp_event_vu_data->data);
|
||||
|
||||
parse_ocp_telemetry_string_log(0, vu_event_id,
|
||||
pevent_descriptor->debug_event_class_type,
|
||||
VU_EVENT_STRING, description_str);
|
||||
}
|
||||
|
||||
if (pevent_fifos_object != NULL) {
|
||||
json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA,
|
||||
ptime_stamp_event->time_stamp, DATA_SIZE_8);
|
||||
json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
|
||||
vu_event_id);
|
||||
json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
|
||||
description_str);
|
||||
json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
|
||||
data_size);
|
||||
if (vu_data_present) {
|
||||
json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
|
||||
vu_event_id);
|
||||
json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
|
||||
description_str);
|
||||
json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
|
||||
vu_data_size);
|
||||
}
|
||||
} else {
|
||||
if (fp) {
|
||||
print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
|
||||
ptime_stamp_event->time_stamp, DATA_SIZE_8, fp);
|
||||
fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
|
||||
if (vu_data_present) {
|
||||
fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, vu_data_size, fp);
|
||||
}
|
||||
} else {
|
||||
print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
|
||||
ptime_stamp_event->time_stamp, DATA_SIZE_8, fp);
|
||||
printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
|
||||
if (vu_data_present) {
|
||||
printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, vu_data_size, fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -689,37 +709,60 @@ void parse_pcie_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descrip
|
|||
{
|
||||
struct nvme_ocp_pcie_dbg_evt_class_format *ppcie_event =
|
||||
(struct nvme_ocp_pcie_dbg_evt_class_format *) pevent_specific_data;
|
||||
int vu_event_id = (int) ppcie_event->vu_event_identifier;
|
||||
unsigned int data_size = ((pevent_descriptor->event_data_size * SIZE_OF_DWORD) -
|
||||
sizeof(struct nvme_ocp_pcie_dbg_evt_class_format));
|
||||
__u8 *pdata = (__u8 *) ppcie_event + sizeof(struct nvme_ocp_pcie_dbg_evt_class_format);
|
||||
struct nvme_ocp_common_dbg_evt_class_vu_data *ppcie_event_vu_data = NULL;
|
||||
__u16 vu_event_id = 0;
|
||||
__u8 *pdata = NULL;
|
||||
char description_str[256] = "";
|
||||
unsigned int vu_data_size = 0;
|
||||
bool vu_data_present = false;
|
||||
|
||||
parse_ocp_telemetry_string_log(0, ppcie_event->vu_event_identifier,
|
||||
pevent_descriptor->debug_event_class_type, VU_EVENT_STRING, description_str);
|
||||
if ((pevent_descriptor->event_data_size * SIZE_OF_DWORD) >
|
||||
sizeof(struct nvme_ocp_pcie_dbg_evt_class_format)) {
|
||||
vu_data_present = true;
|
||||
vu_data_size =
|
||||
((pevent_descriptor->event_data_size * SIZE_OF_DWORD) -
|
||||
(sizeof(struct nvme_ocp_pcie_dbg_evt_class_format) +
|
||||
SIZE_OF_VU_EVENT_ID));
|
||||
|
||||
ppcie_event_vu_data =
|
||||
(struct nvme_ocp_common_dbg_evt_class_vu_data *)((__u64)ppcie_event +
|
||||
sizeof(struct nvme_ocp_pcie_dbg_evt_class_format));
|
||||
vu_event_id = le16_to_cpu(ppcie_event_vu_data->vu_event_identifier);
|
||||
pdata = (__u8 *)&(ppcie_event_vu_data->data);
|
||||
|
||||
parse_ocp_telemetry_string_log(0, vu_event_id,
|
||||
pevent_descriptor->debug_event_class_type,
|
||||
VU_EVENT_STRING, description_str);
|
||||
}
|
||||
|
||||
if (pevent_fifos_object != NULL) {
|
||||
json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA,
|
||||
ppcie_event->pCIeDebugEventData, DATA_SIZE_4);
|
||||
json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
|
||||
vu_event_id);
|
||||
json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
|
||||
description_str);
|
||||
json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
|
||||
data_size);
|
||||
if (vu_data_present) {
|
||||
json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
|
||||
vu_event_id);
|
||||
json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
|
||||
description_str);
|
||||
json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
|
||||
vu_data_size);
|
||||
}
|
||||
} else {
|
||||
if (fp) {
|
||||
print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
|
||||
ppcie_event->pCIeDebugEventData, DATA_SIZE_4, fp);
|
||||
fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
|
||||
if (vu_data_present) {
|
||||
fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, vu_data_size, fp);
|
||||
}
|
||||
} else {
|
||||
print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
|
||||
ppcie_event->pCIeDebugEventData, DATA_SIZE_4, fp);
|
||||
printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
|
||||
if (vu_data_present) {
|
||||
printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, vu_data_size, fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -730,38 +773,61 @@ void parse_nvme_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descrip
|
|||
{
|
||||
struct nvme_ocp_nvme_dbg_evt_class_format *pnvme_event =
|
||||
(struct nvme_ocp_nvme_dbg_evt_class_format *) pevent_specific_data;
|
||||
int vu_event_id = (int) pnvme_event->vu_event_identifier;
|
||||
unsigned int data_size = ((pevent_descriptor->event_data_size *
|
||||
SIZE_OF_DWORD) - sizeof(struct nvme_ocp_nvme_dbg_evt_class_format));
|
||||
__u8 *pdata = (__u8 *) pnvme_event + sizeof(struct nvme_ocp_nvme_dbg_evt_class_format);
|
||||
struct nvme_ocp_common_dbg_evt_class_vu_data *pnvme_event_vu_data = NULL;
|
||||
__u16 vu_event_id = 0;
|
||||
__u8 *pdata = NULL;
|
||||
char description_str[256] = "";
|
||||
unsigned int vu_data_size = 0;
|
||||
bool vu_data_present = false;
|
||||
|
||||
parse_ocp_telemetry_string_log(0, pnvme_event->vu_event_identifier,
|
||||
pevent_descriptor->debug_event_class_type, VU_EVENT_STRING,
|
||||
description_str);
|
||||
if ((pevent_descriptor->event_data_size * SIZE_OF_DWORD) >
|
||||
sizeof(struct nvme_ocp_nvme_dbg_evt_class_format)) {
|
||||
vu_data_present = true;
|
||||
vu_data_size =
|
||||
((pevent_descriptor->event_data_size * SIZE_OF_DWORD) -
|
||||
(sizeof(struct nvme_ocp_nvme_dbg_evt_class_format) +
|
||||
SIZE_OF_VU_EVENT_ID));
|
||||
pnvme_event_vu_data =
|
||||
(struct nvme_ocp_common_dbg_evt_class_vu_data *)((__u64)pnvme_event +
|
||||
sizeof(struct nvme_ocp_nvme_dbg_evt_class_format));
|
||||
|
||||
vu_event_id = le16_to_cpu(pnvme_event_vu_data->vu_event_identifier);
|
||||
pdata = (__u8 *)&(pnvme_event_vu_data->data);
|
||||
|
||||
parse_ocp_telemetry_string_log(0, vu_event_id,
|
||||
pevent_descriptor->debug_event_class_type,
|
||||
VU_EVENT_STRING,
|
||||
description_str);
|
||||
}
|
||||
|
||||
if (pevent_fifos_object != NULL) {
|
||||
json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA,
|
||||
pnvme_event->nvmeDebugEventData, DATA_SIZE_8);
|
||||
json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
|
||||
vu_event_id);
|
||||
json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
|
||||
description_str);
|
||||
json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
|
||||
data_size);
|
||||
pnvme_event->nvmeDebugEventData, DATA_SIZE_8);
|
||||
if (vu_data_present) {
|
||||
json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
|
||||
vu_event_id);
|
||||
json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
|
||||
description_str);
|
||||
json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
|
||||
vu_data_size);
|
||||
}
|
||||
} else {
|
||||
if (fp) {
|
||||
print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
|
||||
pnvme_event->nvmeDebugEventData, DATA_SIZE_8, fp);
|
||||
fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
|
||||
if (vu_data_present) {
|
||||
fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, vu_data_size, fp);
|
||||
}
|
||||
} else {
|
||||
print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
|
||||
pnvme_event->nvmeDebugEventData, DATA_SIZE_8, fp);
|
||||
printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
|
||||
if (vu_data_present) {
|
||||
printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, vu_data_size, fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -770,34 +836,38 @@ void parse_common_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descr
|
|||
struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
|
||||
struct json_object *pevent_fifos_object, FILE *fp)
|
||||
{
|
||||
struct nvme_ocp_common_dbg_evt_class_format *pcommon_debug_event =
|
||||
(struct nvme_ocp_common_dbg_evt_class_format *) pevent_specific_data;
|
||||
int vu_event_id = (int) pcommon_debug_event->vu_event_identifier;
|
||||
unsigned int data_size = ((pevent_descriptor->event_data_size *
|
||||
SIZE_OF_DWORD) - sizeof(struct nvme_ocp_common_dbg_evt_class_format));
|
||||
__u8 *pdata = (__u8 *) pcommon_debug_event +
|
||||
sizeof(struct nvme_ocp_common_dbg_evt_class_format);
|
||||
char description_str[256] = "";
|
||||
if (pevent_specific_data) {
|
||||
struct nvme_ocp_common_dbg_evt_class_vu_data *pcommon_debug_event_vu_data =
|
||||
(struct nvme_ocp_common_dbg_evt_class_vu_data *) pevent_specific_data;
|
||||
|
||||
parse_ocp_telemetry_string_log(0, pcommon_debug_event->vu_event_identifier,
|
||||
pevent_descriptor->debug_event_class_type, VU_EVENT_STRING, description_str);
|
||||
__u16 vu_event_id = le16_to_cpu(pcommon_debug_event_vu_data->vu_event_identifier);
|
||||
char description_str[256] = "";
|
||||
__u8 *pdata = (__u8 *)&(pcommon_debug_event_vu_data->data);
|
||||
|
||||
if (pevent_fifos_object != NULL) {
|
||||
json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
|
||||
vu_event_id);
|
||||
json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
|
||||
description_str);
|
||||
json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
|
||||
data_size);
|
||||
} else {
|
||||
if (fp) {
|
||||
fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
|
||||
unsigned int vu_data_size = ((pevent_descriptor->event_data_size *
|
||||
SIZE_OF_DWORD) - SIZE_OF_VU_EVENT_ID);
|
||||
|
||||
parse_ocp_telemetry_string_log(0, vu_event_id,
|
||||
pevent_descriptor->debug_event_class_type,
|
||||
VU_EVENT_STRING, description_str);
|
||||
|
||||
if (pevent_fifos_object != NULL) {
|
||||
json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
|
||||
vu_event_id);
|
||||
json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
|
||||
description_str);
|
||||
json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
|
||||
vu_data_size);
|
||||
} else {
|
||||
printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
|
||||
if (fp) {
|
||||
fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, vu_data_size, fp);
|
||||
} else {
|
||||
printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, vu_data_size, fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -808,39 +878,62 @@ void parse_media_wear_event(struct nvme_ocp_telemetry_event_descriptor *pevent_d
|
|||
{
|
||||
struct nvme_ocp_media_wear_dbg_evt_class_format *pmedia_wear_event =
|
||||
(struct nvme_ocp_media_wear_dbg_evt_class_format *) pevent_specific_data;
|
||||
int vu_event_id = (int) pmedia_wear_event->vu_event_identifier;
|
||||
unsigned int data_size = ((pevent_descriptor->event_data_size * SIZE_OF_DWORD) -
|
||||
sizeof(struct nvme_ocp_media_wear_dbg_evt_class_format));
|
||||
__u8 *pdata = (__u8 *) pmedia_wear_event +
|
||||
sizeof(struct nvme_ocp_media_wear_dbg_evt_class_format);
|
||||
char description_str[256] = "";
|
||||
struct nvme_ocp_common_dbg_evt_class_vu_data *pmedia_wear_event_vu_data = NULL;
|
||||
|
||||
parse_ocp_telemetry_string_log(0, pmedia_wear_event->vu_event_identifier,
|
||||
pevent_descriptor->debug_event_class_type, VU_EVENT_STRING,
|
||||
description_str);
|
||||
__u16 vu_event_id = 0;
|
||||
__u8 *pdata = NULL;
|
||||
char description_str[256] = "";
|
||||
unsigned int vu_data_size = 0;
|
||||
bool vu_data_present = false;
|
||||
|
||||
if ((pevent_descriptor->event_data_size * SIZE_OF_DWORD) >
|
||||
sizeof(struct nvme_ocp_media_wear_dbg_evt_class_format)) {
|
||||
vu_data_present = true;
|
||||
vu_data_size =
|
||||
((pevent_descriptor->event_data_size * SIZE_OF_DWORD) -
|
||||
(sizeof(struct nvme_ocp_media_wear_dbg_evt_class_format) +
|
||||
SIZE_OF_VU_EVENT_ID));
|
||||
|
||||
pmedia_wear_event_vu_data =
|
||||
(struct nvme_ocp_common_dbg_evt_class_vu_data *)((__u64)pmedia_wear_event +
|
||||
sizeof(struct nvme_ocp_media_wear_dbg_evt_class_format));
|
||||
vu_event_id = le16_to_cpu(pmedia_wear_event_vu_data->vu_event_identifier);
|
||||
pdata = (__u8 *)&(pmedia_wear_event_vu_data->data);
|
||||
|
||||
parse_ocp_telemetry_string_log(0, vu_event_id,
|
||||
pevent_descriptor->debug_event_class_type,
|
||||
VU_EVENT_STRING,
|
||||
description_str);
|
||||
}
|
||||
|
||||
if (pevent_fifos_object != NULL) {
|
||||
json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA,
|
||||
pmedia_wear_event->currentMediaWear, DATA_SIZE_12);
|
||||
json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
|
||||
vu_event_id);
|
||||
json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
|
||||
description_str);
|
||||
json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
|
||||
data_size);
|
||||
if (vu_data_present) {
|
||||
json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
|
||||
vu_event_id);
|
||||
json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
|
||||
description_str);
|
||||
json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
|
||||
vu_data_size);
|
||||
}
|
||||
} else {
|
||||
if (fp) {
|
||||
print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
|
||||
pmedia_wear_event->currentMediaWear, DATA_SIZE_12, fp);
|
||||
fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
|
||||
if (vu_data_present) {
|
||||
fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, vu_data_size, fp);
|
||||
}
|
||||
} else {
|
||||
print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
|
||||
pmedia_wear_event->currentMediaWear, DATA_SIZE_12, NULL);
|
||||
printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
|
||||
if (vu_data_present) {
|
||||
printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
|
||||
printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
|
||||
print_formatted_var_size_str(STR_VU_DATA, pdata, vu_data_size, fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -895,16 +988,27 @@ int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start,
|
|||
(struct nvme_ocp_telemetry_event_descriptor *)
|
||||
(pfifo_start + offset_to_move);
|
||||
|
||||
/* check if at the end of the list */
|
||||
if (pevent_descriptor->debug_event_class_type == RESERVED_CLASS_TYPE)
|
||||
break;
|
||||
|
||||
if (pevent_descriptor != NULL && pevent_descriptor->event_data_size >= 0) {
|
||||
//Data is present in the form of DWORDS, So multiplying with sizeof(DWORD)
|
||||
/* Data is present in the form of DWORDS,
|
||||
* So multiplying with sizeof(DWORD)
|
||||
*/
|
||||
unsigned int data_size = pevent_descriptor->event_data_size *
|
||||
SIZE_OF_DWORD;
|
||||
|
||||
__u8 *pevent_specific_data = (__u8 *)pevent_descriptor + event_des_size;
|
||||
|
||||
__u8 *pevent_specific_data = NULL;
|
||||
__u16 event_id = 0;
|
||||
char description_str[256] = "";
|
||||
|
||||
parse_ocp_telemetry_string_log(0, pevent_descriptor->event_id,
|
||||
if (pevent_descriptor != NULL && pevent_descriptor->event_data_size > 0)
|
||||
pevent_specific_data = (__u8 *)pevent_descriptor + event_des_size;
|
||||
|
||||
event_id = le16_to_cpu(pevent_descriptor->event_id);
|
||||
|
||||
parse_ocp_telemetry_string_log(0, event_id,
|
||||
pevent_descriptor->debug_event_class_type, EVENT_STRING,
|
||||
description_str);
|
||||
|
||||
|
@ -916,7 +1020,7 @@ int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start,
|
|||
STR_DBG_EVENT_CLASS_TYPE,
|
||||
pevent_descriptor->debug_event_class_type);
|
||||
json_add_formatted_u32_str(pevent_descriptor_obj,
|
||||
STR_EVENT_IDENTIFIER, pevent_descriptor->event_id);
|
||||
STR_EVENT_IDENTIFIER, event_id);
|
||||
json_object_add_value_string(pevent_descriptor_obj,
|
||||
STR_EVENT_STRING, description_str);
|
||||
json_add_formatted_u32_str(pevent_descriptor_obj,
|
||||
|
@ -930,18 +1034,18 @@ int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start,
|
|||
fprintf(fp, "%s: 0x%x\n", STR_DBG_EVENT_CLASS_TYPE,
|
||||
pevent_descriptor->debug_event_class_type);
|
||||
fprintf(fp, "%s: 0x%x\n", STR_EVENT_IDENTIFIER,
|
||||
pevent_descriptor->event_id);
|
||||
event_id);
|
||||
fprintf(fp, "%s: %s\n", STR_EVENT_STRING, description_str);
|
||||
fprintf(fp, "%s: 0x%x\n", STR_EVENT_DATA_SIZE,
|
||||
pevent_descriptor->event_data_size);
|
||||
} else {
|
||||
printf("%s: 0x%x\n", STR_DBG_EVENT_CLASS_TYPE,
|
||||
pevent_descriptor->debug_event_class_type);
|
||||
pevent_descriptor->debug_event_class_type);
|
||||
printf("%s: 0x%x\n", STR_EVENT_IDENTIFIER,
|
||||
pevent_descriptor->event_id);
|
||||
event_id);
|
||||
printf("%s: %s\n", STR_EVENT_STRING, description_str);
|
||||
printf("%s: 0x%x\n", STR_EVENT_DATA_SIZE,
|
||||
pevent_descriptor->event_data_size);
|
||||
pevent_descriptor->event_data_size);
|
||||
}
|
||||
|
||||
if (pevent_descriptor->debug_event_class_type >= 0x80)
|
||||
|
@ -951,28 +1055,43 @@ int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start,
|
|||
|
||||
switch (pevent_descriptor->debug_event_class_type) {
|
||||
case TIME_STAMP_CLASS_TYPE:
|
||||
parse_time_stamp_event(pevent_descriptor, pevent_descriptor_obj,
|
||||
pevent_specific_data, pevent_fifos_object, fp);
|
||||
parse_time_stamp_event(pevent_descriptor,
|
||||
pevent_descriptor_obj,
|
||||
pevent_specific_data,
|
||||
pevent_fifos_object,
|
||||
fp);
|
||||
break;
|
||||
case PCIE_CLASS_TYPE:
|
||||
parse_pcie_event(pevent_descriptor, pevent_descriptor_obj,
|
||||
pevent_specific_data, pevent_fifos_object, fp);
|
||||
parse_pcie_event(pevent_descriptor,
|
||||
pevent_descriptor_obj,
|
||||
pevent_specific_data,
|
||||
pevent_fifos_object,
|
||||
fp);
|
||||
break;
|
||||
case NVME_CLASS_TYPE:
|
||||
parse_nvme_event(pevent_descriptor, pevent_descriptor_obj,
|
||||
pevent_specific_data, pevent_fifos_object, fp);
|
||||
parse_nvme_event(pevent_descriptor,
|
||||
pevent_descriptor_obj,
|
||||
pevent_specific_data,
|
||||
pevent_fifos_object,
|
||||
fp);
|
||||
break;
|
||||
case RESET_CLASS_TYPE:
|
||||
case BOOT_SEQUENCE_CLASS_TYPE:
|
||||
case FIRMWARE_ASSERT_CLASS_TYPE:
|
||||
case TEMPERATURE_CLASS_TYPE:
|
||||
case MEDIA_CLASS_TYPE:
|
||||
parse_common_event(pevent_descriptor, pevent_descriptor_obj,
|
||||
pevent_specific_data, pevent_fifos_object, fp);
|
||||
parse_common_event(pevent_descriptor,
|
||||
pevent_descriptor_obj,
|
||||
pevent_specific_data,
|
||||
pevent_fifos_object,
|
||||
fp);
|
||||
break;
|
||||
case MEDIA_WEAR_CLASS_TYPE:
|
||||
parse_media_wear_event(pevent_descriptor, pevent_descriptor_obj,
|
||||
pevent_specific_data, pevent_fifos_object, fp);
|
||||
parse_media_wear_event(pevent_descriptor,
|
||||
pevent_descriptor_obj,
|
||||
pevent_specific_data,
|
||||
pevent_fifos_object,
|
||||
fp);
|
||||
break;
|
||||
case STATISTIC_SNAPSHOT_CLASS_TYPE: {
|
||||
struct nvme_ocp_statistic_snapshot_evt_class_format
|
||||
|
@ -989,20 +1108,22 @@ int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start,
|
|||
case RESERVED_CLASS_TYPE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pevent_descriptor_obj != NULL && pevent_fifo_array != NULL)
|
||||
json_array_add_value_object(pevent_fifo_array, pevent_descriptor_obj);
|
||||
else {
|
||||
if (fp)
|
||||
fprintf(fp, STR_LINE2);
|
||||
else
|
||||
printf(STR_LINE2);
|
||||
}
|
||||
} else
|
||||
break;
|
||||
if (pevent_descriptor_obj != NULL && pevent_fifo_array != NULL)
|
||||
json_array_add_value_object(pevent_fifo_array,
|
||||
pevent_descriptor_obj);
|
||||
else {
|
||||
if (fp)
|
||||
fprintf(fp, STR_LINE2);
|
||||
else
|
||||
printf(STR_LINE2);
|
||||
}
|
||||
} else
|
||||
break;
|
||||
|
||||
offset_to_move += (pevent_descriptor->event_data_size * SIZE_OF_DWORD + event_des_size);
|
||||
offset_to_move += (pevent_descriptor->event_data_size * SIZE_OF_DWORD +
|
||||
event_des_size);
|
||||
}
|
||||
|
||||
if (pevent_fifos_object != NULL && pevent_fifo_array != NULL)
|
||||
|
@ -1241,9 +1362,16 @@ int print_ocp_telemetry_normal(struct ocp_telemetry_parse_options *options)
|
|||
fprintf(fp, STR_LINE);
|
||||
fprintf(fp, "%s\n", STR_LOG_PAGE_HEADER);
|
||||
fprintf(fp, STR_LINE);
|
||||
if (!strcmp(options->telemetry_type, "host"))
|
||||
generic_structure_parser(ptelemetry_buffer, host_log_page_header,
|
||||
ARRAY_SIZE(host_log_page_header), NULL, 0, fp);
|
||||
if (!strcmp(options->telemetry_type, "host")) {
|
||||
if ((ptelemetry_buffer == NULL) ||
|
||||
(ARRAY_SIZE(host_log_page_header) == 0))
|
||||
printf("skip generic_structure_parser\n");
|
||||
else
|
||||
generic_structure_parser(ptelemetry_buffer,
|
||||
host_log_page_header,
|
||||
ARRAY_SIZE(host_log_page_header),
|
||||
NULL, 0, fp);
|
||||
}
|
||||
else if (!strcmp(options->telemetry_type, "controller"))
|
||||
generic_structure_parser(ptelemetry_buffer,
|
||||
controller_log_page_header,
|
||||
|
@ -1350,9 +1478,15 @@ int print_ocp_telemetry_normal(struct ocp_telemetry_parse_options *options)
|
|||
printf(STR_LINE);
|
||||
printf("%s\n", STR_LOG_PAGE_HEADER);
|
||||
printf(STR_LINE);
|
||||
if (!strcmp(options->telemetry_type, "host"))
|
||||
generic_structure_parser(ptelemetry_buffer, host_log_page_header,
|
||||
ARRAY_SIZE(host_log_page_header), NULL, 0, NULL);
|
||||
if (!strcmp(options->telemetry_type, "host")) {
|
||||
if ((ptelemetry_buffer == NULL) ||
|
||||
(ARRAY_SIZE(host_log_page_header) == 0))
|
||||
printf("skip generic_structure_parser\n");
|
||||
else {
|
||||
generic_structure_parser(ptelemetry_buffer, host_log_page_header,
|
||||
ARRAY_SIZE(host_log_page_header), NULL, 0, NULL);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(options->telemetry_type, "controller"))
|
||||
generic_structure_parser(ptelemetry_buffer, controller_log_page_header,
|
||||
ARRAY_SIZE(controller_log_page_header), NULL, 0, NULL);
|
||||
|
@ -1363,7 +1497,7 @@ int print_ocp_telemetry_normal(struct ocp_telemetry_parse_options *options)
|
|||
__u8 *preason_identifier_offset = ptelemetry_buffer +
|
||||
offsetof(struct nvme_ocp_telemetry_host_initiated_header, reason_id);
|
||||
generic_structure_parser(preason_identifier_offset, reason_identifier,
|
||||
ARRAY_SIZE(reason_identifier), NULL, 0, NULL);
|
||||
ARRAY_SIZE(reason_identifier), NULL, 0, NULL);
|
||||
|
||||
printf(STR_LINE);
|
||||
printf("%s\n", STR_TELEMETRY_HOST_DATA_BLOCK_1);
|
||||
|
@ -1382,7 +1516,7 @@ int print_ocp_telemetry_normal(struct ocp_telemetry_parse_options *options)
|
|||
__u8 *pda1_header_offset = ptelemetry_buffer + offsets.da1_start_offset;//512
|
||||
|
||||
generic_structure_parser(pda1_header_offset, ocp_header_in_da1,
|
||||
ARRAY_SIZE(ocp_header_in_da1), NULL, 0, NULL);
|
||||
ARRAY_SIZE(ocp_header_in_da1), NULL, 0, NULL);
|
||||
|
||||
printf(STR_LINE);
|
||||
printf("%s\n", STR_SMART_HEALTH_INFO);
|
||||
|
@ -1391,7 +1525,7 @@ int print_ocp_telemetry_normal(struct ocp_telemetry_parse_options *options)
|
|||
offsetof(struct nvme_ocp_header_in_da1, smart_health_info);
|
||||
|
||||
generic_structure_parser(pda1_smart_offset, smart, ARRAY_SIZE(smart), NULL, 0,
|
||||
NULL);
|
||||
NULL);
|
||||
|
||||
printf(STR_LINE);
|
||||
printf("%s\n", STR_SMART_HEALTH_INTO_EXTENDED);
|
||||
|
@ -1400,7 +1534,7 @@ int print_ocp_telemetry_normal(struct ocp_telemetry_parse_options *options)
|
|||
offsetof(struct nvme_ocp_header_in_da1, smart_health_info_extended);
|
||||
|
||||
generic_structure_parser(pda1_smart_ext_offset, smart_extended,
|
||||
ARRAY_SIZE(smart_extended), NULL, 0, NULL);
|
||||
ARRAY_SIZE(smart_extended), NULL, 0, NULL);
|
||||
|
||||
printf(STR_LINE);
|
||||
printf("%s\n", STR_DA_1_STATS);
|
||||
|
@ -1564,3 +1698,4 @@ int print_ocp_telemetry_json(struct ocp_telemetry_parse_options *options)
|
|||
|
||||
return status;
|
||||
}
|
||||
#endif /* CONFIG_JSONC */
|
||||
|
|
|
@ -3,11 +3,14 @@
|
|||
*
|
||||
* Authors: Jeff Lien <jeff.lien@wdc.com>,
|
||||
*/
|
||||
#ifndef OCP_TELEMETRY_DECODE_H
|
||||
#define OCP_TELEMETRY_DECODE_H
|
||||
|
||||
#include "nvme.h"
|
||||
#include "nvme-print.h"
|
||||
#include "util/utils.h"
|
||||
#include "common.h"
|
||||
#include "ocp-nvme.h"
|
||||
|
||||
extern __u8 *ptelemetry_buffer;
|
||||
extern __u8 *pstring_buffer;
|
||||
|
@ -382,7 +385,7 @@ struct telemetry_stats_desc {
|
|||
__u8 data[];
|
||||
};
|
||||
|
||||
struct telemetry_event_desc {
|
||||
struct __packed telemetry_event_desc {
|
||||
__u8 class;
|
||||
__le16 id;
|
||||
__u8 size;
|
||||
|
@ -399,7 +402,7 @@ struct telemetry_data_area_1 {
|
|||
__le16 minor_version;
|
||||
__u8 reserved1[4];
|
||||
__le64 timestamp;
|
||||
__u8 log_page_guid[16];
|
||||
__u8 log_page_guid[GUID_LEN];
|
||||
__u8 no_of_tps_supp;
|
||||
__u8 tps;
|
||||
__u8 reserved2[6];
|
||||
|
@ -428,13 +431,13 @@ struct telemetry_data_area_1 {
|
|||
#define MAX_NUM_FIFOS 16
|
||||
#define DA1_OFFSET 512
|
||||
#define DEFAULT_ASCII_STRING_SIZE 16
|
||||
#define SIZE_OF_VU_EVENT_ID 2
|
||||
|
||||
#define DEFAULT_TELEMETRY_BIN "telemetry.bin"
|
||||
#define DEFAULT_STRING_BIN "string.bin"
|
||||
#define DEFAULT_OUTPUT_FORMAT_JSON "json"
|
||||
|
||||
/* C9 Telemetry String Log Format Log Page */
|
||||
#define C9_GUID_LENGTH 16
|
||||
#define C9_TELEMETRY_STRING_LOG_ENABLE_OPCODE 0xC9
|
||||
#define C9_TELEMETRY_STR_LOG_LEN 432
|
||||
#define C9_TELEMETRY_STR_LOG_SIST_OFST 431
|
||||
|
@ -566,7 +569,7 @@ enum ocp_telemetry_debug_event_class_types {
|
|||
struct __packed telemetry_str_log_format {
|
||||
__u8 log_page_version;
|
||||
__u8 reserved1[15];
|
||||
__u8 log_page_guid[C9_GUID_LENGTH];
|
||||
__u8 log_page_guid[GUID_LEN];
|
||||
__le64 sls;
|
||||
__u8 reserved2[24];
|
||||
__le64 sits;
|
||||
|
@ -778,7 +781,7 @@ struct __packed nvme_ocp_telemetry_smart_extended
|
|||
__le64 lowest_permitted_firmware_revision; // Bytes 215:208
|
||||
__u8 reserved4[278]; // Bytes 493:216
|
||||
__le16 log_page_version; // Bytes 495:494
|
||||
__u8 log_page_guid[16]; // Bytes 511:496
|
||||
__u8 log_page_guid[GUID_LEN]; // Bytes 511:496
|
||||
};
|
||||
|
||||
struct __packed nvme_ocp_event_fifo_data
|
||||
|
@ -815,7 +818,7 @@ struct __packed nvme_ocp_header_in_da1
|
|||
__le16 minor_version; // Bytes 3:2
|
||||
__le32 reserved1; // Bytes 7:4
|
||||
__le64 time_stamp; // Bytes 15:8
|
||||
__u8 log_page_guid[16]; // Bytes 31:16
|
||||
__u8 log_page_guid[GUID_LEN]; // Bytes 31:16
|
||||
__u8 num_telemetry_profiles_supported; // Byte 32
|
||||
__u8 telemetry_profile_selected; // Byte 33
|
||||
__u8 reserved2[6]; // Bytes 39:34
|
||||
|
@ -856,30 +859,28 @@ struct __packed nvme_ocp_telemetry_event_descriptor
|
|||
struct __packed nvme_ocp_time_stamp_dbg_evt_class_format
|
||||
{
|
||||
__u8 time_stamp[DATA_SIZE_8]; // Bytes 11:4
|
||||
__le16 vu_event_identifier; // Bytes 13:12
|
||||
};
|
||||
|
||||
struct __packed nvme_ocp_pcie_dbg_evt_class_format
|
||||
{
|
||||
__u8 pCIeDebugEventData[DATA_SIZE_4]; // Bytes 7:4
|
||||
__le16 vu_event_identifier; // Bytes 9:8
|
||||
};
|
||||
|
||||
struct __packed nvme_ocp_nvme_dbg_evt_class_format
|
||||
{
|
||||
__u8 nvmeDebugEventData[DATA_SIZE_8]; // Bytes 11:4
|
||||
__le16 vu_event_identifier; // Bytes 13:12
|
||||
};
|
||||
|
||||
struct __packed nvme_ocp_common_dbg_evt_class_format
|
||||
{
|
||||
__le16 vu_event_identifier; // Bytes 5:4
|
||||
};
|
||||
|
||||
struct __packed nvme_ocp_media_wear_dbg_evt_class_format
|
||||
{
|
||||
__u8 currentMediaWear[DATA_SIZE_12]; // Bytes 15:4
|
||||
__le16 vu_event_identifier; // Bytes 17:16
|
||||
|
||||
};
|
||||
|
||||
struct __packed nvme_ocp_common_dbg_evt_class_vu_data
|
||||
{
|
||||
__le16 vu_event_identifier; // Bytes 5:4
|
||||
__u8 data[]; // Bytes N:6
|
||||
};
|
||||
|
||||
struct __packed nvme_ocp_statistic_snapshot_evt_class_format
|
||||
|
@ -918,7 +919,7 @@ struct __packed nvme_ocp_telemetry_string_header
|
|||
{
|
||||
__u8 version; //0:0
|
||||
__u8 reserved1[15]; //15:1
|
||||
__u8 guid[16]; //32:16
|
||||
__u8 guid[GUID_LEN]; //32:16
|
||||
__le64 string_log_size; //39:32
|
||||
__u8 reserved2[24]; //63:40
|
||||
__le64 sits; //71:64 Statistics Identifier String Table Start(SITS)
|
||||
|
@ -1226,3 +1227,4 @@ void parse_common_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descr
|
|||
void parse_media_wear_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
|
||||
struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
|
||||
struct json_object *pevent_fifos_object, FILE *fp);
|
||||
#endif /* OCP_TELEMETRY_DECODE_H */
|
||||
|
|
|
@ -134,7 +134,7 @@ int sedopal_set_key(struct opal_key *key)
|
|||
key->key_type = OPAL_INCLUDED;
|
||||
#endif
|
||||
key->key_len = strlen(pass);
|
||||
memcpy(key->key, pass, key->key_len);
|
||||
memcpy(key->key, pass, key->key_len + 1);
|
||||
|
||||
/*
|
||||
* If getting a new key, ask for it to be re-entered
|
||||
|
@ -446,9 +446,23 @@ int sedopal_cmd_password(int fd)
|
|||
if (sedopal_set_key(&new_pw.new_user_pw.opal_key) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* set admin1 password
|
||||
*/
|
||||
rc = ioctl(fd, IOC_OPAL_SET_PW, &new_pw);
|
||||
if (rc != 0)
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "Error: failed setting password - %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef IOC_OPAL_SET_SID_PW
|
||||
/*
|
||||
* set sid password
|
||||
*/
|
||||
rc = ioctl(fd, IOC_OPAL_SET_SID_PW, &new_pw);
|
||||
if (rc != 0)
|
||||
fprintf(stderr, "Error: failed setting SID password - %d\n", rc);
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*
|
||||
* Authors: leonardo.da.cunha@solidigm.com
|
||||
* shankaralingegowda.singonahalli@solidigm.com
|
||||
* haro.panosyan@solidigm.com
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
|
@ -136,7 +137,6 @@ struct ilog {
|
|||
int count;
|
||||
struct nvme_id_ctrl id_ctrl;
|
||||
enum nvme_telemetry_da max_da;
|
||||
__u32 max_tx;
|
||||
};
|
||||
|
||||
static void print_nlog_header(__u8 *buffer)
|
||||
|
@ -458,7 +458,6 @@ static int log_save(struct log *log, const char *parent_dir_name, const char *su
|
|||
_cleanup_fd_ int output = -1;
|
||||
char file_path[PATH_MAX] = {0};
|
||||
size_t bytes_remaining = 0;
|
||||
int err = 0;
|
||||
|
||||
ensure_dir(parent_dir_name, subdir_name);
|
||||
|
||||
|
@ -473,19 +472,14 @@ static int log_save(struct log *log, const char *parent_dir_name, const char *su
|
|||
while (bytes_remaining) {
|
||||
ssize_t bytes_written = write(output, buffer, bytes_remaining);
|
||||
|
||||
if (bytes_written < 0) {
|
||||
err = -errno;
|
||||
goto log_save_close_output;
|
||||
}
|
||||
if (bytes_written < 0)
|
||||
return -errno;
|
||||
|
||||
bytes_remaining -= bytes_written;
|
||||
buffer += bytes_written;
|
||||
}
|
||||
printf("Successfully wrote %s to %s\n", log->desc, file_path);
|
||||
|
||||
log_save_close_output:
|
||||
close(output);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ilog_dump_identify_page(struct ilog *ilog, struct log *cns, __u32 nsid)
|
||||
|
@ -527,11 +521,6 @@ static int ilog_ensure_dump_id_ctrl(struct ilog *ilog)
|
|||
if (ilog->id_ctrl.lpa & 0x40)
|
||||
ilog->max_da = NVME_TELEMETRY_DA_4;
|
||||
|
||||
/* assuming CAP.MPSMIN is zero minimum Memory Page Size is at least 4096 bytes */
|
||||
ilog->max_tx = (1 << ilog->id_ctrl.mdts) * NVME_LOG_PAGE_PDU_SIZE;
|
||||
if (ilog->max_tx > DRIVER_MAX_TX_256K)
|
||||
ilog->max_tx = DRIVER_MAX_TX_256K;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -539,7 +528,7 @@ static int ilog_dump_telemetry(struct ilog *ilog, enum log_type ttype)
|
|||
{
|
||||
int err = 0;
|
||||
enum nvme_telemetry_da da;
|
||||
size_t max_data_tx;
|
||||
size_t mdts;
|
||||
const char *file_name;
|
||||
struct nvme_feat_host_behavior prev = {0};
|
||||
bool host_behavior_changed = false;
|
||||
|
@ -550,7 +539,7 @@ static int ilog_dump_telemetry(struct ilog *ilog, enum log_type ttype)
|
|||
return err;
|
||||
|
||||
da = ilog->max_da;
|
||||
max_data_tx = ilog->max_tx;
|
||||
mdts = ilog->id_ctrl.mdts;
|
||||
|
||||
if (da == 4) {
|
||||
__u32 result;
|
||||
|
@ -569,16 +558,16 @@ static int ilog_dump_telemetry(struct ilog *ilog, enum log_type ttype)
|
|||
case HIT:
|
||||
file_name = "lid_0x07_lsp_0x01_lsi_0x0000.bin";
|
||||
log.desc = "Host Initiated Telemetry";
|
||||
err = nvme_get_telemetry_log(dev_fd(ilog->dev), true, false, false, max_data_tx, da,
|
||||
(struct nvme_telemetry_log **) &log.buffer,
|
||||
&log.buffer_size);
|
||||
err = sldgm_dynamic_telemetry(dev_fd(ilog->dev), true, false, false, mdts,
|
||||
da, (struct nvme_telemetry_log **) &log.buffer,
|
||||
&log.buffer_size);
|
||||
break;
|
||||
case CIT:
|
||||
file_name = "lid_0x08_lsp_0x00_lsi_0x0000.bin";
|
||||
log.desc = "Controller Initiated Telemetry";
|
||||
err = nvme_get_telemetry_log(dev_fd(ilog->dev), false, true, true, max_data_tx, da,
|
||||
(struct nvme_telemetry_log **) &log.buffer,
|
||||
&log.buffer_size);
|
||||
err = sldgm_dynamic_telemetry(dev_fd(ilog->dev), false, true, true, mdts,
|
||||
da, (struct nvme_telemetry_log **) &log.buffer,
|
||||
&log.buffer_size);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -597,14 +586,17 @@ static int ilog_dump_telemetry(struct ilog *ilog, enum log_type ttype)
|
|||
|
||||
static int ilog_dump_identify_pages(struct ilog *ilog)
|
||||
{
|
||||
struct nvme_ns_list ns_list;
|
||||
struct nvme_ns_list ns_attached_list;
|
||||
struct nvme_ns_list ns_allocated_list;
|
||||
__u32 j = 0;
|
||||
|
||||
struct log identify_base_list[] = {
|
||||
{NVME_IDENTIFY_CNS_NS_ACTIVE_LIST, "Id Active Namespace ID list",
|
||||
sizeof(ns_list), (__u8 *) &ns_list},
|
||||
sizeof(ns_attached_list), (__u8 *) &ns_attached_list},
|
||||
{NVME_IDENTIFY_CNS_NVMSET_LIST, "Id NVM Set List"},
|
||||
{NVME_IDENTIFY_CNS_CSI_CTRL, "Id I/O Command Set specific"},
|
||||
{NVME_IDENTIFY_CNS_ALLOCATED_NS_LIST, "Id Allocated Namespace ID list"},
|
||||
{NVME_IDENTIFY_CNS_ALLOCATED_NS_LIST, "Id Allocated Namespace ID list",
|
||||
sizeof(ns_allocated_list), (__u8 *) &ns_allocated_list},
|
||||
{NVME_IDENTIFY_CNS_CTRL_LIST, "Id Controller List"}
|
||||
};
|
||||
struct log identify_ns_required_list[] = {
|
||||
|
@ -613,10 +605,12 @@ static int ilog_dump_identify_pages(struct ilog *ilog)
|
|||
{NVME_IDENTIFY_CNS_CSI_NS, "Id Namespace ID I/O Command Set specific"},
|
||||
{NVME_IDENTIFY_CNS_CSI_INDEPENDENT_ID_NS,
|
||||
"I/O Command Set Independent Identify Namespace Data"},
|
||||
{NVME_IDENTIFY_CNS_ALLOCATED_NS, "Id Namespace data "},
|
||||
{NVME_IDENTIFY_CNS_NS_CTRL_LIST, "Id Namespace Id Controller List"},
|
||||
};
|
||||
|
||||
struct log allocated = {NVME_IDENTIFY_CNS_ALLOCATED_NS, "Allocated Namespace Data",
|
||||
NVME_IDENTIFY_DATA_SIZE, NULL};
|
||||
|
||||
ilog_ensure_dump_id_ctrl(ilog);
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(identify_base_list); i++) {
|
||||
|
@ -626,10 +620,10 @@ static int ilog_dump_identify_pages(struct ilog *ilog)
|
|||
ilog->count++;
|
||||
}
|
||||
|
||||
while (ns_list.ns[j]) {
|
||||
while (ns_attached_list.ns[j]) {
|
||||
for (int i = 0; i < ARRAY_SIZE(identify_ns_required_list); i++) {
|
||||
int err = ilog_dump_identify_page(ilog, &identify_ns_required_list[i],
|
||||
ns_list.ns[j]);
|
||||
ns_attached_list.ns[j]);
|
||||
|
||||
if (err == 0)
|
||||
ilog->count++;
|
||||
|
@ -637,6 +631,15 @@ static int ilog_dump_identify_pages(struct ilog *ilog)
|
|||
j++;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
while (ns_allocated_list.ns[j]) {
|
||||
int err = ilog_dump_identify_page(ilog, &allocated, ns_allocated_list.ns[j]);
|
||||
|
||||
if (err == 0)
|
||||
ilog->count++;
|
||||
j++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -740,6 +743,7 @@ static int ilog_dump_pel(struct ilog *ilog)
|
|||
void *pevent_log_full;
|
||||
int err;
|
||||
struct nvme_get_log_args args;
|
||||
size_t max_data_tx;
|
||||
|
||||
_cleanup_free_ struct nvme_persistent_event_log *pevent = NULL;
|
||||
|
||||
|
@ -785,7 +789,13 @@ static int ilog_dump_pel(struct ilog *ilog)
|
|||
.rae = false,
|
||||
.ot = false,
|
||||
};
|
||||
err = nvme_get_log_page(dev_fd(ilog->dev), ilog->max_tx, &args);
|
||||
|
||||
max_data_tx = (1 << ilog->id_ctrl.mdts) * NVME_LOG_PAGE_PDU_SIZE;
|
||||
do {
|
||||
err = nvme_get_log_page(dev_fd(ilog->dev), max_data_tx, &args);
|
||||
max_data_tx /= 2;
|
||||
} while (err == -EPERM && max_data_tx >= NVME_LOG_PAGE_PDU_SIZE);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "cmd.h"
|
||||
|
||||
#define SOLIDIGM_PLUGIN_VERSION "1.6"
|
||||
#define SOLIDIGM_PLUGIN_VERSION "1.8"
|
||||
|
||||
PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_VERSION),
|
||||
COMMAND_LIST(
|
||||
|
|
|
@ -144,6 +144,8 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc
|
|||
|
||||
if (!cfg.is_input_file) {
|
||||
size_t max_data_tx;
|
||||
size_t power2;
|
||||
__u8 mdts = 0;
|
||||
|
||||
err = nvme_get_telemetry_max(dev_fd(dev), NULL, &max_data_tx);
|
||||
if (err < 0) {
|
||||
|
@ -155,11 +157,14 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc
|
|||
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;
|
||||
power2 = max_data_tx / NVME_LOG_PAGE_PDU_SIZE;
|
||||
while (power2 && !(1 & power2)) {
|
||||
power2 >>= 1;
|
||||
mdts++;
|
||||
}
|
||||
|
||||
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);
|
||||
err = sldgm_dynamic_telemetry(dev_fd(dev), cfg.host_gen, cfg.ctrl_init, true,
|
||||
mdts, cfg.data_area, &tl.log, &tl.log_size);
|
||||
if (err < 0) {
|
||||
SOLIDIGM_LOG_WARNING("get-telemetry-log: %s",
|
||||
nvme_strerror(errno));
|
||||
|
|
|
@ -37,3 +37,19 @@ int sldgm_get_uuid_index(struct nvme_dev *dev, __u8 *index)
|
|||
|
||||
return sldgm_find_uuid_index(&uuid_list, index);
|
||||
}
|
||||
|
||||
int sldgm_dynamic_telemetry(int dev_fd, bool create, bool ctrl, bool log_page, __u8 mtds,
|
||||
enum nvme_telemetry_da da, struct nvme_telemetry_log **log_buffer,
|
||||
size_t *log_buffer_size)
|
||||
{
|
||||
int err;
|
||||
size_t max_data_tx = (1 << mtds) * NVME_LOG_PAGE_PDU_SIZE;
|
||||
|
||||
do {
|
||||
err = nvme_get_telemetry_log(dev_fd, create, ctrl, log_page, max_data_tx, da,
|
||||
log_buffer, log_buffer_size);
|
||||
max_data_tx /= 2;
|
||||
create = false;
|
||||
} while (err == -EPERM && max_data_tx >= NVME_LOG_PAGE_PDU_SIZE);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
|
||||
#include "nvme.h"
|
||||
|
||||
#define DRIVER_MAX_TX_256K (256 * 1024)
|
||||
|
||||
int sldgm_find_uuid_index(struct nvme_id_uuid_list *uuid_list, __u8 *index);
|
||||
int sldgm_get_uuid_index(struct nvme_dev *dev, __u8 *index);
|
||||
int sldgm_dynamic_telemetry(int dev_fd, bool create, bool ctrl, bool log_page, __u8 mtds,
|
||||
enum nvme_telemetry_da da, struct nvme_telemetry_log **log_buffer,
|
||||
size_t *log_buffer_size);
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
|
||||
#define LID 0xf9
|
||||
#define FID 0xf1
|
||||
#define WLT2MS 25000
|
||||
#define WLT2US 25
|
||||
#define WLT2MS (WLT2US * 1000)
|
||||
#define MAX_WORKLOAD_LOG_ENTRIES 126
|
||||
#define MAX_WORKLOAD_LOG_ENTRY_SIZE 32
|
||||
#define MAX_FIELDS 15
|
||||
|
@ -174,11 +175,11 @@ union WorkloadLogEnable {
|
|||
__u32 contentGroup : 4; // content group select
|
||||
__u32 stopCount : 12;// event limit,if<>0,stop tracker after stopCount events
|
||||
__u32 eventDumpEnable : 1; // trigger event dump enable
|
||||
} field;
|
||||
};
|
||||
__u32 dword;
|
||||
};
|
||||
|
||||
struct workloadLogHeader {
|
||||
struct workloadLog { // Full WL Log Structure
|
||||
__u16 majorVersion; // Major Version
|
||||
__u16 minorVersion; // Minor Version
|
||||
__u32 workloadLogCount; // Number of Entries in the Workload Log
|
||||
|
@ -187,14 +188,9 @@ struct workloadLogHeader {
|
|||
__u32 samplePeriodInMilliseconds; // Sample Period In Milliseconds
|
||||
__u64 timestamp_lastEntry; // Timestamp for the last full entry
|
||||
__u64 timestamp_triggered; // Timestamp at the point of trigger
|
||||
__u32 trackerEnable; // Workload trigger and enable settings
|
||||
union WorkloadLogEnable config; // Workload trigger and enable settings
|
||||
__u32 triggerthreshold; // Trigger threshold
|
||||
__u32 triggeredValue; // Actual value fired the trigger
|
||||
};
|
||||
|
||||
|
||||
struct workloadLog { // Full WL Log Structure
|
||||
struct workloadLogHeader header;
|
||||
__u8 entry[MAX_WORKLOAD_LOG_ENTRIES][MAX_WORKLOAD_LOG_ENTRY_SIZE];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
@ -202,24 +198,26 @@ struct workloadLog { // Full WL Log Structure
|
|||
struct wltracker {
|
||||
int fd;
|
||||
struct workloadLog workload_log;
|
||||
size_t entry_count;
|
||||
size_t poll_count;
|
||||
bool show_wall_timestamp;
|
||||
__u64 us_epoch_ssd_delta;
|
||||
unsigned int verbose;
|
||||
__u64 start_time_us;
|
||||
__u64 run_time_us;
|
||||
bool disable;
|
||||
};
|
||||
|
||||
static void wltracker_print_field_names(struct wltracker *wlt)
|
||||
{
|
||||
struct workloadLog *log = &wlt->workload_log;
|
||||
__u8 cnt = log->header.workloadLogCount;
|
||||
union WorkloadLogEnable workloadEnable = (union WorkloadLogEnable)log->header.trackerEnable;
|
||||
__u8 content_group = workloadEnable.field.contentGroup;
|
||||
|
||||
if (cnt == 0)
|
||||
if (log->workloadLogCount == 0)
|
||||
return;
|
||||
|
||||
printf("%-16s", "timestamp");
|
||||
|
||||
for (int i = 0 ; i < MAX_FIELDS; i++) {
|
||||
struct field f = group_fields[content_group][i];
|
||||
struct field f = group_fields[log->config.contentGroup][i];
|
||||
|
||||
if (f.size == 0)
|
||||
break;
|
||||
|
@ -228,8 +226,11 @@ static void wltracker_print_field_names(struct wltracker *wlt)
|
|||
printf("%s ", f.name);
|
||||
}
|
||||
|
||||
if (wlt->show_wall_timestamp)
|
||||
printf("%-*s", (int)sizeof("YYYY-MM-DD-hh:mm:ss.uuuuuu"), "wall-time");
|
||||
|
||||
if (wlt->verbose > 1)
|
||||
printf("%s", "entry#");
|
||||
printf("%s", "entry# ");
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
@ -237,35 +238,59 @@ static void wltracker_print_field_names(struct wltracker *wlt)
|
|||
static void wltracker_print_header(struct wltracker *wlt)
|
||||
{
|
||||
struct workloadLog *log = &wlt->workload_log;
|
||||
__u8 cnt = log->header.workloadLogCount;
|
||||
union WorkloadLogEnable workloadEnable = (union WorkloadLogEnable)log->header.trackerEnable;
|
||||
__u8 content_group = workloadEnable.field.contentGroup;
|
||||
|
||||
printf("%-20s %u.%u\n", "Log page version:", le16_to_cpu(log->header.majorVersion),
|
||||
le16_to_cpu(log->header.minorVersion));
|
||||
printf("%-20s %u\n", "Sample period(ms):",
|
||||
le32_to_cpu(log->header.samplePeriodInMilliseconds));
|
||||
printf("%-20s %lu\n", "timestamp_lastEntry:",
|
||||
le64_to_cpu(log->header.timestamp_lastEntry) / WLT2MS);
|
||||
printf("%-20s %lu\n", "timestamp_triggered:",
|
||||
le64_to_cpu(log->header.timestamp_triggered/1000));
|
||||
printf("%-20s 0x%x\n", "trackerEnable:", le32_to_cpu(log->header.trackerEnable));
|
||||
printf("%-20s %u\n", "Triggerthreshold:",
|
||||
le32_to_cpu(log->header.triggerthreshold));
|
||||
printf("%-20s %u\n", "ValueTriggered:", le32_to_cpu(log->header.triggeredValue));
|
||||
printf("%-20s %s\n", "Tracker Type:", trk_types[content_group]);
|
||||
printf("%-30s %u\n", "Total workload log entries:", le16_to_cpu(cnt));
|
||||
printf("%-20s %ld\n\n", "Sample count:", wlt->entry_count);
|
||||
if (wlt->entry_count != 0)
|
||||
printf("%-24s %u.%u\n", "Log page version:", le16_to_cpu(log->majorVersion),
|
||||
le16_to_cpu(log->minorVersion));
|
||||
printf("%-24s %u\n", "Sample period(ms):", le32_to_cpu(log->samplePeriodInMilliseconds));
|
||||
printf("%-24s %lu\n", "timestamp_lastChange:", le64_to_cpu(log->timestamp_lastEntry));
|
||||
printf("%-24s %lu\n", "timestamp_triggered:", le64_to_cpu(log->timestamp_triggered));
|
||||
printf("%-24s 0x%x\n", "config:", le32_to_cpu(log->config.dword));
|
||||
printf("%-24s %u\n", "Triggerthreshold:", le32_to_cpu(log->triggerthreshold));
|
||||
printf("%-24s %u\n", "ValueTriggered:", le32_to_cpu(log->triggeredValue));
|
||||
printf("%-24s %s\n", "Tracker Type:", trk_types[log->config.contentGroup]);
|
||||
printf("%-24s %u\n", "Total log page entries:", le32_to_cpu(log->workloadLogCount));
|
||||
printf("%-24s %u\n", "Trigger count:", log->triggeredEvents);
|
||||
if (wlt->verbose > 1)
|
||||
printf("%-24s %ld\n", "Poll count:", wlt->poll_count);
|
||||
if (wlt->poll_count != 0)
|
||||
wltracker_print_field_names(wlt);
|
||||
}
|
||||
|
||||
__u64 micros_id(clockid_t clk_id)
|
||||
{
|
||||
struct timespec ts;
|
||||
__u64 us;
|
||||
|
||||
clock_gettime(clk_id, &ts);
|
||||
us = (((__u64)ts.tv_sec)*1000000) + (((__u64)ts.tv_nsec)/1000);
|
||||
return us;
|
||||
}
|
||||
|
||||
__u64 micros(void)
|
||||
{
|
||||
return micros_id(CLOCK_REALTIME);
|
||||
}
|
||||
|
||||
int wltracker_config(struct wltracker *wlt, union WorkloadLogEnable *we)
|
||||
{
|
||||
struct nvme_set_features_args args = {
|
||||
.args_size = sizeof(args),
|
||||
.fd = wlt->fd,
|
||||
.fid = FID,
|
||||
.cdw11 = we->dword,
|
||||
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
|
||||
};
|
||||
|
||||
return nvme_set_features(&args);
|
||||
}
|
||||
|
||||
static int wltracker_show_newer_entries(struct wltracker *wlt)
|
||||
{
|
||||
struct workloadLog *log = &wlt->workload_log;
|
||||
__u8 cnt;
|
||||
__u8 content_group;
|
||||
static __u64 last_timestamp_ms;
|
||||
static __u64 last_timestamp_us;
|
||||
__u64 timestamp_us = 0;
|
||||
__u64 timestamp = 0;
|
||||
union WorkloadLogEnable workloadEnable;
|
||||
|
||||
|
@ -281,29 +306,75 @@ static int wltracker_show_newer_entries(struct wltracker *wlt)
|
|||
if (wlt->verbose)
|
||||
wltracker_print_header(wlt);
|
||||
|
||||
cnt = log->header.workloadLogCount;
|
||||
workloadEnable = (union WorkloadLogEnable)log->header.trackerEnable;
|
||||
content_group = workloadEnable.field.contentGroup;
|
||||
cnt = log->workloadLogCount;
|
||||
workloadEnable = log->config;
|
||||
content_group = workloadEnable.contentGroup;
|
||||
|
||||
if (cnt == 0) {
|
||||
nvme_show_error("Warning : No valid workload log data\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
timestamp = (le64_to_cpu(log->header.timestamp_lastEntry) / WLT2MS) -
|
||||
(log->header.samplePeriodInMilliseconds * (cnt - 1));
|
||||
timestamp_us = (le64_to_cpu(log->timestamp_lastEntry) / WLT2US) -
|
||||
(log->samplePeriodInMilliseconds * 1000 * (cnt - 1));
|
||||
timestamp = le64_to_cpu(log->timestamp_lastEntry) -
|
||||
(log->samplePeriodInMilliseconds * WLT2MS * (cnt - 1));
|
||||
|
||||
if (wlt->poll_count++ == 0) {
|
||||
__u64 tle = log->timestamp_lastEntry;
|
||||
__u8 tracker_enable_bit = workloadEnable.trackerEnable;
|
||||
|
||||
if (wlt->entry_count == 0)
|
||||
wltracker_print_field_names(wlt);
|
||||
|
||||
if (wlt->show_wall_timestamp &&
|
||||
((log->triggeredEvents && wlt->disable) || !tracker_enable_bit)) {
|
||||
// retrieve fresh timestamp to reconstruct wall time
|
||||
union WorkloadLogEnable we = log->config;
|
||||
|
||||
if (wlt->verbose > 1) {
|
||||
printf("Temporarily enabling tracker to find current timestamp\n");
|
||||
printf("Original config value: 0x%08x\n", we.dword);
|
||||
}
|
||||
we.trackerEnable = true;
|
||||
we.triggerEnable = false;
|
||||
we.sampleTime = 1;
|
||||
|
||||
if (wlt->verbose > 1)
|
||||
printf("Modified config value: 0x%08x\n", we.dword);
|
||||
|
||||
err = wltracker_config(wlt, &we);
|
||||
usleep(1000);
|
||||
if (!err) {
|
||||
struct workloadLog tl;
|
||||
|
||||
err = nvme_get_log_simple(wlt->fd, LID, sizeof(tl), &tl);
|
||||
tle = tl.timestamp_lastEntry;
|
||||
}
|
||||
if (err) {
|
||||
nvme_show_error("Failed to retrieve latest SSD timestamp");
|
||||
} else {
|
||||
// Restore original config , but don't reenable trigger
|
||||
we = log->config;
|
||||
we.triggerEnable = false;
|
||||
err = wltracker_config(wlt, &we);
|
||||
if (wlt->verbose > 1)
|
||||
printf("Restored config value: 0x%08x\n",
|
||||
we.dword);
|
||||
}
|
||||
}
|
||||
wlt->us_epoch_ssd_delta = (micros() - le64_to_cpu(tle) / WLT2US);
|
||||
}
|
||||
|
||||
for (int i = cnt - 1; i >= 0; i--) {
|
||||
int offset = 0;
|
||||
__u8 *entry = (__u8 *) &log->entry[i];
|
||||
bool is_old = timestamp <= last_timestamp_ms;
|
||||
// allow 10% sample skew
|
||||
bool is_old = timestamp_us <= last_timestamp_us +
|
||||
(log->samplePeriodInMilliseconds * 100);
|
||||
|
||||
if (is_old) {
|
||||
timestamp += log->header.samplePeriodInMilliseconds;
|
||||
timestamp_us += (log->samplePeriodInMilliseconds * 1000);
|
||||
timestamp += log->samplePeriodInMilliseconds * WLT2MS;
|
||||
continue;
|
||||
}
|
||||
printf("%-16llu", timestamp);
|
||||
|
@ -312,8 +383,21 @@ static int wltracker_show_newer_entries(struct wltracker *wlt)
|
|||
struct field f = group_fields[content_group][j];
|
||||
|
||||
if (f.size == 0) {
|
||||
if (wlt->show_wall_timestamp) {
|
||||
time_t epoch_ts_us = timestamp_us +
|
||||
wlt->us_epoch_ssd_delta;
|
||||
time_t ts_s = epoch_ts_us / 1000000;
|
||||
struct tm ts = *localtime(&ts_s);
|
||||
char buf[80];
|
||||
|
||||
strftime(buf, sizeof(buf), "%Y-%m-%d-%H:%M:%S", &ts);
|
||||
printf("%s.%06" PRIu64 " ", buf,
|
||||
(uint64_t)(epoch_ts_us % 1000000ULL));
|
||||
}
|
||||
|
||||
if (wlt->verbose > 1)
|
||||
printf("%-*i", (int)sizeof("entry#"), i);
|
||||
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
|
@ -337,28 +421,24 @@ static int wltracker_show_newer_entries(struct wltracker *wlt)
|
|||
|
||||
printf("%-*u ", (int)strlen(f.name), val);
|
||||
}
|
||||
wlt->entry_count++;
|
||||
timestamp += log->header.samplePeriodInMilliseconds;
|
||||
timestamp_us += (log->samplePeriodInMilliseconds * 1000);
|
||||
timestamp += log->samplePeriodInMilliseconds * WLT2MS;
|
||||
}
|
||||
last_timestamp_ms = log->header.timestamp_lastEntry / WLT2MS;
|
||||
last_timestamp_us = log->timestamp_lastEntry / WLT2US;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wltracker_config(struct wltracker *wlt, union WorkloadLogEnable *we)
|
||||
void wltracker_run_time_update(struct wltracker *wlt)
|
||||
{
|
||||
struct nvme_set_features_args args = {
|
||||
.args_size = sizeof(args),
|
||||
.fd = wlt->fd,
|
||||
.fid = FID,
|
||||
.cdw11 = we->dword,
|
||||
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
|
||||
};
|
||||
|
||||
return nvme_set_features(&args);
|
||||
wlt->run_time_us = micros() - wlt->start_time_us;
|
||||
if (wlt->verbose > 0)
|
||||
printf("run_time: %lluus\n", wlt->run_time_us);
|
||||
}
|
||||
|
||||
static int stricmp(char const *a, char const *b)
|
||||
{
|
||||
if (!a || !b)
|
||||
return 1;
|
||||
for (; *a || *b; a++, b++)
|
||||
if (tolower((unsigned char)*a) != tolower((unsigned char)*b))
|
||||
return 1;
|
||||
|
@ -367,14 +447,14 @@ static int stricmp(char const *a, char const *b)
|
|||
|
||||
static int find_option(char const *list[], int size, const char *val)
|
||||
{
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (!stricmp(val, list[i]))
|
||||
return i;
|
||||
}
|
||||
return -EINVAL;
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (!stricmp(val, list[i]))
|
||||
return i;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void join(char *dest, char const *list[], size_t list_size)
|
||||
static void join_options(char *dest, char const *list[], size_t list_size)
|
||||
{
|
||||
strcat(dest, list[0]);
|
||||
for (int i = 1; i < list_size; i++) {
|
||||
|
@ -383,14 +463,26 @@ static void join(char *dest, char const *list[], size_t list_size)
|
|||
}
|
||||
}
|
||||
|
||||
__u64 micros(void)
|
||||
static int find_field(struct field *fields, const char *val)
|
||||
{
|
||||
struct timespec ts;
|
||||
__u64 us;
|
||||
for (int i = 0; i < MAX_FIELDS; i++) {
|
||||
if (!stricmp(val, fields[i].name))
|
||||
return i;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
|
||||
us = (((__u64)ts.tv_sec)*1000000) + (((__u64)ts.tv_nsec)/1000);
|
||||
return us;
|
||||
static void join_fields(char *dest, struct field *fields)
|
||||
{
|
||||
strcat(dest, fields[0].name);
|
||||
for (int i = 1; i < MAX_FIELDS; i++) {
|
||||
char *name = fields[i].name;
|
||||
|
||||
if (name) {
|
||||
strcat(dest, "|");
|
||||
strcat(dest, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int sldgm_get_workload_tracker(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
|
@ -406,9 +498,7 @@ int sldgm_get_workload_tracker(int argc, char **argv, struct command *cmd, struc
|
|||
"Samples (1 to 126) to wait for extracting data. Default 100 samples";
|
||||
char type_options[80] = {0};
|
||||
char sample_options[80] = {0};
|
||||
__u64 us_start;
|
||||
__u64 run_time_us;
|
||||
__u64 elapsed_run_time_us = 0;
|
||||
__u64 stop_time_us;
|
||||
__u64 next_sample_us = 0;
|
||||
int opt;
|
||||
int err;
|
||||
|
@ -416,29 +506,43 @@ int sldgm_get_workload_tracker(int argc, char **argv, struct command *cmd, struc
|
|||
struct config {
|
||||
bool enable;
|
||||
bool disable;
|
||||
bool trigger_on_delta;
|
||||
bool trigger_on_latency;
|
||||
const char *tracker_type;
|
||||
const char *sample_time;
|
||||
int run_time_s;
|
||||
__u32 run_time_s;
|
||||
int flush_frequency;
|
||||
char *trigger_field;
|
||||
__u32 trigger_treshold;
|
||||
};
|
||||
|
||||
struct config cfg = {
|
||||
.sample_time = samplet[0],
|
||||
.flush_frequency = 100,
|
||||
.tracker_type = trk_types[0],
|
||||
.trigger_field = "",
|
||||
};
|
||||
|
||||
join(type_options, trk_types, ARRAY_SIZE(trk_types));
|
||||
join(sample_options, samplet, ARRAY_SIZE(samplet));
|
||||
join_options(type_options, trk_types, ARRAY_SIZE(trk_types));
|
||||
join_options(sample_options, samplet, ARRAY_SIZE(samplet));
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_FLAG("enable", 'e', &cfg.enable, "tracker enable"),
|
||||
OPT_FLAG("disable", 'd', &cfg.disable, "tracker disable"),
|
||||
OPT_STRING("sample-time", 's', sample_options, &cfg.sample_time, sample_interval),
|
||||
OPT_STRING("type", 't', type_options, &cfg.tracker_type, "Tracker type"),
|
||||
OPT_INT("run-time", 'r', &cfg.run_time_s, run_time),
|
||||
OPT_UINT("run-time", 'r', &cfg.run_time_s, run_time),
|
||||
OPT_INT("flush-freq", 'f', &cfg.flush_frequency, flush_frequency),
|
||||
OPT_INCR("verbose", 'v', &wlt.verbose, "Increase logging verbosity"),
|
||||
OPT_FLAG("wall-clock", 'w', &wlt.show_wall_timestamp,
|
||||
"Logs current wall timestamp when entry was retrieved"),
|
||||
OPT_STR("trigger-field", 'T', &cfg.trigger_field, "Field name to stop trigger on"),
|
||||
OPT_UINT("trigger-threshold", 'V', &cfg.trigger_treshold,
|
||||
"Field value to trigger stop sampling"),
|
||||
OPT_FLAG("trigger-on-delta", 'D', &cfg.trigger_on_delta,
|
||||
"Trigger on delta to stop sampling"),
|
||||
OPT_FLAG("trigger-on-latency", 'L', &cfg.trigger_on_latency,
|
||||
"Use latency tracker to trigger stop sampling"),
|
||||
OPT_INCR("verbose", 'v', &wlt.verbose, "Increase logging verbosity"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
|
@ -460,23 +564,59 @@ int sldgm_get_workload_tracker(int argc, char **argv, struct command *cmd, struc
|
|||
cfg.sample_time, sample_options);
|
||||
return -EINVAL;
|
||||
}
|
||||
we.field.sampleTime = opt;
|
||||
we.sampleTime = opt;
|
||||
|
||||
opt = find_option(trk_types, ARRAY_SIZE(trk_types), cfg.tracker_type);
|
||||
if (opt < 0) {
|
||||
nvme_show_error("Invalid tracker type: %s. Valid types: %s",
|
||||
nvme_show_error("Invalid tracker type: \"%s\". Valid types: %s",
|
||||
cfg.tracker_type, type_options);
|
||||
return -EINVAL;
|
||||
}
|
||||
we.field.contentGroup = opt;
|
||||
we.contentGroup = opt;
|
||||
if (argconfig_parse_seen(opts, "trigger-field")) {
|
||||
int field_pos = find_field(group_fields[opt], cfg.trigger_field);
|
||||
int field_offset = 0;
|
||||
|
||||
if (field_pos < 0) {
|
||||
char field_options[256];
|
||||
|
||||
join_fields(field_options, group_fields[opt]);
|
||||
nvme_show_error(
|
||||
"Invalid field name: %s. For type: \"%s\", valid fields are: %s",
|
||||
cfg.trigger_field, cfg.tracker_type, field_options);
|
||||
return -EINVAL;
|
||||
}
|
||||
for (int i = 0; i < field_pos; i++)
|
||||
field_offset += group_fields[opt][i].size;
|
||||
|
||||
we.triggerDwordIndex += field_offset / 4;
|
||||
we.triggerSize =
|
||||
group_fields[opt][field_pos].size ==
|
||||
4 ? 3 : group_fields[opt][field_pos].size;
|
||||
we.triggerByteWordIndex = field_offset % 4 /
|
||||
group_fields[opt][field_pos].size;
|
||||
we.triggerEnable = true;
|
||||
we.triggerDelta = cfg.trigger_on_delta;
|
||||
we.triggerSynchronous = !cfg.trigger_on_latency;
|
||||
err = nvme_set_features_data(wlt.fd, 0xf5, 0, cfg.trigger_treshold, 0, 0, NULL,
|
||||
NULL);
|
||||
if (err < 0) {
|
||||
nvme_show_error("Trigger Threshold set-feature: %s", nvme_strerror(errno));
|
||||
return err;
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg.enable && cfg.disable) {
|
||||
nvme_show_error("Can't enable disable simultaneously");
|
||||
return -EINVAL;
|
||||
}
|
||||
wlt.disable = cfg.disable;
|
||||
|
||||
if (cfg.enable || cfg.disable) {
|
||||
we.field.trackerEnable = cfg.enable;
|
||||
if (cfg.enable) {
|
||||
we.trackerEnable = true;
|
||||
err = wltracker_config(&wlt, &we);
|
||||
if (err < 0) {
|
||||
nvme_show_error("tracker set-feature: %s", nvme_strerror(errno));
|
||||
|
@ -487,17 +627,12 @@ int sldgm_get_workload_tracker(int argc, char **argv, struct command *cmd, struc
|
|||
}
|
||||
}
|
||||
|
||||
if (cfg.disable && !cfg.enable) {
|
||||
printf("Tracker disabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
us_start = micros();
|
||||
run_time_us = cfg.run_time_s * 1000000;
|
||||
while (elapsed_run_time_us < run_time_us) {
|
||||
wlt.start_time_us = micros();
|
||||
stop_time_us = cfg.run_time_s * 1000000;
|
||||
while (wlt.run_time_us < stop_time_us) {
|
||||
__u64 interval;
|
||||
__u64 elapsed;
|
||||
__u64 prev_elapsed_run_time_us = elapsed_run_time_us;
|
||||
__u64 prev_run_time_us = wlt.run_time_us;
|
||||
|
||||
err = wltracker_show_newer_entries(&wlt);
|
||||
|
||||
|
@ -505,28 +640,50 @@ int sldgm_get_workload_tracker(int argc, char **argv, struct command *cmd, struc
|
|||
nvme_show_status(err);
|
||||
return err;
|
||||
}
|
||||
interval = ((__u64)wlt.workload_log.header.samplePeriodInMilliseconds) * 1000 *
|
||||
interval = ((__u64)wlt.workload_log.samplePeriodInMilliseconds) * 1000 *
|
||||
cfg.flush_frequency;
|
||||
next_sample_us += interval;
|
||||
elapsed_run_time_us = micros() - us_start;
|
||||
elapsed = elapsed_run_time_us - prev_elapsed_run_time_us;
|
||||
if (wlt.verbose > 1)
|
||||
printf("elapsed_run_time: %lluus\n", elapsed_run_time_us);
|
||||
wltracker_run_time_update(&wlt);
|
||||
|
||||
if (wlt.workload_log.triggeredEvents)
|
||||
break;
|
||||
elapsed = wlt.run_time_us - prev_run_time_us;
|
||||
if (interval > elapsed) {
|
||||
__u64 period_us = min(next_sample_us - elapsed_run_time_us,
|
||||
run_time_us - elapsed_run_time_us);
|
||||
__u64 period_us = min(next_sample_us - wlt.run_time_us,
|
||||
stop_time_us - wlt.run_time_us);
|
||||
if (wlt.verbose > 1)
|
||||
printf("Sleeping %lluus..\n", period_us);
|
||||
usleep(period_us);
|
||||
wltracker_run_time_update(&wlt);
|
||||
}
|
||||
elapsed_run_time_us = micros() - us_start;
|
||||
}
|
||||
|
||||
err = wltracker_show_newer_entries(&wlt);
|
||||
if (!wlt.workload_log.triggeredEvents) {
|
||||
err = wltracker_show_newer_entries(&wlt);
|
||||
wltracker_run_time_update(&wlt);
|
||||
}
|
||||
|
||||
elapsed_run_time_us = micros() - us_start;
|
||||
if (wlt.verbose > 0)
|
||||
printf("elapsed_run_time: %lluus\n", elapsed_run_time_us);
|
||||
if (cfg.disable) {
|
||||
union WorkloadLogEnable we2 = wlt.workload_log.config;
|
||||
|
||||
if (wlt.verbose > 1)
|
||||
printf("Original config value: 0x%08x\n", we2.dword);
|
||||
|
||||
we2.trackerEnable = false;
|
||||
we2.triggerEnable = false;
|
||||
err = wltracker_config(&wlt, &we2);
|
||||
if (err < 0) {
|
||||
nvme_show_error("tracker set-feature: %s", nvme_strerror(errno));
|
||||
return err;
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
return err;
|
||||
}
|
||||
if (wlt.verbose > 1)
|
||||
printf("Modified config value: 0x%08x\n", we2.dword);
|
||||
printf("Tracker disabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
#define WDC_NVME_SN650_DEV_ID_3 0x2720
|
||||
#define WDC_NVME_SN650_DEV_ID_4 0x2721
|
||||
#define WDC_NVME_SN655_DEV_ID 0x2722
|
||||
#define WDC_NVME_SN655_DEV_ID_1 0x2723
|
||||
#define WDC_NVME_SN860_DEV_ID 0x2730
|
||||
#define WDC_NVME_SN660_DEV_ID 0x2704
|
||||
#define WDC_NVME_SN560_DEV_ID_1 0x2712
|
||||
|
@ -86,6 +87,8 @@
|
|||
#define WDC_NVME_SN560_DEV_ID_3 0x2714
|
||||
#define WDC_NVME_SN861_DEV_ID 0x2750
|
||||
#define WDC_NVME_SN861_DEV_ID_1 0x2751
|
||||
#define WDC_NVME_SN861_DEV_ID_2 0x2752
|
||||
#define WDC_NVME_SNTMP_DEV_ID 0x2761
|
||||
|
||||
/* This id's are no longer supported, delete ?? */
|
||||
#define WDC_NVME_SN550_DEV_ID 0x2708
|
||||
|
@ -138,6 +141,10 @@
|
|||
#define WDC_NVME_SN810_DEV_ID 0x5011
|
||||
#define WDC_NVME_SN820CL_DEV_ID 0x5037
|
||||
|
||||
#define WDC_NVME_SN5100S_DEV_ID_1 0x5061
|
||||
#define WDC_NVME_SN5100S_DEV_ID_2 0x5062
|
||||
#define WDC_NVME_SN5100S_DEV_ID_3 0x5063
|
||||
|
||||
#define WDC_DRIVE_CAP_CAP_DIAG 0x0000000000000001
|
||||
#define WDC_DRIVE_CAP_INTERNAL_LOG 0x0000000000000002
|
||||
#define WDC_DRIVE_CAP_C1_LOG_PAGE 0x0000000000000004
|
||||
|
@ -1530,7 +1537,8 @@ static int wdc_get_vendor_id(struct nvme_dev *dev, uint32_t *vendor_id)
|
|||
static bool wdc_is_sn861(__u32 device_id)
|
||||
{
|
||||
if ((device_id == WDC_NVME_SN861_DEV_ID) ||
|
||||
(device_id == WDC_NVME_SN861_DEV_ID_1))
|
||||
(device_id == WDC_NVME_SN861_DEV_ID_1) ||
|
||||
(device_id == WDC_NVME_SN861_DEV_ID_2))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
@ -1822,6 +1830,7 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev)
|
|||
case WDC_NVME_SN650_DEV_ID_3:
|
||||
case WDC_NVME_SN650_DEV_ID_4:
|
||||
case WDC_NVME_SN655_DEV_ID:
|
||||
case WDC_NVME_SN655_DEV_ID_1:
|
||||
case WDC_NVME_SN550_DEV_ID:
|
||||
/* verify the 0xC0 log page is supported */
|
||||
if (wdc_nvme_check_supported_log_page(r, dev,
|
||||
|
@ -1872,6 +1881,8 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev)
|
|||
|
||||
case WDC_NVME_SN861_DEV_ID:
|
||||
case WDC_NVME_SN861_DEV_ID_1:
|
||||
case WDC_NVME_SN861_DEV_ID_2:
|
||||
case WDC_NVME_SNTMP_DEV_ID:
|
||||
capabilities |= (WDC_DRIVE_CAP_C0_LOG_PAGE |
|
||||
WDC_DRIVE_CAP_C3_LOG_PAGE |
|
||||
WDC_DRIVE_CAP_CA_LOG_PAGE |
|
||||
|
@ -1970,6 +1981,12 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev)
|
|||
fallthrough;
|
||||
case WDC_NVME_SN8000S_DEV_ID:
|
||||
fallthrough;
|
||||
case WDC_NVME_SN5100S_DEV_ID_1:
|
||||
fallthrough;
|
||||
case WDC_NVME_SN5100S_DEV_ID_2:
|
||||
fallthrough;
|
||||
case WDC_NVME_SN5100S_DEV_ID_3:
|
||||
fallthrough;
|
||||
case WDC_NVME_SN740_DEV_ID:
|
||||
case WDC_NVME_SN740_DEV_ID_1:
|
||||
case WDC_NVME_SN740_DEV_ID_2:
|
||||
|
@ -2357,28 +2374,24 @@ end:
|
|||
static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev,
|
||||
__u8 log_id, void **cbs_data)
|
||||
{
|
||||
int ret = -1;
|
||||
bool found = false;
|
||||
__u8 uuid_ix = 0;
|
||||
__u8 lid = 0;
|
||||
*cbs_data = NULL;
|
||||
__u32 device_id, read_vendor_id;
|
||||
__u32 device_id = 0, vendor_id = 0;
|
||||
bool uuid_present = false;
|
||||
int index = 0, uuid_index = 0;
|
||||
struct nvme_id_uuid_list uuid_list;
|
||||
|
||||
ret = wdc_get_pci_ids(r, dev, &device_id, &read_vendor_id);
|
||||
if (ret == 0) {
|
||||
if (device_id == WDC_NVME_ZN350_DEV_ID || device_id == WDC_NVME_ZN350_DEV_ID_1) {
|
||||
lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID_C8;
|
||||
uuid_ix = 0;
|
||||
} else {
|
||||
lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: WDC: get pci ids: %d\n", ret);
|
||||
return false;
|
||||
}
|
||||
/* The wdc_get_pci_ids function could fail when drives are connected
|
||||
* via a PCIe switch. Therefore, the return code is intentionally
|
||||
* being ignored. The device_id and vendor_id variables have been
|
||||
* initialized to 0 so the code can continue on without issue for
|
||||
* both cases: wdc_get_pci_ids successful or failed.
|
||||
*/
|
||||
wdc_get_pci_ids(r, dev, &device_id, &vendor_id);
|
||||
|
||||
lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID;
|
||||
|
||||
typedef struct nvme_id_uuid_list_entry *uuid_list_entry;
|
||||
|
||||
|
@ -6909,6 +6922,7 @@ static int wdc_get_c0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format
|
|||
case WDC_NVME_SN650_DEV_ID_3:
|
||||
case WDC_NVME_SN650_DEV_ID_4:
|
||||
case WDC_NVME_SN655_DEV_ID:
|
||||
case WDC_NVME_SN655_DEV_ID_1:
|
||||
if (uuid_index == 0) {
|
||||
ret = nvme_get_print_ocp_cloud_smart_log(dev,
|
||||
uuid_index,
|
||||
|
@ -10832,13 +10846,13 @@ static void wdc_print_nand_stats_json(__u16 version, void *data)
|
|||
le32_to_cpu(nand_stats_v3->ssd_correction_counts[12]));
|
||||
json_object_add_value_uint(root, "System data % life-used",
|
||||
nand_stats_v3->percent_life_used);
|
||||
json_object_add_value_uint64(root, "User Data Erase Counts - SLC Min",
|
||||
le64_to_cpu(nand_stats_v3->user_data_erase_counts[0]));
|
||||
json_object_add_value_uint64(root, "User Data Erase Counts - SLC Max",
|
||||
le64_to_cpu(nand_stats_v3->user_data_erase_counts[1]));
|
||||
json_object_add_value_uint64(root, "User Data Erase Counts - TLC Min",
|
||||
le64_to_cpu(nand_stats_v3->user_data_erase_counts[2]));
|
||||
le64_to_cpu(nand_stats_v3->user_data_erase_counts[0]));
|
||||
json_object_add_value_uint64(root, "User Data Erase Counts - TLC Max",
|
||||
le64_to_cpu(nand_stats_v3->user_data_erase_counts[1]));
|
||||
json_object_add_value_uint64(root, "User Data Erase Counts - SLC Min",
|
||||
le64_to_cpu(nand_stats_v3->user_data_erase_counts[2]));
|
||||
json_object_add_value_uint64(root, "User Data Erase Counts - SLC Max",
|
||||
le64_to_cpu(nand_stats_v3->user_data_erase_counts[3]));
|
||||
temp_ptr = (__u64 *)nand_stats_v3->program_fail_count;
|
||||
temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
|
||||
|
@ -11305,12 +11319,14 @@ static int wdc_vs_drive_info(int argc, char **argv,
|
|||
case WDC_NVME_SN650_DEV_ID_3:
|
||||
case WDC_NVME_SN650_DEV_ID_4:
|
||||
case WDC_NVME_SN655_DEV_ID:
|
||||
case WDC_NVME_SN655_DEV_ID_1:
|
||||
case WDC_NVME_SN560_DEV_ID_1:
|
||||
case WDC_NVME_SN560_DEV_ID_2:
|
||||
case WDC_NVME_SN560_DEV_ID_3:
|
||||
case WDC_NVME_SN550_DEV_ID:
|
||||
case WDC_NVME_ZN350_DEV_ID:
|
||||
case WDC_NVME_ZN350_DEV_ID_1:
|
||||
case WDC_NVME_SNTMP_DEV_ID:
|
||||
ret = wdc_do_drive_info(dev, &result);
|
||||
|
||||
if (!ret) {
|
||||
|
@ -11429,6 +11445,7 @@ static int wdc_vs_drive_info(int argc, char **argv,
|
|||
break;
|
||||
case WDC_NVME_SN861_DEV_ID:
|
||||
case WDC_NVME_SN861_DEV_ID_1:
|
||||
case WDC_NVME_SN861_DEV_ID_2:
|
||||
data_len = sizeof(info);
|
||||
num_dwords = data_len / 4;
|
||||
if (data_len % 4 != 0)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#if !defined(WDC_NVME) || defined(CMD_HEADER_MULTI_READ)
|
||||
#define WDC_NVME
|
||||
|
||||
#define WDC_PLUGIN_VERSION "2.9.1"
|
||||
#define WDC_PLUGIN_VERSION "2.11.1"
|
||||
#include "cmd.h"
|
||||
|
||||
PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERSION),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue