Adding upstream version 2.5.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
7819359ae2
commit
acf5b2ec4c
507 changed files with 19440 additions and 17258 deletions
|
@ -28,15 +28,15 @@ static void json_amzn_id_ctrl(struct nvme_vu_id_ctrl_field *id,
|
|||
|
||||
static void amzn_id_ctrl(__u8 *vs, struct json_object *root)
|
||||
{
|
||||
struct nvme_vu_id_ctrl_field* id = (struct nvme_vu_id_ctrl_field *)vs;
|
||||
struct nvme_vu_id_ctrl_field *id = (struct nvme_vu_id_ctrl_field *)vs;
|
||||
|
||||
char bdev[32] = { 0 };
|
||||
|
||||
int len = 0;
|
||||
|
||||
while (len < 31) {
|
||||
if (id->bdev[++len] == ' ') {
|
||||
if (id->bdev[++len] == ' ')
|
||||
break;
|
||||
}
|
||||
}
|
||||
snprintf(bdev, len+1, "%s", id->bdev);
|
||||
|
||||
|
|
|
@ -104,13 +104,12 @@ static int nvme_dera_get_device_status(int fd, enum dera_device_status *result)
|
|||
.addr = (__u64)(uintptr_t)NULL,
|
||||
.data_len = 0,
|
||||
.cdw10 = 0,
|
||||
.cdw12 = 0x104,
|
||||
.cdw12 = 0x104,
|
||||
};
|
||||
|
||||
err = nvme_submit_admin_passthru(fd, &cmd, NULL);
|
||||
if (!err && result) {
|
||||
if (!err && result)
|
||||
*result = cmd.result;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -130,13 +129,12 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin
|
|||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = nvme_get_log_simple(dev_fd(dev), 0xc0, sizeof(log), &log);
|
||||
if (err) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
const char* dev_status[] = {
|
||||
err = nvme_get_log_simple(dev_fd(dev), 0xc0, sizeof(log), &log);
|
||||
if (err)
|
||||
goto exit;
|
||||
|
||||
static const char *dev_status[] = {
|
||||
"Normal",
|
||||
"Quick Rebuilding",
|
||||
"Full Rebuilding",
|
||||
|
@ -148,25 +146,22 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin
|
|||
"Firmware Committing",
|
||||
"Over Temperature" };
|
||||
|
||||
const char *volt_status[] = {
|
||||
static const char *volt_status[] = {
|
||||
"Normal",
|
||||
"Initial Low",
|
||||
"Runtime Low",
|
||||
};
|
||||
|
||||
err = nvme_dera_get_device_status(dev_fd(dev), &state);
|
||||
if (!err){
|
||||
if (state > 0 && state < 4){
|
||||
if (!err) {
|
||||
if (state > 0 && state < 4)
|
||||
printf("device_status : %s %d%% completed\n", dev_status[state], log.rebuild_percent);
|
||||
}
|
||||
else{
|
||||
else
|
||||
printf("device_status : %s\n", dev_status[state]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
||||
printf("dev_status_up : %s\n", dev_status[log.dev_status_up]);
|
||||
printf("cap_aged : %s\n", log.cap_aged == 1 ? "True" : "False");
|
||||
printf("cap_aged_ratio : %d%%\n", log.cap_aged_ratio < 100 ? log.cap_aged_ratio : 100);
|
||||
|
@ -188,12 +183,10 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin
|
|||
printf("fw_loader_version : %.*s\n", 8, log.fw_loader_version);
|
||||
printf("uefi_driver_version : %.*s\n", 8, log.uefi_driver_version);
|
||||
|
||||
if (log.pcie_volt_status < sizeof(volt_status) / sizeof(const char *)){
|
||||
if (log.pcie_volt_status < sizeof(volt_status) / sizeof(const char *))
|
||||
printf("pcie_volt_status : %s\n", volt_status[log.pcie_volt_status]);
|
||||
}
|
||||
else{
|
||||
else
|
||||
printf("pcie_volt_status : Unknown\n");
|
||||
}
|
||||
|
||||
printf("current_pcie_volt : %d mV\n", log.current_pcie_volt[1] << 8 | log.current_pcie_volt[0]);
|
||||
printf("init_pcie_volt_low_cnt : %d\n", log.init_pcie_volt_low[1] << 8 | log.init_pcie_volt_low[0]);
|
||||
|
|
|
@ -121,7 +121,7 @@ static int fdp_usage(int argc, char **argv, struct command *cmd, struct plugin *
|
|||
};
|
||||
|
||||
struct config cfg = {
|
||||
.egid = 0,
|
||||
.egid = 0,
|
||||
.output_format = "normal",
|
||||
.raw_binary = false,
|
||||
};
|
||||
|
@ -192,7 +192,7 @@ static int fdp_stats(int argc, char **argv, struct command *cmd, struct plugin *
|
|||
};
|
||||
|
||||
struct config cfg = {
|
||||
.egid = 0,
|
||||
.egid = 0,
|
||||
.output_format = "normal",
|
||||
.raw_binary = false,
|
||||
};
|
||||
|
@ -251,8 +251,8 @@ static int fdp_events(int argc, char **argv, struct command *cmd, struct plugin
|
|||
};
|
||||
|
||||
struct config cfg = {
|
||||
.egid = 0,
|
||||
.host_events = false,
|
||||
.egid = 0,
|
||||
.host_events = false,
|
||||
.output_format = "normal",
|
||||
.raw_binary = false,
|
||||
};
|
||||
|
@ -424,9 +424,8 @@ static int fdp_update(int argc, char **argv, struct command *cmd, struct plugin
|
|||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < npids; i++) {
|
||||
for (unsigned int i = 0; i < npids; i++)
|
||||
buf[i] = cpu_to_le16(pids[i]);
|
||||
}
|
||||
|
||||
err = nvme_fdp_reclaim_unit_handle_update(dev_fd(dev), cfg.namespace_id, npids, buf);
|
||||
if (err) {
|
||||
|
@ -449,6 +448,7 @@ static int fdp_set_events(int argc, char **argv, struct command *cmd, struct plu
|
|||
const char *enable = "Enable/disable event";
|
||||
const char *event_types = "Comma-separated list of event types";
|
||||
const char *ph = "Placement Handle";
|
||||
const char *save = "specifies that the controller shall save the attribute";
|
||||
|
||||
struct nvme_dev *dev;
|
||||
int err = -1;
|
||||
|
@ -458,19 +458,22 @@ static int fdp_set_events(int argc, char **argv, struct command *cmd, struct plu
|
|||
|
||||
struct config {
|
||||
__u32 namespace_id;
|
||||
__u16 ph;
|
||||
char *event_types;
|
||||
bool enable;
|
||||
__u16 ph;
|
||||
char *event_types;
|
||||
bool enable;
|
||||
bool save;
|
||||
};
|
||||
|
||||
struct config cfg = {
|
||||
.enable = false,
|
||||
.enable = false,
|
||||
.save = false,
|
||||
};
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
|
||||
OPT_SHRT("placement-handle", 'p', &cfg.ph, ph),
|
||||
OPT_FLAG("enable", 'e', &cfg.enable, enable),
|
||||
OPT_FLAG("save", 's', &cfg.save, save),
|
||||
OPT_LIST("event-types", 't', &cfg.event_types, event_types),
|
||||
OPT_END()
|
||||
};
|
||||
|
@ -506,14 +509,14 @@ static int fdp_set_events(int argc, char **argv, struct command *cmd, struct plu
|
|||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < nev; i++) {
|
||||
for (unsigned int i = 0; i < nev; i++)
|
||||
buf[i] = (__u8)evts[i];
|
||||
}
|
||||
|
||||
struct nvme_set_features_args args = {
|
||||
.args_size = sizeof(args),
|
||||
.fd = dev_fd(dev),
|
||||
.fid = NVME_FEAT_FID_FDP_EVENTS,
|
||||
.save = cfg.save,
|
||||
.nsid = cfg.namespace_id,
|
||||
.cdw11 = (nev << 16) | cfg.ph,
|
||||
.cdw12 = cfg.enable ? 0x1 : 0x0,
|
||||
|
|
|
@ -47,9 +47,9 @@
|
|||
struct huawei_list_item {
|
||||
char node[1024];
|
||||
struct nvme_id_ctrl ctrl;
|
||||
unsigned nsid;
|
||||
unsigned int nsid;
|
||||
struct nvme_id_ns ns;
|
||||
unsigned block;
|
||||
unsigned int block;
|
||||
char ns_name[NS_NAME_LEN];
|
||||
char array_name[ARRAY_NAME_LEN];
|
||||
bool huawei_device;
|
||||
|
@ -98,23 +98,19 @@ static int huawei_get_nvme_info(int fd, struct huawei_list_item *item, const cha
|
|||
item->block = S_ISBLK(nvme_stat_info.st_mode);
|
||||
|
||||
if (item->ns.vs[0] == 0) {
|
||||
|
||||
len = snprintf(item->ns_name, NS_NAME_LEN, "%s", "----");
|
||||
if (len < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
memcpy(item->ns_name, item->ns.vs, NS_NAME_LEN);
|
||||
item->ns_name[NS_NAME_LEN - 1] = '\0';
|
||||
}
|
||||
|
||||
if (item->ctrl.vs[0] == 0) {
|
||||
|
||||
len = snprintf(item->array_name, ARRAY_NAME_LEN, "%s", "----");
|
||||
if (len < 0)
|
||||
if (len < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
memcpy(item->array_name, item->ctrl.vs, ARRAY_NAME_LEN);
|
||||
item->array_name[ARRAY_NAME_LEN - 1] = '\0';
|
||||
}
|
||||
|
@ -123,9 +119,8 @@ static int huawei_get_nvme_info(int fd, struct huawei_list_item *item, const cha
|
|||
|
||||
static void format(char *formatter, size_t fmt_sz, char *tofmt, size_t tofmtsz)
|
||||
{
|
||||
fmt_sz = snprintf(formatter, fmt_sz, "%-*.*s", (int)tofmtsz, (int)tofmtsz, tofmt);
|
||||
|
||||
fmt_sz = snprintf(formatter,fmt_sz, "%-*.*s",
|
||||
(int)tofmtsz, (int)tofmtsz, tofmt);
|
||||
/* trim() the obnoxious trailing white lines */
|
||||
while (fmt_sz) {
|
||||
if (formatter[fmt_sz - 1] != ' ' && formatter[fmt_sz - 1] != '\0') {
|
||||
|
@ -137,7 +132,7 @@ static void format(char *formatter, size_t fmt_sz, char *tofmt, size_t tofmtsz)
|
|||
}
|
||||
|
||||
static void huawei_json_print_list_items(struct huawei_list_item *list_items,
|
||||
unsigned len)
|
||||
unsigned int len)
|
||||
{
|
||||
struct json_object *root;
|
||||
struct json_object *devices;
|
||||
|
@ -210,8 +205,9 @@ static void huawei_print_list_item(struct huawei_list_item *list_item,
|
|||
struct huawei_list_element_len element_len)
|
||||
{
|
||||
__u8 lba_index;
|
||||
|
||||
nvme_id_ns_flbas_to_lbaf_inuse(list_item->ns.flbas, &lba_index);
|
||||
unsigned long long int lba = 1ULL << list_item->ns.lbaf[lba_index].ds;
|
||||
unsigned long long lba = 1ULL << list_item->ns.lbaf[lba_index].ds;
|
||||
double nsze = le64_to_cpu(list_item->ns.nsze) * lba;
|
||||
double nuse = le64_to_cpu(list_item->ns.nuse) * lba;
|
||||
|
||||
|
@ -223,8 +219,7 @@ static void huawei_print_list_item(struct huawei_list_item *list_item,
|
|||
char *nguid = nguid_buf;
|
||||
int i;
|
||||
|
||||
sprintf(usage,"%6.2f %2sB / %6.2f %2sB", nuse, u_suffix,
|
||||
nsze, s_suffix);
|
||||
sprintf(usage, "%6.2f %2sB / %6.2f %2sB", nuse, u_suffix, nsze, s_suffix);
|
||||
|
||||
memset(nguid, 0, sizeof(nguid_buf));
|
||||
for (i = 0; i < sizeof(list_item->ns.nguid); i++)
|
||||
|
@ -247,37 +242,37 @@ static unsigned int choose_len(unsigned int old_len, unsigned int cur_len, unsig
|
|||
|
||||
temp_len = (cur_len > default_len) ? cur_len : default_len;
|
||||
if (temp_len > old_len)
|
||||
{
|
||||
return temp_len;
|
||||
}
|
||||
return old_len;
|
||||
}
|
||||
|
||||
static unsigned int huawei_get_ns_len(struct huawei_list_item *list_items, unsigned len, unsigned default_len)
|
||||
static unsigned int huawei_get_ns_len(struct huawei_list_item *list_items, unsigned int len,
|
||||
unsigned int default_len)
|
||||
{
|
||||
int i;
|
||||
unsigned int min_len = default_len;
|
||||
|
||||
for (i = 0 ; i < len ; i++)
|
||||
min_len = choose_len(min_len , strlen(list_items->ns_name), default_len);
|
||||
min_len = choose_len(min_len, strlen(list_items->ns_name), default_len);
|
||||
|
||||
return min_len;
|
||||
}
|
||||
|
||||
static int huawei_get_array_len(struct huawei_list_item *list_items, unsigned len, unsigned default_len)
|
||||
static int huawei_get_array_len(struct huawei_list_item *list_items, unsigned int len,
|
||||
unsigned int default_len)
|
||||
{
|
||||
int i;
|
||||
int min_len = default_len;
|
||||
|
||||
for (i = 0 ; i < len ; i++)
|
||||
min_len = choose_len(min_len , strlen(list_items->array_name), default_len);
|
||||
min_len = choose_len(min_len, strlen(list_items->array_name), default_len);
|
||||
|
||||
return min_len;
|
||||
}
|
||||
|
||||
static void huawei_print_list_items(struct huawei_list_item *list_items, unsigned len)
|
||||
static void huawei_print_list_items(struct huawei_list_item *list_items, unsigned int len)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
struct huawei_list_element_len element_len;
|
||||
|
||||
element_len.node = 16;
|
||||
|
@ -350,13 +345,12 @@ static int huawei_list(int argc, char **argv, struct command *command,
|
|||
close(fd);
|
||||
goto out_free_list_items;
|
||||
}
|
||||
if (list_items[huawei_num].huawei_device == true) {
|
||||
if (list_items[huawei_num].huawei_device == true)
|
||||
huawei_num++;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (huawei_num > 0){
|
||||
if (huawei_num > 0) {
|
||||
if (fmt == JSON)
|
||||
huawei_json_print_list_items(list_items, huawei_num);
|
||||
else
|
||||
|
|
|
@ -146,11 +146,13 @@ static int nvme_vucmd(int fd, unsigned char opcode, unsigned int cdw12,
|
|||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.opcode = opcode;
|
||||
cmd.cdw2 = IGVSC_SIG;
|
||||
cmd.cdw10 = data_len / 4;
|
||||
cmd.cdw12 = cdw12;
|
||||
cmd.cdw13 = cdw13;
|
||||
cmd.cdw14 = cdw14;
|
||||
cmd.cdw15 = cdw15;
|
||||
cmd.nsid = 0;
|
||||
cmd.nsid = 0xffffffff;
|
||||
cmd.addr = (__u64)(__u64)(uintptr_t)data;
|
||||
cmd.data_len = data_len;
|
||||
return nvme_submit_admin_passthru(fd, &cmd, NULL);
|
||||
|
@ -198,8 +200,8 @@ static int innogrit_vsc_geteventlog(int argc, char **argv,
|
|||
ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x82, 0x03, 0x00, 0x00, (char *)data, 4096);
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
|
||||
if (data[0] == 0x5A)
|
||||
|
||||
if (data[0] == 0x5A)
|
||||
ivsctype = 1;
|
||||
else
|
||||
ivsctype = 0;
|
||||
|
@ -227,8 +229,9 @@ static int innogrit_vsc_geteventlog(int argc, char **argv,
|
|||
icount++;
|
||||
|
||||
memset(data, 0, 4096);
|
||||
if (ivsctype == 1)
|
||||
ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x60, 0x00, 0x00, 0x00,(char *)data, 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),
|
||||
|
@ -345,10 +348,10 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command,
|
|||
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);
|
||||
ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x82, 0x08, 0x00, 0x00, (char *)data, 4096);
|
||||
} else {
|
||||
ivsctype = 0;
|
||||
ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET, VSC_FN_GET_CDUMP, 0x00,
|
||||
|
@ -403,12 +406,13 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command,
|
|||
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);
|
||||
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);
|
||||
(char *)data, 4096);
|
||||
} else {
|
||||
ret = nvme_get_nsid_log(dev_fd(dev), true,
|
||||
0x07,
|
||||
|
@ -429,12 +433,13 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command,
|
|||
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);
|
||||
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);
|
||||
(char *)data, 4096);
|
||||
} else {
|
||||
ret = nvme_get_nsid_log(dev_fd(dev), true,
|
||||
0x07,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#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"
|
||||
|
||||
|
|
|
@ -23,215 +23,211 @@
|
|||
|
||||
void show_r1_vendor_log(r1_cli_vendor_log_t *vendorlog)
|
||||
{
|
||||
int i = 0;
|
||||
int i = 0;
|
||||
|
||||
if (vendorlog->device_state == 0) {
|
||||
printf("device_state : [healthy]\n");
|
||||
} else {
|
||||
printf("device_state : [warning]\n");
|
||||
}
|
||||
if (vendorlog->device_state == 0)
|
||||
printf("device_state : [healthy]\n");
|
||||
else
|
||||
printf("device_state : [warning]\n");
|
||||
|
||||
printf("commit id : %s\n", vendorlog->commit_id);
|
||||
printf("mcu data id(mcu) : 0x%x\n", le32_to_cpu(vendorlog->mcu_data_id));
|
||||
printf("power_info(mcu) : %u mW\n", le32_to_cpu(vendorlog->power_info));
|
||||
printf("voltage_info(mcu) : %u mV\n", le32_to_cpu(vendorlog->voltage_info));
|
||||
printf("current_info(mcu) : %u mA\n", le32_to_cpu(vendorlog->current_info));
|
||||
printf("history max_power(mcu) : %u mW\n", le32_to_cpu(vendorlog->max_power));
|
||||
printf("disk_max_temper(mcu) : %d C\n", le32_to_cpu(vendorlog->disk_max_temper) - 273);
|
||||
printf("disk_overtemper_cout(mcu) : %u\n", le32_to_cpu(vendorlog->disk_overtemper_cout));
|
||||
printf("ctrl_max_temper(mcu) : %d C\n", le32_to_cpu(vendorlog->ctrl_max_temper) - 273);
|
||||
printf("ctrl_overtemper_cout(mcu) : %u\n", le32_to_cpu(vendorlog->ctrl_overtemper_cout));
|
||||
printf("nand_max_temper(mcu) : %d C\n", le32_to_cpu(vendorlog->nand_max_temper) - 273);
|
||||
printf("nand_overtemper_cout(mcu) : %u\n", le32_to_cpu(vendorlog->nand_overtemper_cout));
|
||||
printf("commit id : %s\n", vendorlog->commit_id);
|
||||
printf("mcu data id(mcu) : 0x%x\n", le32_to_cpu(vendorlog->mcu_data_id));
|
||||
printf("power_info(mcu) : %u mW\n", le32_to_cpu(vendorlog->power_info));
|
||||
printf("voltage_info(mcu) : %u mV\n", le32_to_cpu(vendorlog->voltage_info));
|
||||
printf("current_info(mcu) : %u mA\n", le32_to_cpu(vendorlog->current_info));
|
||||
printf("history max_power(mcu) : %u mW\n", le32_to_cpu(vendorlog->max_power));
|
||||
printf("disk_max_temper(mcu) : %d C\n", le32_to_cpu(vendorlog->disk_max_temper) - 273);
|
||||
printf("disk_overtemper_cout(mcu) : %u\n", le32_to_cpu(vendorlog->disk_overtemper_cout));
|
||||
printf("ctrl_max_temper(mcu) : %d C\n", le32_to_cpu(vendorlog->ctrl_max_temper) - 273);
|
||||
printf("ctrl_overtemper_cout(mcu) : %u\n", le32_to_cpu(vendorlog->ctrl_overtemper_cout));
|
||||
printf("nand_max_temper(mcu) : %d C\n", le32_to_cpu(vendorlog->nand_max_temper) - 273);
|
||||
printf("nand_overtemper_cout(mcu) : %u\n", le32_to_cpu(vendorlog->nand_overtemper_cout));
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
printf("temperature[%d](mcu) : %d C\n", i, le32_to_cpu(vendorlog->current_temp[i]) - 273);
|
||||
}
|
||||
for (i = 0; i < 4; i++)
|
||||
printf("temperature[%d](mcu) : %d C\n", i, le32_to_cpu(vendorlog->current_temp[i]) - 273);
|
||||
|
||||
printf("CAP Time from 32v to 27v(mcu) : %u ms\n", le32_to_cpu(vendorlog->cap_transtime.cap_trans_time1));
|
||||
printf("CAP Time from 27v to 10v(mcu) : %u ms\n", le32_to_cpu(vendorlog->cap_transtime.cap_trans_time2));
|
||||
printf("cap_health_state(mcu) : %u\n", le32_to_cpu(vendorlog->cap_health_state));
|
||||
printf("warning bit(mcu) : 0x%x%08x\n", le32_to_cpu(vendorlog->detail_warning[1]),
|
||||
le32_to_cpu(vendorlog->detail_warning[0]));
|
||||
printf("-->high_format_fail : %x\n", vendorlog->detail_warning_bit.high_format_fail);
|
||||
printf("-->low_format_fail : %x\n", vendorlog->detail_warning_bit.low_format_fail);
|
||||
printf("-->current sensor : %x\n", vendorlog->detail_warning_bit.self_test_fail1);
|
||||
printf("-->nand temp sensor : %x\n", vendorlog->detail_warning_bit.self_test_fail2);
|
||||
printf("-->board temp sensor : %x\n", vendorlog->detail_warning_bit.self_test_fail3);
|
||||
printf("-->cntl temp sensor : %x\n", vendorlog->detail_warning_bit.self_test_fail4);
|
||||
printf("-->cap_timer_test_fail : %x\n", vendorlog->detail_warning_bit.capacitance_test_fail);
|
||||
printf("-->readOnly_after_rebuild : %x\n", vendorlog->detail_warning_bit.readOnly_after_rebuild);
|
||||
printf("-->firmware_loss : %x\n", vendorlog->detail_warning_bit.firmware_loss);
|
||||
printf("-->cap_self_test : %x\n", vendorlog->detail_warning_bit.cap_unsupply);
|
||||
printf("-->spare_space_warning : %x\n", vendorlog->detail_warning_bit.spare_space_warning);
|
||||
printf("-->lifetime_warning : %x\n", vendorlog->detail_warning_bit.lifetime_warning);
|
||||
printf("-->temp_high_warning : %x\n", vendorlog->detail_warning_bit.temp_high_warning);
|
||||
printf("-->temp_low_warning : %x\n", vendorlog->detail_warning_bit.temp_low_warning);
|
||||
printf("-->mcu_disable(mcu) : %x\n", vendorlog->detail_warning_bit.mcu_disable);
|
||||
printf("warning history bit(mcu) : 0x%x%08x\n", le32_to_cpu(vendorlog->detail_warning_his[1]),
|
||||
le32_to_cpu(vendorlog->detail_warning_his[0]));
|
||||
printf("-->high_format_fail : %x\n", vendorlog->detail_warning_his_bit.high_format_fail);
|
||||
printf("-->low_format_fail : %x\n", vendorlog->detail_warning_his_bit.low_format_fail);
|
||||
printf("-->current sensor : %x\n", vendorlog->detail_warning_his_bit.self_test_fail1);
|
||||
printf("-->nand temp sensor : %x\n", vendorlog->detail_warning_his_bit.self_test_fail2);
|
||||
printf("-->board temp sensor : %x\n", vendorlog->detail_warning_his_bit.self_test_fail3);
|
||||
printf("-->cntl temp sensor : %x\n", vendorlog->detail_warning_his_bit.self_test_fail4);
|
||||
printf("-->cap_timer_test_fail : %x\n", vendorlog->detail_warning_his_bit.capacitance_test_fail);
|
||||
printf("-->readOnly_after_rebuild : %x\n", vendorlog->detail_warning_his_bit.readOnly_after_rebuild);
|
||||
printf("-->firmware_loss : %x\n", vendorlog->detail_warning_his_bit.firmware_loss);
|
||||
printf("-->cap_self_test : %x\n", vendorlog->detail_warning_his_bit.cap_unsupply);
|
||||
printf("-->spare_space_warning : %x\n", vendorlog->detail_warning_his_bit.spare_space_warning);
|
||||
printf("-->lifetime_warning : %x\n", vendorlog->detail_warning_his_bit.lifetime_warning);
|
||||
printf("-->temp_high_warning : %x\n", vendorlog->detail_warning_his_bit.temp_high_warning);
|
||||
printf("-->temp_low_warning : %x\n", vendorlog->detail_warning_his_bit.temp_low_warning);
|
||||
printf("-->mcu_disable(mcu) : %x\n", vendorlog->detail_warning_his_bit.mcu_disable);
|
||||
printf("CAP Time from 32v to 27v(mcu) : %u ms\n", le32_to_cpu(vendorlog->cap_transtime.cap_trans_time1));
|
||||
printf("CAP Time from 27v to 10v(mcu) : %u ms\n", le32_to_cpu(vendorlog->cap_transtime.cap_trans_time2));
|
||||
printf("cap_health_state(mcu) : %u\n", le32_to_cpu(vendorlog->cap_health_state));
|
||||
printf("warning bit(mcu) : 0x%x%08x\n", le32_to_cpu(vendorlog->detail_warning[1]),
|
||||
le32_to_cpu(vendorlog->detail_warning[0]));
|
||||
printf("-->high_format_fail : %x\n", vendorlog->detail_warning_bit.high_format_fail);
|
||||
printf("-->low_format_fail : %x\n", vendorlog->detail_warning_bit.low_format_fail);
|
||||
printf("-->current sensor : %x\n", vendorlog->detail_warning_bit.self_test_fail1);
|
||||
printf("-->nand temp sensor : %x\n", vendorlog->detail_warning_bit.self_test_fail2);
|
||||
printf("-->board temp sensor : %x\n", vendorlog->detail_warning_bit.self_test_fail3);
|
||||
printf("-->cntl temp sensor : %x\n", vendorlog->detail_warning_bit.self_test_fail4);
|
||||
printf("-->cap_timer_test_fail : %x\n", vendorlog->detail_warning_bit.capacitance_test_fail);
|
||||
printf("-->readOnly_after_rebuild : %x\n", vendorlog->detail_warning_bit.readOnly_after_rebuild);
|
||||
printf("-->firmware_loss : %x\n", vendorlog->detail_warning_bit.firmware_loss);
|
||||
printf("-->cap_self_test : %x\n", vendorlog->detail_warning_bit.cap_unsupply);
|
||||
printf("-->spare_space_warning : %x\n", vendorlog->detail_warning_bit.spare_space_warning);
|
||||
printf("-->lifetime_warning : %x\n", vendorlog->detail_warning_bit.lifetime_warning);
|
||||
printf("-->temp_high_warning : %x\n", vendorlog->detail_warning_bit.temp_high_warning);
|
||||
printf("-->temp_low_warning : %x\n", vendorlog->detail_warning_bit.temp_low_warning);
|
||||
printf("-->mcu_disable(mcu) : %x\n", vendorlog->detail_warning_bit.mcu_disable);
|
||||
printf("warning history bit(mcu) : 0x%x%08x\n", le32_to_cpu(vendorlog->detail_warning_his[1]),
|
||||
le32_to_cpu(vendorlog->detail_warning_his[0]));
|
||||
printf("-->high_format_fail : %x\n", vendorlog->detail_warning_his_bit.high_format_fail);
|
||||
printf("-->low_format_fail : %x\n", vendorlog->detail_warning_his_bit.low_format_fail);
|
||||
printf("-->current sensor : %x\n", vendorlog->detail_warning_his_bit.self_test_fail1);
|
||||
printf("-->nand temp sensor : %x\n", vendorlog->detail_warning_his_bit.self_test_fail2);
|
||||
printf("-->board temp sensor : %x\n", vendorlog->detail_warning_his_bit.self_test_fail3);
|
||||
printf("-->cntl temp sensor : %x\n", vendorlog->detail_warning_his_bit.self_test_fail4);
|
||||
printf("-->cap_timer_test_fail : %x\n", vendorlog->detail_warning_his_bit.capacitance_test_fail);
|
||||
printf("-->readOnly_after_rebuild : %x\n", vendorlog->detail_warning_his_bit.readOnly_after_rebuild);
|
||||
printf("-->firmware_loss : %x\n", vendorlog->detail_warning_his_bit.firmware_loss);
|
||||
printf("-->cap_self_test : %x\n", vendorlog->detail_warning_his_bit.cap_unsupply);
|
||||
printf("-->spare_space_warning : %x\n", vendorlog->detail_warning_his_bit.spare_space_warning);
|
||||
printf("-->lifetime_warning : %x\n", vendorlog->detail_warning_his_bit.lifetime_warning);
|
||||
printf("-->temp_high_warning : %x\n", vendorlog->detail_warning_his_bit.temp_high_warning);
|
||||
printf("-->temp_low_warning : %x\n", vendorlog->detail_warning_his_bit.temp_low_warning);
|
||||
printf("-->mcu_disable(mcu) : %x\n", vendorlog->detail_warning_his_bit.mcu_disable);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
printf("[%d]nand_bytes_written : %" PRIu64 " GB\n", i, le64_to_cpu(vendorlog->nand_bytes_written[i]));
|
||||
}
|
||||
for (i = 0; i < 4; i++)
|
||||
printf("[%d]nand_bytes_written : %" PRIu64 " GB\n", i, le64_to_cpu(vendorlog->nand_bytes_written[i]));
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
printf("[%d]io_apptag_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_apptag_err));
|
||||
printf("[%d]io_guard_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_guard_err));
|
||||
printf("[%d]io_reftag_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_reftag_err));
|
||||
printf("[%d]io_read_fail_cout : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_read_fail_cout));
|
||||
printf("[%d]io_write_fail_cout : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_write_fail_cout));
|
||||
printf("[%d]io_dma_disable_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_dma_disable_err));
|
||||
printf("[%d]io_dma_fatal_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_dma_fatal_err));
|
||||
printf("[%d]io_dma_linkdown_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_dma_linkdown_err));
|
||||
printf("[%d]io_dma_timeout_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_dma_timeout_err));
|
||||
printf("[%d]lba_err[0] : %u\n", i, le32_to_cpu(vendorlog->io_err[i].lba_err[0]));
|
||||
printf("[%d]lba_err[1] : %u\n", i, le32_to_cpu(vendorlog->io_err[i].lba_err[1]));
|
||||
printf("[%d]lba_err[2] : %u\n", i, le32_to_cpu(vendorlog->io_err[i].lba_err[2]));
|
||||
printf("[%d]lba_err[3] : %u\n", i, le32_to_cpu(vendorlog->io_err[i].lba_err[3]));
|
||||
printf("[%d]lba_err[4] : %u\n", i, le32_to_cpu(vendorlog->io_err[i].lba_err[4]));
|
||||
printf("[%d]lba_err[5] : %u\n", i, le32_to_cpu(vendorlog->io_err[i].lba_err[5]));
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
printf("[%d]io_apptag_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_apptag_err));
|
||||
printf("[%d]io_guard_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_guard_err));
|
||||
printf("[%d]io_reftag_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_reftag_err));
|
||||
printf("[%d]io_read_fail_cout : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_read_fail_cout));
|
||||
printf("[%d]io_write_fail_cout : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_write_fail_cout));
|
||||
printf("[%d]io_dma_disable_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_dma_disable_err));
|
||||
printf("[%d]io_dma_fatal_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_dma_fatal_err));
|
||||
printf("[%d]io_dma_linkdown_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_dma_linkdown_err));
|
||||
printf("[%d]io_dma_timeout_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_dma_timeout_err));
|
||||
printf("[%d]lba_err[0] : %u\n", i, le32_to_cpu(vendorlog->io_err[i].lba_err[0]));
|
||||
printf("[%d]lba_err[1] : %u\n", i, le32_to_cpu(vendorlog->io_err[i].lba_err[1]));
|
||||
printf("[%d]lba_err[2] : %u\n", i, le32_to_cpu(vendorlog->io_err[i].lba_err[2]));
|
||||
printf("[%d]lba_err[3] : %u\n", i, le32_to_cpu(vendorlog->io_err[i].lba_err[3]));
|
||||
printf("[%d]lba_err[4] : %u\n", i, le32_to_cpu(vendorlog->io_err[i].lba_err[4]));
|
||||
printf("[%d]lba_err[5] : %u\n", i, le32_to_cpu(vendorlog->io_err[i].lba_err[5]));
|
||||
}
|
||||
|
||||
printf("temp_throttle_per : %u\n", le32_to_cpu(vendorlog->temp_throttle_per));
|
||||
printf("port0_flreset_cnt : %" PRIu64 "\n", le64_to_cpu(vendorlog->port0_fundamental_reset_cnt));
|
||||
printf("port0_hot_reset_cnt : %" PRIu64 "\n", le64_to_cpu(vendorlog->port0_hot_reset_cnt));
|
||||
printf("port0_func_reset_cnt : %" PRIu64 "\n", le64_to_cpu(vendorlog->port0_func_reset_cnt));
|
||||
printf("port0_linkdown_cnt : %" PRIu64 "\n", le64_to_cpu(vendorlog->port0_linkdown_cnt));
|
||||
printf("port0_ctrl_reset_cnt : %" PRIu64 "\n", le64_to_cpu(vendorlog->port0_ctrl_reset_cnt));
|
||||
printf("ces_RcvErr_cnt : %u\n", le32_to_cpu(vendorlog->ces_RcvErr_cnt));
|
||||
printf("ces_BadTlp_cnt : %u\n", le32_to_cpu(vendorlog->ces_BadTlp_cnt));
|
||||
printf("ces_BadDllp_cnt : %u\n", le32_to_cpu(vendorlog->ces_BadDllp_cnt));
|
||||
printf("ces_Rplyover_cnt : %u\n", le32_to_cpu(vendorlog->ces_Rplyover_cnt));
|
||||
printf("ces_RplyTo_cnt : %u\n", le32_to_cpu(vendorlog->ces_RplyTo_cnt));
|
||||
printf("ces_Hlo_cnt : %u\n", le32_to_cpu(vendorlog->ces_Hlo_cnt));
|
||||
printf("scan doorbell err cnt : %u\n", le32_to_cpu(vendorlog->scan_db_err_cnt));
|
||||
printf("doorbell interrupt err cnt : %u\n", le32_to_cpu(vendorlog->db_int_err_cnt));
|
||||
printf("temp_throttle_per : %u\n", le32_to_cpu(vendorlog->temp_throttle_per));
|
||||
printf("port0_flreset_cnt : %" PRIu64 "\n", le64_to_cpu(vendorlog->port0_fundamental_reset_cnt));
|
||||
printf("port0_hot_reset_cnt : %" PRIu64 "\n", le64_to_cpu(vendorlog->port0_hot_reset_cnt));
|
||||
printf("port0_func_reset_cnt : %" PRIu64 "\n", le64_to_cpu(vendorlog->port0_func_reset_cnt));
|
||||
printf("port0_linkdown_cnt : %" PRIu64 "\n", le64_to_cpu(vendorlog->port0_linkdown_cnt));
|
||||
printf("port0_ctrl_reset_cnt : %" PRIu64 "\n", le64_to_cpu(vendorlog->port0_ctrl_reset_cnt));
|
||||
printf("ces_RcvErr_cnt : %u\n", le32_to_cpu(vendorlog->ces_RcvErr_cnt));
|
||||
printf("ces_BadTlp_cnt : %u\n", le32_to_cpu(vendorlog->ces_BadTlp_cnt));
|
||||
printf("ces_BadDllp_cnt : %u\n", le32_to_cpu(vendorlog->ces_BadDllp_cnt));
|
||||
printf("ces_Rplyover_cnt : %u\n", le32_to_cpu(vendorlog->ces_Rplyover_cnt));
|
||||
printf("ces_RplyTo_cnt : %u\n", le32_to_cpu(vendorlog->ces_RplyTo_cnt));
|
||||
printf("ces_Hlo_cnt : %u\n", le32_to_cpu(vendorlog->ces_Hlo_cnt));
|
||||
printf("scan doorbell err cnt : %u\n", le32_to_cpu(vendorlog->scan_db_err_cnt));
|
||||
printf("doorbell interrupt err cnt : %u\n", le32_to_cpu(vendorlog->db_int_err_cnt));
|
||||
|
||||
printf("------------ncm-----------------------\n");
|
||||
for (i = 0; i < 4; i++) {
|
||||
printf("------------part%d-----------------------\n", i);
|
||||
printf("[%d]nand_rd_unc_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_rd_unc_cnt));
|
||||
printf("[%d]nand_rd_srr_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_rd_srr_cnt));
|
||||
printf("[%d]nand_rd_sdecode_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_rd_soft_decode_cnt));
|
||||
printf("[%d]nand_rd_rb_fail_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_rd_rebuild_fail_cnt));
|
||||
printf("[%d]nand_prg_fail_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_prg_fail_cnt));
|
||||
printf("[%d]nand_eras_fail_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_eras_fail_cnt));
|
||||
printf("[%d]nand_rd_count : %" PRIu64 "\n", i,
|
||||
le64_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_rd_cnt));
|
||||
printf("[%d]nand_prg_count : %" PRIu64 "\n", i,
|
||||
le64_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_prg_cnt));
|
||||
printf("[%d]nand_eras_count : %" PRIu64 "\n", i,
|
||||
le64_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_eras_cnt));
|
||||
printf("[%d]BE_scan_unc_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].BE_scan_unc_cnt));
|
||||
printf("[%d]rebuild_req_cnt : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].rebuild_req_cnt));
|
||||
printf("[%d]retry_req_cnt : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].retry_req_cnt));
|
||||
printf("[%d]retry_success_cnt : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].retry_success_cnt));
|
||||
printf("[%d]prg_badblk_num : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].prg_badblk_num));
|
||||
printf("[%d]eras_badblk_num : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].eras_badblk_num));
|
||||
printf("[%d]read_badblk_num : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].unc_badblk_num));
|
||||
}
|
||||
printf("------------ncm-----------------------\n");
|
||||
for (i = 0; i < 4; i++) {
|
||||
printf("------------part%d-----------------------\n", i);
|
||||
printf("[%d]nand_rd_unc_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_rd_unc_cnt));
|
||||
printf("[%d]nand_rd_srr_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_rd_srr_cnt));
|
||||
printf("[%d]nand_rd_sdecode_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_rd_soft_decode_cnt));
|
||||
printf("[%d]nand_rd_rb_fail_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_rd_rebuild_fail_cnt));
|
||||
printf("[%d]nand_prg_fail_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_prg_fail_cnt));
|
||||
printf("[%d]nand_eras_fail_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_eras_fail_cnt));
|
||||
printf("[%d]nand_rd_count : %" PRIu64 "\n", i,
|
||||
le64_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_rd_cnt));
|
||||
printf("[%d]nand_prg_count : %" PRIu64 "\n", i,
|
||||
le64_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_prg_cnt));
|
||||
printf("[%d]nand_eras_count : %" PRIu64 "\n", i,
|
||||
le64_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_eras_cnt));
|
||||
printf("[%d]BE_scan_unc_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].BE_scan_unc_cnt));
|
||||
printf("[%d]rebuild_req_cnt : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].rebuild_req_cnt));
|
||||
printf("[%d]retry_req_cnt : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].retry_req_cnt));
|
||||
printf("[%d]retry_success_cnt : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].retry_success_cnt));
|
||||
printf("[%d]prg_badblk_num : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].prg_badblk_num));
|
||||
printf("[%d]eras_badblk_num : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].eras_badblk_num));
|
||||
printf("[%d]read_badblk_num : %u\n", i,
|
||||
le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].unc_badblk_num));
|
||||
}
|
||||
|
||||
printf("[%d]temp_ctrl_limit_count : %u\n", i, le32_to_cpu(vendorlog->temp_ctrl_limit_cnt));
|
||||
printf("[%d]temp_ctrl_stop_count : %u\n", i, le32_to_cpu(vendorlog->temp_ctrl_stop_cnt));
|
||||
printf("------------wlm-----------------------\n");
|
||||
for (i = 0; i < 4; i++) {
|
||||
printf("------------part%d-----------------------\n", i);
|
||||
printf("[%d]fbb_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].fbb_count));
|
||||
printf("[%d]ebb_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].ebb_count));
|
||||
printf("[%d]lbb_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].lbb_count));
|
||||
printf("[%d]gc_read_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].gc_read_count));
|
||||
printf("[%d]gc_write_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].gc_write_count));
|
||||
printf("[%d]gc_write_fail_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].gc_write_fail_count));
|
||||
printf("[%d]force_gc_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].force_gc_count));
|
||||
printf("[%d]avg_pe_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].avg_pe_count));
|
||||
printf("[%d]max_pe_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].max_pe_count));
|
||||
printf("[%d]free_blk_num1 : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].free_blk_num1));
|
||||
printf("[%d]free_blk_num2 : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].free_blk_num2));
|
||||
}
|
||||
printf("[%d]temp_ctrl_limit_count : %u\n", i, le32_to_cpu(vendorlog->temp_ctrl_limit_cnt));
|
||||
printf("[%d]temp_ctrl_stop_count : %u\n", i, le32_to_cpu(vendorlog->temp_ctrl_stop_cnt));
|
||||
printf("------------wlm-----------------------\n");
|
||||
for (i = 0; i < 4; i++) {
|
||||
printf("------------part%d-----------------------\n", i);
|
||||
printf("[%d]fbb_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].fbb_count));
|
||||
printf("[%d]ebb_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].ebb_count));
|
||||
printf("[%d]lbb_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].lbb_count));
|
||||
printf("[%d]gc_read_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].gc_read_count));
|
||||
printf("[%d]gc_write_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].gc_write_count));
|
||||
printf("[%d]gc_write_fail_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].gc_write_fail_count));
|
||||
printf("[%d]force_gc_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].force_gc_count));
|
||||
printf("[%d]avg_pe_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].avg_pe_count));
|
||||
printf("[%d]max_pe_count : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].max_pe_count));
|
||||
printf("[%d]free_blk_num1 : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].free_blk_num1));
|
||||
printf("[%d]free_blk_num2 : %u\n", i,
|
||||
le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].free_blk_num2));
|
||||
}
|
||||
|
||||
printf("------------lkm-----------------------\n");
|
||||
printf("[%d]e2e_check_err_count1 : %u\n", i, le32_to_cpu(vendorlog->e2e_check_err_cnt1));
|
||||
printf("[%d]e2e_check_err_count2 : %u\n", i, le32_to_cpu(vendorlog->e2e_check_err_cnt2));
|
||||
printf("[%d]e2e_check_err_count3 : %u\n", i, le32_to_cpu(vendorlog->e2e_check_err_cnt3));
|
||||
printf("[%d]e2e_check_err_count4 : %u\n", i, le32_to_cpu(vendorlog->e2e_check_err_cnt4));
|
||||
printf("------------lkm-----------------------\n");
|
||||
printf("[%d]e2e_check_err_count1 : %u\n", i, le32_to_cpu(vendorlog->e2e_check_err_cnt1));
|
||||
printf("[%d]e2e_check_err_count2 : %u\n", i, le32_to_cpu(vendorlog->e2e_check_err_cnt2));
|
||||
printf("[%d]e2e_check_err_count3 : %u\n", i, le32_to_cpu(vendorlog->e2e_check_err_cnt3));
|
||||
printf("[%d]e2e_check_err_count4 : %u\n", i, le32_to_cpu(vendorlog->e2e_check_err_cnt4));
|
||||
}
|
||||
|
||||
void show_r1_media_err_log(r1_cli_vendor_log_t *vendorlog)
|
||||
{
|
||||
int i, j;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
printf("DM%d read err lba:\n", i);
|
||||
for (j = 0; j < 10; j++) {
|
||||
printf("[%d]lba : %" PRIu64 "\n", j, le64_to_cpu(vendorlog->media_err[i].lba_err[j]));
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
printf("DM%d read err lba:\n", i);
|
||||
for (j = 0; j < 10; j++)
|
||||
printf("[%d]lba : %" PRIu64 "\n", j, le64_to_cpu(vendorlog->media_err[i].lba_err[j]));
|
||||
}
|
||||
}
|
||||
|
||||
static int nvme_get_vendor_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
__u8 local_mem[BYTE_OF_4K];
|
||||
char *desc = "Get the Inspur vendor log";
|
||||
struct nvme_dev *dev;
|
||||
int err;
|
||||
__u8 local_mem[BYTE_OF_4K];
|
||||
char *desc = "Get the Inspur vendor log";
|
||||
struct nvme_dev *dev;
|
||||
int err;
|
||||
|
||||
OPT_ARGS(opts) = { OPT_END() };
|
||||
OPT_ARGS(opts) = { OPT_END() };
|
||||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err)
|
||||
return err;
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
memset(local_mem, 0, BYTE_OF_4K);
|
||||
err = nvme_get_log_simple(dev_fd(dev),
|
||||
(enum nvme_cmd_get_log_lid)VENDOR_SMART_LOG_PAGE,
|
||||
sizeof(r1_cli_vendor_log_t), local_mem);
|
||||
if (!err) {
|
||||
show_r1_vendor_log((r1_cli_vendor_log_t *)local_mem);
|
||||
show_r1_media_err_log((r1_cli_vendor_log_t *)local_mem);
|
||||
} else {
|
||||
nvme_show_status(err);
|
||||
}
|
||||
memset(local_mem, 0, BYTE_OF_4K);
|
||||
err = nvme_get_log_simple(dev_fd(dev),
|
||||
(enum nvme_cmd_get_log_lid)VENDOR_SMART_LOG_PAGE,
|
||||
sizeof(r1_cli_vendor_log_t), local_mem);
|
||||
if (!err) {
|
||||
show_r1_vendor_log((r1_cli_vendor_log_t *)local_mem);
|
||||
show_r1_media_err_log((r1_cli_vendor_log_t *)local_mem);
|
||||
} else {
|
||||
nvme_show_status(err);
|
||||
}
|
||||
|
||||
dev_close(dev);
|
||||
return err;
|
||||
dev_close(dev);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -16,25 +16,25 @@
|
|||
#define CREATE_CMD
|
||||
#include "intel-nvme.h"
|
||||
|
||||
struct __attribute__((packed)) nvme_additional_smart_log_item {
|
||||
struct __packed nvme_additional_smart_log_item {
|
||||
__u8 key;
|
||||
__u8 _kp[2];
|
||||
__u8 norm;
|
||||
__u8 _np;
|
||||
union __attribute__((packed)) {
|
||||
union __packed {
|
||||
__u8 raw[6];
|
||||
struct __attribute__((packed)) wear_level {
|
||||
struct __packed wear_level {
|
||||
__le16 min;
|
||||
__le16 max;
|
||||
__le16 avg;
|
||||
} wear_level;
|
||||
struct __attribute__((packed)) thermal_throttle {
|
||||
struct __packed thermal_throttle {
|
||||
__u8 pct;
|
||||
__u32 count;
|
||||
} thermal_throttle;
|
||||
} ;
|
||||
};
|
||||
__u8 _rp;
|
||||
} ;
|
||||
};
|
||||
|
||||
struct nvme_additional_smart_log {
|
||||
struct nvme_additional_smart_log_item program_fail_cnt;
|
||||
|
@ -79,7 +79,7 @@ static void json_intel_id_ctrl(struct nvme_vu_id_ctrl_field *id,
|
|||
struct json_object *root)
|
||||
{
|
||||
json_object_add_value_int(root, "ss", id->ss);
|
||||
json_object_add_value_string(root, "health", health );
|
||||
json_object_add_value_string(root, "health", health);
|
||||
json_object_add_value_int(root, "cls", id->cls);
|
||||
json_object_add_value_int(root, "nlw", id->nlw);
|
||||
json_object_add_value_int(root, "scap", id->scap);
|
||||
|
@ -92,7 +92,7 @@ static void json_intel_id_ctrl(struct nvme_vu_id_ctrl_field *id,
|
|||
|
||||
static void intel_id_ctrl(__u8 *vs, struct json_object *root)
|
||||
{
|
||||
struct nvme_vu_id_ctrl_field* id = (struct nvme_vu_id_ctrl_field *)vs;
|
||||
struct nvme_vu_id_ctrl_field *id = (struct nvme_vu_id_ctrl_field *)vs;
|
||||
|
||||
char health[21] = { 0 };
|
||||
char bl[9] = { 0 };
|
||||
|
@ -100,15 +100,10 @@ static void intel_id_ctrl(__u8 *vs, struct json_object *root)
|
|||
char mic_bl[5] = { 0 };
|
||||
char mic_fw[5] = { 0 };
|
||||
|
||||
|
||||
if (id->health[0]==0)
|
||||
{
|
||||
snprintf(health, 21, "%s", "healthy");
|
||||
}
|
||||
if (id->health[0] == 0)
|
||||
snprintf(health, 21, "%s", "healthy");
|
||||
else
|
||||
{
|
||||
snprintf(health, 21, "%s", id->health);
|
||||
}
|
||||
snprintf(health, 21, "%s", id->health);
|
||||
|
||||
snprintf(bl, 9, "%s", id->bl);
|
||||
snprintf(ww, 19, "%02X%02X%02X%02X%02X%02X%02X%02X", id->ww[7],
|
||||
|
@ -203,57 +198,57 @@ static void show_intel_smart_log_jsn(struct nvme_additional_smart_log *smart,
|
|||
|
||||
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_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_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_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_int(entry_stats, "raw", int48_to_long(smart->host_bytes_written.raw));
|
||||
json_object_add_value_object(dev_stats, "host_bytes_written", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->host_ctx_wear_used.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->host_ctx_wear_used.raw));
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->host_ctx_wear_used.raw));
|
||||
json_object_add_value_object(dev_stats, "host_ctx_wear_used", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->perf_stat_indicator.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->perf_stat_indicator.raw));
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->perf_stat_indicator.raw));
|
||||
json_object_add_value_object(dev_stats, "perf_stat_indicator", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->re_alloc_sectr_cnt.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->re_alloc_sectr_cnt.raw));
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->re_alloc_sectr_cnt.raw));
|
||||
json_object_add_value_object(dev_stats, "re_alloc_sectr_cnt", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->soft_ecc_err_rate.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->soft_ecc_err_rate.raw));
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->soft_ecc_err_rate.raw));
|
||||
json_object_add_value_object(dev_stats, "soft_ecc_err_rate", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->unexp_power_loss.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->unexp_power_loss.raw));
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->unexp_power_loss.raw));
|
||||
json_object_add_value_object(dev_stats, "unexp_power_loss", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->media_bytes_read.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->media_bytes_read.raw));
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->media_bytes_read.raw));
|
||||
json_object_add_value_object(dev_stats, "media_bytes_read", entry_stats);
|
||||
|
||||
entry_stats = json_create_object();
|
||||
json_object_add_value_int(entry_stats, "normalized", smart->avail_fw_downgrades.norm);
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->avail_fw_downgrades.raw));
|
||||
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->avail_fw_downgrades.raw));
|
||||
json_object_add_value_object(dev_stats, "avail_fw_downgrades", entry_stats);
|
||||
|
||||
json_object_add_value_object(root, "Device stats", dev_stats);
|
||||
|
@ -337,11 +332,11 @@ static void show_intel_smart_log(struct nvme_additional_smart_log *smart,
|
|||
|
||||
static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "Get Intel vendor specific additional smart log (optionally, "\
|
||||
"for the specified namespace), and show it.";
|
||||
const char *desc =
|
||||
"Get Intel vendor specific additional smart log (optionally, for the specified namespace), 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";
|
||||
const char *json = "Dump output in json format";
|
||||
|
||||
struct nvme_additional_smart_log smart_log;
|
||||
struct nvme_dev *dev;
|
||||
|
@ -379,9 +374,9 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
|
|||
dev->name);
|
||||
else
|
||||
d_raw((unsigned char *)&smart_log, sizeof(smart_log));
|
||||
}
|
||||
else if (err > 0)
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
}
|
||||
dev_close(dev);
|
||||
return err;
|
||||
}
|
||||
|
@ -490,7 +485,7 @@ struct intel_lat_stats {
|
|||
__u32 data[1216];
|
||||
};
|
||||
|
||||
struct __attribute__((__packed__)) optane_lat_stats {
|
||||
struct __packed optane_lat_stats {
|
||||
__u16 maj;
|
||||
__u16 min;
|
||||
__u64 data[9];
|
||||
|
@ -645,7 +640,7 @@ static void show_optane_lat_stats_bucket(struct optane_lat_stats *stats,
|
|||
set_unit_string(buffer, upper_us, fu, end_type);
|
||||
printf("%-*s", COL_WIDTH, buffer);
|
||||
|
||||
printf("%-*lu\n", COL_WIDTH, (long unsigned int)stats->data[i]);
|
||||
printf("%-*lu\n", COL_WIDTH, (unsigned long)stats->data[i]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -888,6 +883,7 @@ static void json_lat_stats_v1000_0(struct optane_lat_stats *stats, int write)
|
|||
}
|
||||
|
||||
struct json_object *subroot = json_create_object();
|
||||
|
||||
json_object_add_value_object(root, "Average latency since last reset", subroot);
|
||||
|
||||
json_object_add_value_uint(subroot, "value in us", stats->data[8]);
|
||||
|
@ -900,12 +896,13 @@ static void json_lat_stats_v1000_0(struct optane_lat_stats *stats, int write)
|
|||
static void show_lat_stats_v1000_0(struct optane_lat_stats *stats, int write)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (write) {
|
||||
for (i = 0; i < OPTANE_V1000_BUCKET_LEN - 1; i++)
|
||||
show_optane_lat_stats_bucket(stats,
|
||||
v1000_bucket.write[i],
|
||||
NOINF,
|
||||
v1000_bucket.write[i + 1] -1,
|
||||
v1000_bucket.write[i + 1] - 1,
|
||||
NOINF, i);
|
||||
|
||||
show_optane_lat_stats_bucket(stats, v1000_bucket.write[i],
|
||||
|
@ -916,7 +913,7 @@ static void show_lat_stats_v1000_0(struct optane_lat_stats *stats, int write)
|
|||
show_optane_lat_stats_bucket(stats,
|
||||
v1000_bucket.read[i],
|
||||
NOINF,
|
||||
v1000_bucket.read[i + 1] -1,
|
||||
v1000_bucket.read[i + 1] - 1,
|
||||
NOINF, i);
|
||||
|
||||
show_optane_lat_stats_bucket(stats, v1000_bucket.read[i],
|
||||
|
@ -924,7 +921,7 @@ static void show_lat_stats_v1000_0(struct optane_lat_stats *stats, int write)
|
|||
POSINF, i);
|
||||
}
|
||||
|
||||
printf("Average latency since last reset: %lu us\n", (long unsigned int)stats->data[8]);
|
||||
printf("Average latency since last reset: %lu us\n", (unsigned long)stats->data[8]);
|
||||
|
||||
}
|
||||
|
||||
|
@ -1035,7 +1032,7 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
|
|||
|
||||
const char *desc = "Get Intel Latency Statistics log and show it.";
|
||||
const char *raw = "Dump output in binary format";
|
||||
const char *json= "Dump output in json format";
|
||||
const char *json = "Dump output in json format";
|
||||
const char *write = "Get write statistics (read default)";
|
||||
|
||||
struct config {
|
||||
|
@ -1159,11 +1156,11 @@ struct intel_event_header {
|
|||
};
|
||||
|
||||
struct intel_vu_log {
|
||||
struct intel_vu_version ver;
|
||||
__u32 header;
|
||||
__u32 size;
|
||||
__u32 numcores;
|
||||
__u8 reserved[4080];
|
||||
struct intel_vu_version ver;
|
||||
__u32 header;
|
||||
__u32 size;
|
||||
__u32 numcores;
|
||||
__u8 reserved[4080];
|
||||
};
|
||||
|
||||
struct intel_vu_nlog {
|
||||
|
@ -1197,7 +1194,7 @@ struct intel_cd_log {
|
|||
__u32 reserved2 : 16;
|
||||
} fields;
|
||||
__u32 entireDword;
|
||||
} u;
|
||||
} u;
|
||||
};
|
||||
|
||||
static void print_intel_nlog(struct intel_vu_nlog *intel_nlog)
|
||||
|
@ -1272,7 +1269,7 @@ static int write_header(__u8 *buf, int fd, size_t amnt)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int read_header(struct nvme_passthru_cmd *cmd,__u8 *buf, int ioctl_fd,
|
||||
static int read_header(struct nvme_passthru_cmd *cmd, __u8 *buf, int ioctl_fd,
|
||||
__u32 dw12, int nsid)
|
||||
{
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
|
@ -1476,7 +1473,7 @@ static int get_internal_log(int argc, char **argv, struct command *command,
|
|||
if (err)
|
||||
goto out;
|
||||
|
||||
} else if(cfg.log == 0) {
|
||||
} else if (cfg.log == 0) {
|
||||
/* If the user selected to read the entire nlog */
|
||||
if (count > 1)
|
||||
cdlog.u.fields.selectNlog = i;
|
||||
|
@ -1640,7 +1637,7 @@ static int enable_lat_stats_tracking(int argc, char **argv,
|
|||
break;
|
||||
default:
|
||||
printf("%d not supported.\n", option);
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
dev_close(dev);
|
||||
return err;
|
||||
|
@ -1697,6 +1694,7 @@ static int set_lat_stats_thresholds(int argc, char **argv,
|
|||
|
||||
if (media_version[0] == 1000) {
|
||||
int thresholds[OPTANE_V1000_BUCKET_LEN] = {0};
|
||||
|
||||
num = argconfig_parse_comma_sep_array(cfg.bucket_thresholds,
|
||||
thresholds,
|
||||
sizeof(thresholds));
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,220 +2,216 @@
|
|||
#ifndef __MEMBLAZE_UTILS_H__
|
||||
#define __MEMBLAZE_UTILS_H__
|
||||
|
||||
#define SMART_INFO_OLD_SIZE 512
|
||||
#define SMART_INFO_NEW_SIZE 4096
|
||||
#define SMART_INFO_OLD_SIZE 512
|
||||
#define SMART_INFO_NEW_SIZE 4096
|
||||
|
||||
#define ID_SIZE 3
|
||||
#define NM_SIZE 2
|
||||
#define RAW_SIZE 7
|
||||
#define ID_SIZE 3
|
||||
#define NM_SIZE 2
|
||||
#define RAW_SIZE 7
|
||||
|
||||
// Intel Format & new format
|
||||
/* Raisin Additional smart external ID */
|
||||
#define RAISIN_SI_VD_PROGRAM_FAIL_ID 0xAB
|
||||
#define RAISIN_SI_VD_ERASE_FAIL_ID 0xAC
|
||||
#define RAISIN_SI_VD_WEARLEVELING_COUNT_ID 0xAD
|
||||
#define RAISIN_SI_VD_E2E_DECTECTION_COUNT_ID 0xB8
|
||||
#define RAISIN_SI_VD_PCIE_CRC_ERR_COUNT_ID 0xC7
|
||||
#define RAISIN_SI_VD_TIMED_WORKLOAD_MEDIA_WEAR_ID 0xE2
|
||||
#define RAISIN_SI_VD_TIMED_WORKLOAD_HOST_READ_ID 0xE3
|
||||
#define RAISIN_SI_VD_TIMED_WORKLOAD_TIMER_ID 0xE4
|
||||
#define RAISIN_SI_VD_THERMAL_THROTTLE_STATUS_ID 0xEA
|
||||
#define RAISIN_SI_VD_RETRY_BUFF_OVERFLOW_COUNT_ID 0xF0
|
||||
#define RAISIN_SI_VD_PLL_LOCK_LOSS_COUNT_ID 0xF3
|
||||
#define RAISIN_SI_VD_TOTAL_WRITE_ID 0xF4
|
||||
#define RAISIN_SI_VD_HOST_WRITE_ID 0xF5
|
||||
#define RAISIN_SI_VD_SYSTEM_AREA_LIFE_LEFT_ID 0xF6
|
||||
#define RAISIN_SI_VD_TOTAL_READ_ID 0xFA
|
||||
#define RAISIN_SI_VD_TEMPT_SINCE_BORN_ID 0xE7
|
||||
#define RAISIN_SI_VD_POWER_CONSUMPTION_ID 0xE8
|
||||
#define RAISIN_SI_VD_TEMPT_SINCE_BOOTUP_ID 0xAF
|
||||
#define RAISIN_SI_VD_POWER_LOSS_PROTECTION_ID 0xEC
|
||||
#define RAISIN_SI_VD_READ_FAIL_ID 0xF2
|
||||
#define RAISIN_SI_VD_THERMAL_THROTTLE_TIME_ID 0xEB
|
||||
#define RAISIN_SI_VD_FLASH_MEDIA_ERROR_ID 0xED
|
||||
#define RAISIN_SI_VD_PROGRAM_FAIL_ID 0xAB
|
||||
#define RAISIN_SI_VD_ERASE_FAIL_ID 0xAC
|
||||
#define RAISIN_SI_VD_WEARLEVELING_COUNT_ID 0xAD
|
||||
#define RAISIN_SI_VD_E2E_DECTECTION_COUNT_ID 0xB8
|
||||
#define RAISIN_SI_VD_PCIE_CRC_ERR_COUNT_ID 0xC7
|
||||
#define RAISIN_SI_VD_TIMED_WORKLOAD_MEDIA_WEAR_ID 0xE2
|
||||
#define RAISIN_SI_VD_TIMED_WORKLOAD_HOST_READ_ID 0xE3
|
||||
#define RAISIN_SI_VD_TIMED_WORKLOAD_TIMER_ID 0xE4
|
||||
#define RAISIN_SI_VD_THERMAL_THROTTLE_STATUS_ID 0xEA
|
||||
#define RAISIN_SI_VD_RETRY_BUFF_OVERFLOW_COUNT_ID 0xF0
|
||||
#define RAISIN_SI_VD_PLL_LOCK_LOSS_COUNT_ID 0xF3
|
||||
#define RAISIN_SI_VD_TOTAL_WRITE_ID 0xF4
|
||||
#define RAISIN_SI_VD_HOST_WRITE_ID 0xF5
|
||||
#define RAISIN_SI_VD_SYSTEM_AREA_LIFE_LEFT_ID 0xF6
|
||||
#define RAISIN_SI_VD_TOTAL_READ_ID 0xFA
|
||||
#define RAISIN_SI_VD_TEMPT_SINCE_BORN_ID 0xE7
|
||||
#define RAISIN_SI_VD_POWER_CONSUMPTION_ID 0xE8
|
||||
#define RAISIN_SI_VD_TEMPT_SINCE_BOOTUP_ID 0xAF
|
||||
#define RAISIN_SI_VD_POWER_LOSS_PROTECTION_ID 0xEC
|
||||
#define RAISIN_SI_VD_READ_FAIL_ID 0xF2
|
||||
#define RAISIN_SI_VD_THERMAL_THROTTLE_TIME_ID 0xEB
|
||||
#define RAISIN_SI_VD_FLASH_MEDIA_ERROR_ID 0xED
|
||||
|
||||
/* Raisin Addtional smart internal ID */
|
||||
typedef enum
|
||||
{
|
||||
/* smart attr following intel */
|
||||
RAISIN_SI_VD_PROGRAM_FAIL = 0, /* 0xAB */
|
||||
RAISIN_SI_VD_ERASE_FAIL = 1, /* 0xAC */
|
||||
RAISIN_SI_VD_WEARLEVELING_COUNT = 2,/* 0xAD */
|
||||
RAISIN_SI_VD_E2E_DECTECTION_COUNT = 3, /* 0xB8 */
|
||||
RAISIN_SI_VD_PCIE_CRC_ERR_COUNT = 4, /* 0xC7, 2 port data in one attribute */
|
||||
RAISIN_SI_VD_TIMED_WORKLOAD_MEDIA_WEAR = 5, /* 0xE2 , unknown definition*/
|
||||
RAISIN_SI_VD_TIMED_WORKLOAD_HOST_READ = 6, /* 0xE3 , unknown definition */
|
||||
RAISIN_SI_VD_TIMED_WORKLOAD_TIMER = 7, /* 0xE4 , unknown definition */
|
||||
RAISIN_SI_VD_THERMAL_THROTTLE_STATUS = 8, /* 0xEA */
|
||||
RAISIN_SI_VD_RETRY_BUFF_OVERFLOW_COUNT = 9, /* 0xF0, unknown definition*/
|
||||
RAISIN_SI_VD_PLL_LOCK_LOSS_COUNT = 10, /* 0xF3, unknown definition*/
|
||||
RAISIN_SI_VD_TOTAL_WRITE = 11, /* 0xF4, unit is 32MiB */
|
||||
RAISIN_SI_VD_HOST_WRITE = 12, /* 0xF5, unit is 32MiB */
|
||||
RAISIN_SI_VD_SYSTEM_AREA_LIFE_LEFT = 13, /* 0xF6, unknown definition*/
|
||||
RAISIN_SI_VD_TOTAL_READ = 14, /* 0xFA, unit is 32MiB */
|
||||
/* smart attr following intel */
|
||||
RAISIN_SI_VD_PROGRAM_FAIL = 0, /* 0xAB */
|
||||
RAISIN_SI_VD_ERASE_FAIL = 1, /* 0xAC */
|
||||
RAISIN_SI_VD_WEARLEVELING_COUNT = 2,/* 0xAD */
|
||||
RAISIN_SI_VD_E2E_DECTECTION_COUNT = 3, /* 0xB8 */
|
||||
RAISIN_SI_VD_PCIE_CRC_ERR_COUNT = 4, /* 0xC7, 2 port data in one attribute */
|
||||
RAISIN_SI_VD_TIMED_WORKLOAD_MEDIA_WEAR = 5, /* 0xE2 , unknown definition*/
|
||||
RAISIN_SI_VD_TIMED_WORKLOAD_HOST_READ = 6, /* 0xE3 , unknown definition */
|
||||
RAISIN_SI_VD_TIMED_WORKLOAD_TIMER = 7, /* 0xE4 , unknown definition */
|
||||
RAISIN_SI_VD_THERMAL_THROTTLE_STATUS = 8, /* 0xEA */
|
||||
RAISIN_SI_VD_RETRY_BUFF_OVERFLOW_COUNT = 9, /* 0xF0, unknown definition*/
|
||||
RAISIN_SI_VD_PLL_LOCK_LOSS_COUNT = 10, /* 0xF3, unknown definition*/
|
||||
RAISIN_SI_VD_TOTAL_WRITE = 11, /* 0xF4, unit is 32MiB */
|
||||
RAISIN_SI_VD_HOST_WRITE = 12, /* 0xF5, unit is 32MiB */
|
||||
RAISIN_SI_VD_SYSTEM_AREA_LIFE_LEFT = 13, /* 0xF6, unknown definition*/
|
||||
RAISIN_SI_VD_TOTAL_READ = 14, /* 0xFA, unit is 32MiB */
|
||||
|
||||
/* smart attr self defined */
|
||||
RAISIN_SI_VD_TEMPT_SINCE_BORN = 15, /* 0xE7 */
|
||||
RAISIN_SI_VD_POWER_CONSUMPTION = 16, /* 0xE8 */
|
||||
RAISIN_SI_VD_TEMPT_SINCE_BOOTUP = 17, /* 0xAF */
|
||||
RAISIN_SI_VD_POWER_LOSS_PROTECTION = 18, /* 0xEC */
|
||||
RAISIN_SI_VD_READ_FAIL = 19, /* 0xF2 */
|
||||
RAISIN_SI_VD_THERMAL_THROTTLE_TIME = 20, /* 0xEB */
|
||||
RAISIN_SI_VD_FLASH_MEDIA_ERROR = 21, /* 0xED */
|
||||
RAISIN_SI_VD_SMART_INFO_ITEMS_MAX,
|
||||
/* smart attr self defined */
|
||||
RAISIN_SI_VD_TEMPT_SINCE_BORN = 15, /* 0xE7 */
|
||||
RAISIN_SI_VD_POWER_CONSUMPTION = 16, /* 0xE8 */
|
||||
RAISIN_SI_VD_TEMPT_SINCE_BOOTUP = 17, /* 0xAF */
|
||||
RAISIN_SI_VD_POWER_LOSS_PROTECTION = 18, /* 0xEC */
|
||||
RAISIN_SI_VD_READ_FAIL = 19, /* 0xF2 */
|
||||
RAISIN_SI_VD_THERMAL_THROTTLE_TIME = 20, /* 0xEB */
|
||||
RAISIN_SI_VD_FLASH_MEDIA_ERROR = 21, /* 0xED */
|
||||
RAISIN_SI_VD_SMART_INFO_ITEMS_MAX,
|
||||
} RAISIN_si_vendor_smart_item_e;
|
||||
|
||||
// Memblaze Format & old format
|
||||
enum {
|
||||
/*0*/TOTAL_WRITE = 0,
|
||||
/*1*/TOTAL_READ,
|
||||
/*2*/THERMAL_THROTTLE,
|
||||
/*3*/TEMPT_SINCE_RESET,
|
||||
/*4*/POWER_CONSUMPTION,
|
||||
/*5*/TEMPT_SINCE_BOOTUP,
|
||||
/*6*/POWER_LOSS_PROTECTION,
|
||||
/*7*/WEARLEVELING_COUNT,
|
||||
/*8*/HOST_WRITE,
|
||||
/*9*/THERMAL_THROTTLE_CNT,
|
||||
/*10*/CORRECT_PCIE_PORT0,
|
||||
/*11*/CORRECT_PCIE_PORT1,
|
||||
/*12*/REBUILD_FAIL,
|
||||
/*13*/ERASE_FAIL,
|
||||
/*14*/PROGRAM_FAIL,
|
||||
/*15*/READ_FAIL,
|
||||
/*16*/NR_SMART_ITEMS = RAISIN_SI_VD_SMART_INFO_ITEMS_MAX,
|
||||
/*0*/TOTAL_WRITE = 0,
|
||||
/*1*/TOTAL_READ,
|
||||
/*2*/THERMAL_THROTTLE,
|
||||
/*3*/TEMPT_SINCE_RESET,
|
||||
/*4*/POWER_CONSUMPTION,
|
||||
/*5*/TEMPT_SINCE_BOOTUP,
|
||||
/*6*/POWER_LOSS_PROTECTION,
|
||||
/*7*/WEARLEVELING_COUNT,
|
||||
/*8*/HOST_WRITE,
|
||||
/*9*/THERMAL_THROTTLE_CNT,
|
||||
/*10*/CORRECT_PCIE_PORT0,
|
||||
/*11*/CORRECT_PCIE_PORT1,
|
||||
/*12*/REBUILD_FAIL,
|
||||
/*13*/ERASE_FAIL,
|
||||
/*14*/PROGRAM_FAIL,
|
||||
/*15*/READ_FAIL,
|
||||
/*16*/NR_SMART_ITEMS = RAISIN_SI_VD_SMART_INFO_ITEMS_MAX,
|
||||
};
|
||||
|
||||
// Memblaze Format & old format
|
||||
#pragma pack(push, 1)
|
||||
struct nvme_memblaze_smart_log_item {
|
||||
__u8 id[3];
|
||||
union {
|
||||
__u8 __nmval[2];
|
||||
__le16 nmval;
|
||||
};
|
||||
union {
|
||||
__u8 rawval[6];
|
||||
struct temperature {
|
||||
__le16 max;
|
||||
__le16 min;
|
||||
__le16 curr;
|
||||
} temperature;
|
||||
struct power {
|
||||
__le16 max;
|
||||
__le16 min;
|
||||
__le16 curr;
|
||||
} power;
|
||||
struct thermal_throttle_mb {
|
||||
__u8 on;
|
||||
__u32 count;
|
||||
} thermal_throttle;
|
||||
struct temperature_p {
|
||||
__le16 max;
|
||||
__le16 min;
|
||||
} temperature_p;
|
||||
struct power_loss_protection {
|
||||
__u8 curr;
|
||||
} power_loss_protection;
|
||||
struct wearleveling_count {
|
||||
__le16 min;
|
||||
__le16 max;
|
||||
__le16 avg;
|
||||
} wearleveling_count;
|
||||
struct thermal_throttle_cnt {
|
||||
__u8 active;
|
||||
__le32 cnt;
|
||||
} thermal_throttle_cnt;
|
||||
};
|
||||
__u8 resv;
|
||||
__u8 id[3];
|
||||
union {
|
||||
__u8 __nmval[2];
|
||||
__le16 nmval;
|
||||
};
|
||||
union {
|
||||
__u8 rawval[6];
|
||||
struct temperature {
|
||||
__le16 max;
|
||||
__le16 min;
|
||||
__le16 curr;
|
||||
} temperature;
|
||||
struct power {
|
||||
__le16 max;
|
||||
__le16 min;
|
||||
__le16 curr;
|
||||
} power;
|
||||
struct thermal_throttle_mb {
|
||||
__u8 on;
|
||||
__u32 count;
|
||||
} thermal_throttle;
|
||||
struct temperature_p {
|
||||
__le16 max;
|
||||
__le16 min;
|
||||
} temperature_p;
|
||||
struct power_loss_protection {
|
||||
__u8 curr;
|
||||
} power_loss_protection;
|
||||
struct wearleveling_count {
|
||||
__le16 min;
|
||||
__le16 max;
|
||||
__le16 avg;
|
||||
} wearleveling_count;
|
||||
struct thermal_throttle_cnt {
|
||||
__u8 active;
|
||||
__le32 cnt;
|
||||
} thermal_throttle_cnt;
|
||||
};
|
||||
__u8 resv;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct nvme_memblaze_smart_log {
|
||||
struct nvme_memblaze_smart_log_item items[NR_SMART_ITEMS];
|
||||
__u8 resv[SMART_INFO_OLD_SIZE - sizeof(struct nvme_memblaze_smart_log_item) * NR_SMART_ITEMS];
|
||||
struct nvme_memblaze_smart_log_item items[NR_SMART_ITEMS];
|
||||
__u8 resv[SMART_INFO_OLD_SIZE - sizeof(struct nvme_memblaze_smart_log_item) * NR_SMART_ITEMS];
|
||||
};
|
||||
|
||||
// Intel Format & new format
|
||||
struct nvme_p4_smart_log_item
|
||||
{
|
||||
/* Item identifier */
|
||||
__u8 id[ID_SIZE];
|
||||
/* Normalized value or percentage. In the range from 0 to 100. */
|
||||
__u8 nmVal[NM_SIZE];
|
||||
/* raw value */
|
||||
__u8 rawVal[RAW_SIZE];
|
||||
/* Item identifier */
|
||||
__u8 id[ID_SIZE];
|
||||
/* Normalized value or percentage. In the range from 0 to 100. */
|
||||
__u8 nmVal[NM_SIZE];
|
||||
/* raw value */
|
||||
__u8 rawVal[RAW_SIZE];
|
||||
};
|
||||
|
||||
struct nvme_p4_smart_log
|
||||
{
|
||||
struct nvme_p4_smart_log_item itemArr[NR_SMART_ITEMS];
|
||||
struct nvme_p4_smart_log_item itemArr[NR_SMART_ITEMS];
|
||||
|
||||
/**
|
||||
* change 512 to 4096.
|
||||
* because micron's getlogpage request,the size of many commands have changed to 4k.
|
||||
* request size > user malloc size,casuing parameters that are closed in momery are dirty.
|
||||
*/
|
||||
__u8 resv[SMART_INFO_NEW_SIZE - sizeof(struct nvme_p4_smart_log_item) * NR_SMART_ITEMS];
|
||||
/**
|
||||
* change 512 to 4096.
|
||||
* because micron's getlogpage request,the size of many commands have changed to 4k.
|
||||
* request size > user malloc size,casuing parameters that are closed in momery are dirty.
|
||||
*/
|
||||
__u8 resv[SMART_INFO_NEW_SIZE - sizeof(struct nvme_p4_smart_log_item) * NR_SMART_ITEMS];
|
||||
};
|
||||
|
||||
// base
|
||||
#define DD do{ printf("=Memblaze= %s[%d]-%s():\n", __FILE__, __LINE__, __func__); }while(0)
|
||||
#define DE(str) do{ printf("===ERROR!=== %s[%d]-%s():str=%s\n", __FILE__, __LINE__, __func__, \
|
||||
str); }while(0)
|
||||
#define DD do{ printf("=Memblaze= %s[%d]-%s():\n", __FILE__, __LINE__, __func__); }while(0)
|
||||
#define DE(str) do{ printf("===ERROR!=== %s[%d]-%s():str=%s\n", __FILE__, __LINE__, __func__, \
|
||||
str); }while(0)
|
||||
// integer
|
||||
#define DI(i) do{ printf("=Memblaze= %s[%d]-%s():int=%d\n", __FILE__, __LINE__, __func__, \
|
||||
(int)i); } while(0)
|
||||
#define DPI(prompt, i) do{ printf("=Memblaze= %s[%d]-%s():%s=%d\n", __FILE__, __LINE__, __func__, \
|
||||
prompt, i); }while(0)
|
||||
#define DAI(prompt, i, arr, max) do{ printf("=Memblaze= %s[%d]-%s():%s", __FILE__, __LINE__, __func__, prompt); \
|
||||
for(i=0;i<max;i++) printf(" %d:%d", i, arr[i]); \
|
||||
printf("\n"); }while(0)
|
||||
#define DI(i) do{ printf("=Memblaze= %s[%d]-%s():int=%d\n", __FILE__, __LINE__, __func__, \
|
||||
(int)i); } while(0)
|
||||
#define DPI(prompt, i) do{ printf("=Memblaze= %s[%d]-%s():%s=%d\n", __FILE__, __LINE__, __func__, \
|
||||
prompt, i); }while(0)
|
||||
#define DAI(prompt, i, arr, max) do{ printf("=Memblaze= %s[%d]-%s():%s", __FILE__, __LINE__, __func__, prompt); \
|
||||
for(i=0;i<max;i++) printf(" %d:%d", i, arr[i]); \
|
||||
printf("\n"); }while(0)
|
||||
// char
|
||||
#define DC(c) do{ printf("=Memblaze= %s[%d]-%s():char=%c\n", __FILE__, __LINE__, __func__, c); \
|
||||
}while(0)
|
||||
#define DPC(prompt, c) do{ printf("=Memblaze= %s[%d]-%s():%s=%c\n", __FILE__, __LINE__, __func__, \
|
||||
prompt, c); }while(0)
|
||||
#define DC(c) do{ printf("=Memblaze= %s[%d]-%s():char=%c\n", __FILE__, __LINE__, __func__, c); \
|
||||
}while(0)
|
||||
#define DPC(prompt, c) do{ printf("=Memblaze= %s[%d]-%s():%s=%c\n", __FILE__, __LINE__, __func__, \
|
||||
prompt, c); }while(0)
|
||||
// address
|
||||
#define DA(add) do{ printf("=Memblaze= %s[%d]-%s():address=0x%08X\n", __FILE__, __LINE__, \
|
||||
__func__, add); }while(0)
|
||||
#define DPA(prompt, add) do{ printf("=Memblaze= %s[%d]-%s():%s=0x%08X\n", __FILE__, __LINE__, __func__, \
|
||||
prompt, add); }while(0)
|
||||
#define DA(add) do{ printf("=Memblaze= %s[%d]-%s():address=0x%08X\n", __FILE__, __LINE__, \
|
||||
__func__, add); }while(0)
|
||||
#define DPA(prompt, add) do{ printf("=Memblaze= %s[%d]-%s():%s=0x%08X\n", __FILE__, __LINE__, __func__, \
|
||||
prompt, add); }while(0)
|
||||
// string
|
||||
#define DS(str) do{ printf("=Memblaze= %s[%d]-%s():str=%s\n", __FILE__, __LINE__, __func__, str); \
|
||||
}while(0)
|
||||
#define DPS(prompt, str) do{ printf("=Memblaze= %s[%d]-%s():%s=%s\n", __FILE__, __LINE__, __func__, \
|
||||
prompt, str); }while(0)
|
||||
#define DAS(prompt, i, arr, max) do{ printf("=Memblaze= %s[%d]-%s():%s", __FILE__, __LINE__, __func__, prompt); \
|
||||
for(i=0;i<max;i++) printf(" %d:%s", i, arr[i]); \
|
||||
printf("\n"); }while(0)
|
||||
#define DS(str) do{ printf("=Memblaze= %s[%d]-%s():str=%s\n", __FILE__, __LINE__, __func__, str); \
|
||||
}while(0)
|
||||
#define DPS(prompt, str) do{ printf("=Memblaze= %s[%d]-%s():%s=%s\n", __FILE__, __LINE__, __func__, \
|
||||
prompt, str); }while(0)
|
||||
#define DAS(prompt, i, arr, max) do{ printf("=Memblaze= %s[%d]-%s():%s", __FILE__, __LINE__, __func__, prompt); \
|
||||
for(i=0;i<max;i++) printf(" %d:%s", i, arr[i]); \
|
||||
printf("\n"); }while(0)
|
||||
// array
|
||||
#define DR(str, k) do{ int ip; for(ip=0;ip<k;ip++) if(NULL != argv[ip]) \
|
||||
printf("=Memblaze= %s[%d]-%s():%d=%s\n", \
|
||||
__FILE__, __LINE__, __func__, ip, str[ip]); }while(0)
|
||||
#define DARG do{ DPI("argc", argc); \
|
||||
int ip; for(ip=0;ip<argc;ip++) if(NULL != argv[ip]) \
|
||||
printf("=Memblaze= %s[%d]-%s():%d=%s\n", \
|
||||
__FILE__, __LINE__, __func__, ip, argv[ip]); }while(0)
|
||||
#define DR(str, k) do{ int ip; for(ip=0;ip<k;ip++) if(NULL != argv[ip]) \
|
||||
printf("=Memblaze= %s[%d]-%s():%d=%s\n", \
|
||||
__FILE__, __LINE__, __func__, ip, str[ip]); }while(0)
|
||||
#define DARG do{ DPI("argc", argc); \
|
||||
int ip; for(ip=0;ip<argc;ip++) if(NULL != argv[ip]) \
|
||||
printf("=Memblaze= %s[%d]-%s():%d=%s\n", \
|
||||
__FILE__, __LINE__, __func__, ip, argv[ip]); }while(0)
|
||||
|
||||
#define fPRINT_PARAM1(format) \
|
||||
{ \
|
||||
do { \
|
||||
if (fdi) \
|
||||
fprintf(fdi, format); \
|
||||
if (print) \
|
||||
printf(format); \
|
||||
} while (0); \
|
||||
}
|
||||
#define fPRINT_PARAM1(format) \
|
||||
do { \
|
||||
if (fdi) \
|
||||
fprintf(fdi, format); \
|
||||
if (print) \
|
||||
printf(format); \
|
||||
} while (0)
|
||||
|
||||
#define fPRINT_PARAM2(format, value) \
|
||||
{ \
|
||||
do { \
|
||||
if (fdi) \
|
||||
fprintf(fdi, format, value); \
|
||||
if (print) \
|
||||
printf(format, value); \
|
||||
} while (0); \
|
||||
}
|
||||
#define fPRINT_PARAM2(format, value) \
|
||||
do { \
|
||||
if (fdi) \
|
||||
fprintf(fdi, format, value); \
|
||||
if (print) \
|
||||
printf(format, value); \
|
||||
} while (0)
|
||||
|
||||
#endif // __MEMBLAZE_UTILS_H__
|
||||
|
|
|
@ -12,6 +12,7 @@ if json_c_dep.found()
|
|||
'plugins/intel/intel-nvme.c',
|
||||
'plugins/memblaze/memblaze-nvme.c',
|
||||
'plugins/micron/micron-nvme.c',
|
||||
'plugins/nbft/nbft-plugin.c',
|
||||
'plugins/netapp/netapp-nvme.c',
|
||||
'plugins/nvidia/nvidia-nvme.c',
|
||||
'plugins/scaleflux/sfx-nvme.c',
|
||||
|
|
File diff suppressed because it is too large
Load diff
563
plugins/nbft/nbft-plugin.c
Normal file
563
plugins/nbft/nbft-plugin.c
Normal file
|
@ -0,0 +1,563 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <fnmatch.h>
|
||||
|
||||
#include "nvme-print.h"
|
||||
#include "nvme.h"
|
||||
#include "nbft.h"
|
||||
#include "libnvme.h"
|
||||
#include "fabrics.h"
|
||||
|
||||
#define CREATE_CMD
|
||||
#include "nbft-plugin.h"
|
||||
|
||||
static const char dash[100] = {[0 ... 98] = '-', [99] = '\0'};
|
||||
|
||||
#define PCI_SEGMENT(sbdf) ((sbdf & 0xffff0000) >> 16)
|
||||
#define PCI_BUS(sbdf) ((sbdf & 0x0000ff00) >> 8)
|
||||
#define PCI_DEV(sbdf) ((sbdf & 0x000000f8) >> 3)
|
||||
#define PCI_FUNC(sbdf) ((sbdf & 0x00000007) >> 0)
|
||||
|
||||
static const char *pci_sbdf_to_string(__u16 pci_sbdf)
|
||||
{
|
||||
static char pcidev[13];
|
||||
|
||||
snprintf(pcidev, sizeof(pcidev), "%x:%x:%x.%x",
|
||||
PCI_SEGMENT(pci_sbdf),
|
||||
PCI_BUS(pci_sbdf),
|
||||
PCI_DEV(pci_sbdf),
|
||||
PCI_FUNC(pci_sbdf));
|
||||
return pcidev;
|
||||
}
|
||||
|
||||
static char *mac_addr_to_string(unsigned char mac_addr[6])
|
||||
{
|
||||
static char mac_string[18];
|
||||
|
||||
snprintf(mac_string, sizeof(mac_string), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
mac_addr[0],
|
||||
mac_addr[1],
|
||||
mac_addr[2],
|
||||
mac_addr[3],
|
||||
mac_addr[4],
|
||||
mac_addr[5]);
|
||||
return mac_string;
|
||||
}
|
||||
|
||||
static json_object *hfi_to_json(struct nbft_info_hfi *hfi)
|
||||
{
|
||||
struct json_object *hfi_json;
|
||||
|
||||
hfi_json = json_create_object();
|
||||
if (!hfi_json)
|
||||
return NULL;
|
||||
|
||||
if (json_object_add_value_int(hfi_json, "index", hfi->index)
|
||||
|| json_object_add_value_string(hfi_json, "transport", hfi->transport))
|
||||
goto fail;
|
||||
|
||||
if (strcmp(hfi->transport, "tcp") == 0) {
|
||||
if (json_object_add_value_string(hfi_json, "pcidev",
|
||||
pci_sbdf_to_string(hfi->tcp_info.pci_sbdf))
|
||||
|| json_object_add_value_string(hfi_json, "mac_addr",
|
||||
mac_addr_to_string(hfi->tcp_info.mac_addr))
|
||||
|| json_object_add_value_int(hfi_json, "vlan",
|
||||
hfi->tcp_info.vlan)
|
||||
|| json_object_add_value_int(hfi_json, "ip_origin",
|
||||
hfi->tcp_info.ip_origin)
|
||||
|| json_object_add_value_string(hfi_json, "ipaddr",
|
||||
hfi->tcp_info.ipaddr)
|
||||
|| json_object_add_value_int(hfi_json, "subnet_mask_prefix",
|
||||
hfi->tcp_info.subnet_mask_prefix)
|
||||
|| json_object_add_value_string(hfi_json, "gateway_ipaddr",
|
||||
hfi->tcp_info.gateway_ipaddr)
|
||||
|| json_object_add_value_int(hfi_json, "route_metric",
|
||||
hfi->tcp_info.route_metric)
|
||||
|| json_object_add_value_string(hfi_json, "primary_dns_ipaddr",
|
||||
hfi->tcp_info.primary_dns_ipaddr)
|
||||
|| json_object_add_value_string(hfi_json, "secondary_dns_ipaddr",
|
||||
hfi->tcp_info.secondary_dns_ipaddr)
|
||||
|| json_object_add_value_string(hfi_json, "dhcp_server_ipaddr",
|
||||
hfi->tcp_info.dhcp_server_ipaddr)
|
||||
|| (hfi->tcp_info.host_name
|
||||
&& json_object_add_value_string(hfi_json, "host_name",
|
||||
hfi->tcp_info.host_name))
|
||||
|| json_object_add_value_int(hfi_json, "this_hfi_is_default_route",
|
||||
hfi->tcp_info.this_hfi_is_default_route)
|
||||
|| json_object_add_value_int(hfi_json, "dhcp_override",
|
||||
hfi->tcp_info.dhcp_override))
|
||||
goto fail;
|
||||
else
|
||||
return hfi_json;
|
||||
}
|
||||
fail:
|
||||
json_free_object(hfi_json);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static json_object *ssns_to_json(struct nbft_info_subsystem_ns *ss)
|
||||
{
|
||||
struct json_object *ss_json;
|
||||
struct json_object *hfi_array_json;
|
||||
char json_str[40];
|
||||
char *json_str_p;
|
||||
int i;
|
||||
|
||||
ss_json = json_create_object();
|
||||
if (!ss_json)
|
||||
return NULL;
|
||||
|
||||
hfi_array_json = json_create_array();
|
||||
if (!hfi_array_json)
|
||||
goto fail;
|
||||
|
||||
for (i = 0; i < ss->num_hfis; i++)
|
||||
if (json_array_add_value_object(hfi_array_json,
|
||||
json_object_new_int(ss->hfis[i]->index)))
|
||||
goto fail;
|
||||
|
||||
if (json_object_add_value_int(ss_json, "index", ss->index)
|
||||
|| json_object_add_value_int(ss_json, "num_hfis", ss->num_hfis)
|
||||
|| json_object_object_add(ss_json, "hfis", hfi_array_json)
|
||||
|| json_object_add_value_string(ss_json, "transport", ss->transport)
|
||||
|| json_object_add_value_string(ss_json, "traddr", ss->traddr)
|
||||
|| json_object_add_value_string(ss_json, "trsvcid", ss->trsvcid)
|
||||
|| json_object_add_value_int(ss_json, "subsys_port_id", ss->subsys_port_id)
|
||||
|| json_object_add_value_int(ss_json, "nsid", ss->nsid))
|
||||
goto fail;
|
||||
|
||||
memset(json_str, 0, sizeof(json_str));
|
||||
json_str_p = json_str;
|
||||
|
||||
switch (ss->nid_type) {
|
||||
case NBFT_INFO_NID_TYPE_EUI64:
|
||||
if (json_object_add_value_string(ss_json, "nid_type", "eui64"))
|
||||
goto fail;
|
||||
for (i = 0; i < 8; i++)
|
||||
json_str_p += sprintf(json_str_p, "%02x", ss->nid[i]);
|
||||
break;
|
||||
|
||||
case NBFT_INFO_NID_TYPE_NGUID:
|
||||
if (json_object_add_value_string(ss_json, "nid_type", "nguid"))
|
||||
goto fail;
|
||||
for (i = 0; i < 16; i++)
|
||||
json_str_p += sprintf(json_str_p, "%02x", ss->nid[i]);
|
||||
break;
|
||||
|
||||
case NBFT_INFO_NID_TYPE_NS_UUID:
|
||||
if (json_object_add_value_string(ss_json, "nid_type", "uuid"))
|
||||
goto fail;
|
||||
nvme_uuid_to_string(ss->nid, json_str);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (json_object_add_value_string(ss_json, "nid", json_str))
|
||||
goto fail;
|
||||
|
||||
if ((ss->subsys_nqn
|
||||
&& json_object_add_value_string(ss_json, "subsys_nqn", ss->subsys_nqn))
|
||||
|| json_object_add_value_int(ss_json, "controller_id", ss->controller_id)
|
||||
|| json_object_add_value_int(ss_json, "asqsz", ss->asqsz)
|
||||
|| (ss->dhcp_root_path_string
|
||||
&& json_object_add_value_string(ss_json, "dhcp_root_path_string",
|
||||
ss->dhcp_root_path_string))
|
||||
|| json_object_add_value_int(ss_json, "pdu_header_digest_required",
|
||||
ss->pdu_header_digest_required)
|
||||
|| json_object_add_value_int(ss_json, "data_digest_required",
|
||||
ss->data_digest_required))
|
||||
goto fail;
|
||||
|
||||
return ss_json;
|
||||
fail:
|
||||
json_free_object(ss_json);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static json_object *discovery_to_json(struct nbft_info_discovery *disc)
|
||||
{
|
||||
struct json_object *disc_json;
|
||||
|
||||
disc_json = json_create_object();
|
||||
if (!disc_json)
|
||||
return NULL;
|
||||
|
||||
if (json_object_add_value_int(disc_json, "index", disc->index)
|
||||
|| (disc->security
|
||||
&& json_object_add_value_int(disc_json, "security", disc->security->index))
|
||||
|| (disc->hfi
|
||||
&& json_object_add_value_int(disc_json, "hfi", disc->hfi->index))
|
||||
|| (disc->uri
|
||||
&& json_object_add_value_string(disc_json, "uri", disc->uri))
|
||||
|| (disc->nqn
|
||||
&& json_object_add_value_string(disc_json, "nqn", disc->nqn))) {
|
||||
json_free_object(disc_json);
|
||||
return NULL;
|
||||
} else
|
||||
return disc_json;
|
||||
}
|
||||
|
||||
static const char *primary_admin_host_flag_to_str(unsigned int primary)
|
||||
{
|
||||
static const char * const str[] = {
|
||||
[NBFT_INFO_PRIMARY_ADMIN_HOST_FLAG_NOT_INDICATED] = "not indicated",
|
||||
[NBFT_INFO_PRIMARY_ADMIN_HOST_FLAG_UNSELECTED] = "unselected",
|
||||
[NBFT_INFO_PRIMARY_ADMIN_HOST_FLAG_SELECTED] = "selected",
|
||||
[NBFT_INFO_PRIMARY_ADMIN_HOST_FLAG_RESERVED] = "reserved",
|
||||
};
|
||||
|
||||
if (primary > NBFT_INFO_PRIMARY_ADMIN_HOST_FLAG_RESERVED)
|
||||
return "INVALID";
|
||||
return str[primary];
|
||||
}
|
||||
|
||||
static struct json_object *nbft_to_json(struct nbft_info *nbft, bool show_subsys,
|
||||
bool show_hfi, bool show_discovery)
|
||||
{
|
||||
struct json_object *nbft_json, *host_json;
|
||||
|
||||
nbft_json = json_create_object();
|
||||
if (!nbft_json)
|
||||
return NULL;
|
||||
|
||||
if (json_object_add_value_string(nbft_json, "filename", nbft->filename))
|
||||
goto fail;
|
||||
|
||||
host_json = json_create_object();
|
||||
if (!host_json)
|
||||
goto fail;
|
||||
if ((nbft->host.nqn
|
||||
&& json_object_add_value_string(host_json, "nqn", nbft->host.nqn))
|
||||
|| (nbft->host.id
|
||||
&& json_object_add_value_string(host_json, "id",
|
||||
util_uuid_to_string(nbft->host.id))))
|
||||
goto fail;
|
||||
json_object_add_value_int(host_json, "host_id_configured",
|
||||
nbft->host.host_id_configured);
|
||||
json_object_add_value_int(host_json, "host_nqn_configured",
|
||||
nbft->host.host_nqn_configured);
|
||||
json_object_add_value_string(host_json, "primary_admin_host_flag",
|
||||
primary_admin_host_flag_to_str(nbft->host.primary));
|
||||
if (json_object_object_add(nbft_json, "host", host_json)) {
|
||||
json_free_object(host_json);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (show_subsys) {
|
||||
struct json_object *subsys_array_json, *subsys_json;
|
||||
struct nbft_info_subsystem_ns **ss;
|
||||
|
||||
subsys_array_json = json_create_array();
|
||||
if (!subsys_array_json)
|
||||
goto fail;
|
||||
for (ss = nbft->subsystem_ns_list; ss && *ss; ss++) {
|
||||
subsys_json = ssns_to_json(*ss);
|
||||
if (!subsys_json)
|
||||
goto fail;
|
||||
if (json_object_array_add(subsys_array_json, subsys_json)) {
|
||||
json_free_object(subsys_json);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (json_object_object_add(nbft_json, "subsystem", subsys_array_json)) {
|
||||
json_free_object(subsys_array_json);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (show_hfi) {
|
||||
struct json_object *hfi_array_json, *hfi_json;
|
||||
struct nbft_info_hfi **hfi;
|
||||
|
||||
hfi_array_json = json_create_array();
|
||||
if (!hfi_array_json)
|
||||
goto fail;
|
||||
for (hfi = nbft->hfi_list; hfi && *hfi; hfi++) {
|
||||
hfi_json = hfi_to_json(*hfi);
|
||||
if (!hfi_json)
|
||||
goto fail;
|
||||
if (json_object_array_add(hfi_array_json, hfi_json)) {
|
||||
json_free_object(hfi_json);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (json_object_object_add(nbft_json, "hfi", hfi_array_json)) {
|
||||
json_free_object(hfi_array_json);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (show_discovery) {
|
||||
struct json_object *discovery_array_json, *discovery_json;
|
||||
struct nbft_info_discovery **disc;
|
||||
|
||||
discovery_array_json = json_create_array();
|
||||
if (!discovery_array_json)
|
||||
goto fail;
|
||||
for (disc = nbft->discovery_list; disc && *disc; disc++) {
|
||||
discovery_json = discovery_to_json(*disc);
|
||||
if (!discovery_json)
|
||||
goto fail;
|
||||
if (json_object_array_add(discovery_array_json, discovery_json)) {
|
||||
json_free_object(discovery_json);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (json_object_object_add(nbft_json, "discovery", discovery_array_json)) {
|
||||
json_free_object(discovery_array_json);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
return nbft_json;
|
||||
fail:
|
||||
json_free_object(nbft_json);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int json_show_nbfts(struct list_head *nbft_list, bool show_subsys,
|
||||
bool show_hfi, bool show_discovery)
|
||||
{
|
||||
struct json_object *nbft_json_array, *nbft_json;
|
||||
struct nbft_file_entry *entry;
|
||||
|
||||
nbft_json_array = json_create_array();
|
||||
if (!nbft_json_array)
|
||||
return -ENOMEM;
|
||||
|
||||
list_for_each(nbft_list, entry, node) {
|
||||
nbft_json = nbft_to_json(entry->nbft, show_subsys, show_hfi, show_discovery);
|
||||
if (!nbft_json)
|
||||
goto fail;
|
||||
if (json_object_array_add(nbft_json_array, nbft_json)) {
|
||||
json_free_object(nbft_json);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
json_print_object(nbft_json_array, NULL);
|
||||
printf("\n");
|
||||
json_free_object(nbft_json_array);
|
||||
return 0;
|
||||
fail:
|
||||
json_free_object(nbft_json_array);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void print_nbft_hfi_info(struct nbft_info *nbft)
|
||||
{
|
||||
struct nbft_info_hfi **hfi;
|
||||
unsigned int ip_width = 8, gw_width = 8, dns_width = 8;
|
||||
|
||||
hfi = nbft->hfi_list;
|
||||
if (!hfi || !*hfi)
|
||||
return;
|
||||
|
||||
for (; *hfi; hfi++) {
|
||||
unsigned int len;
|
||||
|
||||
len = strlen((*hfi)->tcp_info.ipaddr);
|
||||
if (len > ip_width)
|
||||
ip_width = len;
|
||||
len = strlen((*hfi)->tcp_info.gateway_ipaddr);
|
||||
if (len > gw_width)
|
||||
gw_width = len;
|
||||
len = strlen((*hfi)->tcp_info.primary_dns_ipaddr);
|
||||
if (len > dns_width)
|
||||
dns_width = len;
|
||||
}
|
||||
|
||||
printf("\nNBFT HFIs:\n\n");
|
||||
printf("%-3.3s|%-4.4s|%-10.10s|%-17.17s|%-4.4s|%-*.*s|%-4.4s|%-*.*s|%-*.*s\n",
|
||||
"Idx", "Trsp", "PCI Addr", "MAC Addr", "DHCP",
|
||||
ip_width, ip_width, "IP Addr", "Mask",
|
||||
gw_width, gw_width, "Gateway", dns_width, dns_width, "DNS");
|
||||
printf("%-.3s+%-.4s+%-.10s+%-.17s+%-.4s+%-.*s+%-.4s+%-.*s+%-.*s\n",
|
||||
dash, dash, dash, dash, dash, ip_width, dash, dash,
|
||||
gw_width, dash, dns_width, dash);
|
||||
for (hfi = nbft->hfi_list; *hfi; hfi++)
|
||||
printf("%-3d|%-4.4s|%-10.10s|%-17.17s|%-4.4s|%-*.*s|%-4d|%-*.*s|%-*.*s\n",
|
||||
(*hfi)->index,
|
||||
(*hfi)->transport,
|
||||
pci_sbdf_to_string((*hfi)->tcp_info.pci_sbdf),
|
||||
mac_addr_to_string((*hfi)->tcp_info.mac_addr),
|
||||
(*hfi)->tcp_info.dhcp_override ? "yes" : "no",
|
||||
ip_width, ip_width, (*hfi)->tcp_info.ipaddr,
|
||||
(*hfi)->tcp_info.subnet_mask_prefix,
|
||||
gw_width, gw_width, (*hfi)->tcp_info.gateway_ipaddr,
|
||||
dns_width, dns_width, (*hfi)->tcp_info.primary_dns_ipaddr);
|
||||
}
|
||||
|
||||
static void print_nbft_discovery_info(struct nbft_info *nbft)
|
||||
{
|
||||
struct nbft_info_discovery **disc;
|
||||
unsigned int nqn_width = 20, uri_width = 12;
|
||||
|
||||
disc = nbft->discovery_list;
|
||||
if (!disc || !*disc)
|
||||
return;
|
||||
|
||||
for (; *disc; disc++) {
|
||||
size_t len;
|
||||
|
||||
len = strlen((*disc)->uri);
|
||||
if (len > uri_width)
|
||||
uri_width = len;
|
||||
len = strlen((*disc)->nqn);
|
||||
if (len > nqn_width)
|
||||
nqn_width = len;
|
||||
}
|
||||
|
||||
printf("\nNBFT Discovery Controllers:\n\n");
|
||||
printf("%-3.3s|%-*.*s|%-*.*s\n", "Idx", uri_width, uri_width, "URI",
|
||||
nqn_width, nqn_width, "NQN");
|
||||
printf("%-.3s+%-.*s+%-.*s\n", dash, uri_width, dash, nqn_width, dash);
|
||||
for (disc = nbft->discovery_list; *disc; disc++)
|
||||
printf("%-3d|%-*.*s|%-*.*s\n", (*disc)->index,
|
||||
uri_width, uri_width, (*disc)->uri,
|
||||
nqn_width, nqn_width, (*disc)->nqn);
|
||||
}
|
||||
|
||||
#define HFIS_LEN 20
|
||||
static size_t print_hfis(const struct nbft_info_subsystem_ns *ss, char buf[HFIS_LEN])
|
||||
{
|
||||
char hfi_buf[HFIS_LEN];
|
||||
size_t len, ofs;
|
||||
int i;
|
||||
|
||||
len = snprintf(hfi_buf, sizeof(hfi_buf), "%d", ss->hfis[0]->index);
|
||||
for (i = 1; i < ss->num_hfis; i++) {
|
||||
ofs = len;
|
||||
len += snprintf(hfi_buf + ofs, sizeof(hfi_buf) - ofs, ",%d",
|
||||
ss->hfis[i]->index);
|
||||
/*
|
||||
* If the list doesn't fit in HFIS_LEN characters,
|
||||
* truncate and end with "..."
|
||||
*/
|
||||
if (len >= sizeof(hfi_buf)) {
|
||||
while (ofs < sizeof(hfi_buf) - 1)
|
||||
hfi_buf[ofs++] = '.';
|
||||
hfi_buf[ofs] = '\0';
|
||||
len = sizeof(hfi_buf) - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (buf)
|
||||
memcpy(buf, hfi_buf, len + 1);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static void print_nbft_subsys_info(struct nbft_info *nbft)
|
||||
{
|
||||
struct nbft_info_subsystem_ns **ss;
|
||||
unsigned int nqn_width = 20, adr_width = 8, hfi_width = 4;
|
||||
|
||||
ss = nbft->subsystem_ns_list;
|
||||
if (!ss || !*ss)
|
||||
return;
|
||||
for (; *ss; ss++) {
|
||||
size_t len;
|
||||
|
||||
len = strlen((*ss)->subsys_nqn);
|
||||
if (len > nqn_width)
|
||||
nqn_width = len;
|
||||
len = strlen((*ss)->traddr);
|
||||
if (len > adr_width)
|
||||
adr_width = len;
|
||||
len = print_hfis(*ss, NULL);
|
||||
if (len > hfi_width)
|
||||
hfi_width = len;
|
||||
}
|
||||
|
||||
printf("\nNBFT Subsystems:\n\n");
|
||||
printf("%-3.3s|%-*.*s|%-4.4s|%-*.*s|%-5.5s|%-*.*s\n",
|
||||
"Idx", nqn_width, nqn_width, "NQN",
|
||||
"Trsp", adr_width, adr_width, "Address", "SvcId", hfi_width, hfi_width, "HFIs");
|
||||
printf("%-.3s+%-.*s+%-.4s+%-.*s+%-.5s+%-.*s\n",
|
||||
dash, nqn_width, dash, dash, adr_width, dash, dash, hfi_width, dash);
|
||||
for (ss = nbft->subsystem_ns_list; *ss; ss++) {
|
||||
char hfi_buf[HFIS_LEN];
|
||||
|
||||
print_hfis(*ss, hfi_buf);
|
||||
printf("%-3d|%-*.*s|%-4.4s|%-*.*s|%-5.5s|%-*.*s\n",
|
||||
(*ss)->index, nqn_width, nqn_width, (*ss)->subsys_nqn,
|
||||
(*ss)->transport, adr_width, adr_width, (*ss)->traddr,
|
||||
(*ss)->trsvcid, hfi_width, hfi_width, hfi_buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void normal_show_nbft(struct nbft_info *nbft, bool show_subsys,
|
||||
bool show_hfi, bool show_discovery)
|
||||
{
|
||||
printf("%s:\n", nbft->filename);
|
||||
if ((!nbft->hfi_list || !*nbft->hfi_list) &&
|
||||
(!nbft->security_list || !*nbft->security_list) &&
|
||||
(!nbft->discovery_list || !*nbft->discovery_list) &&
|
||||
(!nbft->subsystem_ns_list || !*nbft->subsystem_ns_list))
|
||||
printf("(empty)\n");
|
||||
else {
|
||||
if (show_subsys)
|
||||
print_nbft_subsys_info(nbft);
|
||||
if (show_hfi)
|
||||
print_nbft_hfi_info(nbft);
|
||||
if (show_discovery)
|
||||
print_nbft_discovery_info(nbft);
|
||||
}
|
||||
}
|
||||
|
||||
static void normal_show_nbfts(struct list_head *nbft_list, bool show_subsys,
|
||||
bool show_hfi, bool show_discovery)
|
||||
{
|
||||
bool not_first = false;
|
||||
struct nbft_file_entry *entry;
|
||||
|
||||
list_for_each(nbft_list, entry, node) {
|
||||
if (not_first)
|
||||
printf("\n");
|
||||
normal_show_nbft(entry->nbft, show_subsys, show_hfi, show_discovery);
|
||||
not_first = true;
|
||||
}
|
||||
}
|
||||
|
||||
int show_nbft(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "Display contents of the ACPI NBFT files.";
|
||||
struct list_head nbft_list;
|
||||
char *format = "normal";
|
||||
char *nbft_path = NBFT_SYSFS_PATH;
|
||||
enum nvme_print_flags flags;
|
||||
int ret;
|
||||
bool show_subsys = false, show_hfi = false, show_discovery = false;
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_FMT("output-format", 'o', &format, "Output format: normal|json"),
|
||||
OPT_FLAG("subsystem", 's', &show_subsys, "show NBFT subsystems"),
|
||||
OPT_FLAG("hfi", 'H', &show_hfi, "show NBFT HFIs"),
|
||||
OPT_FLAG("discovery", 'd', &show_discovery, "show NBFT discovery controllers"),
|
||||
OPT_STRING("nbft-path", 0, "STR", &nbft_path, "user-defined path for NBFT tables"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
ret = argconfig_parse(argc, argv, desc, opts);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = flags = validate_output_format(format);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!(show_subsys || show_hfi || show_discovery))
|
||||
show_subsys = show_hfi = show_discovery = true;
|
||||
|
||||
list_head_init(&nbft_list);
|
||||
ret = read_nbft_files(&nbft_list, nbft_path);
|
||||
if (!ret) {
|
||||
if (flags == NORMAL)
|
||||
normal_show_nbfts(&nbft_list, show_subsys, show_hfi, show_discovery);
|
||||
else if (flags == JSON)
|
||||
ret = json_show_nbfts(&nbft_list, show_subsys, show_hfi, show_discovery);
|
||||
free_nbfts(&nbft_list);
|
||||
}
|
||||
return ret;
|
||||
}
|
18
plugins/nbft/nbft-plugin.h
Normal file
18
plugins/nbft/nbft-plugin.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#undef CMD_INC_FILE
|
||||
#define CMD_INC_FILE plugins/nbft/nbft-plugin
|
||||
|
||||
#if !defined(NBFT) || defined(CMD_HEADER_MULTI_READ)
|
||||
#define NBFT
|
||||
|
||||
#include "cmd.h"
|
||||
|
||||
PLUGIN(NAME("nbft", "ACPI NBFT table extensions", NVME_VERSION),
|
||||
COMMAND_LIST(
|
||||
ENTRY("show", "Show contents of ACPI NBFT tables", show_nbft)
|
||||
)
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
#include "define_cmd.h"
|
|
@ -1,18 +1,18 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2018 NetApp, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
* Copyright (c) 2018 NetApp, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
|
@ -57,14 +57,14 @@ enum {
|
|||
static const char *dev_path = "/dev/";
|
||||
|
||||
struct smdevice_info {
|
||||
unsigned nsid;
|
||||
unsigned int nsid;
|
||||
struct nvme_id_ctrl ctrl;
|
||||
struct nvme_id_ns ns;
|
||||
char dev[265];
|
||||
};
|
||||
|
||||
struct ontapdevice_info {
|
||||
unsigned nsid;
|
||||
unsigned int nsid;
|
||||
struct nvme_id_ctrl ctrl;
|
||||
struct nvme_id_ns ns;
|
||||
unsigned char uuid[NVME_UUID_LEN];
|
||||
|
@ -107,6 +107,7 @@ static void netapp_get_ns_size(char *size, unsigned long long *lba,
|
|||
struct nvme_id_ns *ns)
|
||||
{
|
||||
__u8 lba_index;
|
||||
|
||||
nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &lba_index);
|
||||
*lba = 1ULL << ns->lbaf[lba_index].ds;
|
||||
double nsze = le64_to_cpu(ns->nsze) * (*lba);
|
||||
|
@ -237,8 +238,8 @@ static void netapp_smdevices_print(struct smdevice_info *devices, int count, int
|
|||
char array_label[ARRAY_LABEL_LEN / 2 + 1];
|
||||
char volume_label[VOLUME_LABEL_LEN / 2 + 1];
|
||||
char nguid_str[33];
|
||||
char basestr[] = "%s, Array Name %s, Volume Name %s, NSID %d, "
|
||||
"Volume ID %s, Controller %c, Access State %s, %s\n";
|
||||
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;
|
||||
|
@ -254,8 +255,7 @@ static void netapp_smdevices_print(struct smdevice_info *devices, int count, int
|
|||
"------------------------------", "----",
|
||||
"--------------------------------", "----",
|
||||
"------------", "---------");
|
||||
}
|
||||
else if (format == NJSON) {
|
||||
} else if (format == NJSON) {
|
||||
/* prepare for json output */
|
||||
root = json_create_object();
|
||||
json_devices = json_create_array();
|
||||
|
@ -263,7 +263,7 @@ static void netapp_smdevices_print(struct smdevice_info *devices, int count, int
|
|||
|
||||
for (i = 0; i < count; i++) {
|
||||
nvme_id_ns_flbas_to_lbaf_inuse(devices[i].ns.flbas, &lba_index);
|
||||
unsigned long long int 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];
|
||||
|
@ -464,7 +464,7 @@ static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item,
|
|||
err = nvme_get_ontap_c2_log(fd, item->nsid, item->log_data, ONTAP_C2_LOG_SIZE);
|
||||
if (err) {
|
||||
fprintf(stderr, "Unable to get log page data for %s (%s)\n",
|
||||
dev, err < 0 ? strerror(-err):
|
||||
dev, err < 0 ? strerror(-err) :
|
||||
nvme_status_to_string(err, false));
|
||||
return 0;
|
||||
}
|
||||
|
@ -553,7 +553,7 @@ static int netapp_smdevices(int argc, char **argv, struct command *command,
|
|||
smdevices = calloc(num, sizeof(*smdevices));
|
||||
if (!smdevices) {
|
||||
fprintf(stderr, "Unable to allocate memory for devices.\n");
|
||||
return ENOMEM;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
|
|
|
@ -3,5 +3,6 @@ sources += [
|
|||
'plugins/ocp/ocp-nvme.c',
|
||||
'plugins/ocp/ocp-clear-fw-update-history.c',
|
||||
'plugins/ocp/ocp-smart-extended-log.c',
|
||||
'plugins/ocp/ocp-fw-activation-history.c',
|
||||
]
|
||||
|
||||
|
|
|
@ -16,6 +16,5 @@ int ocp_clear_fw_update_history(int argc, char **argv, struct command *cmd, stru
|
|||
{
|
||||
const char *desc = "OCP Clear Firmware Update History";
|
||||
|
||||
return ocp_clear_feature(argc, argv, desc,
|
||||
OCP_FID_CLEAR_FW_ACTIVATION_HISTORY);
|
||||
return ocp_clear_feature(argc, argv, desc, OCP_FID_CLEAR_FW_ACTIVATION_HISTORY);
|
||||
}
|
||||
|
|
223
plugins/ocp/ocp-fw-activation-history.c
Normal file
223
plugins/ocp/ocp-fw-activation-history.c
Normal file
|
@ -0,0 +1,223 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2022 Solidigm.
|
||||
*
|
||||
* Author: karl.dedow@solidigm.com
|
||||
*/
|
||||
|
||||
#include "ocp-fw-activation-history.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "nvme-print.h"
|
||||
|
||||
#include "ocp-utils.h"
|
||||
|
||||
static const unsigned char ocp_fw_activation_history_guid[16] = {
|
||||
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:",
|
||||
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",
|
||||
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)
|
||||
{
|
||||
const __u8 log_id = 0xC2;
|
||||
const char *description = "Retrieves the OCP firmware activation history log.";
|
||||
|
||||
char *format = "normal";
|
||||
|
||||
OPT_ARGS(options) = {
|
||||
OPT_FMT("output-format", 'o', &format, "output format : normal | json"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
struct nvme_dev *dev = NULL;
|
||||
int err = parse_and_open(&dev, argc, argv, description, options);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
int uuid_index = 0;
|
||||
|
||||
/*
|
||||
* Best effort attempt at uuid. Otherwise, assume no index (i.e. 0)
|
||||
* Log GUID check will ensure correctness of returned data
|
||||
*/
|
||||
ocp_get_uuid_index(dev, &uuid_index);
|
||||
|
||||
struct fw_activation_history fw_history = { 0 };
|
||||
|
||||
struct nvme_get_log_args args = {
|
||||
.lpo = 0,
|
||||
.result = NULL,
|
||||
.log = &fw_history,
|
||||
.args_size = sizeof(args),
|
||||
.fd = dev_fd(dev),
|
||||
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
|
||||
.lid = log_id,
|
||||
.len = sizeof(fw_history),
|
||||
.nsid = NVME_NSID_ALL,
|
||||
.csi = NVME_CSI_NVM,
|
||||
.lsi = NVME_LOG_LSI_NONE,
|
||||
.lsp = 0,
|
||||
.uuidx = uuid_index,
|
||||
.rae = false,
|
||||
.ot = false,
|
||||
};
|
||||
|
||||
err = nvme_get_log(&args);
|
||||
|
||||
if (err)
|
||||
nvme_show_status(err);
|
||||
|
||||
dev_close(dev);
|
||||
|
||||
int guid_cmp_res = memcmp(fw_history.log_page_guid, ocp_fw_activation_history_guid,
|
||||
sizeof(ocp_fw_activation_history_guid));
|
||||
|
||||
if (!err && guid_cmp_res) {
|
||||
fprintf(stderr,
|
||||
"Error: Unexpected data. Log page guid does not match with expected.\n");
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
const enum nvme_print_flags print_flag = validate_output_format(format);
|
||||
|
||||
if (print_flag == JSON)
|
||||
ocp_fw_activation_history_json(&fw_history);
|
||||
else if (print_flag == NORMAL)
|
||||
ocp_fw_activation_history_normal(&fw_history);
|
||||
else {
|
||||
fprintf(stderr, "Error: Invalid output format.\n");
|
||||
err = -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
17
plugins/ocp/ocp-fw-activation-history.h
Normal file
17
plugins/ocp/ocp-fw-activation-history.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (c) 2022 Solidigm.
|
||||
*
|
||||
* Authors: karl.dedow@solidigm.com
|
||||
*/
|
||||
|
||||
#ifndef OCP_FIRMWARE_ACTIVATION_HISTORY_H
|
||||
#define OCP_FIRMWARE_ACTIVATION_HISTORY_H
|
||||
|
||||
struct command;
|
||||
struct plugin;
|
||||
|
||||
int ocp_fw_activation_history_log(int argc, char **argv,
|
||||
struct command *cmd, struct plugin *plugin);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -17,9 +17,15 @@ PLUGIN(NAME("ocp", "OCP cloud SSD extensions", NVME_VERSION),
|
|||
COMMAND_LIST(
|
||||
ENTRY("smart-add-log", "Retrieve extended SMART Information", smart_add_log)
|
||||
ENTRY("latency-monitor-log", "Get Latency Monitor Log Page", ocp_latency_monitor_log)
|
||||
ENTRY("set-latency-monitor-feature", "Set Latency Monitor feature", ocp_set_latency_monitor_feature)
|
||||
ENTRY("internal-log", "Retrieve and save internal device telemetry log", ocp_telemetry_log)
|
||||
ENTRY("clear-fw-activate-history", "Clear firmware update history log", clear_fw_update_history)
|
||||
ENTRY("eol-plp-failure-mode", "Define EOL or PLP circuitry failure mode.", eol_plp_failure_mode)
|
||||
ENTRY("clear-pcie-correctable-error-counters", "Clear PCIe correctable error counters", clear_pcie_corectable_error_counters)
|
||||
ENTRY("vs-fw-activate-history", "Get firmware activation history log", fw_activation_history_log)
|
||||
ENTRY("unsupported-reqs-log", "Get Unsupported Requirements Log Page", ocp_unsupported_requirements_log)
|
||||
ENTRY("error-recovery-log", "Retrieve Error Recovery Log Page", ocp_error_recovery_log)
|
||||
ENTRY("device-capability-log", "Get Device capabilities Requirements Log Page", ocp_device_capabilities_log)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ static __u8 scao_guid[C0_GUID_LENGTH] = {
|
|||
0xC9, 0x14, 0xD5, 0xAF
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
enum {
|
||||
SCAO_PMUW = 0, /* Physical media units written */
|
||||
SCAO_PMUR = 16, /* Physical media units read */
|
||||
SCAO_BUNBR = 32, /* Bad user nand blocks raw */
|
||||
|
@ -62,7 +62,7 @@ typedef enum {
|
|||
SCAO_PSCC = 200, /* Power State Change Count */
|
||||
SCAO_LPV = 494, /* Log page version */
|
||||
SCAO_LPG = 496, /* Log page GUID */
|
||||
} SMART_CLOUD_ATTRIBUTE_OFFSETS;
|
||||
};
|
||||
|
||||
static void ocp_print_C0_log_normal(void *data)
|
||||
{
|
||||
|
@ -71,10 +71,10 @@ static void ocp_print_C0_log_normal(void *data)
|
|||
|
||||
printf("SMART Cloud Attributes :-\n");
|
||||
|
||||
printf(" Physical media units written - %"PRIu64" %"PRIu64"\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",
|
||||
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",
|
||||
|
@ -105,7 +105,7 @@ static void ocp_print_C0_log_normal(void *data)
|
|||
(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",
|
||||
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]));
|
||||
|
@ -286,14 +286,12 @@ static int get_c0_log_page(int fd, char *format)
|
|||
|
||||
fprintf(stderr, "ERROR : OCP : Unknown GUID in C0 Log Page data\n");
|
||||
fprintf(stderr, "ERROR : OCP : Expected GUID: 0x");
|
||||
for (j = 0; j < 16; j++) {
|
||||
for (j = 0; j < 16; j++)
|
||||
fprintf(stderr, "%x", scao_guid[j]);
|
||||
}
|
||||
|
||||
fprintf(stderr, "\nERROR : OCP : Actual GUID: 0x");
|
||||
for (j = 0; j < 16; j++) {
|
||||
for (j = 0; j < 16; j++)
|
||||
fprintf(stderr, "%x", data[SCAO_LPG + j]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
ret = -1;
|
||||
|
|
|
@ -3,19 +3,23 @@
|
|||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/fs.h>
|
||||
#include <inttypes.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "nvme.h"
|
||||
#include "libnvme.h"
|
||||
#include "plugin.h"
|
||||
#include "linux/types.h"
|
||||
#include "nvme-wrap.h"
|
||||
#include "nvme-print.h"
|
||||
|
||||
#define CREATE_CMD
|
||||
|
@ -57,8 +61,7 @@ enum sfx_nvme_admin_opcode {
|
|||
nvme_admin_sfx_get_features = 0xd6,
|
||||
};
|
||||
|
||||
struct sfx_freespace_ctx
|
||||
{
|
||||
struct sfx_freespace_ctx {
|
||||
__u64 free_space;
|
||||
__u64 phy_cap; /* physical capacity, in unit of sector */
|
||||
__u64 phy_space; /* physical space considering OP, in unit of sector */
|
||||
|
@ -66,6 +69,10 @@ struct sfx_freespace_ctx
|
|||
__u64 hw_used; /* hw space used in 4K */
|
||||
__u64 app_written; /* app data written in 4K */
|
||||
__u64 out_of_space;
|
||||
__u64 map_unit;
|
||||
__u64 max_user_space;
|
||||
__u64 extendible_user_cap_lba_count;
|
||||
__u64 friendly_change_cap_support;
|
||||
};
|
||||
|
||||
struct nvme_capacity_info {
|
||||
|
@ -75,72 +82,73 @@ struct nvme_capacity_info {
|
|||
__u64 free_space;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) nvme_additional_smart_log_item {
|
||||
struct __packed nvme_additional_smart_log_item {
|
||||
__u8 key;
|
||||
__u8 _kp[2];
|
||||
__u8 norm;
|
||||
__u8 _np;
|
||||
union __attribute__((packed)) {
|
||||
union __packed {
|
||||
__u8 raw[6];
|
||||
struct __attribute__((packed)) wear_level {
|
||||
struct __packed wear_level {
|
||||
__le16 min;
|
||||
__le16 max;
|
||||
__le16 avg;
|
||||
} wear_level;
|
||||
struct __attribute__((packed)) thermal_throttle {
|
||||
struct __packed thermal_throttle {
|
||||
__u8 pct;
|
||||
__u32 count;
|
||||
} thermal_throttle;
|
||||
} ;
|
||||
};
|
||||
__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_additional_smart_log_item raid_recover_cnt; // errors which can be recovered by RAID
|
||||
struct nvme_additional_smart_log_item prog_timeout_cnt;
|
||||
struct nvme_additional_smart_log_item erase_timeout_cnt;
|
||||
struct nvme_additional_smart_log_item read_timeout_cnt;
|
||||
struct nvme_additional_smart_log_item read_ecc_cnt;//retry cnt
|
||||
struct nvme_additional_smart_log_item non_media_crc_err_cnt;
|
||||
struct nvme_additional_smart_log_item compression_path_err_cnt;
|
||||
struct nvme_additional_smart_log_item out_of_space_flag;
|
||||
struct nvme_additional_smart_log_item physical_usage_ratio;
|
||||
struct nvme_additional_smart_log_item grown_bb; //grown bad block
|
||||
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_additional_smart_log_item raid_recover_cnt; /* errors which can be recovered by RAID */
|
||||
struct nvme_additional_smart_log_item prog_timeout_cnt;
|
||||
struct nvme_additional_smart_log_item erase_timeout_cnt;
|
||||
struct nvme_additional_smart_log_item read_timeout_cnt;
|
||||
struct nvme_additional_smart_log_item read_ecc_cnt; /* retry cnt */
|
||||
struct nvme_additional_smart_log_item non_media_crc_err_cnt;
|
||||
struct nvme_additional_smart_log_item compression_path_err_cnt;
|
||||
struct nvme_additional_smart_log_item out_of_space_flag;
|
||||
struct nvme_additional_smart_log_item physical_usage_ratio;
|
||||
struct nvme_additional_smart_log_item grown_bb; /* grown bad block */
|
||||
};
|
||||
|
||||
int nvme_query_cap(int fd, __u32 nsid, __u32 data_len, void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
struct nvme_passthru_cmd cmd = {
|
||||
.opcode = nvme_admin_query_cap_info,
|
||||
.nsid = nsid,
|
||||
.addr = (__u64)(uintptr_t) data,
|
||||
.data_len = data_len,
|
||||
};
|
||||
int rc = 0;
|
||||
struct nvme_passthru_cmd cmd = {
|
||||
.opcode = nvme_admin_query_cap_info,
|
||||
.nsid = nsid,
|
||||
.addr = (__u64)(uintptr_t) data,
|
||||
.data_len = data_len,
|
||||
};
|
||||
|
||||
rc = ioctl(fd, SFX_GET_FREESPACE, data);
|
||||
return rc == 0 ? 0 : nvme_submit_admin_passthru(fd, &cmd, NULL);
|
||||
rc = ioctl(fd, SFX_GET_FREESPACE, data);
|
||||
return rc ? nvme_submit_admin_passthru(fd, &cmd, NULL) : 0;
|
||||
}
|
||||
|
||||
int nvme_change_cap(int fd, __u32 nsid, __u64 capacity)
|
||||
{
|
||||
struct nvme_passthru_cmd cmd = {
|
||||
.opcode = nvme_admin_change_cap,
|
||||
.nsid = nsid,
|
||||
.cdw10 = (capacity & 0xffffffff),
|
||||
.cdw11 = (capacity >> 32),
|
||||
.opcode = nvme_admin_change_cap,
|
||||
.nsid = nsid,
|
||||
.cdw10 = (capacity & 0xffffffff),
|
||||
.cdw11 = (capacity >> 32),
|
||||
};
|
||||
|
||||
return nvme_submit_admin_passthru(fd, &cmd, NULL);
|
||||
|
@ -149,10 +157,10 @@ int nvme_change_cap(int fd, __u32 nsid, __u64 capacity)
|
|||
int nvme_sfx_set_features(int fd, __u32 nsid, __u32 fid, __u32 value)
|
||||
{
|
||||
struct nvme_passthru_cmd cmd = {
|
||||
.opcode = nvme_admin_sfx_set_features,
|
||||
.nsid = nsid,
|
||||
.cdw10 = fid,
|
||||
.cdw11 = value,
|
||||
.opcode = nvme_admin_sfx_set_features,
|
||||
.nsid = nsid,
|
||||
.cdw10 = fid,
|
||||
.cdw11 = value,
|
||||
};
|
||||
|
||||
return nvme_submit_admin_passthru(fd, &cmd, NULL);
|
||||
|
@ -161,16 +169,15 @@ int nvme_sfx_set_features(int fd, __u32 nsid, __u32 fid, __u32 value)
|
|||
int nvme_sfx_get_features(int fd, __u32 nsid, __u32 fid, __u32 *result)
|
||||
{
|
||||
int err = 0;
|
||||
struct nvme_passthru_cmd cmd = {
|
||||
.opcode = nvme_admin_sfx_get_features,
|
||||
.nsid = nsid,
|
||||
.cdw10 = fid,
|
||||
struct nvme_passthru_cmd cmd = {
|
||||
.opcode = nvme_admin_sfx_get_features,
|
||||
.nsid = nsid,
|
||||
.cdw10 = fid,
|
||||
};
|
||||
|
||||
err = nvme_submit_admin_passthru(fd, &cmd, NULL);
|
||||
if (!err && result) {
|
||||
if (!err && result)
|
||||
*result = cmd.result;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -398,11 +405,11 @@ static void show_sfx_smart_log(struct nvme_additional_smart_log *smart,
|
|||
static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
struct nvme_additional_smart_log smart_log;
|
||||
char *desc = "Get ScaleFlux vendor specific additional smart log (optionally, "\
|
||||
"for the specified namespace), and show it.";
|
||||
char *desc =
|
||||
"Get ScaleFlux vendor specific additional smart log (optionally, for the specified namespace), 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";
|
||||
const char *json = "Dump output in json format";
|
||||
struct nvme_dev *dev;
|
||||
struct config {
|
||||
__u32 namespace_id;
|
||||
|
@ -438,14 +445,14 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
|
|||
dev->name);
|
||||
else
|
||||
d_raw((unsigned char *)&smart_log, sizeof(smart_log));
|
||||
}
|
||||
else if (err > 0)
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
}
|
||||
dev_close(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
struct __attribute__((__packed__)) sfx_lat_stats_vanda {
|
||||
struct __packed sfx_lat_stats_vanda {
|
||||
__u16 maj;
|
||||
__u16 min;
|
||||
__u32 bucket_1[32]; /* 0~1ms, step 32us */
|
||||
|
@ -456,7 +463,7 @@ struct __attribute__((__packed__)) sfx_lat_stats_vanda {
|
|||
__u32 bucket_6[1]; /* 4s+, specifically 4096ms+ */
|
||||
};
|
||||
|
||||
struct __attribute__((__packed__)) sfx_lat_stats_myrtle {
|
||||
struct __packed sfx_lat_stats_myrtle {
|
||||
__u16 maj;
|
||||
__u16 min;
|
||||
__u32 bucket_1[64]; /* 0us~63us, step 1us */
|
||||
|
@ -482,7 +489,7 @@ struct __attribute__((__packed__)) sfx_lat_stats_myrtle {
|
|||
};
|
||||
|
||||
|
||||
struct __attribute__((__packed__)) sfx_lat_status_ver {
|
||||
struct __packed sfx_lat_status_ver {
|
||||
__u16 maj;
|
||||
__u16 min;
|
||||
};
|
||||
|
@ -646,23 +653,22 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
|
|||
sizeof(stats), (void *)&stats);
|
||||
if (!err) {
|
||||
if ((stats.ver.maj == VANDA_MAJOR_IDX) && (stats.ver.min == VANDA_MINOR_IDX)) {
|
||||
if (!cfg.raw_binary) {
|
||||
if (!cfg.raw_binary)
|
||||
show_lat_stats_vanda(&stats.vanda, cfg.write);
|
||||
} else {
|
||||
else
|
||||
d_raw((unsigned char *)&stats.vanda, sizeof(struct sfx_lat_stats_vanda));
|
||||
}
|
||||
} else if ((stats.ver.maj == MYRTLE_MAJOR_IDX) && (stats.ver.min == MYRTLE_MINOR_IDX)) {
|
||||
if (!cfg.raw_binary) {
|
||||
if (!cfg.raw_binary)
|
||||
show_lat_stats_myrtle(&stats.myrtle, cfg.write);
|
||||
} else {
|
||||
else
|
||||
d_raw((unsigned char *)&stats.myrtle, sizeof(struct sfx_lat_stats_myrtle));
|
||||
}
|
||||
} else {
|
||||
printf("ScaleFlux IO %s Command Latency Statistics Invalid Version Maj %d Min %d\n",
|
||||
cfg.write ? "Write" : "Read", stats.ver.maj, stats.ver.min);
|
||||
}
|
||||
} else if (err > 0)
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
}
|
||||
dev_close(dev);
|
||||
return err;
|
||||
}
|
||||
|
@ -697,7 +703,7 @@ static int get_bb_table(int fd, __u32 nsid, unsigned char *buf, __u64 size)
|
|||
{
|
||||
if (fd < 0 || !buf || size != 256*4096*sizeof(unsigned char)) {
|
||||
fprintf(stderr, "Invalid Param \r\n");
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return sfx_nvme_get_log(fd, nsid, SFX_LOG_BBT, size, (void *)buf);
|
||||
|
@ -731,7 +737,7 @@ static void bd_table_show(unsigned char *bd_table, __u64 table_size)
|
|||
remap_gbb_count = *((__u32 *)(bd_table + 4 * sizeof(__u32)));
|
||||
bb_elem = (__u64 *)(bd_table + 5 * sizeof(__u32));
|
||||
|
||||
printf("Bad Block Table \n");
|
||||
printf("Bad Block Table\n");
|
||||
printf("MF_BB_COUNT: %u\n", mf_bb_count);
|
||||
printf("GROWN_BB_COUNT: %u\n", grown_bb_count);
|
||||
printf("TOTAL_BB_COUNT: %u\n", total_bb_count);
|
||||
|
@ -792,7 +798,7 @@ static int sfx_get_bad_block(int argc, char **argv, struct command *cmd, struct
|
|||
err = get_bb_table(dev_fd(dev), 0xffffffff, data_buf, buf_size);
|
||||
if (err < 0) {
|
||||
perror("get-bad-block");
|
||||
} else if (err != 0) {
|
||||
} else if (err) {
|
||||
nvme_show_status(err);
|
||||
} else {
|
||||
bd_table_show(data_buf, buf_size);
|
||||
|
@ -816,6 +822,7 @@ static void show_cap_info(struct sfx_freespace_ctx *ctx)
|
|||
printf("used provisioned capacity:%5lluGB(0x%"PRIx64")\n",
|
||||
IDEMA_CAP2GB(ctx->phy_space) - IDEMA_CAP2GB(ctx->free_space),
|
||||
(uint64_t)(ctx->phy_space - ctx->free_space));
|
||||
printf("map_unit :0x%"PRIx64"K\n", (uint64_t)(ctx->map_unit * 4));
|
||||
}
|
||||
|
||||
static int query_cap_info(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
|
@ -845,11 +852,10 @@ static int query_cap_info(int argc, char **argv, struct command *cmd, struct plu
|
|||
}
|
||||
|
||||
if (!err) {
|
||||
if (!cfg.raw_binary) {
|
||||
if (!cfg.raw_binary)
|
||||
show_cap_info(&ctx);
|
||||
} else {
|
||||
else
|
||||
d_raw((unsigned char *)&ctx, sizeof(ctx));
|
||||
}
|
||||
}
|
||||
dev_close(dev);
|
||||
return err;
|
||||
|
@ -864,9 +870,8 @@ static int change_sanity_check(int fd, __u64 trg_in_4k, int *shrink)
|
|||
__u64 provisoned_cap_4k = 0;
|
||||
int extend = 0;
|
||||
|
||||
if (nvme_query_cap(fd, 0xffffffff, sizeof(freespace_ctx), &freespace_ctx)) {
|
||||
return -1;
|
||||
}
|
||||
if (nvme_query_cap(fd, 0xffffffff, sizeof(freespace_ctx), &freespace_ctx))
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* capacity illegal check
|
||||
|
@ -877,13 +882,12 @@ static int change_sanity_check(int fd, __u64 trg_in_4k, int *shrink)
|
|||
trg_in_4k > ((__u64)provisoned_cap_4k * 4)) {
|
||||
fprintf(stderr,
|
||||
"WARNING: Only support 1.0~4.0 x provisoned capacity!\n");
|
||||
if (trg_in_4k < provisoned_cap_4k) {
|
||||
if (trg_in_4k < provisoned_cap_4k)
|
||||
fprintf(stderr,
|
||||
"WARNING: The target capacity is less than 1.0 x provisioned capacity!\n");
|
||||
} else {
|
||||
else
|
||||
fprintf(stderr,
|
||||
"WARNING: The target capacity is larger than 4.0 x provisioned capacity!\n");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (trg_in_4k > ((__u64)provisoned_cap_4k*4)) {
|
||||
|
@ -893,7 +897,7 @@ static int change_sanity_check(int fd, __u64 trg_in_4k, int *shrink)
|
|||
|
||||
/*
|
||||
* check whether mem enough if extend
|
||||
* */
|
||||
*/
|
||||
cur_in_4k = freespace_ctx.user_space >> (SFX_PAGE_SHIFT - SECTOR_SHIFT);
|
||||
extend = (cur_in_4k <= trg_in_4k);
|
||||
if (extend) {
|
||||
|
@ -904,10 +908,9 @@ static int change_sanity_check(int fd, __u64 trg_in_4k, int *shrink)
|
|||
mem_need = (trg_in_4k - cur_in_4k) * 8;
|
||||
if (s_info.freeram <= 10 || mem_need > s_info.freeram) {
|
||||
fprintf(stderr,
|
||||
"WARNING: Free memory is not enough! "
|
||||
"Please drop cache or extend more memory and retry\n"
|
||||
"WARNING: Memory needed is %"PRIu64", free memory is %"PRIu64"\n",
|
||||
(uint64_t)mem_need, (uint64_t)s_info.freeram);
|
||||
"WARNING: Free memory is not enough! Please drop cache or extend more memory and retry\n"
|
||||
"WARNING: Memory needed is %"PRIu64", free memory is %"PRIu64"\n",
|
||||
(uint64_t)mem_need, (uint64_t)s_info.freeram);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -926,6 +929,7 @@ static int change_sanity_check(int fd, __u64 trg_in_4k, int *shrink)
|
|||
static int sfx_confirm_change(const char *str)
|
||||
{
|
||||
unsigned char confirm;
|
||||
|
||||
fprintf(stderr, "WARNING: %s.\n"
|
||||
"Use the force [--force] option to suppress this warning.\n", str);
|
||||
|
||||
|
@ -935,7 +939,7 @@ static int sfx_confirm_change(const char *str)
|
|||
fprintf(stderr, "Cancled.\n");
|
||||
return 0;
|
||||
}
|
||||
fprintf(stderr, "Sending operation ... \n");
|
||||
fprintf(stderr, "Sending operation ...\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -993,11 +997,11 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin
|
|||
}
|
||||
|
||||
err = nvme_change_cap(dev_fd(dev), 0xffffffff, cap_in_4k);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
perror("sfx-change-cap");
|
||||
else if (err != 0)
|
||||
} else if (err) {
|
||||
nvme_show_status(err);
|
||||
else {
|
||||
} else {
|
||||
printf("ScaleFlux change-capacity: success\n");
|
||||
ioctl(dev_fd(dev), BLKRRPART);
|
||||
}
|
||||
|
@ -1017,7 +1021,7 @@ static int sfx_verify_chr(int fd)
|
|||
if (!S_ISCHR(nvme_stat.st_mode)) {
|
||||
fprintf(stderr,
|
||||
"Error: requesting clean card on non-controller handle\n");
|
||||
return ENOTBLK;
|
||||
return -ENOTBLK;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1041,13 +1045,12 @@ static int sfx_clean_card(int fd)
|
|||
char *sfx_feature_to_string(int feature)
|
||||
{
|
||||
switch (feature) {
|
||||
case SFX_FEAT_ATOMIC:
|
||||
return "ATOMIC";
|
||||
case SFX_FEAT_UP_P_CAP:
|
||||
return "UPDATE_PROVISION_CAPACITY";
|
||||
|
||||
default:
|
||||
return "Unknown";
|
||||
case SFX_FEAT_ATOMIC:
|
||||
return "ATOMIC";
|
||||
case SFX_FEAT_UP_P_CAP:
|
||||
return "UPDATE_PROVISION_CAPACITY";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1093,7 +1096,7 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl
|
|||
if (!cfg.feature_id) {
|
||||
fprintf(stderr, "feature-id required param\n");
|
||||
dev_close(dev);
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cfg.feature_id == SFX_FEAT_CLR_CARD) {
|
||||
|
@ -1107,7 +1110,7 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl
|
|||
|
||||
}
|
||||
|
||||
if (cfg.feature_id == SFX_FEAT_ATOMIC && cfg.value != 0) {
|
||||
if (cfg.feature_id == SFX_FEAT_ATOMIC && cfg.value) {
|
||||
if (cfg.namespace_id != 0xffffffff) {
|
||||
err = nvme_identify_ns(dev_fd(dev), cfg.namespace_id,
|
||||
&ns);
|
||||
|
@ -1125,14 +1128,14 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl
|
|||
if ((ns.flbas & 0xf) != 1) {
|
||||
printf("Please change-sector size to 4K, then retry\n");
|
||||
dev_close(dev);
|
||||
return EFAULT;
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
} else if (cfg.feature_id == SFX_FEAT_UP_P_CAP) {
|
||||
if (cfg.value <= 0) {
|
||||
fprintf(stderr, "Invalid Param\n");
|
||||
dev_close(dev);
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*Warning for change pacp by GB*/
|
||||
|
@ -1153,8 +1156,9 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl
|
|||
} else if (!err) {
|
||||
printf("ScaleFlux set-feature:%#02x (%s), value:%d\n", cfg.feature_id,
|
||||
sfx_feature_to_string(cfg.feature_id), cfg.value);
|
||||
} else if (err > 0)
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
}
|
||||
|
||||
dev_close(dev);
|
||||
return err;
|
||||
|
@ -1192,7 +1196,7 @@ static int sfx_get_feature(int argc, char **argv, struct command *cmd, struct pl
|
|||
if (!cfg.feature_id) {
|
||||
fprintf(stderr, "feature-id required param\n");
|
||||
dev_close(dev);
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = nvme_sfx_get_features(dev_fd(dev), cfg.namespace_id,
|
||||
|
@ -1204,10 +1208,481 @@ static int sfx_get_feature(int argc, char **argv, struct command *cmd, struct pl
|
|||
} else if (!err) {
|
||||
printf("ScaleFlux get-feature:%02x (%s), value:%d\n", cfg.feature_id,
|
||||
sfx_feature_to_string(cfg.feature_id), result);
|
||||
} else if (err > 0)
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
}
|
||||
|
||||
dev_close(dev);
|
||||
return err;
|
||||
|
||||
}
|
||||
|
||||
static int nvme_parse_evtlog(void *pevent_log_info, __u32 log_len, char *output)
|
||||
{
|
||||
__u32 offset = 0;
|
||||
__u32 length = log_len;
|
||||
__u16 fw_core;
|
||||
__u64 fw_time;
|
||||
__u8 code_level;
|
||||
__u8 code_type;
|
||||
char str_buffer[512];
|
||||
__u32 str_pos;
|
||||
FILE *fd;
|
||||
int err = 0;
|
||||
|
||||
enum sfx_evtlog_level {
|
||||
sfx_evtlog_level_warning,
|
||||
sfx_evtlog_level_error,
|
||||
};
|
||||
|
||||
const char *sfx_evtlog_warning[4] = {
|
||||
"RESERVED",
|
||||
"TOO_MANY_BB",
|
||||
"LOW_SPACE",
|
||||
"HIGH_TEMPERATURE"
|
||||
};
|
||||
|
||||
const char *sfx_evtlog_error[14] = {
|
||||
"RESERVED",
|
||||
"HAS_ASSERT",
|
||||
"HAS_PANIC_DUMP",
|
||||
"INVALID_FORMAT_CAPACITY",
|
||||
"MAT_FAILED",
|
||||
"FREEZE_DUE_TO_RECOVERY_FAILED",
|
||||
"RFS_BROKEN",
|
||||
"MEDIA_ERR_ON_PAGE_IN",
|
||||
"MEDIA_ERR_ON_MPAGE_HEADER",
|
||||
"CAPACITOR_BROKEN",
|
||||
"READONLY_DUE_TO_RECOVERY_FAILED",
|
||||
"RD_ERR_IN_GSD_RECOVERY",
|
||||
"RD_ERR_ON_PF_RECOVERY",
|
||||
"MEDIA_ERR_ON_FULL_RECOVERY"
|
||||
};
|
||||
|
||||
struct sfx_nvme_evtlog_info {
|
||||
__u16 time_stamp[4];
|
||||
__u64 magic1;
|
||||
__u8 reverse[10];
|
||||
char evt_name[32];
|
||||
__u64 magic2;
|
||||
char fw_ver[24];
|
||||
char bl2_ver[32];
|
||||
__u16 code;
|
||||
__u16 assert_id;
|
||||
} __packed;
|
||||
|
||||
struct sfx_nvme_evtlog_info *info = NULL;
|
||||
|
||||
fd = fopen(output, "w+");
|
||||
if (!fd) {
|
||||
fprintf(stderr, "Failed to open %s file to write\n", output);
|
||||
err = ENOENT;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
while (length > 0) {
|
||||
info = (struct sfx_nvme_evtlog_info *)(pevent_log_info + offset);
|
||||
|
||||
if ((info->magic1 == 0x474F4C545645) &&
|
||||
(info->magic2 == 0x38B0B3ABA9BA)) {
|
||||
|
||||
memset(str_buffer, 0, 512);
|
||||
str_pos = 0;
|
||||
|
||||
fw_core = info->time_stamp[3];
|
||||
snprintf(str_buffer + str_pos, 16, "[%d-", fw_core);
|
||||
str_pos = strlen(str_buffer);
|
||||
|
||||
fw_time = ((__u64)info->time_stamp[2] << 32) + ((__u64)info->time_stamp[1] << 16) + (__u64)info->time_stamp[0];
|
||||
convert_ts(fw_time, str_buffer + str_pos);
|
||||
str_pos = strlen(str_buffer);
|
||||
|
||||
strcpy(str_buffer + str_pos, "] event-log:\n");
|
||||
str_pos = strlen(str_buffer);
|
||||
|
||||
snprintf(str_buffer + str_pos, 128,
|
||||
" > fw_version: %s\n > bl2_version: %s\n",
|
||||
info->fw_ver, info->bl2_ver);
|
||||
str_pos = strlen(str_buffer);
|
||||
|
||||
code_level = (info->code & 0x100) >> 8;
|
||||
code_type = (info->code % 0x100);
|
||||
if (code_level == sfx_evtlog_level_warning) {
|
||||
snprintf(str_buffer + str_pos, 128,
|
||||
" > error_str: [WARNING][%s]\n\n",
|
||||
sfx_evtlog_warning[code_type]);
|
||||
} else {
|
||||
if (info->assert_id)
|
||||
snprintf(str_buffer + str_pos, 128,
|
||||
" > error_str: [ERROR][%s]\n > assert_id: %d\n\n",
|
||||
sfx_evtlog_error[code_type], info->assert_id);
|
||||
else
|
||||
snprintf(str_buffer + str_pos, 128,
|
||||
" > error_str: [ERROR][%s]\n\n",
|
||||
sfx_evtlog_error[code_type]);
|
||||
}
|
||||
str_pos = strlen(str_buffer);
|
||||
|
||||
if (fwrite(str_buffer, 1, str_pos, fd) != str_pos) {
|
||||
fprintf(stderr, "Failed to write parse result to output file\n");
|
||||
goto close_fd;
|
||||
}
|
||||
}
|
||||
|
||||
offset++;
|
||||
length--;
|
||||
|
||||
if (!(offset % (log_len / 100)) || (offset == log_len))
|
||||
util_spinner("Parse", (float) (offset) / (float) (log_len));
|
||||
}
|
||||
|
||||
printf("\nParse-evtlog: Success\n");
|
||||
|
||||
close_fd:
|
||||
fclose(fd);
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nvme_dump_evtlog(struct nvme_dev *dev, __u32 namespace_id, __u32 storage_medium,
|
||||
char *file, bool parse, char *output)
|
||||
{
|
||||
struct nvme_persistent_event_log *pevent;
|
||||
void *pevent_log_info;
|
||||
__u8 lsp_base;
|
||||
__u32 offset = 0;
|
||||
__u32 length = 0;
|
||||
__u32 log_len;
|
||||
__u32 single_len;
|
||||
bool huge;
|
||||
int err = 0;
|
||||
FILE *fd = NULL;
|
||||
struct nvme_get_log_args args = {
|
||||
.args_size = sizeof(args),
|
||||
.fd = dev_fd(dev),
|
||||
.lid = NVME_LOG_LID_PERSISTENT_EVENT,
|
||||
.nsid = namespace_id,
|
||||
.lpo = NVME_LOG_LPO_NONE,
|
||||
.lsp = NVME_LOG_LSP_NONE,
|
||||
.lsi = NVME_LOG_LSI_NONE,
|
||||
.rae = false,
|
||||
.uuidx = NVME_UUID_NONE,
|
||||
.csi = NVME_CSI_NVM,
|
||||
.ot = false,
|
||||
.len = 0,
|
||||
.log = NULL,
|
||||
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
|
||||
.result = NULL,
|
||||
};
|
||||
|
||||
if (!storage_medium) {
|
||||
lsp_base = 0;
|
||||
single_len = 64 * 1024 - 4;
|
||||
} else {
|
||||
lsp_base = 4;
|
||||
single_len = 32 * 1024;
|
||||
}
|
||||
|
||||
pevent = calloc(sizeof(*pevent), sizeof(__u8));
|
||||
if (!pevent) {
|
||||
err = -ENOMEM;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
args.lsp = lsp_base + NVME_PEVENT_LOG_RELEASE_CTX;
|
||||
args.log = pevent;
|
||||
args.len = sizeof(*pevent);
|
||||
|
||||
err = nvme_get_log(&args);
|
||||
if (err) {
|
||||
fprintf(stderr, "Unable to get evtlog lsp=0x%x, ret = 0x%x\n", args.lsp, err);
|
||||
goto free_pevent;
|
||||
}
|
||||
|
||||
args.lsp = lsp_base + NVME_PEVENT_LOG_EST_CTX_AND_READ;
|
||||
err = nvme_get_log(&args);
|
||||
if (err) {
|
||||
fprintf(stderr, "Unable to get evtlog lsp=0x%x, ret = 0x%x\n", args.lsp, err);
|
||||
goto free_pevent;
|
||||
}
|
||||
|
||||
log_len = le64_to_cpu(pevent->tll);
|
||||
if (log_len % 4)
|
||||
log_len = (log_len / 4 + 1) * 4;
|
||||
|
||||
pevent_log_info = nvme_alloc(single_len, &huge);
|
||||
if (!pevent_log_info) {
|
||||
err = -ENOMEM;
|
||||
goto free_pevent;
|
||||
}
|
||||
|
||||
fd = fopen(file, "wb+");
|
||||
if (!fd) {
|
||||
fprintf(stderr, "Failed to open %s file to write\n", file);
|
||||
err = ENOENT;
|
||||
goto free;
|
||||
}
|
||||
|
||||
args.lsp = lsp_base + NVME_PEVENT_LOG_READ;
|
||||
args.log = pevent_log_info;
|
||||
length = log_len;
|
||||
while (length > 0) {
|
||||
args.lpo = offset;
|
||||
if (length > single_len) {
|
||||
args.len = single_len;
|
||||
} else {
|
||||
memset(args.log, 0, args.len);
|
||||
args.len = length;
|
||||
}
|
||||
err = nvme_get_log(&args);
|
||||
if (err) {
|
||||
fprintf(stderr, "Unable to get evtlog offset=0x%x len 0x%x ret = 0x%x\n", offset, args.len, err);
|
||||
goto close_fd;
|
||||
}
|
||||
|
||||
if (fwrite(args.log, 1, args.len, fd) != args.len) {
|
||||
fprintf(stderr, "Failed to write evtlog to file\n");
|
||||
goto close_fd;
|
||||
}
|
||||
|
||||
offset += args.len;
|
||||
length -= args.len;
|
||||
util_spinner("Parse", (float) (offset) / (float) (log_len));
|
||||
}
|
||||
|
||||
printf("\nDump-evtlog: Success\n");
|
||||
|
||||
if (parse) {
|
||||
nvme_free(pevent_log_info, huge);
|
||||
pevent_log_info = nvme_alloc(log_len, &huge);
|
||||
if (!pevent_log_info) {
|
||||
fprintf(stderr, "Failed to alloc enough memory 0x%x to parse evtlog\n", log_len);
|
||||
err = -ENOMEM;
|
||||
goto close_fd;
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
fd = fopen(file, "rb");
|
||||
if (!fd) {
|
||||
fprintf(stderr, "Failed to open %s file to read\n", file);
|
||||
err = ENOENT;
|
||||
goto free;
|
||||
}
|
||||
if (fread(pevent_log_info, 1, log_len, fd) != log_len) {
|
||||
fprintf(stderr, "Failed to read evtlog to buffer\n");
|
||||
goto close_fd;
|
||||
}
|
||||
|
||||
err = nvme_parse_evtlog(pevent_log_info, log_len, output);
|
||||
}
|
||||
|
||||
close_fd:
|
||||
fclose(fd);
|
||||
free:
|
||||
nvme_free(pevent_log_info, huge);
|
||||
free_pevent:
|
||||
free(pevent);
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sfx_dump_evtlog(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
char *desc = "dump evtlog into file and parse";
|
||||
const char *file = "evtlog file(required)";
|
||||
const char *namespace_id = "desired namespace";
|
||||
const char *storage_medium = "evtlog storage medium\n"
|
||||
"0: nand(default) 1: nor";
|
||||
const char *parse = "parse error & warning evtlog from evtlog file";
|
||||
const char *output = "parse result output file";
|
||||
struct nvme_dev *dev;
|
||||
int err = 0;
|
||||
|
||||
struct config {
|
||||
char *file;
|
||||
__u32 namespace_id;
|
||||
__u32 storage_medium;
|
||||
bool parse;
|
||||
char *output;
|
||||
};
|
||||
struct config cfg = {
|
||||
.file = NULL,
|
||||
.namespace_id = 0xffffffff,
|
||||
.storage_medium = 0,
|
||||
.parse = false,
|
||||
.output = NULL,
|
||||
};
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_FILE("file", 'f', &cfg.file, file),
|
||||
OPT_UINT("namespace_id", 'n', &cfg.namespace_id, namespace_id),
|
||||
OPT_UINT("storage_medium", 's', &cfg.storage_medium, storage_medium),
|
||||
OPT_FLAG("parse", 'p', &cfg.parse, parse),
|
||||
OPT_FILE("output", 'o', &cfg.output, output),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err)
|
||||
goto ret;
|
||||
|
||||
if (!cfg.file) {
|
||||
fprintf(stderr, "file required param\n");
|
||||
err = EINVAL;
|
||||
goto close_dev;
|
||||
}
|
||||
|
||||
if (cfg.parse && !cfg.output) {
|
||||
fprintf(stderr, "output file required if evtlog need be parsed\n");
|
||||
err = EINVAL;
|
||||
goto close_dev;
|
||||
}
|
||||
|
||||
err = nvme_dump_evtlog(dev, cfg.namespace_id, cfg.storage_medium, cfg.file, cfg.parse, cfg.output);
|
||||
|
||||
close_dev:
|
||||
dev_close(dev);
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nvme_expand_cap(struct nvme_dev *dev, __u32 namespace_id, __u64 namespace_size,
|
||||
__u64 namespace_cap, __u32 lbaf, __u32 units)
|
||||
{
|
||||
struct dirent **devices;
|
||||
char dev_name[32] = "";
|
||||
int i = 0;
|
||||
int num = 0;
|
||||
int err = 0;
|
||||
|
||||
struct sfx_expand_cap_info {
|
||||
__u64 namespace_size;
|
||||
__u64 namespace_cap;
|
||||
__u8 reserve[10];
|
||||
__u8 lbaf;
|
||||
__u8 reserve1[5];
|
||||
} __packed;
|
||||
|
||||
if (S_ISCHR(dev->direct.stat.st_mode))
|
||||
snprintf(dev_name, 32, "%sn%u", dev->name, namespace_id);
|
||||
else
|
||||
strcpy(dev_name, dev->name);
|
||||
|
||||
num = scandir("/dev", &devices, nvme_namespace_filter, alphasort);
|
||||
if (num <= 0) {
|
||||
err = num;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if (strcmp(dev_name, devices[num-1]->d_name)) {
|
||||
fprintf(stderr, "Expand namespace not the last one\n");
|
||||
err = EINVAL;
|
||||
goto free_devices;
|
||||
}
|
||||
|
||||
if (!units) {
|
||||
namespace_size = IDEMA_CAP(namespace_size) / (1 << (lbaf * 3));
|
||||
namespace_cap = IDEMA_CAP(namespace_cap) / (1 << (lbaf * 3));
|
||||
}
|
||||
|
||||
struct sfx_expand_cap_info info = {
|
||||
.namespace_size = namespace_size,
|
||||
.namespace_cap = namespace_cap,
|
||||
.lbaf = lbaf,
|
||||
};
|
||||
|
||||
struct nvme_passthru_cmd cmd = {
|
||||
.opcode = nvme_admin_ns_mgmt,
|
||||
.nsid = namespace_id,
|
||||
.addr = (__u64)(uintptr_t)&info,
|
||||
.data_len = sizeof(info),
|
||||
.cdw10 = 0x0e,
|
||||
};
|
||||
|
||||
err = nvme_submit_admin_passthru(dev_fd(dev), &cmd, NULL);
|
||||
if (err) {
|
||||
fprintf(stderr, "Create ns failed\n");
|
||||
nvme_show_status(err);
|
||||
goto free_devices;
|
||||
}
|
||||
|
||||
free_devices:
|
||||
for (i = 0; i < num; i++)
|
||||
free(devices[i]);
|
||||
free(devices);
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sfx_expand_cap(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
char *desc = "expand capacity";
|
||||
const char *namespace_id = "desired namespace";
|
||||
const char *namespace_size = "namespace size(required)";
|
||||
const char *namespace_cap = "namespace capacity(required)";
|
||||
const char *lbaf = "LBA format to apply\n"
|
||||
"0: 512(default) 1: 4096";
|
||||
const char *units = "namespace size/capacity units\n"
|
||||
"0: GB(default) 1: LBA";
|
||||
struct nvme_dev *dev;
|
||||
int err = 0;
|
||||
|
||||
struct config {
|
||||
__u32 namespace_id;
|
||||
__u64 namespace_size;
|
||||
__u64 namespace_cap;
|
||||
__u32 lbaf;
|
||||
__u32 units;
|
||||
};
|
||||
struct config cfg = {
|
||||
.namespace_id = 0xffffffff,
|
||||
.lbaf = 0,
|
||||
.units = 0,
|
||||
};
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_UINT("namespace_id", 'n', &cfg.namespace_id, namespace_id),
|
||||
OPT_LONG("namespace_size", 's', &cfg.namespace_size, namespace_size),
|
||||
OPT_LONG("namespace_cap", 'c', &cfg.namespace_cap, namespace_cap),
|
||||
OPT_UINT("lbaf", 'l', &cfg.lbaf, lbaf),
|
||||
OPT_UINT("units", 'u', &cfg.units, units),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err)
|
||||
goto ret;
|
||||
|
||||
if (cfg.namespace_id == 0xffffffff) {
|
||||
if (S_ISCHR(dev->direct.stat.st_mode)) {
|
||||
fprintf(stderr, "namespace_id or blk device required\n");
|
||||
err = EINVAL;
|
||||
goto ret;
|
||||
} else {
|
||||
cfg.namespace_id = atoi(&dev->name[strlen(dev->name) - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!cfg.namespace_size) {
|
||||
fprintf(stderr, "namespace_size required param\n");
|
||||
err = EINVAL;
|
||||
goto close_dev;
|
||||
}
|
||||
|
||||
if (!cfg.namespace_cap) {
|
||||
fprintf(stderr, "namespace_cap required param\n");
|
||||
err = EINVAL;
|
||||
goto close_dev;
|
||||
}
|
||||
|
||||
err = nvme_expand_cap(dev, cfg.namespace_id, cfg.namespace_size, cfg.namespace_cap, cfg.lbaf, cfg.units);
|
||||
if (err)
|
||||
goto close_dev;
|
||||
|
||||
printf("%s: Success, create nsid:%d\n", cmd->name, cfg.namespace_id);
|
||||
|
||||
close_dev:
|
||||
dev_close(dev);
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ PLUGIN(NAME("sfx", "ScaleFlux vendor specific extensions", NVME_VERSION),
|
|||
ENTRY("change-cap", "Dynamic change capacity", change_cap)
|
||||
ENTRY("set-feature", "Set a feature", sfx_set_feature)
|
||||
ENTRY("get-feature", "Get a feature", sfx_get_feature)
|
||||
ENTRY("dump-evtlog", "dump evtlog into file and parse warning & error log", sfx_dump_evtlog)
|
||||
ENTRY("expand-cap", "expand the last namespace capacity lossless", sfx_expand_cap)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -54,79 +54,54 @@ static char *log_pages_supp_print(__u32 pageID)
|
|||
switch (pageID) {
|
||||
case 0x01:
|
||||
return "ERROR_INFORMATION";
|
||||
break;
|
||||
case 0x02:
|
||||
return "SMART_INFORMATION";
|
||||
break;
|
||||
case 0x03:
|
||||
return "FW_SLOT_INFORMATION";
|
||||
break;
|
||||
case 0x04:
|
||||
return "CHANGED_NAMESPACE_LIST";
|
||||
break;
|
||||
case 0x05:
|
||||
return "COMMANDS_SUPPORTED_AND_EFFECTS";
|
||||
break;
|
||||
case 0x06:
|
||||
return "DEVICE_SELF_TEST";
|
||||
break;
|
||||
case 0x07:
|
||||
return "TELEMETRY_HOST_INITIATED";
|
||||
break;
|
||||
case 0x08:
|
||||
return "TELEMETRY_CONTROLLER_INITIATED";
|
||||
break;
|
||||
case 0xC0:
|
||||
return "VS_MEDIA_SMART_LOG";
|
||||
break;
|
||||
case 0xC1:
|
||||
return "VS_DEBUG_LOG1";
|
||||
break;
|
||||
case 0xC2:
|
||||
return "VS_SEC_ERROR_LOG_PAGE";
|
||||
break;
|
||||
case 0xC3:
|
||||
return "VS_LIFE_TIME_DRIVE_HISTORY";
|
||||
break;
|
||||
case 0xC4:
|
||||
return "VS_EXTENDED_SMART_INFO";
|
||||
break;
|
||||
case 0xC5:
|
||||
return "VS_LIST_SUPPORTED_LOG_PAGE";
|
||||
break;
|
||||
case 0xC6:
|
||||
return "VS_POWER_MONITOR_LOG_PAGE";
|
||||
break;
|
||||
case 0xC7:
|
||||
return "VS_CRITICAL_EVENT_LOG_PAGE";
|
||||
break;
|
||||
case 0xC8:
|
||||
return "VS_RECENT_DRIVE_HISTORY";
|
||||
break;
|
||||
case 0xC9:
|
||||
return "VS_SEC_ERROR_LOG_PAGE";
|
||||
break;
|
||||
case 0xCA:
|
||||
return "VS_LIFE_TIME_DRIVE_HISTORY";
|
||||
break;
|
||||
case 0xCB:
|
||||
return "VS_PCIE_ERROR_LOG_PAGE";
|
||||
break;
|
||||
case 0xCF:
|
||||
return "DRAM Supercap SMART Attributes";
|
||||
break;
|
||||
case 0xD6:
|
||||
return "VS_OEM2_WORK_LOAD";
|
||||
break;
|
||||
case 0xD7:
|
||||
return "VS_OEM2_FW_SECURITY";
|
||||
break;
|
||||
case 0xD8:
|
||||
return "VS_OEM2_REVISION";
|
||||
break;
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,9 +111,8 @@ static int stx_is_jag_pan(char *devMN)
|
|||
|
||||
for (int i = 0; i < STX_NUM_LEGACY_DRV; i++) {
|
||||
match_found = strncmp(devMN, stx_jag_pan_mn[i], strlen(stx_jag_pan_mn[i]));
|
||||
if (match_found == 0) {
|
||||
if (!match_found)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return match_found;
|
||||
|
@ -157,6 +131,7 @@ static void json_log_pages_supp(log_page_map *logPageMap)
|
|||
|
||||
for (i = 0; i < le32_to_cpu(logPageMap->NumLogPages); i++) {
|
||||
struct json_object *lbaf = json_create_object();
|
||||
|
||||
json_object_add_value_int(lbaf, "logpage_id",
|
||||
le32_to_cpu(logPageMap->LogPageEntry[i].LogPageID));
|
||||
json_object_add_value_string(lbaf, "logpage_name",
|
||||
|
@ -199,9 +174,9 @@ static int log_pages_supp(int argc, char **argv, struct command *cmd,
|
|||
sizeof(logPageMap), &logPageMap);
|
||||
if (!err) {
|
||||
if (strcmp(cfg.output_format, "json")) {
|
||||
printf ("Seagate Supported Log-pages count :%d\n",
|
||||
printf("Seagate Supported Log-pages count :%d\n",
|
||||
le32_to_cpu(logPageMap.NumLogPages));
|
||||
printf ("%-15s %-30s\n", "LogPage-Id", "LogPage-Name");
|
||||
printf("%-15s %-30s\n", "LogPage-Id", "LogPage-Name");
|
||||
|
||||
for (fmt = 0; fmt < 45; fmt++)
|
||||
printf("-");
|
||||
|
@ -227,154 +202,107 @@ static int log_pages_supp(int argc, char **argv, struct command *cmd,
|
|||
|
||||
/* EOF Command for "log-pages-supp" */
|
||||
|
||||
|
||||
/***************************************
|
||||
* Extended-SMART Information
|
||||
***************************************/
|
||||
* Extended-SMART Information
|
||||
***************************************/
|
||||
static char *print_ext_smart_id(__u8 attrId)
|
||||
{
|
||||
switch (attrId) {
|
||||
case VS_ATTR_ID_SOFT_READ_ERROR_RATE:
|
||||
return "Soft ECC error count";
|
||||
break;
|
||||
case VS_ATTR_ID_REALLOCATED_SECTOR_COUNT:
|
||||
return "Bad NAND block count";
|
||||
break;
|
||||
case VS_ATTR_ID_POWER_ON_HOURS:
|
||||
return "Power On Hours";
|
||||
break;
|
||||
case VS_ATTR_ID_POWER_FAIL_EVENT_COUNT:
|
||||
return "Power Fail Event Count";
|
||||
break;
|
||||
case VS_ATTR_ID_DEVICE_POWER_CYCLE_COUNT:
|
||||
return "Device Power Cycle Count";
|
||||
break;
|
||||
case VS_ATTR_ID_RAW_READ_ERROR_RATE:
|
||||
return "Raw Read Error Count";
|
||||
break;
|
||||
case VS_ATTR_ID_GROWN_BAD_BLOCK_COUNT:
|
||||
return "Bad NAND block count";
|
||||
break;
|
||||
case VS_ATTR_ID_END_2_END_CORRECTION_COUNT:
|
||||
return "SSD End to end correction counts";
|
||||
break;
|
||||
case VS_ATTR_ID_MIN_MAX_WEAR_RANGE_COUNT:
|
||||
return "User data erase counts";
|
||||
break;
|
||||
case VS_ATTR_ID_REFRESH_COUNT:
|
||||
return "Refresh count";
|
||||
break;
|
||||
case VS_ATTR_ID_BAD_BLOCK_COUNT_USER:
|
||||
return "User data erase fail count";
|
||||
break;
|
||||
case VS_ATTR_ID_BAD_BLOCK_COUNT_SYSTEM:
|
||||
return "System area erase fail count";
|
||||
break;
|
||||
case VS_ATTR_ID_THERMAL_THROTTLING_STATUS:
|
||||
return "Thermal throttling status and count";
|
||||
break;
|
||||
case VS_ATTR_ID_ALL_PCIE_CORRECTABLE_ERROR_COUNT:
|
||||
return "PCIe Correctable Error count";
|
||||
break;
|
||||
case VS_ATTR_ID_ALL_PCIE_UNCORRECTABLE_ERROR_COUNT:
|
||||
return "PCIe Uncorrectable Error count";
|
||||
break;
|
||||
case VS_ATTR_ID_INCOMPLETE_SHUTDOWN_COUNT:
|
||||
return "Incomplete shutdowns";
|
||||
break;
|
||||
case VS_ATTR_ID_GB_ERASED_LSB:
|
||||
return "LSB of Flash GB erased";
|
||||
break;
|
||||
case VS_ATTR_ID_GB_ERASED_MSB:
|
||||
return "MSB of Flash GB erased";
|
||||
break;
|
||||
case VS_ATTR_ID_LIFETIME_DEVSLEEP_EXIT_COUNT:
|
||||
return "LIFETIME_DEV_SLEEP_EXIT_COUNT";
|
||||
break;
|
||||
case VS_ATTR_ID_LIFETIME_ENTERING_PS4_COUNT:
|
||||
return "LIFETIME_ENTERING_PS4_COUNT";
|
||||
break;
|
||||
case VS_ATTR_ID_LIFETIME_ENTERING_PS3_COUNT:
|
||||
return "LIFETIME_ENTERING_PS3_COUNT";
|
||||
break;
|
||||
case VS_ATTR_ID_RETIRED_BLOCK_COUNT:
|
||||
return "Retired block count";
|
||||
break;
|
||||
case VS_ATTR_ID_PROGRAM_FAILURE_COUNT:
|
||||
return "Program fail count";
|
||||
break;
|
||||
case VS_ATTR_ID_ERASE_FAIL_COUNT:
|
||||
return "Erase Fail Count";
|
||||
break;
|
||||
case VS_ATTR_ID_AVG_ERASE_COUNT:
|
||||
return "System data % used";
|
||||
break;
|
||||
case VS_ATTR_ID_UNEXPECTED_POWER_LOSS_COUNT:
|
||||
return "Unexpected power loss count";
|
||||
break;
|
||||
case VS_ATTR_ID_WEAR_RANGE_DELTA:
|
||||
return "Wear range delta";
|
||||
break;
|
||||
case VS_ATTR_ID_SATA_INTERFACE_DOWNSHIFT_COUNT:
|
||||
return "PCIE_INTF_DOWNSHIFT_COUNT";
|
||||
break;
|
||||
case VS_ATTR_ID_END_TO_END_CRC_ERROR_COUNT:
|
||||
return "E2E_CRC_ERROR_COUNT";
|
||||
break;
|
||||
case VS_ATTR_ID_UNCORRECTABLE_READ_ERRORS:
|
||||
return "Uncorrectable Read Error Count";
|
||||
break;
|
||||
case VS_ATTR_ID_MAX_LIFE_TEMPERATURE:
|
||||
return "Max lifetime temperature";
|
||||
break;
|
||||
case VS_ATTR_ID_RAISE_ECC_CORRECTABLE_ERROR_COUNT:
|
||||
return "RAIS_ECC_CORRECT_ERR_COUNT";
|
||||
break;
|
||||
case VS_ATTR_ID_UNCORRECTABLE_RAISE_ERRORS:
|
||||
return "Uncorrectable RAISE error count";
|
||||
break;
|
||||
case VS_ATTR_ID_DRIVE_LIFE_PROTECTION_STATUS:
|
||||
return "DRIVE_LIFE_PROTECTION_STATUS";
|
||||
break;
|
||||
case VS_ATTR_ID_REMAINING_SSD_LIFE:
|
||||
return "Remaining SSD life";
|
||||
break;
|
||||
case VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_LSB:
|
||||
return "LSB of Physical (NAND) bytes written";
|
||||
break;
|
||||
case VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_MSB:
|
||||
return "MSB of Physical (NAND) bytes written";
|
||||
break;
|
||||
case VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_LSB:
|
||||
return "LSB of Physical (HOST) bytes written";
|
||||
break;
|
||||
case VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_MSB:
|
||||
return "MSB of Physical (HOST) bytes written";
|
||||
break;
|
||||
case VS_ATTR_ID_LIFETIME_READS_TO_HOST_LSB:
|
||||
return "LSB of Physical (NAND) bytes read";
|
||||
break;
|
||||
case VS_ATTR_ID_LIFETIME_READS_TO_HOST_MSB:
|
||||
return "MSB of Physical (NAND) bytes read";
|
||||
break;
|
||||
case VS_ATTR_ID_FREE_SPACE:
|
||||
return "Free Space";
|
||||
break;
|
||||
case VS_ATTR_ID_TRIM_COUNT_LSB:
|
||||
return "LSB of Trim count";
|
||||
break;
|
||||
case VS_ATTR_ID_TRIM_COUNT_MSB:
|
||||
return "MSB of Trim count";
|
||||
break;
|
||||
case VS_ATTR_ID_OP_PERCENTAGE:
|
||||
return "OP percentage";
|
||||
break;
|
||||
case VS_ATTR_ID_MAX_SOC_LIFE_TEMPERATURE:
|
||||
return "Max lifetime SOC temperature";
|
||||
break;
|
||||
default:
|
||||
return "Un-Known";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static __u64 smart_attribute_vs(__u16 verNo, SmartVendorSpecific attr)
|
||||
|
@ -451,14 +379,13 @@ static void print_smart_log(__u16 verNo, SmartVendorSpecific attr, int lastAttr)
|
|||
hideAttr = 1;
|
||||
}
|
||||
|
||||
if ((attr.AttributeNumber != 0) && (hideAttr != 1)) {
|
||||
if ((attr.AttributeNumber) && (hideAttr != 1)) {
|
||||
printf("%-40s", print_ext_smart_id(attr.AttributeNumber));
|
||||
printf("%-15d", attr.AttributeNumber);
|
||||
printf(" 0x%016"PRIx64"\n", (uint64_t)smart_attribute_vs(verNo, attr));
|
||||
}
|
||||
|
||||
if (lastAttr == 1) {
|
||||
|
||||
sprintf(strBuf, "%s", (print_ext_smart_id(VS_ATTR_ID_GB_ERASED_LSB) + 7));
|
||||
printf("%-40s", strBuf);
|
||||
|
||||
|
@ -516,7 +443,8 @@ static void json_print_smart_log(struct json_object *root, EXTENDED_SMART_INFO_T
|
|||
|
||||
for (index = 0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++) {
|
||||
struct json_object *lbaf = json_create_object();
|
||||
if (ExtdSMARTInfo->vendorData[index].AttributeNumber != 0) {
|
||||
|
||||
if (ExtdSMARTInfo->vendorData[index].AttributeNumber) {
|
||||
json_object_add_value_string(lbaf, "attribute_name", print_ext_smart_id(ExtdSMARTInfo->vendorData[index].AttributeNumber));
|
||||
json_object_add_value_int(lbaf, "attribute_id", ExtdSMARTInfo->vendorData[index].AttributeNumber);
|
||||
json_object_add_value_int(lbaf, "attribute_value", smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]));
|
||||
|
@ -612,8 +540,9 @@ static void json_print_smart_log(struct json_object *root, EXTENDED_SMART_INFO_T
|
|||
static void print_smart_log_CF(vendor_log_page_CF *pLogPageCF)
|
||||
{
|
||||
__u64 currentTemp, maxTemp;
|
||||
|
||||
printf("\n\nSeagate DRAM Supercap SMART Attributes :\n");
|
||||
printf("%-39s %-19s \n", "Description", "Supercap Attributes");
|
||||
printf("%-39s %-19s\n", "Description", "Supercap Attributes");
|
||||
|
||||
printf("%-40s", "Super-cap current temperature");
|
||||
currentTemp = pLogPageCF->AttrCF.SuperCapCurrentTemperature;
|
||||
|
@ -698,7 +627,7 @@ static void json_print_smart_log_CF(struct json_object *root, vendor_log_page_CF
|
|||
static void print_stx_smart_log_C0(STX_EXT_SMART_LOG_PAGE_C0 *pLogPageC0)
|
||||
{
|
||||
printf("\n\nSeagate SMART Health Attributes :\n");
|
||||
printf("%-39s %-19s \n", "Description", "Health Attributes");
|
||||
printf("%-39s %-19s\n", "Description", "Health Attributes");
|
||||
|
||||
printf("%-40s", "Physical Media Units Written");
|
||||
printf(" 0x%016"PRIx64"%016"PRIx64"\n", le64_to_cpu(pLogPageC0->phyMediaUnitsWrt.MS__u64),
|
||||
|
@ -986,7 +915,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi
|
|||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err) {
|
||||
printf ("\nDevice not found \n");
|
||||
printf("\nDevice not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1008,12 +937,11 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi
|
|||
return err;
|
||||
}
|
||||
|
||||
if (stx_is_jag_pan(modelNo) == 0) {
|
||||
|
||||
if (!stx_is_jag_pan(modelNo)) {
|
||||
err = nvme_get_log_simple(dev_fd(dev), 0xC4, sizeof(ExtdSMARTInfo), &ExtdSMARTInfo);
|
||||
if (!err) {
|
||||
if (strcmp(cfg.output_format, "json")) {
|
||||
printf("%-39s %-15s %-19s \n", "Description", "Ext-Smart-Id", "Ext-Smart-Value");
|
||||
printf("%-39s %-15s %-19s\n", "Description", "Ext-Smart-Id", "Ext-Smart-Value");
|
||||
for (index = 0; index < 80; index++)
|
||||
printf("-");
|
||||
printf("\n");
|
||||
|
@ -1046,15 +974,15 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi
|
|||
json_print_object(root, NULL);
|
||||
json_free_object(root);
|
||||
}
|
||||
} else if (err > 0)
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
}
|
||||
} else {
|
||||
err = nvme_get_log_simple(dev_fd(dev), 0xC0, sizeof(ehExtSmart), &ehExtSmart);
|
||||
|
||||
if (!err) {
|
||||
if (strcmp(cfg.output_format, "json")) {
|
||||
print_stx_smart_log_C0(&ehExtSmart);
|
||||
|
||||
} else {
|
||||
lbafs_ExtSmart = json_create_object();
|
||||
json_print_stx_smart_log_C0(lbafs_ExtSmart, &ehExtSmart);
|
||||
|
@ -1075,7 +1003,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi
|
|||
sizeof(ExtdSMARTInfo), &ExtdSMARTInfo);
|
||||
if (!err) {
|
||||
if (strcmp(cfg.output_format, "json")) {
|
||||
printf("%-39s %-15s %-19s \n", "Description", "Ext-Smart-Id", "Ext-Smart-Value");
|
||||
printf("%-39s %-15s %-19s\n", "Description", "Ext-Smart-Id", "Ext-Smart-Value");
|
||||
for (index = 0; index < 80; index++)
|
||||
printf("-");
|
||||
printf("\n");
|
||||
|
@ -1105,10 +1033,12 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi
|
|||
json_array_add_value_object(lbafs, lbafs_DramSmart);
|
||||
json_print_object(root, NULL);
|
||||
}
|
||||
} else if (!strcmp(cfg.output_format, "json"))
|
||||
} else if (!strcmp(cfg.output_format, "json")) {
|
||||
json_print_object(root, NULL);
|
||||
} else if (err > 0)
|
||||
}
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
}
|
||||
|
||||
dev_close(dev);
|
||||
|
||||
|
@ -1123,8 +1053,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi
|
|||
static void json_temp_stats(__u32 temperature, __u32 PcbTemp, __u32 SocTemp, __u32 maxTemperature,
|
||||
__u32 MaxSocTemp, __u32 cf_err, __u32 scCurrentTemp, __u32 scMaxTem)
|
||||
{
|
||||
struct json_object *root;
|
||||
root = json_create_object();
|
||||
struct json_object *root = json_create_object();
|
||||
|
||||
json_object_add_value_int(root, "Current temperature", temperature);
|
||||
json_object_add_value_int(root, "Current PCB temperature", PcbTemp);
|
||||
|
@ -1167,7 +1096,7 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin
|
|||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err) {
|
||||
printf ("\nDevice not found \n");;
|
||||
printf("\nDevice not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1239,19 +1168,16 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin
|
|||
***************************************/
|
||||
static void print_vs_pcie_error_log(pcie_error_log_page pcieErrorLog)
|
||||
{
|
||||
__u32 correctPcieEc = 0;
|
||||
__u32 uncorrectPcieEc = 0;
|
||||
correctPcieEc = pcieErrorLog.BadDllpErrCnt + pcieErrorLog.BadTlpErrCnt
|
||||
+ pcieErrorLog.RcvrErrCnt + pcieErrorLog.ReplayTOErrCnt
|
||||
+ pcieErrorLog.ReplayNumRolloverErrCnt;
|
||||
|
||||
uncorrectPcieEc = pcieErrorLog.FCProtocolErrCnt + pcieErrorLog.DllpProtocolErrCnt
|
||||
+ pcieErrorLog.CmpltnTOErrCnt + pcieErrorLog.RcvrQOverflowErrCnt
|
||||
+ pcieErrorLog.UnexpectedCplTlpErrCnt + pcieErrorLog.CplTlpURErrCnt
|
||||
+ pcieErrorLog.CplTlpCAErrCnt + pcieErrorLog.ReqCAErrCnt
|
||||
+ pcieErrorLog.ReqURErrCnt + pcieErrorLog.EcrcErrCnt
|
||||
+ pcieErrorLog.MalformedTlpErrCnt + pcieErrorLog.CplTlpPoisonedErrCnt
|
||||
+ pcieErrorLog.MemRdTlpPoisonedErrCnt;
|
||||
__u32 correctPcieEc = pcieErrorLog.BadDllpErrCnt + pcieErrorLog.BadTlpErrCnt +
|
||||
pcieErrorLog.RcvrErrCnt + pcieErrorLog.ReplayTOErrCnt +
|
||||
pcieErrorLog.ReplayNumRolloverErrCnt;
|
||||
__u32 uncorrectPcieEc = pcieErrorLog.FCProtocolErrCnt + pcieErrorLog.DllpProtocolErrCnt +
|
||||
pcieErrorLog.CmpltnTOErrCnt + pcieErrorLog.RcvrQOverflowErrCnt +
|
||||
pcieErrorLog.UnexpectedCplTlpErrCnt + pcieErrorLog.CplTlpURErrCnt +
|
||||
pcieErrorLog.CplTlpCAErrCnt + pcieErrorLog.ReqCAErrCnt +
|
||||
pcieErrorLog.ReqURErrCnt + pcieErrorLog.EcrcErrCnt +
|
||||
pcieErrorLog.MalformedTlpErrCnt + pcieErrorLog.CplTlpPoisonedErrCnt +
|
||||
pcieErrorLog.MemRdTlpPoisonedErrCnt;
|
||||
|
||||
printf("%-45s : %u\n", "PCIe Correctable Error Count", correctPcieEc);
|
||||
printf("%-45s : %u\n", "PCIe Un-Correctable Error Count", uncorrectPcieEc);
|
||||
|
@ -1279,21 +1205,17 @@ static void print_vs_pcie_error_log(pcie_error_log_page pcieErrorLog)
|
|||
|
||||
static void json_vs_pcie_error_log(pcie_error_log_page pcieErrorLog)
|
||||
{
|
||||
struct json_object *root;
|
||||
root = json_create_object();
|
||||
__u32 correctPcieEc = 0;
|
||||
__u32 uncorrectPcieEc = 0;
|
||||
correctPcieEc = pcieErrorLog.BadDllpErrCnt + pcieErrorLog.BadTlpErrCnt
|
||||
+ pcieErrorLog.RcvrErrCnt + pcieErrorLog.ReplayTOErrCnt
|
||||
+ pcieErrorLog.ReplayNumRolloverErrCnt;
|
||||
|
||||
uncorrectPcieEc = pcieErrorLog.FCProtocolErrCnt + pcieErrorLog.DllpProtocolErrCnt
|
||||
+ pcieErrorLog.CmpltnTOErrCnt + pcieErrorLog.RcvrQOverflowErrCnt
|
||||
+ pcieErrorLog.UnexpectedCplTlpErrCnt + pcieErrorLog.CplTlpURErrCnt
|
||||
+ pcieErrorLog.CplTlpCAErrCnt + pcieErrorLog.ReqCAErrCnt
|
||||
+ pcieErrorLog.ReqURErrCnt + pcieErrorLog.EcrcErrCnt
|
||||
+ pcieErrorLog.MalformedTlpErrCnt + pcieErrorLog.CplTlpPoisonedErrCnt
|
||||
+ pcieErrorLog.MemRdTlpPoisonedErrCnt;
|
||||
struct json_object *root = json_create_object();
|
||||
__u32 correctPcieEc = pcieErrorLog.BadDllpErrCnt + pcieErrorLog.BadTlpErrCnt +
|
||||
pcieErrorLog.RcvrErrCnt + pcieErrorLog.ReplayTOErrCnt +
|
||||
pcieErrorLog.ReplayNumRolloverErrCnt;
|
||||
__u32 uncorrectPcieEc = pcieErrorLog.FCProtocolErrCnt + pcieErrorLog.DllpProtocolErrCnt +
|
||||
pcieErrorLog.CmpltnTOErrCnt + pcieErrorLog.RcvrQOverflowErrCnt +
|
||||
pcieErrorLog.UnexpectedCplTlpErrCnt + pcieErrorLog.CplTlpURErrCnt +
|
||||
pcieErrorLog.CplTlpCAErrCnt + pcieErrorLog.ReqCAErrCnt +
|
||||
pcieErrorLog.ReqURErrCnt + pcieErrorLog.EcrcErrCnt +
|
||||
pcieErrorLog.MalformedTlpErrCnt + pcieErrorLog.CplTlpPoisonedErrCnt +
|
||||
pcieErrorLog.MemRdTlpPoisonedErrCnt;
|
||||
|
||||
json_object_add_value_int(root, "PCIe Correctable Error Count", correctPcieEc);
|
||||
json_object_add_value_int(root, "PCIe Un-Correctable Error Count", uncorrectPcieEc);
|
||||
|
@ -1341,7 +1263,7 @@ static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct
|
|||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err) {
|
||||
printf ("\nDevice not found \n");;
|
||||
printf("\nDevice not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1351,13 +1273,14 @@ static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct
|
|||
err = nvme_get_log_simple(dev_fd(dev), 0xCB,
|
||||
sizeof(pcieErrorLog), &pcieErrorLog);
|
||||
if (!err) {
|
||||
if (strcmp(cfg.output_format, "json")) {
|
||||
if (strcmp(cfg.output_format, "json"))
|
||||
print_vs_pcie_error_log(pcieErrorLog);
|
||||
} else
|
||||
else
|
||||
json_vs_pcie_error_log(pcieErrorLog);
|
||||
|
||||
} else if (err > 0)
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
}
|
||||
|
||||
dev_close(dev);
|
||||
return err;
|
||||
|
@ -1384,8 +1307,8 @@ static void print_stx_vs_fw_activate_history(stx_fw_activ_history_log_page fwAct
|
|||
printf(" %-4d ", fwActivHis.fwActHisEnt[i].fwActivCnt);
|
||||
|
||||
time_t t = fwActivHis.fwActHisEnt[i].timeStamp / 1000;
|
||||
struct tm ts;
|
||||
ts = *localtime(&t);
|
||||
struct tm ts = *localtime(&t);
|
||||
|
||||
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &ts);
|
||||
printf(" %-20s ", buf);
|
||||
printf("%-5" PRId64 " ",
|
||||
|
@ -1401,7 +1324,7 @@ static void print_stx_vs_fw_activate_history(stx_fw_activ_history_log_page fwAct
|
|||
|
||||
printf(" %-2d ", fwActivHis.fwActHisEnt[i].slotNum);
|
||||
printf(" 0x%02x ", fwActivHis.fwActHisEnt[i].commitActionType);
|
||||
printf(" 0x%02x \n", fwActivHis.fwActHisEnt[i].result);
|
||||
printf(" 0x%02x\n", fwActivHis.fwActHisEnt[i].result);
|
||||
}
|
||||
} else {
|
||||
printf("%s\n", "Do not have valid FW Activation History");
|
||||
|
@ -1410,14 +1333,13 @@ static void print_stx_vs_fw_activate_history(stx_fw_activ_history_log_page fwAct
|
|||
|
||||
static void json_stx_vs_fw_activate_history(stx_fw_activ_history_log_page fwActivHis)
|
||||
{
|
||||
struct json_object *root;
|
||||
root = json_create_object();
|
||||
struct json_object *root = json_create_object();
|
||||
__u32 i;
|
||||
|
||||
char buf[80];
|
||||
|
||||
struct json_object *historyLogPage;
|
||||
historyLogPage = json_create_array();
|
||||
struct json_object *historyLogPage = json_create_array();
|
||||
|
||||
json_object_add_value_array(root, "Seagate FW Activation History", historyLogPage);
|
||||
|
||||
if (fwActivHis.numValidFwActHisEnt > 0) {
|
||||
|
@ -1429,8 +1351,8 @@ static void json_stx_vs_fw_activate_history(stx_fw_activ_history_log_page fwActi
|
|||
json_object_add_value_int(lbaf, "Counter", fwActivHis.fwActHisEnt[i].fwActivCnt);
|
||||
|
||||
time_t t = fwActivHis.fwActHisEnt[i].timeStamp / 1000;
|
||||
struct tm ts;
|
||||
ts = *localtime(&t);
|
||||
struct tm ts = *localtime(&t);
|
||||
|
||||
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &ts);
|
||||
printf(" %-20s ", buf);
|
||||
json_object_add_value_string(lbaf, "Timestamp", buf);
|
||||
|
@ -1479,7 +1401,7 @@ static int stx_vs_fw_activate_history(int argc, char **argv, struct command *cmd
|
|||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err < 0) {
|
||||
printf ("\nDevice not found \n");;
|
||||
printf("\nDevice not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1488,13 +1410,14 @@ static int stx_vs_fw_activate_history(int argc, char **argv, struct command *cmd
|
|||
|
||||
err = nvme_get_log_simple(dev_fd(dev), 0xC2, sizeof(fwActivHis), &fwActivHis);
|
||||
if (!err) {
|
||||
if (strcmp(cfg.output_format, "json")) {
|
||||
if (strcmp(cfg.output_format, "json"))
|
||||
print_stx_vs_fw_activate_history(fwActivHis);
|
||||
} else
|
||||
else
|
||||
json_stx_vs_fw_activate_history(fwActivHis);
|
||||
|
||||
} else if (err > 0)
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
}
|
||||
|
||||
dev_close(dev);
|
||||
return err;
|
||||
|
@ -1527,7 +1450,7 @@ static int clear_fw_activate_history(int argc, char **argv, struct command *cmd,
|
|||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err < 0) {
|
||||
printf ("\nDevice not found \n");
|
||||
printf("\nDevice not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1539,10 +1462,9 @@ static int clear_fw_activate_history(int argc, char **argv, struct command *cmd,
|
|||
return err;
|
||||
}
|
||||
|
||||
if (stx_is_jag_pan(modelNo) == 0) {
|
||||
printf ("\nDevice does not support Clear FW Activation History \n");
|
||||
if (!stx_is_jag_pan(modelNo)) {
|
||||
printf("\nDevice does not support Clear FW Activation History\n");
|
||||
} else {
|
||||
|
||||
struct nvme_set_features_args args = {
|
||||
.args_size = sizeof(args),
|
||||
.fd = dev_fd(dev),
|
||||
|
@ -1560,7 +1482,7 @@ static int clear_fw_activate_history(int argc, char **argv, struct command *cmd,
|
|||
};
|
||||
err = nvme_set_features(&args);
|
||||
if (err)
|
||||
fprintf(stderr, "%s: couldn't clear PCIe correctable errors \n",
|
||||
fprintf(stderr, "%s: couldn't clear PCIe correctable errors\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
|
@ -1602,7 +1524,7 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c
|
|||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err) {
|
||||
printf ("\nDevice not found \n");;
|
||||
printf("\nDevice not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1615,27 +1537,27 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c
|
|||
return err;
|
||||
}
|
||||
|
||||
if (stx_is_jag_pan(modelNo) == 0) {
|
||||
if (!stx_is_jag_pan(modelNo)) {
|
||||
err = nvme_set_features_simple(dev_fd(dev), 0xE1, 0, 0xCB, cfg.save, &result);
|
||||
} else {
|
||||
struct nvme_set_features_args args = {
|
||||
.args_size = sizeof(args),
|
||||
.fd = dev_fd(dev),
|
||||
.fid = 0xC3,
|
||||
.nsid = 0,
|
||||
.cdw11 = 0x80000000,
|
||||
.cdw12 = 0,
|
||||
.save = 0,
|
||||
.uuidx = 0,
|
||||
.cdw15 = 0,
|
||||
.data_len = 0,
|
||||
.data = NULL,
|
||||
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
|
||||
.result = &result,
|
||||
};
|
||||
err = nvme_set_features(&args);
|
||||
if (err)
|
||||
fprintf(stderr, "%s: couldn't clear PCIe correctable errors \n", __func__);
|
||||
.args_size = sizeof(args),
|
||||
.fd = dev_fd(dev),
|
||||
.fid = 0xC3,
|
||||
.nsid = 0,
|
||||
.cdw11 = 0x80000000,
|
||||
.cdw12 = 0,
|
||||
.save = 0,
|
||||
.uuidx = 0,
|
||||
.cdw15 = 0,
|
||||
.data_len = 0,
|
||||
.data = NULL,
|
||||
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
|
||||
.result = &result,
|
||||
};
|
||||
err = nvme_set_features(&args);
|
||||
if (err)
|
||||
fprintf(stderr, "%s: couldn't clear PCIe correctable errors\n", __func__);
|
||||
}
|
||||
|
||||
err = nvme_set_features_simple(dev_fd(dev), 0xE1, 0, 0xCB, cfg.save, &result);
|
||||
|
@ -1651,11 +1573,11 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c
|
|||
|
||||
static int get_host_tele(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "Capture the Telemetry Host-Initiated Data in either " \
|
||||
"hex-dump (default) or binary format";
|
||||
const char *desc =
|
||||
"Capture the Telemetry Host-Initiated Data in either hex-dump (default) or binary format";
|
||||
const char *namespace_id = "desired namespace";
|
||||
const char *log_specific = "1 - controller shall capture Data representing the internal " \
|
||||
"state of the controller at the time the command is processed. " \
|
||||
const char *log_specific = "1 - controller shall capture Data representing the internal\n"
|
||||
"state of the controller at the time the command is processed.\n"
|
||||
"0 - controller shall not update the Telemetry Host Initiated Data.";
|
||||
const char *raw = "output in raw format";
|
||||
struct nvme_temetry_log_hdr tele_log;
|
||||
|
@ -1706,10 +1628,11 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug
|
|||
d((unsigned char *)(&tele_log), sizeof(tele_log), 16, 1);
|
||||
} else
|
||||
seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd);
|
||||
} else if (err > 0)
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
else
|
||||
} else {
|
||||
perror("log page");
|
||||
}
|
||||
|
||||
blkCnt = 0;
|
||||
|
||||
|
@ -1718,7 +1641,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug
|
|||
|
||||
blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt);
|
||||
|
||||
if (blksToGet == 0) {
|
||||
if (!blksToGet) {
|
||||
dev_close(dev);
|
||||
return err;
|
||||
}
|
||||
|
@ -1729,7 +1652,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug
|
|||
if (!log) {
|
||||
fprintf(stderr, "could not alloc buffer for log\n");
|
||||
dev_close(dev);
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(log, 0, bytesToGet);
|
||||
|
@ -1761,10 +1684,11 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug
|
|||
d((unsigned char *)log, bytesToGet, 16, 1);
|
||||
} else
|
||||
seaget_d_raw((unsigned char *)log, bytesToGet, dump_fd);
|
||||
} else if (err > 0)
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
else
|
||||
} else {
|
||||
perror("log page");
|
||||
}
|
||||
|
||||
blkCnt += blksToGet;
|
||||
|
||||
|
@ -1777,8 +1701,8 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug
|
|||
|
||||
static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "Capture the Telemetry Controller-Initiated Data in either " \
|
||||
"hex-dump (default) or binary format";
|
||||
const char *desc =
|
||||
"Capture the Telemetry Controller-Initiated Data in either hex-dump (default) or binary format";
|
||||
const char *namespace_id = "desired namespace";
|
||||
const char *raw = "output in raw format";
|
||||
struct nvme_dev *dev;
|
||||
|
@ -1826,10 +1750,11 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug
|
|||
d((unsigned char *)(&tele_log), sizeof(tele_log), 16, 1);
|
||||
} else
|
||||
seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd);
|
||||
} else if (err > 0)
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
else
|
||||
} else {
|
||||
perror("log page");
|
||||
}
|
||||
|
||||
blkCnt = 0;
|
||||
|
||||
|
@ -1838,7 +1763,7 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug
|
|||
|
||||
blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt);
|
||||
|
||||
if (blksToGet == 0)
|
||||
if (!blksToGet)
|
||||
return err;
|
||||
|
||||
bytesToGet = (unsigned long long)blksToGet * 512;
|
||||
|
@ -1846,7 +1771,7 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug
|
|||
|
||||
if (!log) {
|
||||
fprintf(stderr, "could not alloc buffer for log\n");
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(log, 0, bytesToGet);
|
||||
|
@ -1878,10 +1803,11 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug
|
|||
d((unsigned char *)log, bytesToGet, 16, 1);
|
||||
} else
|
||||
seaget_d_raw((unsigned char *)log, bytesToGet, dump_fd);
|
||||
} else if (err > 0)
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
else
|
||||
} else {
|
||||
perror("log page");
|
||||
}
|
||||
|
||||
blkCnt += blksToGet;
|
||||
|
||||
|
@ -1895,21 +1821,20 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug
|
|||
void seaget_d_raw(unsigned char *buf, int len, int fd)
|
||||
{
|
||||
if (write(fd, (void *)buf, len) <= 0)
|
||||
printf("%s: Write Failed\n", __FUNCTION__);
|
||||
printf("%s: Write Failed\n", __func__);
|
||||
}
|
||||
|
||||
|
||||
static int vs_internal_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "Capture the Telemetry Controller-Initiated Data in " \
|
||||
"binary format";
|
||||
const char *desc = "Capture the Telemetry Controller-Initiated Data in binary format";
|
||||
const char *namespace_id = "desired namespace";
|
||||
|
||||
const char *file = "dump file";
|
||||
struct nvme_dev *dev;
|
||||
int err, dump_fd;
|
||||
int flags = O_WRONLY | O_CREAT;
|
||||
int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
|
||||
int mode = 0664;
|
||||
struct nvme_temetry_log_hdr tele_log;
|
||||
__le64 offset = 0;
|
||||
__u16 log_id;
|
||||
|
@ -1942,7 +1867,7 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl
|
|||
if (dump_fd < 0) {
|
||||
perror(cfg.file);
|
||||
dev_close(dev);
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1954,10 +1879,11 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl
|
|||
offset += 512;
|
||||
|
||||
seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd);
|
||||
} else if (err > 0)
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
else
|
||||
} else {
|
||||
perror("log page");
|
||||
}
|
||||
|
||||
blkCnt = 0;
|
||||
|
||||
|
@ -1966,9 +1892,8 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl
|
|||
|
||||
blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt);
|
||||
|
||||
if (blksToGet == 0) {
|
||||
if (!blksToGet)
|
||||
goto out;
|
||||
}
|
||||
|
||||
bytesToGet = (unsigned long long)blksToGet * 512;
|
||||
log = malloc(bytesToGet);
|
||||
|
@ -2004,10 +1929,11 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl
|
|||
|
||||
seaget_d_raw((unsigned char *)log, bytesToGet, dump_fd);
|
||||
|
||||
} else if (err > 0)
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
else
|
||||
} else {
|
||||
perror("log page");
|
||||
}
|
||||
|
||||
blkCnt += blksToGet;
|
||||
|
||||
|
@ -2024,7 +1950,7 @@ out:
|
|||
/*SEAGATE-PLUGIN Version */
|
||||
static int seagate_plugin_version(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
printf("Seagate-Plugin version : %d.%d \n",
|
||||
printf("Seagate-Plugin version : %d.%d\n",
|
||||
SEAGATE_PLUGIN_VERSION_MAJOR,
|
||||
SEAGATE_PLUGIN_VERSION_MINOR);
|
||||
return 0;
|
||||
|
@ -2034,7 +1960,7 @@ static int seagate_plugin_version(int argc, char **argv, struct command *cmd, st
|
|||
/*OCP SEAGATE-PLUGIN Version */
|
||||
static int stx_ocp_plugin_version(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
printf("Seagate-OCP-Plugin version : %d.%d \n",
|
||||
printf("Seagate-OCP-Plugin version : %d.%d\n",
|
||||
SEAGATE_OCP_PLUGIN_VERSION_MAJOR,
|
||||
SEAGATE_OCP_PLUGIN_VERSION_MINOR);
|
||||
return 0;
|
||||
|
|
|
@ -16,25 +16,25 @@
|
|||
#define CREATE_CMD
|
||||
#include "shannon-nvme.h"
|
||||
|
||||
typedef enum {
|
||||
enum {
|
||||
PROGRAM_FAIL_CNT,
|
||||
ERASE_FAIL_CNT,
|
||||
WEARLEVELING_COUNT,
|
||||
E2E_ERR_CNT,
|
||||
CRC_ERR_CNT,
|
||||
TIME_WORKLOAD_MEDIA_WEAR,
|
||||
TIME_WORKLOAD_HOST_READS,
|
||||
TIME_WORKLOAD_TIMER,
|
||||
THERMAL_THROTTLE,
|
||||
RETRY_BUFFER_OVERFLOW,
|
||||
PLL_LOCK_LOSS,
|
||||
TIME_WORKLOAD_MEDIA_WEAR,
|
||||
TIME_WORKLOAD_HOST_READS,
|
||||
TIME_WORKLOAD_TIMER,
|
||||
THERMAL_THROTTLE,
|
||||
RETRY_BUFFER_OVERFLOW,
|
||||
PLL_LOCK_LOSS,
|
||||
NAND_WRITE,
|
||||
HOST_WRITE,
|
||||
SRAM_ERROR_CNT,
|
||||
ADD_SMART_ITEMS,
|
||||
}addtional_smart_items;
|
||||
};
|
||||
|
||||
#pragma pack(push,1)
|
||||
#pragma pack(push, 1)
|
||||
struct nvme_shannon_smart_log_item {
|
||||
__u8 rsv1[3];
|
||||
__u8 norm;
|
||||
|
@ -45,7 +45,7 @@ struct nvme_shannon_smart_log_item {
|
|||
__le16 min;
|
||||
__le16 max;
|
||||
__le16 avg;
|
||||
} wear_level ;
|
||||
} wear_level;
|
||||
struct thermal_throttle {
|
||||
__u8 st;
|
||||
__u32 count;
|
||||
|
@ -57,68 +57,67 @@ struct nvme_shannon_smart_log_item {
|
|||
|
||||
struct nvme_shannon_smart_log {
|
||||
struct nvme_shannon_smart_log_item items[ADD_SMART_ITEMS];
|
||||
__u8 vend_spec_resv;
|
||||
__u8 vend_spec_resv;
|
||||
};
|
||||
|
||||
static void show_shannon_smart_log(struct nvme_shannon_smart_log *smart,
|
||||
unsigned int nsid, const char *devname)
|
||||
static void show_shannon_smart_log(struct nvme_shannon_smart_log *smart, unsigned int nsid,
|
||||
const char *devname)
|
||||
{
|
||||
printf("Additional Smart Log for NVME device:%s namespace-id:%x\n",
|
||||
devname, nsid);
|
||||
devname, nsid);
|
||||
printf("key normalized value\n");
|
||||
printf("program_fail_count : %3d%% %"PRIu64"\n",
|
||||
smart->items[PROGRAM_FAIL_CNT].norm,
|
||||
int48_to_long(smart->items[PROGRAM_FAIL_CNT].item_val));
|
||||
smart->items[PROGRAM_FAIL_CNT].norm,
|
||||
int48_to_long(smart->items[PROGRAM_FAIL_CNT].item_val));
|
||||
printf("erase_fail_count : %3d%% %"PRIu64"\n",
|
||||
smart->items[ERASE_FAIL_CNT].norm,
|
||||
int48_to_long(smart->items[ERASE_FAIL_CNT].item_val));
|
||||
smart->items[ERASE_FAIL_CNT].norm,
|
||||
int48_to_long(smart->items[ERASE_FAIL_CNT].item_val));
|
||||
printf("wear_leveling : %3d%% min: %u, max: %u, avg: %u\n",
|
||||
smart->items[WEARLEVELING_COUNT].norm,
|
||||
le16_to_cpu(smart->items[WEARLEVELING_COUNT].wear_level.min),
|
||||
le16_to_cpu(smart->items[WEARLEVELING_COUNT].wear_level.max),
|
||||
le16_to_cpu(smart->items[WEARLEVELING_COUNT].wear_level.avg));
|
||||
smart->items[WEARLEVELING_COUNT].norm,
|
||||
le16_to_cpu(smart->items[WEARLEVELING_COUNT].wear_level.min),
|
||||
le16_to_cpu(smart->items[WEARLEVELING_COUNT].wear_level.max),
|
||||
le16_to_cpu(smart->items[WEARLEVELING_COUNT].wear_level.avg));
|
||||
printf("end_to_end_error_detection_count: %3d%% %"PRIu64"\n",
|
||||
smart->items[E2E_ERR_CNT].norm,
|
||||
int48_to_long(smart->items[E2E_ERR_CNT].item_val));
|
||||
smart->items[E2E_ERR_CNT].norm,
|
||||
int48_to_long(smart->items[E2E_ERR_CNT].item_val));
|
||||
printf("crc_error_count : %3d%% %"PRIu64"\n",
|
||||
smart->items[CRC_ERR_CNT].norm,
|
||||
int48_to_long(smart->items[CRC_ERR_CNT].item_val));
|
||||
smart->items[CRC_ERR_CNT].norm,
|
||||
int48_to_long(smart->items[CRC_ERR_CNT].item_val));
|
||||
printf("timed_workload_media_wear : %3d%% %.3f%%\n",
|
||||
smart->items[TIME_WORKLOAD_MEDIA_WEAR].norm,
|
||||
((float)int48_to_long(smart->items[TIME_WORKLOAD_MEDIA_WEAR].item_val)) / 1024);
|
||||
smart->items[TIME_WORKLOAD_MEDIA_WEAR].norm,
|
||||
((float)int48_to_long(smart->items[TIME_WORKLOAD_MEDIA_WEAR].item_val)) / 1024);
|
||||
printf("timed_workload_host_reads : %3d%% %"PRIu64"%%\n",
|
||||
smart->items[TIME_WORKLOAD_HOST_READS].norm,
|
||||
int48_to_long(smart->items[TIME_WORKLOAD_HOST_READS].item_val));
|
||||
smart->items[TIME_WORKLOAD_HOST_READS].norm,
|
||||
int48_to_long(smart->items[TIME_WORKLOAD_HOST_READS].item_val));
|
||||
printf("timed_workload_timer : %3d%% %"PRIu64" min\n",
|
||||
smart->items[TIME_WORKLOAD_TIMER].norm,
|
||||
int48_to_long(smart->items[TIME_WORKLOAD_TIMER].item_val));
|
||||
smart->items[TIME_WORKLOAD_TIMER].norm,
|
||||
int48_to_long(smart->items[TIME_WORKLOAD_TIMER].item_val));
|
||||
printf("thermal_throttle_status : %3d%% CurTTSta: %u%%, TTCnt: %u\n",
|
||||
smart->items[THERMAL_THROTTLE].norm,
|
||||
smart->items[THERMAL_THROTTLE].thermal_throttle.st,
|
||||
smart->items[THERMAL_THROTTLE].thermal_throttle.count);
|
||||
smart->items[THERMAL_THROTTLE].norm,
|
||||
smart->items[THERMAL_THROTTLE].thermal_throttle.st,
|
||||
smart->items[THERMAL_THROTTLE].thermal_throttle.count);
|
||||
printf("retry_buffer_overflow_count : %3d%% %"PRIu64"\n",
|
||||
smart->items[RETRY_BUFFER_OVERFLOW].norm,
|
||||
int48_to_long(smart->items[RETRY_BUFFER_OVERFLOW].item_val));
|
||||
smart->items[RETRY_BUFFER_OVERFLOW].norm,
|
||||
int48_to_long(smart->items[RETRY_BUFFER_OVERFLOW].item_val));
|
||||
printf("pll_lock_loss_count : %3d%% %"PRIu64"\n",
|
||||
smart->items[PLL_LOCK_LOSS].norm,
|
||||
int48_to_long(smart->items[PLL_LOCK_LOSS].item_val));
|
||||
smart->items[PLL_LOCK_LOSS].norm,
|
||||
int48_to_long(smart->items[PLL_LOCK_LOSS].item_val));
|
||||
printf("nand_bytes_written : %3d%% sectors: %"PRIu64"\n",
|
||||
smart->items[NAND_WRITE].norm,
|
||||
int48_to_long(smart->items[NAND_WRITE].item_val));
|
||||
smart->items[NAND_WRITE].norm,
|
||||
int48_to_long(smart->items[NAND_WRITE].item_val));
|
||||
printf("host_bytes_written : %3d%% sectors: %"PRIu64"\n",
|
||||
smart->items[HOST_WRITE].norm,
|
||||
int48_to_long(smart->items[HOST_WRITE].item_val));
|
||||
printf("sram_error_count : %3d%% %"PRIu64"\n",
|
||||
smart->items[RETRY_BUFFER_OVERFLOW].norm,
|
||||
int48_to_long(smart->items[SRAM_ERROR_CNT].item_val));
|
||||
smart->items[HOST_WRITE].norm,
|
||||
int48_to_long(smart->items[HOST_WRITE].item_val));
|
||||
printf("sram_error_count : %3d%% %"PRIu64"\n",
|
||||
smart->items[RETRY_BUFFER_OVERFLOW].norm,
|
||||
int48_to_long(smart->items[SRAM_ERROR_CNT].item_val));
|
||||
}
|
||||
|
||||
|
||||
static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
struct nvme_shannon_smart_log smart_log;
|
||||
char *desc = "Get Shannon vendor specific additional smart log (optionally, "\
|
||||
"for the specified namespace), and show it.";
|
||||
char *desc =
|
||||
"Get Shannon vendor specific additional smart log (optionally, for the specified namespace), and show it.";
|
||||
const char *namespace = "(optional) desired namespace";
|
||||
const char *raw = "dump output in binary format";
|
||||
struct nvme_dev *dev;
|
||||
|
@ -134,7 +133,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
|
|||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace),
|
||||
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
|
||||
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
|
@ -145,30 +144,29 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
|
|||
sizeof(smart_log), &smart_log);
|
||||
if (!err) {
|
||||
if (!cfg.raw_binary)
|
||||
show_shannon_smart_log(&smart_log, cfg.namespace_id,
|
||||
dev->name);
|
||||
show_shannon_smart_log(&smart_log, cfg.namespace_id, dev->name);
|
||||
else
|
||||
d_raw((unsigned char *)&smart_log, sizeof(smart_log));
|
||||
}
|
||||
else if (err > 0)
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
}
|
||||
dev_close(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int get_additional_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "Read operating parameters of the "\
|
||||
"specified controller. Operating parameters are grouped "\
|
||||
"and identified by Feature Identifiers; each Feature "\
|
||||
"Identifier contains one or more attributes that may affect "\
|
||||
"behavior of the feature. Each Feature has three possible "\
|
||||
"settings: default, saveable, and current. If a Feature is "\
|
||||
"saveable, it may be modified by set-feature. Default values "\
|
||||
"are vendor-specific and not changeable. Use set-feature to "\
|
||||
"change saveable Features.\n\n"\
|
||||
"Available additional feature id:\n"\
|
||||
"0x02: Shannon power management\n";
|
||||
const char *desc = "Read operating parameters of the\n"
|
||||
"specified controller. Operating parameters are grouped\n"
|
||||
"and identified by Feature Identifiers; each Feature\n"
|
||||
"Identifier contains one or more attributes that may affect\n"
|
||||
"behavior of the feature. Each Feature has three possible\n"
|
||||
"settings: default, saveable, and current. If a Feature is\n"
|
||||
"saveable, it may be modified by set-feature. Default values\n"
|
||||
"are vendor-specific and not changeable. Use set-feature to\n"
|
||||
"change saveable Features.\n\n"
|
||||
"Available additional feature id:\n"
|
||||
"0x02: Shannon power management\n";
|
||||
const char *raw = "show infos in binary format";
|
||||
const char *namespace_id = "identifier of desired namespace";
|
||||
const char *feature_id = "hexadecimal feature name";
|
||||
|
@ -194,19 +192,19 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st
|
|||
struct config cfg = {
|
||||
.namespace_id = 1,
|
||||
.feature_id = 0,
|
||||
.sel = 0,
|
||||
.cdw11 = 0,
|
||||
.data_len = 0,
|
||||
.sel = 0,
|
||||
.cdw11 = 0,
|
||||
.data_len = 0,
|
||||
};
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
|
||||
OPT_UINT("feature-id", 'f', &cfg.feature_id, feature_id),
|
||||
OPT_BYTE("sel", 's', &cfg.sel, sel),
|
||||
OPT_UINT("data-len", 'l', &cfg.data_len, data_len),
|
||||
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
|
||||
OPT_UINT("cdw11", 'c', &cfg.cdw11, cdw11),
|
||||
OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable),
|
||||
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
|
||||
OPT_UINT("feature-id", 'f', &cfg.feature_id, feature_id),
|
||||
OPT_BYTE("sel", 's', &cfg.sel, sel),
|
||||
OPT_UINT("data-len", 'l', &cfg.data_len, data_len),
|
||||
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
|
||||
OPT_UINT("cdw11", 'c', &cfg.cdw11, cdw11),
|
||||
OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
|
@ -217,16 +215,15 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st
|
|||
if (cfg.sel > 7) {
|
||||
fprintf(stderr, "invalid 'select' param:%d\n", cfg.sel);
|
||||
dev_close(dev);
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!cfg.feature_id) {
|
||||
fprintf(stderr, "feature-id required param\n");
|
||||
dev_close(dev);
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
if (cfg.data_len) {
|
||||
if (posix_memalign(&buf, getpagesize(), cfg.data_len))
|
||||
{
|
||||
if (posix_memalign(&buf, getpagesize(), cfg.data_len)) {
|
||||
dev_close(dev);
|
||||
exit(ENOMEM);
|
||||
}
|
||||
|
@ -247,23 +244,7 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st
|
|||
.result = &result,
|
||||
};
|
||||
err = nvme_get_features(&args);
|
||||
if (!err) {
|
||||
#if 0
|
||||
printf("get-feature:0x%02x (%s), %s value: %#08x\n", cfg.feature_id,
|
||||
nvme_feature_to_string(cfg.feature_id),
|
||||
nvme_select_to_string(cfg.sel), result);
|
||||
if (cfg.human_readable)
|
||||
nvme_feature_show_fields(cfg.feature_id, result, buf);
|
||||
else {
|
||||
if (buf) {
|
||||
if (!cfg.raw_binary)
|
||||
d(buf, cfg.data_len, 16, 1);
|
||||
else
|
||||
d_raw(buf, cfg.data_len);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else if (err > 0)
|
||||
if (err > 0)
|
||||
nvme_show_status(err);
|
||||
if (buf)
|
||||
free(buf);
|
||||
|
@ -272,17 +253,17 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st
|
|||
|
||||
static int set_additional_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "Modify the saveable or changeable "\
|
||||
"current operating parameters of the controller. Operating "\
|
||||
"parameters are grouped and identified by Feature "\
|
||||
"Identifiers. Feature settings can be applied to the entire "\
|
||||
"controller and all associated namespaces, or to only a few "\
|
||||
"namespace(s) associated with the controller. Default values "\
|
||||
"for each Feature are vendor-specific and may not be modified."\
|
||||
"Use get-feature to determine which Features are supported by "\
|
||||
"the controller and are saveable/changeable.\n\n"\
|
||||
"Available additional feature id:\n"\
|
||||
"0x02: Shannon power management\n";
|
||||
const char *desc = "Modify the saveable or changeable\n"
|
||||
"current operating parameters of the controller. Operating\n"
|
||||
"parameters are grouped and identified by Feature\n"
|
||||
"Identifiers. Feature settings can be applied to the entire\n"
|
||||
"controller and all associated namespaces, or to only a few\n"
|
||||
"namespace(s) associated with the controller. Default values\n"
|
||||
"for each Feature are vendor-specific and may not be modified.\n"
|
||||
"Use get-feature to determine which Features are supported by\n"
|
||||
"the controller and are saveable/changeable.\n\n"
|
||||
"Available additional feature id:\n"
|
||||
"0x02: Shannon power management\n";
|
||||
const char *namespace_id = "desired namespace";
|
||||
const char *feature_id = "hex feature name (required)";
|
||||
const char *data_len = "buffer length if data required";
|
||||
|
@ -305,21 +286,21 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st
|
|||
};
|
||||
|
||||
struct config cfg = {
|
||||
.file = "",
|
||||
.file = "",
|
||||
.namespace_id = 0,
|
||||
.feature_id = 0,
|
||||
.value = 0,
|
||||
.value = 0,
|
||||
.data_len = 0,
|
||||
.save = 0,
|
||||
.save = 0,
|
||||
};
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
|
||||
OPT_UINT("feature-id", 'f', &cfg.feature_id, feature_id),
|
||||
OPT_UINT("value", 'v', &cfg.value, value),
|
||||
OPT_UINT("data-len", 'l', &cfg.data_len, data_len),
|
||||
OPT_FILE("data", 'd', &cfg.file, data),
|
||||
OPT_FLAG("save", 's', &cfg.save, save),
|
||||
OPT_UINT("feature-id", 'f', &cfg.feature_id, feature_id),
|
||||
OPT_UINT("value", 'v', &cfg.value, value),
|
||||
OPT_UINT("data-len", 'l', &cfg.data_len, data_len),
|
||||
OPT_FILE("data", 'd', &cfg.file, data),
|
||||
OPT_FLAG("save", 's', &cfg.save, save),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
|
@ -330,14 +311,14 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st
|
|||
if (!cfg.feature_id) {
|
||||
fprintf(stderr, "feature-id required param\n");
|
||||
dev_close(dev);
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cfg.data_len) {
|
||||
if (posix_memalign(&buf, getpagesize(), cfg.data_len)){
|
||||
if (posix_memalign(&buf, getpagesize(), cfg.data_len)) {
|
||||
fprintf(stderr, "can not allocate feature payload\n");
|
||||
dev_close(dev);
|
||||
return ENOMEM;
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(buf, 0, cfg.data_len);
|
||||
}
|
||||
|
@ -380,10 +361,6 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st
|
|||
goto free;
|
||||
}
|
||||
if (!err) {
|
||||
#if 0
|
||||
printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id,
|
||||
nvme_feature_to_string(cfg.feature_id), cfg.value);
|
||||
#endif
|
||||
if (buf)
|
||||
d(buf, cfg.data_len, 16, 1);
|
||||
} else if (err > 0)
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
sources += [
|
||||
'plugins/solidigm/solidigm-id-ctrl.c',
|
||||
'plugins/solidigm/solidigm-util.c',
|
||||
'plugins/solidigm/solidigm-smart.c',
|
||||
'plugins/solidigm/solidigm-garbage-collection.c',
|
||||
'plugins/solidigm/solidigm-latency-tracking.c',
|
||||
'plugins/solidigm/solidigm-log-page-dir.c',
|
||||
'plugins/solidigm/solidigm-telemetry.c',
|
||||
'plugins/solidigm/solidigm-internal-logs.c',
|
||||
'plugins/solidigm/solidigm-market-log.c',
|
||||
]
|
||||
subdir('solidigm-telemetry')
|
||||
|
||||
|
|
|
@ -21,26 +21,27 @@
|
|||
#include "solidigm-garbage-collection.h"
|
||||
#include "solidigm-util.h"
|
||||
|
||||
typedef struct __attribute__((packed)) gc_item {
|
||||
struct __packed gc_item {
|
||||
__le32 timer_type;
|
||||
__le64 timestamp;
|
||||
} gc_item_t;
|
||||
};
|
||||
|
||||
#define VU_GC_MAX_ITEMS 100
|
||||
typedef struct garbage_control_collection_log {
|
||||
struct garbage_control_collection_log {
|
||||
__le16 version_major;
|
||||
__le16 version_minor;
|
||||
gc_item_t item[VU_GC_MAX_ITEMS];
|
||||
struct __packed gc_item item[VU_GC_MAX_ITEMS];
|
||||
__u8 reserved[2892];
|
||||
} garbage_control_collection_log_t;
|
||||
};
|
||||
|
||||
static void vu_gc_log_show_json(garbage_control_collection_log_t *payload, const char *devname)
|
||||
static void vu_gc_log_show_json(struct garbage_control_collection_log *payload, const char *devname)
|
||||
{
|
||||
struct json_object *gc_entries = json_create_array();
|
||||
|
||||
for (int i = 0; i < VU_GC_MAX_ITEMS; i++) {
|
||||
gc_item_t item = payload->item[i];
|
||||
struct __packed gc_item item = payload->item[i];
|
||||
struct json_object *entry = json_create_object();
|
||||
|
||||
json_object_add_value_int(entry, "timestamp", le64_to_cpu(item.timestamp));
|
||||
json_object_add_value_int(entry, "timer_type", le32_to_cpu(item.timer_type));
|
||||
json_array_add_value_object(gc_entries, entry);
|
||||
|
@ -50,7 +51,7 @@ static void vu_gc_log_show_json(garbage_control_collection_log_t *payload, const
|
|||
json_free_object(gc_entries);
|
||||
}
|
||||
|
||||
static void vu_gc_log_show(garbage_control_collection_log_t *payload, const char *devname,
|
||||
static void vu_gc_log_show(struct garbage_control_collection_log *payload, const char *devname,
|
||||
__u8 uuid_index)
|
||||
{
|
||||
printf("Solidigm Garbage Collection Log for NVME device:%s UUID-idx:%d\n", devname,
|
||||
|
@ -58,7 +59,8 @@ static void vu_gc_log_show(garbage_control_collection_log_t *payload, const char
|
|||
printf("Timestamp Timer Type\n");
|
||||
|
||||
for (int i = 0; i < VU_GC_MAX_ITEMS; i++) {
|
||||
gc_item_t item = payload->item[i];
|
||||
struct __packed gc_item item = payload->item[i];
|
||||
|
||||
printf("%-13" PRIu64 " %d\n", le64_to_cpu(item.timestamp), le32_to_cpu(item.timer_type));
|
||||
}
|
||||
}
|
||||
|
@ -88,15 +90,16 @@ int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *c
|
|||
return err;
|
||||
|
||||
enum nvme_print_flags flags = validate_output_format(cfg.output_format);
|
||||
|
||||
if (flags == -EINVAL) {
|
||||
fprintf(stderr, "Invalid output format '%s'\n", cfg.output_format);
|
||||
dev_close(dev);
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
uuid_index = solidigm_get_vu_uuid_index(dev);
|
||||
|
||||
garbage_control_collection_log_t gc_log;
|
||||
struct garbage_control_collection_log gc_log;
|
||||
const int solidigm_vu_gc_log_id = 0xfd;
|
||||
struct nvme_get_log_args args = {
|
||||
.lpo = 0,
|
||||
|
@ -118,15 +121,13 @@ int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *c
|
|||
|
||||
err = nvme_get_log(&args);
|
||||
if (!err) {
|
||||
if (flags & BINARY) {
|
||||
if (flags & BINARY)
|
||||
d_raw((unsigned char *)&gc_log, sizeof(gc_log));
|
||||
} else if (flags & JSON) {
|
||||
else if (flags & JSON)
|
||||
vu_gc_log_show_json(&gc_log, dev->name);
|
||||
} else {
|
||||
else
|
||||
vu_gc_log_show(&gc_log, dev->name, uuid_index);
|
||||
}
|
||||
}
|
||||
else if (err > 0) {
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
}
|
||||
|
||||
|
|
73
plugins/solidigm/solidigm-id-ctrl.c
Normal file
73
plugins/solidigm/solidigm-id-ctrl.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2023 Solidigm.
|
||||
*
|
||||
* Author: leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "common.h"
|
||||
#include "solidigm-id-ctrl.h"
|
||||
|
||||
struct __packed nvme_vu_id_ctrl_field { /* CDR MR5 */
|
||||
__u8 rsvd1[3];
|
||||
__u8 ss;
|
||||
char health[20];
|
||||
__u8 cls;
|
||||
__u8 nlw;
|
||||
__u8 scap;
|
||||
__u8 sstat;
|
||||
char bl[8];
|
||||
__u8 rsvd2[38];
|
||||
__le64 ww;
|
||||
char mic_bl[4];
|
||||
char mic_fw[4];
|
||||
};
|
||||
|
||||
void sldgm_id_ctrl(uint8_t *vs, struct json_object *root)
|
||||
{
|
||||
// text output aligns nicely with property name up to 10 chars
|
||||
const char *str_ss = "stripeSize";
|
||||
const char *str_health = "health";
|
||||
const char *str_cls = "linkSpeed";
|
||||
const char *str_nlw = "negLnkWdth";
|
||||
const char *str_scap = "secCapab";
|
||||
const char *str_sstat = "secStatus";
|
||||
const char *str_bl = "bootLoader";
|
||||
const char *str_ww = "wwid";
|
||||
const char *str_mic_bl = "bwLimGran";
|
||||
const char *str_mic_fw = "ioLimGran";
|
||||
|
||||
struct nvme_vu_id_ctrl_field *id = (struct nvme_vu_id_ctrl_field *)vs;
|
||||
|
||||
const char str_heathy[sizeof(id->health)] = "healthy";
|
||||
const char *health = id->health[0] ? id->health : str_heathy;
|
||||
|
||||
if (root == NULL) {
|
||||
printf("%-10s: %u\n", str_ss, id->ss);
|
||||
printf("%-10s: %.*s\n", str_health, (int)sizeof(id->health), health);
|
||||
printf("%-10s: %u\n", str_cls, id->cls);
|
||||
printf("%-10s: %u\n", str_nlw, id->nlw);
|
||||
printf("%-10s: %u\n", str_scap, id->scap);
|
||||
printf("%-10s: %u\n", str_sstat, id->sstat);
|
||||
printf("%-10s: %.*s\n", str_bl, (int)sizeof(id->bl), id->bl);
|
||||
printf("%-10s: 0x%016"PRIx64"\n", str_ww, le64_to_cpu(id->ww));
|
||||
printf("%-10s: %.*s\n", str_mic_bl, (int)sizeof(id->mic_bl), id->mic_bl);
|
||||
printf("%-10s: %.*s\n", str_mic_fw, (int)sizeof(id->mic_fw), id->mic_fw);
|
||||
return;
|
||||
}
|
||||
|
||||
json_object_add_value_uint(root, str_ss, id->ss);
|
||||
json_object_object_add(root, str_health,
|
||||
json_object_new_string_len(health, sizeof(id->health)));
|
||||
json_object_add_value_uint(root, str_cls, id->cls);
|
||||
json_object_add_value_uint(root, str_nlw, id->nlw);
|
||||
json_object_add_value_uint(root, str_scap, id->scap);
|
||||
json_object_add_value_uint(root, str_sstat, id->sstat);
|
||||
json_object_object_add(root, str_bl, json_object_new_string_len(id->bl, sizeof(id->bl)));
|
||||
json_object_add_value_uint64(root, str_ww, le64_to_cpu(id->ww));
|
||||
json_object_object_add(root, str_mic_bl,
|
||||
json_object_new_string_len(id->mic_bl, sizeof(id->mic_bl)));
|
||||
json_object_object_add(root, str_mic_fw,
|
||||
json_object_new_string_len(id->mic_fw, sizeof(id->mic_fw)));
|
||||
}
|
10
plugins/solidigm/solidigm-id-ctrl.h
Normal file
10
plugins/solidigm/solidigm-id-ctrl.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (c) 2023 Solidigm.
|
||||
*
|
||||
* Author: leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "util/json.h"
|
||||
void sldgm_id_ctrl(uint8_t *vs, struct json_object *root);
|
597
plugins/solidigm/solidigm-internal-logs.c
Normal file
597
plugins/solidigm/solidigm-internal-logs.c
Normal file
|
@ -0,0 +1,597 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2023 Solidigm.
|
||||
*
|
||||
* Authors: leonardo.da.cunha@solidigm.com
|
||||
* shankaralingegowda.singonahalli@solidigm.com
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
#include <linux/limits.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "nvme.h"
|
||||
#include "libnvme.h"
|
||||
#include "plugin.h"
|
||||
#include "nvme-print.h"
|
||||
|
||||
#define DWORD_SIZE 4
|
||||
|
||||
enum log_type {
|
||||
NLOG = 0,
|
||||
EVENTLOG = 1,
|
||||
ASSERTLOG = 2,
|
||||
};
|
||||
|
||||
#pragma pack(push, internal_logs, 1)
|
||||
struct version {
|
||||
__u16 major;
|
||||
__u16 minor;
|
||||
};
|
||||
|
||||
struct event_dump_instance {
|
||||
__u32 numeventdumps;
|
||||
__u32 coresize;
|
||||
__u32 coreoffset;
|
||||
__u32 eventidoffset[16];
|
||||
__u8 eventIdValidity[16];
|
||||
};
|
||||
|
||||
struct commom_header {
|
||||
struct version ver;
|
||||
__u32 header_size;
|
||||
__u32 log_size;
|
||||
__u32 numcores;
|
||||
};
|
||||
|
||||
struct event_dump_header {
|
||||
struct commom_header header;
|
||||
__u32 eventidsize;
|
||||
struct event_dump_instance edumps[0];
|
||||
};
|
||||
|
||||
struct assert_dump_core {
|
||||
__u32 coreoffset;
|
||||
__u32 assertsize;
|
||||
__u8 assertdumptype;
|
||||
__u8 assertvalid;
|
||||
__u8 reserved[2];
|
||||
};
|
||||
|
||||
struct assert_dump_header {
|
||||
struct commom_header header;
|
||||
struct assert_dump_core core[];
|
||||
};
|
||||
|
||||
struct nlog_dump_header_common {
|
||||
struct version ver;
|
||||
__u32 logselect;
|
||||
__u32 totalnlogs;
|
||||
__u32 nlognum;
|
||||
char nlogname[4];
|
||||
__u32 nlogbytesize;
|
||||
__u32 nlogprimarybuffsize;
|
||||
__u32 tickspersecond;
|
||||
__u32 corecount;
|
||||
};
|
||||
|
||||
struct nlog_dump_header3_0 {
|
||||
struct nlog_dump_header_common common;
|
||||
__u32 nlogpausestatus;
|
||||
__u32 selectoffsetref;
|
||||
__u32 selectnlogpause;
|
||||
__u32 selectaddedoffset;
|
||||
__u32 nlogbufnum;
|
||||
__u32 nlogbufnummax;
|
||||
};
|
||||
|
||||
struct nlog_dump_header4_0 {
|
||||
struct nlog_dump_header_common common;
|
||||
__u64 nlogpausestatus;
|
||||
__u32 selectoffsetref;
|
||||
__u32 selectnlogpause;
|
||||
__u32 selectaddedoffset;
|
||||
__u32 nlogbufnum;
|
||||
__u32 nlogbufnummax;
|
||||
__u32 coreselected;
|
||||
__u32 reserved[2];
|
||||
};
|
||||
|
||||
struct nlog_dump_header4_1 {
|
||||
struct nlog_dump_header_common common;
|
||||
__u64 nlogpausestatus;
|
||||
__u32 selectoffsetref;
|
||||
__u32 selectnlogpause;
|
||||
__u32 selectaddedoffset;
|
||||
__u32 nlogbufnum;
|
||||
__u32 nlogbufnummax;
|
||||
__u32 coreselected;
|
||||
__u32 lpaPointer1High;
|
||||
__u32 lpaPointer1Low;
|
||||
__u32 lpaPointer2High;
|
||||
__u32 lpaPointer2Low;
|
||||
};
|
||||
|
||||
#pragma pack(pop, internal_logs)
|
||||
|
||||
struct config {
|
||||
__u32 namespace_id;
|
||||
char *file_prefix;
|
||||
char *type;
|
||||
bool verbose;
|
||||
};
|
||||
|
||||
static void print_nlog_header(__u8 *buffer)
|
||||
{
|
||||
struct nlog_dump_header_common *nlog_header = (struct nlog_dump_header_common *) buffer;
|
||||
|
||||
if (nlog_header->ver.major >= 3) {
|
||||
printf("Version Major %u\n", nlog_header->ver.major);
|
||||
printf("Version Minor %u\n", nlog_header->ver.minor);
|
||||
printf("Log_select %u\n", nlog_header->logselect);
|
||||
printf("totalnlogs %u\n", nlog_header->totalnlogs);
|
||||
printf("nlognum %u\n", nlog_header->nlognum);
|
||||
printf("nlogname %c%c%c%c\n", nlog_header->nlogname[3], nlog_header->nlogname[2],
|
||||
nlog_header->nlogname[1], nlog_header->nlogname[0]);
|
||||
printf("nlogbytesize %u\n", nlog_header->nlogbytesize);
|
||||
printf("nlogprimarybuffsize %u\n", nlog_header->nlogprimarybuffsize);
|
||||
printf("tickspersecond %u\n", nlog_header->tickspersecond);
|
||||
printf("corecount %u\n", nlog_header->corecount);
|
||||
}
|
||||
if (nlog_header->ver.major >= 4) {
|
||||
struct nlog_dump_header4_0 *nlog_header = (struct nlog_dump_header4_0 *) buffer;
|
||||
|
||||
printf("nlogpausestatus %"PRIu64"\n", (uint64_t)nlog_header->nlogpausestatus);
|
||||
printf("selectoffsetref %u\n", nlog_header->selectoffsetref);
|
||||
printf("selectnlogpause %u\n", nlog_header->selectnlogpause);
|
||||
printf("selectaddedoffset %u\n", nlog_header->selectaddedoffset);
|
||||
printf("nlogbufnum %u\n", nlog_header->nlogbufnum);
|
||||
printf("nlogbufnummax %u\n", nlog_header->nlogbufnummax);
|
||||
printf("coreselected %u\n\n", nlog_header->coreselected);
|
||||
}
|
||||
}
|
||||
|
||||
#define INTERNAL_LOG_MAX_BYTE_TRANSFER 4096
|
||||
#define INTERNAL_LOG_MAX_DWORD_TRANSFER (INTERNAL_LOG_MAX_BYTE_TRANSFER / 4)
|
||||
|
||||
static int cmd_dump_repeat(struct nvme_passthru_cmd *cmd, __u32 total_dw_size,
|
||||
int out_fd, int ioctl_fd, bool force_max_transfer)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
while (total_dw_size > 0) {
|
||||
size_t dword_tfer = min(INTERNAL_LOG_MAX_DWORD_TRANSFER, total_dw_size);
|
||||
|
||||
cmd->cdw10 = force_max_transfer ? INTERNAL_LOG_MAX_DWORD_TRANSFER : dword_tfer;
|
||||
cmd->data_len = dword_tfer * 4;
|
||||
err = nvme_submit_admin_passthru(ioctl_fd, cmd, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (out_fd > 0) {
|
||||
err = write(out_fd, (const void *)(uintptr_t)cmd->addr, cmd->data_len);
|
||||
if (err < 0) {
|
||||
perror("write failure");
|
||||
return err;
|
||||
}
|
||||
err = 0;
|
||||
}
|
||||
total_dw_size -= dword_tfer;
|
||||
cmd->cdw13 += dword_tfer;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int write_header(__u8 *buf, int fd, size_t amnt)
|
||||
{
|
||||
if (write(fd, buf, amnt) < 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_header(struct nvme_passthru_cmd *cmd, int ioctl_fd)
|
||||
{
|
||||
memset((void *)(uintptr_t)cmd->addr, 0, INTERNAL_LOG_MAX_BYTE_TRANSFER);
|
||||
return cmd_dump_repeat(cmd, INTERNAL_LOG_MAX_DWORD_TRANSFER, -1, ioctl_fd, false);
|
||||
}
|
||||
|
||||
static int get_serial_number(char *str, int fd)
|
||||
{
|
||||
struct nvme_id_ctrl ctrl = {0};
|
||||
int err;
|
||||
|
||||
err = nvme_identify_ctrl(fd, &ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Remove trailing spaces */
|
||||
for (int i = sizeof(ctrl.sn) - 1; i && ctrl.sn[i] == ' '; i--)
|
||||
ctrl.sn[i] = '\0';
|
||||
sprintf(str, "%-.*s", (int)sizeof(ctrl.sn), ctrl.sn);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int dump_assert_logs(struct nvme_dev *dev, struct config cfg)
|
||||
{
|
||||
__u8 buf[INTERNAL_LOG_MAX_BYTE_TRANSFER];
|
||||
__u8 head_buf[INTERNAL_LOG_MAX_BYTE_TRANSFER];
|
||||
char file_path[PATH_MAX];
|
||||
struct assert_dump_header *ad = (struct assert_dump_header *) head_buf;
|
||||
struct nvme_passthru_cmd cmd = {
|
||||
.opcode = 0xd2,
|
||||
.nsid = cfg.namespace_id,
|
||||
.addr = (unsigned long)(void *)head_buf,
|
||||
.cdw12 = ASSERTLOG,
|
||||
.cdw13 = 0,
|
||||
};
|
||||
int output, err;
|
||||
|
||||
err = read_header(&cmd, dev_fd(dev));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
sprintf(file_path, "%s_AssertLog.bin", cfg.file_prefix);
|
||||
output = open(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if (output < 0)
|
||||
return -errno;
|
||||
err = write_header((__u8 *)ad, output, ad->header.header_size * DWORD_SIZE);
|
||||
if (err) {
|
||||
perror("write failure");
|
||||
close(output);
|
||||
return err;
|
||||
}
|
||||
cmd.addr = (unsigned long)(void *)buf;
|
||||
|
||||
if (cfg.verbose) {
|
||||
printf("Assert Log, cores: %d log size: %d header size: %d\n", ad->header.numcores,
|
||||
ad->header.log_size * DWORD_SIZE, ad->header.header_size * DWORD_SIZE);
|
||||
for (__u32 i = 0; i < ad->header.numcores; i++)
|
||||
printf("core %d assert size: %d\n", i, ad->core[i].assertsize * DWORD_SIZE);
|
||||
}
|
||||
|
||||
for (__u32 i = 0; i < ad->header.numcores; i++) {
|
||||
if (!ad->core[i].assertvalid)
|
||||
continue;
|
||||
cmd.cdw13 = ad->core[i].coreoffset;
|
||||
err = cmd_dump_repeat(&cmd, ad->core[i].assertsize,
|
||||
output,
|
||||
dev_fd(dev), false);
|
||||
if (err) {
|
||||
close(output);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
close(output);
|
||||
printf("Successfully wrote log to %s\n", file_path);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int dump_event_logs(struct nvme_dev *dev, struct config cfg)
|
||||
{
|
||||
__u8 buf[INTERNAL_LOG_MAX_BYTE_TRANSFER];
|
||||
__u8 head_buf[INTERNAL_LOG_MAX_BYTE_TRANSFER];
|
||||
char file_path[PATH_MAX];
|
||||
struct event_dump_header *ehdr = (struct event_dump_header *) head_buf;
|
||||
struct nvme_passthru_cmd cmd = {
|
||||
.opcode = 0xd2,
|
||||
.nsid = cfg.namespace_id,
|
||||
.addr = (unsigned long)(void *)head_buf,
|
||||
.cdw12 = EVENTLOG,
|
||||
.cdw13 = 0,
|
||||
};
|
||||
int output;
|
||||
int core_num, err;
|
||||
|
||||
err = read_header(&cmd, dev_fd(dev));
|
||||
if (err)
|
||||
return err;
|
||||
sprintf(file_path, "%s_EventLog.bin", cfg.file_prefix);
|
||||
output = open(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if (output < 0)
|
||||
return -errno;
|
||||
err = write_header(head_buf, output, INTERNAL_LOG_MAX_BYTE_TRANSFER);
|
||||
|
||||
core_num = ehdr->header.numcores;
|
||||
|
||||
if (err) {
|
||||
close(output);
|
||||
return err;
|
||||
}
|
||||
cmd.addr = (unsigned long)(void *)buf;
|
||||
|
||||
if (cfg.verbose)
|
||||
printf("Event Log, cores: %d log size: %d\n", core_num, ehdr->header.log_size * 4);
|
||||
|
||||
for (__u32 j = 0; j < core_num; j++) {
|
||||
if (cfg.verbose) {
|
||||
for (int k = 0 ; k < 16; k++) {
|
||||
printf("core: %d event: %d ", j, k);
|
||||
printf("validity: %d ", ehdr->edumps[j].eventIdValidity[k]);
|
||||
printf("offset: %d\n", ehdr->edumps[j].eventidoffset[k]);
|
||||
}
|
||||
}
|
||||
cmd.cdw13 = ehdr->edumps[j].coreoffset;
|
||||
err = cmd_dump_repeat(&cmd, ehdr->edumps[j].coresize,
|
||||
output, dev_fd(dev), false);
|
||||
if (err) {
|
||||
close(output);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
close(output);
|
||||
printf("Successfully wrote log to %s\n", file_path);
|
||||
return err;
|
||||
}
|
||||
|
||||
static size_t get_nlog_header_size(struct nlog_dump_header_common *nlog_header)
|
||||
{
|
||||
switch (nlog_header->ver.major) {
|
||||
case 3:
|
||||
return sizeof(struct nlog_dump_header3_0);
|
||||
case 4:
|
||||
if (nlog_header->ver.minor == 0)
|
||||
return sizeof(struct nlog_dump_header4_0);
|
||||
return sizeof(struct nlog_dump_header4_1);
|
||||
default:
|
||||
return INTERNAL_LOG_MAX_BYTE_TRANSFER;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* dumps nlogs from specified core or all cores when core = -1 */
|
||||
static int dump_nlogs(struct nvme_dev *dev, struct config cfg, int core)
|
||||
{
|
||||
int err = 0;
|
||||
__u32 count, core_num;
|
||||
__u8 buf[INTERNAL_LOG_MAX_BYTE_TRANSFER];
|
||||
char file_path[PATH_MAX];
|
||||
struct nlog_dump_header_common *nlog_header = (struct nlog_dump_header_common *)buf;
|
||||
struct nvme_passthru_cmd cmd = {
|
||||
.opcode = 0xd2,
|
||||
.nsid = cfg.namespace_id,
|
||||
.addr = (unsigned long)(void *)buf
|
||||
};
|
||||
|
||||
struct dump_select {
|
||||
union {
|
||||
struct {
|
||||
__u32 selectLog : 3;
|
||||
__u32 selectCore : 2;
|
||||
__u32 selectNlog : 8;
|
||||
};
|
||||
__u32 raw;
|
||||
};
|
||||
} log_select;
|
||||
int output;
|
||||
bool is_open = false;
|
||||
size_t header_size = 0;
|
||||
|
||||
log_select.selectCore = core < 0 ? 0 : core;
|
||||
do {
|
||||
log_select.selectNlog = 0;
|
||||
do {
|
||||
cmd.cdw13 = 0;
|
||||
cmd.cdw12 = log_select.raw;
|
||||
err = read_header(&cmd, dev_fd(dev));
|
||||
if (err) {
|
||||
if (is_open)
|
||||
close(output);
|
||||
return err;
|
||||
}
|
||||
count = nlog_header->totalnlogs;
|
||||
core_num = core < 0 ? nlog_header->corecount : 0;
|
||||
if (!header_size) {
|
||||
sprintf(file_path, "%s_NLog.bin", cfg.file_prefix);
|
||||
output = open(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if (output < 0)
|
||||
return -errno;
|
||||
header_size = get_nlog_header_size(nlog_header);
|
||||
is_open = true;
|
||||
}
|
||||
err = write_header(buf, output, header_size);
|
||||
if (err)
|
||||
break;
|
||||
if (cfg.verbose)
|
||||
print_nlog_header(buf);
|
||||
cmd.cdw13 = 0x400;
|
||||
err = cmd_dump_repeat(&cmd, nlog_header->nlogbytesize / 4,
|
||||
output, dev_fd(dev), true);
|
||||
if (err)
|
||||
break;
|
||||
} while (++log_select.selectNlog < count);
|
||||
if (err)
|
||||
break;
|
||||
} while (++log_select.selectCore < core_num);
|
||||
if (is_open) {
|
||||
close(output);
|
||||
printf("Successfully wrote log to %s\n", file_path);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
enum telemetry_type {
|
||||
HOSTGENOLD,
|
||||
HOSTGENNEW,
|
||||
CONTROLLER
|
||||
};
|
||||
|
||||
static int dump_telemetry(struct nvme_dev *dev, struct config cfg, enum telemetry_type ttype)
|
||||
{
|
||||
struct nvme_telemetry_log *log = NULL;
|
||||
size_t log_size = 0;
|
||||
int err = 0, output;
|
||||
__u8 *buffer = NULL;
|
||||
size_t bytes_remaining = 0;
|
||||
int data_area = NVME_TELEMETRY_DA_3;
|
||||
char file_path[PATH_MAX];
|
||||
char *log_name;
|
||||
|
||||
switch (ttype) {
|
||||
case HOSTGENNEW:
|
||||
log_name = "TelemetryHostGenNew";
|
||||
break;
|
||||
case HOSTGENOLD:
|
||||
log_name = "TelemetryHostGenOld";
|
||||
break;
|
||||
case CONTROLLER:
|
||||
log_name = "TelemetryController";
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sprintf(file_path, "%s_%s.bin", cfg.file_prefix, log_name);
|
||||
output = open(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (output < 0)
|
||||
return -errno;
|
||||
|
||||
switch (ttype) {
|
||||
case HOSTGENNEW:
|
||||
err = nvme_get_new_host_telemetry(dev_fd(dev), &log,
|
||||
data_area, &log_size);
|
||||
break;
|
||||
case HOSTGENOLD:
|
||||
err = nvme_get_host_telemetry(dev_fd(dev), &log,
|
||||
data_area, &log_size);
|
||||
break;
|
||||
case CONTROLLER:
|
||||
err = nvme_get_ctrl_telemetry(dev_fd(dev), true, &log,
|
||||
data_area, &log_size);
|
||||
break;
|
||||
}
|
||||
|
||||
if (err)
|
||||
goto tele_close_output;
|
||||
|
||||
bytes_remaining = log_size;
|
||||
buffer = (__u8 *)log;
|
||||
|
||||
while (bytes_remaining) {
|
||||
ssize_t bytes_written = write(output, buffer, bytes_remaining);
|
||||
|
||||
if (bytes_written < 0) {
|
||||
err = -errno;
|
||||
goto tele_close_output;
|
||||
}
|
||||
bytes_remaining -= bytes_written;
|
||||
buffer += bytes_written;
|
||||
}
|
||||
printf("Successfully wrote log to %s\n", file_path);
|
||||
|
||||
tele_close_output:
|
||||
free(log);
|
||||
close(output);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int solidigm_get_internal_log(int argc, char **argv, struct command *command,
|
||||
struct plugin *plugin)
|
||||
{
|
||||
char sn_prefix[sizeof(((struct nvme_id_ctrl *)0)->sn)+1];
|
||||
int log_count = 0;
|
||||
int err;
|
||||
struct nvme_dev *dev;
|
||||
bool all = false;
|
||||
|
||||
const char *desc = "Get Debug Firmware Logs and save them.";
|
||||
const char *type =
|
||||
"Log type: ALL, CONTROLLERINITTELEMETRY, HOSTINITTELEMETRY, HOSTINITTELEMETRYNOGEN, NLOG, ASSERT, EVENT. Defaults to ALL.";
|
||||
const char *prefix = "Output file prefix; defaults to device serial number.";
|
||||
const char *verbose = "To print out verbose info.";
|
||||
const char *namespace_id = "Namespace to get logs from.";
|
||||
|
||||
|
||||
struct config cfg = {
|
||||
.namespace_id = NVME_NSID_ALL,
|
||||
.file_prefix = NULL,
|
||||
.type = NULL,
|
||||
};
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_STR("type", 't', &cfg.type, type),
|
||||
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
|
||||
OPT_FILE("file-prefix", 'p', &cfg.file_prefix, prefix),
|
||||
OPT_FLAG("verbose", 'v', &cfg.verbose, verbose),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!cfg.file_prefix) {
|
||||
err = get_serial_number(sn_prefix, dev_fd(dev));
|
||||
if (err)
|
||||
goto out_dev;
|
||||
cfg.file_prefix = sn_prefix;
|
||||
}
|
||||
|
||||
if (!cfg.type)
|
||||
cfg.type = "ALL";
|
||||
else {
|
||||
for (char *p = cfg.type; *p; ++p)
|
||||
*p = toupper(*p);
|
||||
}
|
||||
|
||||
if (!strcmp(cfg.type, "ALL"))
|
||||
all = true;
|
||||
if (all || !strcmp(cfg.type, "ASSERT")) {
|
||||
err = dump_assert_logs(dev, cfg);
|
||||
if (err == 0)
|
||||
log_count++;
|
||||
else if (err < 0)
|
||||
perror("Assert log");
|
||||
}
|
||||
if (all || !strcmp(cfg.type, "EVENT")) {
|
||||
err = dump_event_logs(dev, cfg);
|
||||
if (err == 0)
|
||||
log_count++;
|
||||
else if (err < 0)
|
||||
perror("Eventt log");
|
||||
}
|
||||
if (all || !strcmp(cfg.type, "NLOG")) {
|
||||
err = dump_nlogs(dev, cfg, -1);
|
||||
if (err == 0)
|
||||
log_count++;
|
||||
else if (err < 0)
|
||||
perror("Nlog");
|
||||
}
|
||||
if (all || !strcmp(cfg.type, "CONTROLLERINITTELEMETRY")) {
|
||||
err = dump_telemetry(dev, cfg, CONTROLLER);
|
||||
if (err == 0)
|
||||
log_count++;
|
||||
else if (err < 0)
|
||||
perror("Telemetry Controller Initated");
|
||||
}
|
||||
if (all || !strcmp(cfg.type, "HOSTINITTELEMETRYNOGEN")) {
|
||||
err = dump_telemetry(dev, cfg, HOSTGENOLD);
|
||||
if (err == 0)
|
||||
log_count++;
|
||||
else if (err < 0)
|
||||
perror("Previously existing Telemetry Host Initated");
|
||||
}
|
||||
if (all || !strcmp(cfg.type, "HOSTINITTELEMETRY")) {
|
||||
err = dump_telemetry(dev, cfg, HOSTGENNEW);
|
||||
if (err == 0)
|
||||
log_count++;
|
||||
else if (err < 0)
|
||||
perror("Telemetry Host Initated");
|
||||
}
|
||||
|
||||
if (log_count == 0) {
|
||||
if (err > 0)
|
||||
nvme_show_status(err);
|
||||
} else if ((log_count > 1) || cfg.verbose)
|
||||
printf("Total: %d log files with prefix: %s\n", log_count, cfg.file_prefix);
|
||||
out_dev:
|
||||
/* Redundant close() to make static code analysis happy */
|
||||
close(dev->direct.fd);
|
||||
dev_close(dev);
|
||||
return err;
|
||||
}
|
8
plugins/solidigm/solidigm-internal-logs.h
Normal file
8
plugins/solidigm/solidigm-internal-logs.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (c) 2023 Solidigm.
|
||||
*
|
||||
* Author: leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
|
||||
int solidigm_get_internal_log(int argc, char **argv, struct command *cmd, struct plugin *plugin);
|
|
@ -94,7 +94,6 @@ static void latency_tracker_bucket_parse(const struct latency_tracker *lt, int i
|
|||
__u32 bucket_data = le32_to_cpu(lt->stats.data[id]);
|
||||
|
||||
if (lt->print_flags == NORMAL) {
|
||||
|
||||
printf("%-*d", COL_WIDTH, id);
|
||||
|
||||
get_time_unit_label(buffer, lower_us, true);
|
||||
|
@ -137,12 +136,10 @@ static void latency_tracker_parse_linear(const struct latency_tracker *lt,
|
|||
__u32 bytes_per, __u32 us_step,
|
||||
bool nonzero_print)
|
||||
{
|
||||
for (int i = (start_offset / bytes_per) - 1;
|
||||
i < end_offset / bytes_per; i++) {
|
||||
if (nonzero_print && lt->stats.data[i] == 0)
|
||||
for (int i = (start_offset / bytes_per) - 1; i < end_offset / bytes_per; i++) {
|
||||
if (nonzero_print && !lt->stats.data[i])
|
||||
continue;
|
||||
latency_tracker_bucket_parse(lt, i, us_step * i,
|
||||
us_step * (i + 1), true);
|
||||
latency_tracker_bucket_parse(lt, i, us_step * i, us_step * (i + 1), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,6 +150,7 @@ static void latency_tracker_parse_linear(const struct latency_tracker *lt,
|
|||
static int latency_tracker_bucket_pos2us(const struct latency_tracker *lt, int i)
|
||||
{
|
||||
__u32 base_val = 1 << lt->base_range_bits;
|
||||
|
||||
if (i < (base_val << 1))
|
||||
return i;
|
||||
|
||||
|
@ -171,15 +169,15 @@ static int latency_tracker_bucket_pos2us(const struct latency_tracker *lt, int i
|
|||
* "values" : {
|
||||
*/
|
||||
static void latency_tracker_populate_json_root(const struct latency_tracker *lt,
|
||||
struct json_object *root)
|
||||
struct json_object *root)
|
||||
{
|
||||
struct json_object *subroot = json_create_object();
|
||||
|
||||
json_object_add_value_object(root, "latstats", subroot);
|
||||
json_object_add_value_string(subroot, "type", lt->cfg.write ? "write" : "read");
|
||||
if (lt->has_average_latency_field) {
|
||||
json_object_add_value_uint64(subroot, "average_latency", le64_to_cpu(lt->stats.average_latency));
|
||||
}
|
||||
if (lt->has_average_latency_field)
|
||||
json_object_add_value_uint64(subroot, "average_latency",
|
||||
le64_to_cpu(lt->stats.average_latency));
|
||||
json_object_add_value_object(subroot, "values", lt->bucket_list);
|
||||
}
|
||||
|
||||
|
@ -199,13 +197,12 @@ static void latency_tracker_parse_4_0(const struct latency_tracker *lt)
|
|||
int lower_us = latency_tracker_bucket_pos2us(lt, i);
|
||||
int upper_us = latency_tracker_bucket_pos2us(lt, i + 1);
|
||||
|
||||
latency_tracker_bucket_parse(lt, i, lower_us,
|
||||
upper_us,
|
||||
latency_tracker_bucket_parse(lt, i, lower_us, upper_us,
|
||||
i < (lt->bucket_list_size - 1));
|
||||
}
|
||||
}
|
||||
|
||||
static void print_dash_separator()
|
||||
static void print_dash_separator(void)
|
||||
{
|
||||
printf("--------------------------------------------------\n");
|
||||
}
|
||||
|
@ -218,16 +215,14 @@ static void latency_tracker_pre_parse(struct latency_tracker *lt)
|
|||
printf("UUID-idx: %d\n", lt->uuid_index);
|
||||
printf("Major Revision: %u\nMinor Revision: %u\n",
|
||||
le16_to_cpu(lt->stats.version_major), le16_to_cpu(lt->stats.version_minor));
|
||||
if (lt->has_average_latency_field) {
|
||||
if (lt->has_average_latency_field)
|
||||
printf("Average Latency: %" PRIu64 "\n", le64_to_cpu(lt->stats.average_latency));
|
||||
}
|
||||
print_dash_separator();
|
||||
printf("%-12s%-12s%-12s%-20s\n", "Bucket", "Start", "End", "Value");
|
||||
print_dash_separator();
|
||||
}
|
||||
if (lt->print_flags == JSON) {
|
||||
if (lt->print_flags == JSON)
|
||||
lt->bucket_list = json_object_new_array();
|
||||
}
|
||||
}
|
||||
|
||||
static void latency_tracker_post_parse(struct latency_tracker *lt)
|
||||
|
@ -253,11 +248,10 @@ static void latency_tracker_parse(struct latency_tracker *lt)
|
|||
latency_tracker_parse_3_0(lt);
|
||||
break;
|
||||
case 4:
|
||||
if (version_minor >= 8){
|
||||
if (version_minor >= 8)
|
||||
lt->has_average_latency_field = true;
|
||||
}
|
||||
latency_tracker_pre_parse(lt);
|
||||
if (version_minor == 0){
|
||||
if (!version_minor) {
|
||||
lt->base_range_bits = BASE_RANGE_BITS_4_0;
|
||||
lt->bucket_list_size = BUCKET_LIST_SIZE_4_0;
|
||||
}
|
||||
|
@ -275,7 +269,7 @@ static void latency_tracker_parse(struct latency_tracker *lt)
|
|||
#define LATENCY_TRACKING_FID 0xe2
|
||||
#define LATENCY_TRACKING_FID_DATA_LEN 32
|
||||
|
||||
static int latency_tracking_is_enable(struct latency_tracker *lt, __u32 * enabled)
|
||||
static int latency_tracking_is_enable(struct latency_tracker *lt, __u32 *enabled)
|
||||
{
|
||||
struct nvme_get_features_args args_get = {
|
||||
.args_size = sizeof(args_get),
|
||||
|
@ -298,13 +292,12 @@ static int latency_tracking_enable(struct latency_tracker *lt)
|
|||
__u32 result;
|
||||
int err;
|
||||
|
||||
if (!(lt->cfg.enable || lt->cfg.disable)){
|
||||
if (!(lt->cfg.enable || lt->cfg.disable))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lt->cfg.enable && lt->cfg.disable){
|
||||
fprintf(stderr,"Cannot enable and disable simultaneously.\n");
|
||||
return EINVAL;
|
||||
if (lt->cfg.enable && lt->cfg.disable) {
|
||||
fprintf(stderr, "Cannot enable and disable simultaneously.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
struct nvme_set_features_args args_set = {
|
||||
|
@ -345,9 +338,9 @@ static int latency_tracker_get_log(struct latency_tracker *lt)
|
|||
{
|
||||
int err;
|
||||
|
||||
if (lt->cfg.read && lt->cfg.write){
|
||||
fprintf(stderr,"Cannot capture read and write logs simultaneously.\n");
|
||||
return EINVAL;
|
||||
if (lt->cfg.read && lt->cfg.write) {
|
||||
fprintf(stderr, "Cannot capture read and write logs simultaneously.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!(lt->cfg.read || lt->cfg.write))
|
||||
|
@ -422,31 +415,31 @@ int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *cmd
|
|||
if (lt.print_flags == -EINVAL) {
|
||||
fprintf(stderr, "Invalid output format '%s'\n", lt.cfg.output_format);
|
||||
dev_close(dev);
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (lt.cfg.type > 0xf) {
|
||||
fprintf(stderr, "Invalid Log type value '%d'\n", lt.cfg.type);
|
||||
dev_close(dev);
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (lt.cfg.type && !(lt.cfg.read || lt.cfg.write)) {
|
||||
fprintf(stderr, "Log type option valid only when retrieving statistics\n");
|
||||
dev_close(dev);
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
lt.uuid_index = solidigm_get_vu_uuid_index(dev);
|
||||
|
||||
err = latency_tracking_enable(<);
|
||||
if (err){
|
||||
if (err) {
|
||||
dev_close(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = latency_tracker_get_log(<);
|
||||
if (err){
|
||||
if (err) {
|
||||
dev_close(dev);
|
||||
return err;
|
||||
}
|
||||
|
@ -460,16 +453,16 @@ int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *cmd
|
|||
if (!err) {
|
||||
if (lt.print_flags == JSON) {
|
||||
struct json_object *root = json_create_object();
|
||||
json_object_add_value_int(root,"enabled", enabled);
|
||||
|
||||
json_object_add_value_int(root, "enabled", enabled);
|
||||
json_print_object(root, NULL);
|
||||
json_free_object(root);
|
||||
printf("\n");
|
||||
} else if (lt.print_flags == BINARY) {
|
||||
putchar(enabled);
|
||||
} else {
|
||||
printf(
|
||||
"Latency Statistics Tracking (UUID-idx:%d, FID:0x%X) is currently %i.\n",
|
||||
lt.uuid_index, LATENCY_TRACKING_FID, enabled);
|
||||
printf("Latency Statistics Tracking (UUID-idx:%d, FID:0x%X) is currently %i.\n",
|
||||
lt.uuid_index, LATENCY_TRACKING_FID, enabled);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Could not read feature id 0xE2.\n");
|
||||
|
|
300
plugins/solidigm/solidigm-log-page-dir.c
Normal file
300
plugins/solidigm/solidigm-log-page-dir.c
Normal file
|
@ -0,0 +1,300 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2023 Solidigm.
|
||||
*
|
||||
* Author: karl.dedow@solidigm.com
|
||||
*/
|
||||
|
||||
#include "solidigm-log-page-dir.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "nvme-print.h"
|
||||
|
||||
#include "plugins/ocp/ocp-utils.h"
|
||||
|
||||
#define MIN_VENDOR_LID 0xC0
|
||||
#define SOLIDIGM_MAX_UUID 2
|
||||
|
||||
static const char dash[100] = {[0 ... 99] = '-'};
|
||||
|
||||
struct lid_dir {
|
||||
struct __packed {
|
||||
bool supported;
|
||||
const char *str;
|
||||
} lid[NVME_LOG_SUPPORTED_LOG_PAGES_MAX];
|
||||
};
|
||||
|
||||
static void init_lid_dir(struct lid_dir *lid_dir)
|
||||
{
|
||||
static const char *unknown_str = "Unknown";
|
||||
|
||||
for (int lid = 0; lid < NVME_LOG_SUPPORTED_LOG_PAGES_MAX; lid++) {
|
||||
lid_dir->lid[lid].supported = false;
|
||||
lid_dir->lid[lid].str = unknown_str;
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_invalid_uuid(const struct nvme_id_uuid_list_entry entry)
|
||||
{
|
||||
static const unsigned char ALL_ZERO_UUID[NVME_UUID_LEN] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
return memcmp(ALL_ZERO_UUID, entry.uuid, NVME_UUID_LEN) == 0;
|
||||
}
|
||||
|
||||
static bool is_solidigm_uuid(const struct nvme_id_uuid_list_entry entry)
|
||||
{
|
||||
static const unsigned char SOLIDIGM_UUID[NVME_UUID_LEN] = {
|
||||
0x96, 0x19, 0x58, 0x6e, 0xc1, 0x1b, 0x43, 0xad,
|
||||
0xaa, 0xaa, 0x65, 0x41, 0x87, 0xf6, 0xbb, 0xb2
|
||||
};
|
||||
|
||||
return memcmp(SOLIDIGM_UUID, entry.uuid, NVME_UUID_LEN) == 0;
|
||||
}
|
||||
|
||||
static bool is_ocp_uuid(const struct nvme_id_uuid_list_entry entry)
|
||||
{
|
||||
static const unsigned char OCP_UUID[NVME_UUID_LEN] = {
|
||||
0xc1, 0x94, 0xd5, 0x5b, 0xe0, 0x94, 0x47, 0x94,
|
||||
0xa2, 0x1d, 0x29, 0x99, 0x8f, 0x56, 0xbe, 0x6f
|
||||
};
|
||||
|
||||
return memcmp(OCP_UUID, entry.uuid, NVME_UUID_LEN) == 0;
|
||||
}
|
||||
|
||||
static int get_supported_log_pages_log(struct nvme_dev *dev, int uuid_index,
|
||||
struct nvme_supported_log_pages *supported)
|
||||
{
|
||||
static const __u8 LID;
|
||||
|
||||
memset(supported, 0, sizeof(*supported));
|
||||
struct nvme_get_log_args args = {
|
||||
.lpo = 0,
|
||||
.result = NULL,
|
||||
.log = supported,
|
||||
.args_size = sizeof(args),
|
||||
.fd = dev_fd(dev),
|
||||
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
|
||||
.lid = LID,
|
||||
.len = sizeof(*supported),
|
||||
.nsid = NVME_NSID_ALL,
|
||||
.csi = NVME_CSI_NVM,
|
||||
.lsi = NVME_LOG_LSI_NONE,
|
||||
.lsp = 0,
|
||||
.uuidx = uuid_index,
|
||||
.rae = false,
|
||||
.ot = false,
|
||||
};
|
||||
|
||||
return nvme_get_log(&args);
|
||||
}
|
||||
|
||||
static struct lid_dir *get_standard_lids(struct nvme_supported_log_pages *supported)
|
||||
{
|
||||
static struct lid_dir standard_dir = { 0 };
|
||||
|
||||
init_lid_dir(&standard_dir);
|
||||
standard_dir.lid[0x00].str = "Supported Log Pages";
|
||||
standard_dir.lid[0x01].str = "Error Information";
|
||||
standard_dir.lid[0x02].str = "SMART / Health Information";
|
||||
standard_dir.lid[0x03].str = "Firmware Slot Information";
|
||||
standard_dir.lid[0x04].str = "Changed Namespace List";
|
||||
standard_dir.lid[0x05].str = "Commands Supported and Effects";
|
||||
standard_dir.lid[0x06].str = "Device Self Test";
|
||||
standard_dir.lid[0x07].str = "Telemetry Host-Initiated";
|
||||
standard_dir.lid[0x08].str = "Telemetry Controller-Initiated";
|
||||
standard_dir.lid[0x09].str = "Endurance Group Information";
|
||||
standard_dir.lid[0x0A].str = "Predictable Latency Per NVM Set";
|
||||
standard_dir.lid[0x0B].str = "Predictable Latency Event Aggregate";
|
||||
standard_dir.lid[0x0C].str = "Asymmetric Namespace Access";
|
||||
standard_dir.lid[0x0D].str = "Persistent Event Log";
|
||||
standard_dir.lid[0x0E].str = "Predictable Latency Event Aggregate";
|
||||
standard_dir.lid[0x0F].str = "Endurance Group Event Aggregate";
|
||||
standard_dir.lid[0x10].str = "Media Unit Status";
|
||||
standard_dir.lid[0x11].str = "Supported Capacity Configuration List";
|
||||
standard_dir.lid[0x12].str = "Feature Identifiers Supported and Effects";
|
||||
standard_dir.lid[0x13].str = "NVMe-MI Commands Supported and Effects";
|
||||
standard_dir.lid[0x14].str = "Command and Feature lockdown";
|
||||
standard_dir.lid[0x15].str = "Boot Partition";
|
||||
standard_dir.lid[0x16].str = "Rotational Media Information";
|
||||
standard_dir.lid[0x70].str = "Discovery";
|
||||
standard_dir.lid[0x80].str = "Reservation Notification";
|
||||
standard_dir.lid[0x81].str = "Sanitize Status";
|
||||
|
||||
for (int lid = 0; lid < NVME_LOG_SUPPORTED_LOG_PAGES_MAX; lid++) {
|
||||
if (!supported->lid_support[lid] || lid >= MIN_VENDOR_LID)
|
||||
continue;
|
||||
|
||||
standard_dir.lid[lid].supported = true;
|
||||
}
|
||||
|
||||
return &standard_dir;
|
||||
}
|
||||
|
||||
static void update_vendor_lid_supported(struct nvme_supported_log_pages *supported,
|
||||
struct lid_dir *lid_dir)
|
||||
{
|
||||
for (int lid = 0; lid < NVME_LOG_SUPPORTED_LOG_PAGES_MAX; lid++) {
|
||||
if (!supported->lid_support[lid] || lid < MIN_VENDOR_LID)
|
||||
continue;
|
||||
|
||||
lid_dir->lid[lid].supported = true;
|
||||
}
|
||||
}
|
||||
|
||||
static struct lid_dir *get_solidigm_lids(struct nvme_supported_log_pages *supported)
|
||||
{
|
||||
static struct lid_dir solidigm_dir = { 0 };
|
||||
|
||||
init_lid_dir(&solidigm_dir);
|
||||
solidigm_dir.lid[0xC1].str = "Read Commands Latency Statistics";
|
||||
solidigm_dir.lid[0xC2].str = "Write Commands Latency Statistics";
|
||||
solidigm_dir.lid[0xC4].str = "Endurance Manager Statistics";
|
||||
solidigm_dir.lid[0xC5].str = "Temperature Statistics";
|
||||
solidigm_dir.lid[0xCA].str = "SMART Attributes";
|
||||
|
||||
update_vendor_lid_supported(supported, &solidigm_dir);
|
||||
|
||||
return &solidigm_dir;
|
||||
}
|
||||
|
||||
static struct lid_dir *get_ocp_lids(struct nvme_supported_log_pages *supported)
|
||||
{
|
||||
static struct lid_dir ocp_dir = { 0 };
|
||||
|
||||
init_lid_dir(&ocp_dir);
|
||||
ocp_dir.lid[0xC0].str = "OCP SMART / Health Information Extended";
|
||||
ocp_dir.lid[0xC1].str = "OCP Error Recovery";
|
||||
ocp_dir.lid[0xC2].str = "OCP Firmware Activation History";
|
||||
ocp_dir.lid[0xC3].str = "OCP Latency Monitor";
|
||||
ocp_dir.lid[0xC4].str = "OCP Device Capabilities";
|
||||
ocp_dir.lid[0xC5].str = "OCP Unsupported Requirements";
|
||||
|
||||
update_vendor_lid_supported(supported, &ocp_dir);
|
||||
|
||||
return &ocp_dir;
|
||||
}
|
||||
|
||||
static void supported_log_pages_normal(struct lid_dir *lid_dir[SOLIDIGM_MAX_UUID + 1])
|
||||
{
|
||||
printf("%-5s %-4s %-42s\n", "uuidx", "LID", "Description");
|
||||
printf("%-.5s %-.4s %-.42s\n", dash, dash, dash);
|
||||
|
||||
for (int uuid_index = 0; uuid_index <= SOLIDIGM_MAX_UUID; uuid_index++) {
|
||||
if (!lid_dir[uuid_index])
|
||||
continue;
|
||||
|
||||
for (int lid = 0; lid < NVME_LOG_SUPPORTED_LOG_PAGES_MAX; lid++) {
|
||||
if (!lid_dir[uuid_index]->lid[lid].supported)
|
||||
continue;
|
||||
|
||||
printf("%-5d 0x%02x %s\n", le32_to_cpu(uuid_index), le32_to_cpu(lid),
|
||||
lid_dir[uuid_index]->lid[lid].str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void supported_log_pages_json(struct lid_dir *lid_dir[SOLIDIGM_MAX_UUID + 1])
|
||||
{
|
||||
struct json_object *root = json_create_array();
|
||||
|
||||
for (int uuid_index = 0; uuid_index <= SOLIDIGM_MAX_UUID; uuid_index++) {
|
||||
if (!lid_dir[uuid_index])
|
||||
continue;
|
||||
|
||||
for (int lid = 0; lid < NVME_LOG_SUPPORTED_LOG_PAGES_MAX; lid++) {
|
||||
if (!lid_dir[uuid_index]->lid[lid].supported)
|
||||
continue;
|
||||
|
||||
struct json_object *lid_obj = json_create_object();
|
||||
|
||||
json_object_add_value_uint(lid_obj, "uuidx", le32_to_cpu(uuid_index));
|
||||
json_object_add_value_uint(lid_obj, "lid", le32_to_cpu(lid));
|
||||
json_object_add_value_string(lid_obj, "description",
|
||||
lid_dir[uuid_index]->lid[lid].str);
|
||||
json_array_add_value_object(root, lid_obj);
|
||||
}
|
||||
}
|
||||
|
||||
json_print_object(root, NULL);
|
||||
json_free_object(root);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int solidigm_get_log_page_directory_log(int argc, char **argv, struct command *cmd,
|
||||
struct plugin *plugin)
|
||||
{
|
||||
const int NO_UUID_INDEX = 0;
|
||||
const char *description = "Retrieves list of supported log pages for each UUID index.";
|
||||
char *format = "normal";
|
||||
|
||||
OPT_ARGS(options) = {
|
||||
OPT_FMT("output-format", 'o', &format, "output format : normal | json"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
struct nvme_dev *dev = NULL;
|
||||
int err = parse_and_open(&dev, argc, argv, description, options);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
struct lid_dir *lid_dirs[SOLIDIGM_MAX_UUID + 1] = { 0 };
|
||||
struct nvme_id_uuid_list uuid_list = { 0 };
|
||||
struct nvme_supported_log_pages supported = { 0 };
|
||||
|
||||
err = get_supported_log_pages_log(dev, NO_UUID_INDEX, &supported);
|
||||
|
||||
if (!err) {
|
||||
lid_dirs[NO_UUID_INDEX] = get_standard_lids(&supported);
|
||||
|
||||
// Assume VU logs are the Solidigm log pages if UUID not supported.
|
||||
if (nvme_identify_uuid(dev_fd(dev), &uuid_list)) {
|
||||
struct lid_dir *solidigm_lid_dir = get_solidigm_lids(&supported);
|
||||
|
||||
// Transfer supported Solidigm lids to lid directory at UUID index 0
|
||||
for (int lid = 0; lid < NVME_LOG_SUPPORTED_LOG_PAGES_MAX; lid++) {
|
||||
if (solidigm_lid_dir->lid[lid].supported)
|
||||
lid_dirs[NO_UUID_INDEX]->lid[lid] = solidigm_lid_dir->lid[lid];
|
||||
}
|
||||
} else {
|
||||
for (int uuid_index = 1; uuid_index <= SOLIDIGM_MAX_UUID; uuid_index++) {
|
||||
if (is_invalid_uuid(uuid_list.entry[uuid_index - 1]))
|
||||
break;
|
||||
else if (get_supported_log_pages_log(dev, uuid_index, &supported))
|
||||
continue;
|
||||
|
||||
if (is_solidigm_uuid(uuid_list.entry[uuid_index - 1]))
|
||||
lid_dirs[uuid_index] = get_solidigm_lids(&supported);
|
||||
else if (is_ocp_uuid(uuid_list.entry[uuid_index - 1]))
|
||||
lid_dirs[uuid_index] = get_ocp_lids(&supported);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nvme_show_status(err);
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
const enum nvme_print_flags print_flag = validate_output_format(format);
|
||||
|
||||
if (print_flag == NORMAL) {
|
||||
supported_log_pages_normal(lid_dirs);
|
||||
} else if (print_flag == JSON) {
|
||||
supported_log_pages_json(lid_dirs);
|
||||
} else {
|
||||
fprintf(stderr, "Error: Invalid output format specified: %s.\n", format);
|
||||
err = -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Redundant close() to make static code analysis happy */
|
||||
close(dev->direct.fd);
|
||||
dev_close(dev);
|
||||
return err;
|
||||
}
|
17
plugins/solidigm/solidigm-log-page-dir.h
Normal file
17
plugins/solidigm/solidigm-log-page-dir.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (c) 2023 Solidigm.
|
||||
*
|
||||
* Authors: karl.dedow@solidigm.com
|
||||
*/
|
||||
|
||||
#ifndef SOLIDIGM_LOG_PAGE_DIRECTORY_H
|
||||
#define SOLIDIGM_LOG_PAGE_DIRECTORY_H
|
||||
|
||||
struct command;
|
||||
struct plugin;
|
||||
|
||||
int solidigm_get_log_page_directory_log(int argc, char **argv, struct command *cmd,
|
||||
struct plugin *plugin);
|
||||
|
||||
#endif
|
63
plugins/solidigm/solidigm-market-log.c
Normal file
63
plugins/solidigm/solidigm-market-log.c
Normal file
|
@ -0,0 +1,63 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2023 Solidigm.
|
||||
*
|
||||
* Authors: leonardo.da.cunha@solidigm.com
|
||||
* Hardeep.Dhillon@solidigm.com
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
#include <linux/limits.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "nvme.h"
|
||||
#include "libnvme.h"
|
||||
#include "plugin.h"
|
||||
#include "nvme-print.h"
|
||||
|
||||
#define MARKET_LOG_MAX_SIZE 512
|
||||
|
||||
int sldgm_get_market_log(int argc, char **argv, struct command *command,
|
||||
struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "Get Solidigm Marketing Name log and show it.";
|
||||
const char *raw = "dump output in binary format";
|
||||
struct nvme_dev *dev;
|
||||
char log[MARKET_LOG_MAX_SIZE];
|
||||
int err;
|
||||
|
||||
struct config {
|
||||
bool raw_binary;
|
||||
};
|
||||
|
||||
struct config cfg = {
|
||||
};
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = nvme_get_log_simple(dev_fd(dev), 0xdd, sizeof(log), log);
|
||||
if (!err) {
|
||||
if (!cfg.raw_binary)
|
||||
printf("Solidigm Marketing Name Log:\n%s\n", log);
|
||||
else
|
||||
d_raw((unsigned char *)&log, sizeof(log));
|
||||
} else if (err > 0)
|
||||
|
||||
nvme_show_status(err);
|
||||
/* Redundant close() to make static code analysis happy */
|
||||
close(dev->direct.fd);
|
||||
dev_close(dev);
|
||||
return err;
|
||||
}
|
8
plugins/solidigm/solidigm-market-log.h
Normal file
8
plugins/solidigm/solidigm-market-log.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (c) 2023 Solidigm.
|
||||
*
|
||||
* Author: hardeep.dhillon@solidigm.com
|
||||
*/
|
||||
|
||||
int sldgm_get_market_log(int argc, char **argv, struct command *cmd, struct plugin *plugin);
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2022 Solidigm.
|
||||
* Copyright (c) 2022-2023 Solidigm.
|
||||
*
|
||||
* Author: leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
|
@ -10,19 +10,34 @@
|
|||
#define CREATE_CMD
|
||||
#include "solidigm-nvme.h"
|
||||
|
||||
#include "solidigm-id-ctrl.h"
|
||||
#include "solidigm-smart.h"
|
||||
#include "solidigm-internal-logs.h"
|
||||
#include "solidigm-garbage-collection.h"
|
||||
#include "solidigm-latency-tracking.h"
|
||||
#include "solidigm-telemetry.h"
|
||||
#include "solidigm-log-page-dir.h"
|
||||
#include "solidigm-market-log.h"
|
||||
|
||||
#include "plugins/ocp/ocp-clear-fw-update-history.h"
|
||||
#include "plugins/ocp/ocp-smart-extended-log.h"
|
||||
#include "plugins/ocp/ocp-fw-activation-history.h"
|
||||
|
||||
static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
return __id_ctrl(argc, argv, cmd, plugin, sldgm_id_ctrl);
|
||||
}
|
||||
|
||||
static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
return solidigm_get_additional_smart_log(argc, argv, cmd, plugin);
|
||||
}
|
||||
|
||||
static int get_internal_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
return solidigm_get_internal_log(argc, argv, cmd, plugin);
|
||||
}
|
||||
|
||||
static int get_garbage_collection_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
return solidigm_get_garbage_collection_log(argc, argv, cmd, plugin);
|
||||
|
@ -49,3 +64,21 @@ static int smart_cloud(int argc, char **argv, struct command *cmd,
|
|||
{
|
||||
return ocp_smart_add_log(argc, argv, cmd, plugin);
|
||||
}
|
||||
|
||||
static int fw_activation_history(int argc, char **argv, struct command *cmd,
|
||||
struct plugin *plugin)
|
||||
{
|
||||
return ocp_fw_activation_history_log(argc, argv, cmd, plugin);
|
||||
}
|
||||
|
||||
static int get_log_page_directory_log(int argc, char **argv, struct command *cmd,
|
||||
struct plugin *plugin)
|
||||
{
|
||||
return solidigm_get_log_page_directory_log(argc, argv, cmd, plugin);
|
||||
}
|
||||
|
||||
static int get_market_log(int argc, char **argv, struct command *cmd,
|
||||
struct plugin *plugin)
|
||||
{
|
||||
return sldgm_get_market_log(argc, argv, cmd, plugin);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2022 Solidigm.
|
||||
* Copyright (c) 2022-2023 Solidigm.
|
||||
*
|
||||
* Author: leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
|
@ -13,18 +13,21 @@
|
|||
|
||||
#include "cmd.h"
|
||||
|
||||
#define SOLIDIGM_PLUGIN_VERSION "0.8"
|
||||
#define SOLIDIGM_PLUGIN_VERSION "0.14"
|
||||
|
||||
PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_VERSION),
|
||||
COMMAND_LIST(
|
||||
ENTRY("id-ctrl", "Send NVMe Identify Controller", id_ctrl)
|
||||
ENTRY("smart-log-add", "Retrieve Solidigm SMART Log", get_additional_smart_log)
|
||||
ENTRY("vs-smart-add-log", "Get SMART / health extended log (redirects to ocp plug-in)", smart_cloud)
|
||||
ENTRY("vs-internal-log", "Retrieve Debug log binaries", get_internal_log)
|
||||
ENTRY("garbage-collect-log", "Retrieve Garbage Collection Log", get_garbage_collection_log)
|
||||
ENTRY("market-log", "Retrieve Market Log", get_market_log)
|
||||
ENTRY("latency-tracking-log", "Enable/Retrieve Latency tracking Log", get_latency_tracking_log)
|
||||
ENTRY("parse-telemetry-log", "Parse Telemetry Log binary", get_telemetry_log)
|
||||
ENTRY("clear-fw-activate-history",
|
||||
"Clear firmware update history log (redirects to ocp plug-in)",
|
||||
clear_fw_update_history)
|
||||
ENTRY("clear-fw-activate-history", "Clear firmware update history log (redirects to ocp plug-in)", clear_fw_update_history)
|
||||
ENTRY("vs-fw-activate-history", "Get firmware activation history log (redirects to ocp plug-in)", fw_activation_history)
|
||||
ENTRY("log-page-directory", "Retrieve log page directory", get_log_page_directory_log)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -21,32 +21,31 @@
|
|||
#include "solidigm-smart.h"
|
||||
#include "solidigm-util.h"
|
||||
|
||||
struct __attribute__((packed)) nvme_additional_smart_log_item {
|
||||
struct __packed nvme_additional_smart_log_item {
|
||||
__u8 id;
|
||||
__u8 _kp[2];
|
||||
__u8 normalized;
|
||||
__u8 _np;
|
||||
union __attribute__((packed)) {
|
||||
union __packed {
|
||||
__u8 raw[6];
|
||||
struct __attribute__((packed)) wear_level {
|
||||
struct __packed wear_level {
|
||||
__le16 min;
|
||||
__le16 max;
|
||||
__le16 avg;
|
||||
} wear_level;
|
||||
struct __attribute__((packed)) thermal_throttle {
|
||||
struct __packed thermal_throttle {
|
||||
__u8 pct;
|
||||
__u32 count;
|
||||
} thermal_throttle;
|
||||
} ;
|
||||
};
|
||||
__u8 _rp;
|
||||
} ;
|
||||
typedef struct nvme_additional_smart_log_item smart_log_item_t;
|
||||
};
|
||||
|
||||
#define VU_SMART_PAGE_SIZE 512
|
||||
#define VU_SMART_MAX_ITEMS VU_SMART_PAGE_SIZE / sizeof(smart_log_item_t)
|
||||
typedef struct vu_smart_log {
|
||||
smart_log_item_t item[VU_SMART_MAX_ITEMS];
|
||||
} vu_smart_log_t;
|
||||
#define VU_SMART_MAX_ITEMS (VU_SMART_PAGE_SIZE / sizeof(struct nvme_additional_smart_log_item))
|
||||
struct vu_smart_log {
|
||||
struct nvme_additional_smart_log_item item[VU_SMART_MAX_ITEMS];
|
||||
};
|
||||
|
||||
static char *id_to_name(__u8 id)
|
||||
{
|
||||
|
@ -110,11 +109,10 @@ static char *id_to_name(__u8 id)
|
|||
}
|
||||
}
|
||||
|
||||
static void smart_log_item_print(smart_log_item_t *item)
|
||||
static void smart_log_item_print(struct nvme_additional_smart_log_item *item)
|
||||
{
|
||||
if (!item->id) {
|
||||
if (!item->id)
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%#x %-45s %3d ",
|
||||
item->id, id_to_name(item->id), item->normalized);
|
||||
|
@ -136,13 +134,12 @@ static void smart_log_item_print(smart_log_item_t *item)
|
|||
}
|
||||
}
|
||||
|
||||
static void smart_log_item_add_json(smart_log_item_t *item, struct json_object *dev_stats)
|
||||
static void smart_log_item_add_json(struct nvme_additional_smart_log_item *item, struct json_object *dev_stats)
|
||||
{
|
||||
struct json_object *entry_stats = json_create_object();
|
||||
|
||||
if (!item->id) {
|
||||
if (!item->id)
|
||||
return;
|
||||
}
|
||||
|
||||
json_object_add_value_int(entry_stats, "normalized", item->normalized);
|
||||
|
||||
|
@ -162,15 +159,14 @@ static void smart_log_item_add_json(smart_log_item_t *item, struct json_object *
|
|||
json_object_add_value_object(dev_stats, id_to_name(item->id), entry_stats);
|
||||
}
|
||||
|
||||
static void vu_smart_log_show_json(vu_smart_log_t *payload, unsigned int nsid, const char *devname)
|
||||
static void vu_smart_log_show_json(struct vu_smart_log *payload, unsigned int nsid, const char *devname)
|
||||
{
|
||||
struct json_object *dev_stats = json_create_object();
|
||||
smart_log_item_t *item = payload->item;
|
||||
struct nvme_additional_smart_log_item *item = payload->item;
|
||||
struct json_object *root;
|
||||
|
||||
for (int i = 0; i < VU_SMART_MAX_ITEMS; i++) {
|
||||
for (int i = 0; i < VU_SMART_MAX_ITEMS; i++)
|
||||
smart_log_item_add_json(&item[i], dev_stats);
|
||||
}
|
||||
|
||||
root = json_create_object();
|
||||
json_object_add_value_string(root, "Solidigm SMART log", devname);
|
||||
|
@ -180,26 +176,25 @@ static void vu_smart_log_show_json(vu_smart_log_t *payload, unsigned int nsid, c
|
|||
json_free_object(root);
|
||||
}
|
||||
|
||||
static void vu_smart_log_show(vu_smart_log_t *payload, unsigned int nsid, const char *devname,
|
||||
static void vu_smart_log_show(struct vu_smart_log *payload, unsigned int nsid, const char *devname,
|
||||
__u8 uuid_index)
|
||||
{
|
||||
smart_log_item_t *item = payload->item;
|
||||
struct nvme_additional_smart_log_item *item = payload->item;
|
||||
|
||||
printf("Additional Smart Log for NVMe device:%s namespace-id:%x UUID-idx:%d\n",
|
||||
devname, nsid, uuid_index);
|
||||
printf("ID KEY Normalized Raw\n");
|
||||
|
||||
for (int i = 0; i < VU_SMART_MAX_ITEMS; i++) {
|
||||
for (int i = 0; i < VU_SMART_MAX_ITEMS; i++)
|
||||
smart_log_item_print(&item[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int solidigm_get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "Get Solidigm vendor specific smart log (optionally, "\
|
||||
"for the specified namespace), and show it.";
|
||||
const char *desc =
|
||||
"Get Solidigm vendor specific smart log (optionally, for the specified namespace), and show it.";
|
||||
const int solidigm_vu_smart_log_id = 0xCA;
|
||||
vu_smart_log_t smart_log_payload;
|
||||
struct vu_smart_log smart_log_payload;
|
||||
enum nvme_print_flags flags;
|
||||
struct nvme_dev *dev;
|
||||
int err;
|
||||
|
@ -254,15 +249,14 @@ int solidigm_get_additional_smart_log(int argc, char **argv, struct command *cmd
|
|||
|
||||
err = nvme_get_log(&args);
|
||||
if (!err) {
|
||||
if (flags & JSON) {
|
||||
if (flags & JSON)
|
||||
vu_smart_log_show_json(&smart_log_payload,
|
||||
cfg.namespace_id, dev->name);
|
||||
} else if (flags & BINARY) {
|
||||
else if (flags & BINARY)
|
||||
d_raw((unsigned char *)&smart_log_payload, sizeof(smart_log_payload));
|
||||
} else {
|
||||
else
|
||||
vu_smart_log_show(&smart_log_payload, cfg.namespace_id,
|
||||
dev->name, uuid_index);
|
||||
}
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc
|
|||
}
|
||||
|
||||
if (cfg.cfg_file) {
|
||||
char *conf_str = 0;
|
||||
char *conf_str = NULL;
|
||||
size_t length = 0;
|
||||
|
||||
err = read_file2buffer(cfg.cfg_file, &conf_str, &length);
|
||||
|
@ -121,9 +121,10 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc
|
|||
cfg.cfg_file, strerror(err));
|
||||
goto close_fd;
|
||||
}
|
||||
struct json_tokener * jstok = json_tokener_new();
|
||||
struct json_tokener *jstok = json_tokener_new();
|
||||
|
||||
tl.configuration = json_tokener_parse_ex(jstok, conf_str, length);
|
||||
free(conf_str);
|
||||
if (jstok->err != json_tokener_success) {
|
||||
SOLIDIGM_LOG_WARNING("Parsing error on JSON configuration file %s: %s (at offset %d)",
|
||||
cfg.cfg_file,
|
||||
|
@ -160,11 +161,7 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc
|
|||
goto close_fd;
|
||||
}
|
||||
}
|
||||
solidigm_telemetry_log_header_parse(&tl);
|
||||
if (cfg.cfg_file)
|
||||
solidigm_telemetry_log_data_areas_parse(&tl, cfg.data_area);
|
||||
else
|
||||
solidigm_telemetry_log_cod_parse(&tl);
|
||||
solidigm_telemetry_log_data_areas_parse(&tl, cfg.data_area);
|
||||
|
||||
json_print_object(tl.root, NULL);
|
||||
json_free_object(tl.root);
|
||||
|
|
|
@ -51,22 +51,20 @@ const char *oemDataMapDesc[] = {
|
|||
"All Time Current Max Wear Level", // 0x28
|
||||
"Media Wear Remaining", // 0x29
|
||||
"Total Non-Defrag Writes", // 0x2A
|
||||
"Number of sectors relocated in reaction to an error" //Uid 0x2B = 43
|
||||
"Media Health Relocations" //Uid 0x2B = 43
|
||||
};
|
||||
|
||||
static const char * getOemDataMapDescription(__u32 id)
|
||||
static const char *getOemDataMapDescription(uint32_t id)
|
||||
{
|
||||
if (id < (sizeof(oemDataMapDesc) / sizeof(oemDataMapDesc[0]))) {
|
||||
if (id < ARRAY_SIZE(oemDataMapDesc))
|
||||
return oemDataMapDesc[id];
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
#define OEMSIGNATURE 0x504D4443
|
||||
|
||||
#pragma pack(push, cod, 1)
|
||||
struct cod_header
|
||||
{
|
||||
struct cod_header {
|
||||
uint32_t versionMajor;
|
||||
uint32_t versionMinor;
|
||||
uint32_t Signature; //!Fixed signature value (0x504D4443) for identification and validation
|
||||
|
@ -75,8 +73,7 @@ struct cod_header
|
|||
uint8_t Reserved[12];
|
||||
};
|
||||
|
||||
struct cod_item
|
||||
{
|
||||
struct cod_item {
|
||||
uint32_t DataFieldMapUid; //!The data field unique identifier value
|
||||
uint32_t reserved1 : 8;
|
||||
uint32_t dataFieldType : 8;
|
||||
|
@ -90,8 +87,7 @@ struct cod_item
|
|||
uint8_t Reserved2[8];
|
||||
};
|
||||
|
||||
struct cod_map
|
||||
{
|
||||
struct cod_map {
|
||||
struct cod_header header;
|
||||
struct cod_item items[];
|
||||
};
|
||||
|
@ -100,8 +96,7 @@ struct cod_map
|
|||
|
||||
void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl)
|
||||
{
|
||||
enum cod_field_type
|
||||
{
|
||||
enum cod_field_type {
|
||||
INTEGER,
|
||||
FLOAT,
|
||||
STRING,
|
||||
|
@ -118,77 +113,78 @@ void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl)
|
|||
return;
|
||||
if (!json_object_object_get_ex(telemetry_header, "reasonIdentifier", &reason_id))
|
||||
return;
|
||||
if (!json_object_object_get_ex(reason_id, "OemDataMapOffset", &COD_offset))
|
||||
if (!json_object_object_get_ex(reason_id, "oemDataMapOffset", &COD_offset))
|
||||
return;
|
||||
|
||||
__u64 offset = json_object_get_int(COD_offset);
|
||||
uint64_t offset = json_object_get_int(COD_offset);
|
||||
|
||||
if (offset == 0) {
|
||||
if (!offset)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((offset + sizeof(struct cod_header)) > tl->log_size) {
|
||||
SOLIDIGM_LOG_WARNING("Warning: COD map header out of bounds.");
|
||||
return;
|
||||
}
|
||||
|
||||
const struct cod_map *data = (struct cod_map *) (((__u8 *)tl->log ) + offset);
|
||||
const struct cod_map *data = (struct cod_map *) (((uint8_t *)tl->log) + offset);
|
||||
|
||||
uint32_t signature = be32_to_cpu(data->header.Signature);
|
||||
if ( signature != OEMSIGNATURE){
|
||||
|
||||
if (signature != OEMSIGNATURE) {
|
||||
SOLIDIGM_LOG_WARNING("Warning: Unsupported COD data signature %x!", signature);
|
||||
return;
|
||||
}
|
||||
if ((offset + data->header.MapSizeInBytes) > tl->log_size){
|
||||
if ((offset + data->header.MapSizeInBytes) > tl->log_size) {
|
||||
SOLIDIGM_LOG_WARNING("Warning: COD map data out of bounds.");
|
||||
return;
|
||||
}
|
||||
|
||||
struct json_object *cod = json_create_object();
|
||||
|
||||
json_object_object_add(tl->root, "cod", cod);
|
||||
|
||||
for (int i =0 ; i < data->header.EntryCount; i++) {
|
||||
for (uint64_t i = 0; i < data->header.EntryCount; i++) {
|
||||
if ((offset + sizeof(struct cod_header) + (i + 1) * sizeof(struct cod_item)) >
|
||||
tl->log_size){
|
||||
SOLIDIGM_LOG_WARNING("Warning: COD data out of bounds at item %d!", i);
|
||||
tl->log_size) {
|
||||
SOLIDIGM_LOG_WARNING("Warning: COD data out of bounds at item %"PRIu64"!",
|
||||
i);
|
||||
return;
|
||||
}
|
||||
struct cod_item item = data->items[i];
|
||||
if (item.DataFieldOffset + item.DataFieldOffset > tl->log_size) {
|
||||
|
||||
if (item.DataFieldOffset + item.DataFieldOffset > tl->log_size)
|
||||
continue;
|
||||
}
|
||||
if (item.dataInvalid) {
|
||||
if (item.dataInvalid)
|
||||
continue;
|
||||
}
|
||||
uint8_t *val = ((uint8_t *)tl->log )+ item.DataFieldOffset;
|
||||
uint8_t *val = ((uint8_t *)tl->log) + item.DataFieldOffset;
|
||||
const char *key = getOemDataMapDescription(item.DataFieldMapUid);
|
||||
switch(item.dataFieldType){
|
||||
case(INTEGER):
|
||||
if (item.issigned) {
|
||||
json_object_object_add(cod, key,
|
||||
json_object_new_int64(le64_to_cpu(*(uint64_t *)val)));
|
||||
} else {
|
||||
json_object_add_value_uint64(cod, key, le64_to_cpu(*(uint64_t *)val));
|
||||
}
|
||||
break;
|
||||
case(FLOAT):
|
||||
json_object_add_value_float(cod, key, *(float *) val);
|
||||
break;
|
||||
case(STRING):
|
||||
|
||||
switch (item.dataFieldType) {
|
||||
case INTEGER:
|
||||
if (item.issigned)
|
||||
json_object_object_add(cod, key,
|
||||
json_object_new_string_len((const char *)val, item.DataFieldSizeInBytes));
|
||||
break;
|
||||
case(TWO_BYTE_ASCII):
|
||||
json_object_object_add(cod, key,
|
||||
json_object_new_string_len((const char *)val,2));
|
||||
break;
|
||||
case(FOUR_BYTE_ASCII):
|
||||
json_object_object_add(cod, key,
|
||||
json_object_new_string_len((const char *)val, 4));
|
||||
break;
|
||||
default:
|
||||
SOLIDIGM_LOG_WARNING("Warning: Unknown COD field type (%d)", item.DataFieldMapUid);
|
||||
|
||||
json_object_new_int64(le64_to_cpu(*(uint64_t *)val)));
|
||||
else
|
||||
json_object_add_value_uint64(cod, key, le64_to_cpu(*(uint64_t *)val));
|
||||
break;
|
||||
case FLOAT:
|
||||
json_object_add_value_float(cod, key, *(float *)val);
|
||||
break;
|
||||
case STRING:
|
||||
json_object_object_add(cod, key,
|
||||
json_object_new_string_len((const char *)val, item.DataFieldSizeInBytes));
|
||||
break;
|
||||
case TWO_BYTE_ASCII:
|
||||
json_object_object_add(cod, key,
|
||||
json_object_new_string_len((const char *)val, 2));
|
||||
break;
|
||||
case FOUR_BYTE_ASCII:
|
||||
json_object_object_add(cod, key,
|
||||
json_object_new_string_len((const char *)val, 4));
|
||||
break;
|
||||
default:
|
||||
SOLIDIGM_LOG_WARNING("Warning: Unknown COD field type (%d)", item.DataFieldMapUid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,17 @@
|
|||
*
|
||||
* Author: leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include "util/json.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "config.h"
|
||||
|
||||
// max 16 bit unsigned integer nummber 65535
|
||||
#define MAX_16BIT_NUM_AS_STRING_SIZE 6
|
||||
|
||||
#define OBJ_NAME_PREFIX "UID_"
|
||||
#define NLOG_OBJ_PREFIX OBJ_NAME_PREFIX "NLOG_"
|
||||
|
||||
static bool config_get_by_version(const struct json_object *obj, int version_major,
|
||||
int version_minor, struct json_object **value)
|
||||
{
|
||||
|
@ -28,17 +32,45 @@ static bool config_get_by_version(const struct json_object *obj, int version_maj
|
|||
return value != NULL;
|
||||
}
|
||||
|
||||
bool solidigm_config_get_by_token_version(const struct json_object *obj, int token_id,
|
||||
bool solidigm_config_get_struct_by_token_version(const struct json_object *config, int token_id,
|
||||
int version_major, int version_minor,
|
||||
struct json_object **value)
|
||||
{
|
||||
struct json_object *token_obj = NULL;
|
||||
struct json_object *token = NULL;
|
||||
char str_key[MAX_16BIT_NUM_AS_STRING_SIZE];
|
||||
|
||||
snprintf(str_key, sizeof(str_key), "%d", token_id);
|
||||
if (!json_object_object_get_ex(obj, str_key, &token_obj))
|
||||
if (!json_object_object_get_ex(config, str_key, &token))
|
||||
return false;
|
||||
if (!config_get_by_version(token_obj, version_major, version_minor, value))
|
||||
if (!config_get_by_version(token, version_major, version_minor, value))
|
||||
return false;
|
||||
return value != NULL;
|
||||
}
|
||||
|
||||
const char *solidigm_config_get_nlog_obj_name(const struct json_object *config, uint32_t token)
|
||||
{
|
||||
struct json_object *nlog_names = NULL;
|
||||
struct json_object *obj_name;
|
||||
char hex_header[STR_HEX32_SIZE];
|
||||
const char *name;
|
||||
|
||||
if (!json_object_object_get_ex(config, "TELEMETRY_OBJECT_UIDS", &nlog_names))
|
||||
return NULL;
|
||||
snprintf(hex_header, STR_HEX32_SIZE, "0x%08X", token);
|
||||
|
||||
if (!json_object_object_get_ex(nlog_names, hex_header, &obj_name))
|
||||
return NULL;
|
||||
name = json_object_get_string(obj_name);
|
||||
if (strncmp(NLOG_OBJ_PREFIX, name, strlen(NLOG_OBJ_PREFIX)))
|
||||
return NULL;
|
||||
|
||||
return &name[strlen(OBJ_NAME_PREFIX)];
|
||||
}
|
||||
|
||||
struct json_object *solidigm_config_get_nlog_formats(const struct json_object *config)
|
||||
{
|
||||
struct json_object *nlog_formats = NULL;
|
||||
|
||||
json_object_object_get_ex(config, "NLOG_FORMATS", &nlog_formats);
|
||||
return nlog_formats;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,13 @@
|
|||
#include <stdbool.h>
|
||||
#include "util/json.h"
|
||||
|
||||
bool solidigm_config_get_by_token_version(const struct json_object *obj,
|
||||
#define STR_HEX32_SIZE sizeof("0x00000000")
|
||||
|
||||
bool solidigm_config_get_struct_by_token_version(const struct json_object *obj,
|
||||
int key, int subkey,
|
||||
int subsubkey,
|
||||
struct json_object **value);
|
||||
|
||||
const char *solidigm_config_get_nlog_obj_name(const struct json_object *config, uint32_t token);
|
||||
struct json_object *solidigm_config_get_nlog_formats(const struct json_object *config);
|
||||
|
||||
|
|
|
@ -6,25 +6,29 @@
|
|||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "header.h"
|
||||
#include "cod.h"
|
||||
#include "data-area.h"
|
||||
#include "config.h"
|
||||
#include "nlog.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define SIGNED_INT_PREFIX "int"
|
||||
#define BITS_IN_BYTE 8
|
||||
|
||||
#define MAX_WARNING_SIZE 1024
|
||||
#define MAX_ARRAY_RANK 16
|
||||
|
||||
static bool telemetry_log_get_value(const struct telemetry_log *tl,
|
||||
uint32_t offset_bit, uint32_t size_bit,
|
||||
uint64_t offset_bit, uint32_t size_bit,
|
||||
bool is_signed, struct json_object **val_obj)
|
||||
{
|
||||
uint32_t offset_bit_from_byte;
|
||||
uint32_t additional_size_byte;
|
||||
uint32_t offset_byte;
|
||||
uint32_t val;
|
||||
uint64_t val;
|
||||
|
||||
if (size_bit == 0) {
|
||||
if (!size_bit) {
|
||||
char err_msg[MAX_WARNING_SIZE];
|
||||
|
||||
snprintf(err_msg, MAX_WARNING_SIZE,
|
||||
|
@ -34,7 +38,7 @@ static bool telemetry_log_get_value(const struct telemetry_log *tl,
|
|||
return false;
|
||||
}
|
||||
additional_size_byte = (size_bit - 1) ? (size_bit - 1) / BITS_IN_BYTE : 0;
|
||||
offset_byte = offset_bit / BITS_IN_BYTE;
|
||||
offset_byte = (uint32_t)offset_bit / BITS_IN_BYTE;
|
||||
|
||||
if (offset_byte > (tl->log_size - additional_size_byte)) {
|
||||
char err_msg[MAX_WARNING_SIZE];
|
||||
|
@ -47,15 +51,14 @@ static bool telemetry_log_get_value(const struct telemetry_log *tl,
|
|||
return false;
|
||||
}
|
||||
|
||||
offset_bit_from_byte = offset_bit - (offset_byte * BITS_IN_BYTE);
|
||||
offset_bit_from_byte = (uint32_t) (offset_bit - ((uint64_t)offset_byte * BITS_IN_BYTE));
|
||||
|
||||
if ((size_bit + offset_bit_from_byte) > (sizeof(uint64_t) * BITS_IN_BYTE)) {
|
||||
char err_msg[MAX_WARNING_SIZE];
|
||||
|
||||
snprintf(err_msg, MAX_WARNING_SIZE,
|
||||
"Value crossing 64 bit, byte aligned bounday, "
|
||||
"not supported. size_bit=%u, offset_bit_from_byte=%u.",
|
||||
size_bit, offset_bit_from_byte);
|
||||
"Value crossing 64 bit, byte aligned bounday, not supported. size_bit=%u, offset_bit_from_byte=%u.",
|
||||
size_bit, offset_bit_from_byte);
|
||||
*val_obj = json_object_new_string(err_msg);
|
||||
|
||||
return false;
|
||||
|
@ -67,7 +70,7 @@ static bool telemetry_log_get_value(const struct telemetry_log *tl,
|
|||
val &= (1ULL << size_bit) - 1;
|
||||
if (is_signed) {
|
||||
if (val >> (size_bit - 1))
|
||||
val |= -1ULL << size_bit;
|
||||
val |= (0ULL - 1) << size_bit;
|
||||
*val_obj = json_object_new_int64(val);
|
||||
} else {
|
||||
*val_obj = json_object_new_uint64(val);
|
||||
|
@ -78,23 +81,24 @@ static bool telemetry_log_get_value(const struct telemetry_log *tl,
|
|||
|
||||
static int telemetry_log_structure_parse(const struct telemetry_log *tl,
|
||||
struct json_object *struct_def,
|
||||
size_t parent_offset_bit,
|
||||
uint64_t parent_offset_bit,
|
||||
struct json_object *output,
|
||||
struct json_object *metadata)
|
||||
{
|
||||
struct json_object *obj_arraySizeArray = NULL;
|
||||
struct json_object *obj = NULL;
|
||||
struct json_object *obj_memberList;
|
||||
struct json_object *major_dimension;
|
||||
struct json_object *major_dimension = NULL;
|
||||
struct json_object *sub_output;
|
||||
bool is_enumeration = false;
|
||||
bool has_member_list;
|
||||
const char *type = "";
|
||||
const char *name;
|
||||
size_t array_rank;
|
||||
size_t offset_bit;
|
||||
size_t size_bit;
|
||||
uint32_t linear_array_pos_bit;
|
||||
uint64_t offset_bit;
|
||||
uint32_t size_bit;
|
||||
uint64_t linear_array_pos_bit;
|
||||
uint32_t array_size_dimension[MAX_ARRAY_RANK];
|
||||
|
||||
if (!json_object_object_get_ex(struct_def, "name", &obj)) {
|
||||
SOLIDIGM_LOG_WARNING("Warning: Structure definition missing property 'name': %s",
|
||||
|
@ -113,22 +117,22 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
|
|||
type = json_object_get_string(obj);
|
||||
|
||||
if (!json_object_object_get_ex(struct_def, "offsetBit", &obj)) {
|
||||
SOLIDIGM_LOG_WARNING("Warning: Structure definition missing "
|
||||
"property 'offsetBit': %s",
|
||||
json_object_to_json_string(struct_def));
|
||||
SOLIDIGM_LOG_WARNING(
|
||||
"Warning: Structure definition missing property 'offsetBit': %s",
|
||||
json_object_to_json_string(struct_def));
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset_bit = json_object_get_uint64(obj);
|
||||
|
||||
if (!json_object_object_get_ex(struct_def, "sizeBit", &obj)) {
|
||||
SOLIDIGM_LOG_WARNING("Warning: Structure definition missing "
|
||||
"property 'sizeBit': %s",
|
||||
json_object_to_json_string(struct_def));
|
||||
SOLIDIGM_LOG_WARNING(
|
||||
"Warning: Structure definition missing property 'sizeBit': %s",
|
||||
json_object_to_json_string(struct_def));
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_bit = json_object_get_uint64(obj);
|
||||
size_bit = (uint32_t)json_object_get_uint64(obj);
|
||||
|
||||
if (json_object_object_get_ex(struct_def, "enum", &obj))
|
||||
is_enumeration = json_object_get_boolean(obj);
|
||||
|
@ -139,25 +143,30 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
|
|||
|
||||
if (!json_object_object_get_ex(struct_def, "arraySize",
|
||||
&obj_arraySizeArray)) {
|
||||
SOLIDIGM_LOG_WARNING("Warning: Structure definition missing "
|
||||
"property 'arraySize': %s",
|
||||
json_object_to_json_string(struct_def));
|
||||
SOLIDIGM_LOG_WARNING(
|
||||
"Warning: Structure definition missing property 'arraySize': %s",
|
||||
json_object_to_json_string(struct_def));
|
||||
return -1;
|
||||
}
|
||||
|
||||
array_rank = json_object_array_length(obj_arraySizeArray);
|
||||
if (array_rank == 0) {
|
||||
SOLIDIGM_LOG_WARNING("Warning: Structure property 'arraySize' "
|
||||
"don't support flexible array: %s",
|
||||
json_object_to_json_string(struct_def));
|
||||
if (!array_rank) {
|
||||
SOLIDIGM_LOG_WARNING(
|
||||
"Warning: Structure property 'arraySize' don't support flexible array: %s",
|
||||
json_object_to_json_string(struct_def));
|
||||
return -1;
|
||||
}
|
||||
if (array_rank > MAX_ARRAY_RANK) {
|
||||
SOLIDIGM_LOG_WARNING(
|
||||
"Warning: Structure property 'arraySize' don't support more than %d dimensions: %s",
|
||||
MAX_ARRAY_RANK, json_object_to_json_string(struct_def));
|
||||
return -1;
|
||||
}
|
||||
uint32_t array_size_dimension[array_rank];
|
||||
|
||||
for (size_t i = 0; i < array_rank; i++) {
|
||||
struct json_object *dimension = json_object_array_get_idx(obj_arraySizeArray, i);
|
||||
|
||||
array_size_dimension[i] = json_object_get_uint64(dimension);
|
||||
array_size_dimension[i] = json_object_get_int(dimension);
|
||||
major_dimension = dimension;
|
||||
}
|
||||
if (array_rank > 1) {
|
||||
|
@ -165,7 +174,7 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
|
|||
uint32_t prev_index_offset_bit = 0;
|
||||
struct json_object *dimension_output;
|
||||
|
||||
for (int i = 1; i < (array_rank - 1); i++)
|
||||
for (unsigned int i = 1; i < (array_rank - 1); i++)
|
||||
linear_pos_per_index *= array_size_dimension[i];
|
||||
|
||||
dimension_output = json_create_array();
|
||||
|
@ -181,9 +190,9 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
|
|||
json_object_get(major_dimension);
|
||||
json_object_array_del_idx(obj_arraySizeArray, array_rank - 1, 1);
|
||||
|
||||
for (int i = 0 ; i < array_size_dimension[0]; i++) {
|
||||
for (unsigned int i = 0 ; i < array_size_dimension[0]; i++) {
|
||||
struct json_object *sub_array = json_create_array();
|
||||
size_t offset;
|
||||
uint64_t offset;
|
||||
|
||||
offset = parent_offset_bit + prev_index_offset_bit;
|
||||
|
||||
|
@ -214,7 +223,7 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
|
|||
if (is_enumeration || !has_member_list) {
|
||||
bool is_signed = !strncmp(type, SIGNED_INT_PREFIX, sizeof(SIGNED_INT_PREFIX)-1);
|
||||
struct json_object *val_obj;
|
||||
size_t offset;
|
||||
uint64_t offset;
|
||||
|
||||
offset = parent_offset_bit + offset_bit + linear_array_pos_bit;
|
||||
if (telemetry_log_get_value(tl, offset, size_bit, is_signed, &val_obj)) {
|
||||
|
@ -223,10 +232,10 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
|
|||
else
|
||||
json_object_object_add(sub_output, name, val_obj);
|
||||
} else {
|
||||
SOLIDIGM_LOG_WARNING("Warning: %s From property '%s', "
|
||||
"array index %u, structure definition: %s",
|
||||
json_object_get_string(val_obj),
|
||||
name, j, json_object_to_json_string(struct_def));
|
||||
SOLIDIGM_LOG_WARNING(
|
||||
"Warning: %s From property '%s', array index %u, structure definition: %s",
|
||||
json_object_get_string(val_obj), name, j,
|
||||
json_object_to_json_string(struct_def));
|
||||
json_free_object(val_obj);
|
||||
}
|
||||
} else {
|
||||
|
@ -241,7 +250,7 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
|
|||
num_members = json_object_array_length(obj_memberList);
|
||||
for (int k = 0; k < num_members; k++) {
|
||||
struct json_object *member = json_object_array_get_idx(obj_memberList, k);
|
||||
size_t offset;
|
||||
uint64_t offset;
|
||||
|
||||
offset = parent_offset_bit + offset_bit + linear_array_pos_bit;
|
||||
telemetry_log_structure_parse(tl, member, offset,
|
||||
|
@ -293,6 +302,27 @@ static int telemetry_log_data_area_get_offset(const struct telemetry_log *tl,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int telemetry_log_nlog_parse(const struct telemetry_log *tl, struct json_object *formats,
|
||||
uint64_t nlog_file_offset, uint64_t nlog_size,
|
||||
struct json_object *output, struct json_object *metadata)
|
||||
{
|
||||
/* boundary check */
|
||||
if (tl->log_size < (nlog_file_offset + nlog_size)) {
|
||||
const char *name = "";
|
||||
int media_bank = -1;
|
||||
struct json_object *jobj;
|
||||
|
||||
if (json_object_object_get_ex(metadata, "objName", &jobj))
|
||||
name = json_object_get_string(jobj);
|
||||
if (json_object_object_get_ex(metadata, "mediaBankId", &jobj))
|
||||
media_bank = json_object_get_int(jobj);
|
||||
SOLIDIGM_LOG_WARNING("%s:%d do not fit this log dump.", name, media_bank);
|
||||
return -1;
|
||||
}
|
||||
return solidigm_nlog_parse(((char *) tl->log) + nlog_file_offset,
|
||||
nlog_size, formats, metadata, output);
|
||||
}
|
||||
|
||||
struct toc_item {
|
||||
uint32_t OffsetBytes;
|
||||
uint32_t ContentSizeBytes;
|
||||
|
@ -319,7 +349,6 @@ struct telemetry_object_header {
|
|||
uint8_t Reserved[3];
|
||||
};
|
||||
|
||||
|
||||
static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
|
||||
enum nvme_telemetry_da da,
|
||||
struct json_object *toc_array,
|
||||
|
@ -331,30 +360,35 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
|
|||
char *payload;
|
||||
uint32_t da_offset;
|
||||
uint32_t da_size;
|
||||
struct json_object *nlog_formats;
|
||||
|
||||
if (telemetry_log_data_area_get_offset(tl, da, &da_offset, &da_size))
|
||||
return;
|
||||
|
||||
toc = (struct table_of_contents *)(((char *)tl->log) + da_offset);
|
||||
payload = (char *) tl->log;
|
||||
nlog_formats = solidigm_config_get_nlog_formats(tl->configuration);
|
||||
|
||||
for (int i = 0; i < toc->header.TableOfContentsCount; i++) {
|
||||
struct json_object *structure_definition = NULL;
|
||||
struct json_object *toc_item;
|
||||
uint32_t obj_offset;
|
||||
bool has_struct;
|
||||
const char *nlog_name = NULL;
|
||||
uint32_t header_offset = sizeof(const struct telemetry_object_header);
|
||||
|
||||
if ((char *)&toc->items[i] > (((char *)toc) + da_size - sizeof(const struct toc_item))) {
|
||||
SOLIDIGM_LOG_WARNING("Warning: Data Area %d, "
|
||||
"Table of Contents item %d "
|
||||
"crossed Data Area size.", da, i);
|
||||
if ((char *)&toc->items[i] >
|
||||
(((char *)toc) + da_size - sizeof(const struct toc_item))) {
|
||||
SOLIDIGM_LOG_WARNING(
|
||||
"Warning: Data Area %d, Table of Contents item %d crossed Data Area size.",
|
||||
da, i);
|
||||
return;
|
||||
}
|
||||
|
||||
obj_offset = toc->items[i].OffsetBytes;
|
||||
if ((obj_offset + sizeof(const struct telemetry_object_header)) > da_size) {
|
||||
SOLIDIGM_LOG_WARNING("Warning: Data Area %d, item %d "
|
||||
"data, crossed Data Area size.", da, i);
|
||||
SOLIDIGM_LOG_WARNING(
|
||||
"Warning: Data Area %d, item %d data, crossed Data Area size.", da, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -372,53 +406,67 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
|
|||
json_object_add_value_uint(toc_item, "objectId", header->Token);
|
||||
json_object_add_value_uint(toc_item, "mediaBankId", header->CoreId);
|
||||
|
||||
has_struct = solidigm_config_get_by_token_version(tl->configuration,
|
||||
header->Token,
|
||||
header->versionMajor,
|
||||
header->versionMinor,
|
||||
&structure_definition);
|
||||
has_struct = solidigm_config_get_struct_by_token_version(tl->configuration,
|
||||
header->Token,
|
||||
header->versionMajor,
|
||||
header->versionMinor,
|
||||
&structure_definition);
|
||||
if (!has_struct) {
|
||||
if (!nlog_formats)
|
||||
continue;
|
||||
nlog_name = solidigm_config_get_nlog_obj_name(tl->configuration,
|
||||
header->Token);
|
||||
if (!nlog_name)
|
||||
continue;
|
||||
}
|
||||
struct json_object *tele_obj_item = json_create_object();
|
||||
|
||||
json_object_array_add(tele_obj_array, tele_obj_item);
|
||||
json_object_get(toc_item);
|
||||
json_object_add_value_object(tele_obj_item, "metadata", toc_item);
|
||||
struct json_object *parsed_struct = json_create_object();
|
||||
|
||||
json_object_add_value_object(tele_obj_item, "objectData", parsed_struct);
|
||||
struct json_object *obj_hasTelemObjHdr = NULL;
|
||||
uint64_t object_file_offset;
|
||||
|
||||
if (json_object_object_get_ex(structure_definition,
|
||||
"hasTelemObjHdr",
|
||||
&obj_hasTelemObjHdr)) {
|
||||
bool hasHeader = json_object_get_boolean(obj_hasTelemObjHdr);
|
||||
|
||||
if (hasHeader)
|
||||
header_offset = 0;
|
||||
}
|
||||
object_file_offset = ((uint64_t)da_offset) + obj_offset + header_offset;
|
||||
if (has_struct) {
|
||||
struct json_object *tele_obj_item = json_create_object();
|
||||
|
||||
json_object_array_add(tele_obj_array, tele_obj_item);
|
||||
json_object_get(toc_item);
|
||||
json_object_add_value_object(tele_obj_item, "metadata", toc_item);
|
||||
struct json_object *parsed_struct = json_create_object();
|
||||
|
||||
json_object_add_value_object(tele_obj_item, "objectData", parsed_struct);
|
||||
struct json_object *obj_hasTelemObjHdr = NULL;
|
||||
uint32_t header_offset = sizeof(const struct telemetry_object_header);
|
||||
uint32_t file_offset;
|
||||
|
||||
if (json_object_object_get_ex(structure_definition,
|
||||
"hasTelemObjHdr",
|
||||
&obj_hasTelemObjHdr)) {
|
||||
bool hasHeader = json_object_get_boolean(obj_hasTelemObjHdr);
|
||||
|
||||
if (hasHeader)
|
||||
header_offset = 0;
|
||||
}
|
||||
|
||||
file_offset = da_offset + obj_offset + header_offset;
|
||||
telemetry_log_structure_parse(tl, structure_definition,
|
||||
BITS_IN_BYTE * file_offset,
|
||||
parsed_struct, toc_item);
|
||||
BITS_IN_BYTE * object_file_offset,
|
||||
parsed_struct, toc_item);
|
||||
} else if (nlog_formats) {
|
||||
json_object_object_add(toc_item, "objName",
|
||||
json_object_new_string(nlog_name));
|
||||
telemetry_log_nlog_parse(tl, nlog_formats, object_file_offset,
|
||||
toc->items[i].ContentSizeBytes - header_offset,
|
||||
parsed_struct, toc_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int solidigm_telemetry_log_data_areas_parse(const struct telemetry_log *tl,
|
||||
int solidigm_telemetry_log_data_areas_parse(struct telemetry_log *tl,
|
||||
enum nvme_telemetry_da last_da)
|
||||
{
|
||||
struct json_object *tele_obj_array = json_create_array();
|
||||
struct json_object *toc_array = json_create_array();
|
||||
|
||||
json_object_add_value_array(tl->root, "tableOfContents", toc_array);
|
||||
json_object_add_value_array(tl->root, "telemetryObjects", tele_obj_array);
|
||||
|
||||
for (enum nvme_telemetry_da da = NVME_TELEMETRY_DA_1; da <= last_da; da++)
|
||||
telemetry_log_data_area_toc_parse(tl, da, toc_array, tele_obj_array);
|
||||
solidigm_telemetry_log_header_parse(tl);
|
||||
solidigm_telemetry_log_cod_parse(tl);
|
||||
if (tl->configuration) {
|
||||
json_object_add_value_array(tl->root, "tableOfContents", toc_array);
|
||||
json_object_add_value_array(tl->root, "telemetryObjects", tele_obj_array);
|
||||
|
||||
for (enum nvme_telemetry_da da = NVME_TELEMETRY_DA_1; da <= last_da; da++)
|
||||
telemetry_log_data_area_toc_parse(tl, da, toc_array, tele_obj_array);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
*
|
||||
* Author: leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
#include "common.h"
|
||||
#include "telemetry-log.h"
|
||||
|
||||
int solidigm_telemetry_log_data_areas_parse(const struct telemetry_log *tl,
|
||||
int solidigm_telemetry_log_data_areas_parse(struct telemetry_log *tl,
|
||||
enum nvme_telemetry_da last_da);
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
#include "header.h"
|
||||
|
||||
#pragma pack(push, reason_indentifier, 1)
|
||||
struct reason_indentifier_1_0
|
||||
{
|
||||
struct reason_indentifier_1_0 {
|
||||
uint16_t versionMajor;
|
||||
uint16_t versionMinor;
|
||||
uint32_t reasonCode; //! 0 denotes no issue. All other values denote a potential issue.
|
||||
|
@ -24,8 +23,7 @@ static_assert(sizeof(const struct reason_indentifier_1_0) ==
|
|||
MEMBER_SIZE(struct nvme_telemetry_log, rsnident),
|
||||
"Size mismatch for reason_indentifier_1_0");
|
||||
|
||||
struct reason_indentifier_1_1
|
||||
{
|
||||
struct reason_indentifier_1_1 {
|
||||
uint16_t versionMajor;
|
||||
uint16_t versionMinor;
|
||||
uint32_t reasonCode; //! 0 denotes no issue. All other values denote a potential issue.
|
||||
|
@ -42,8 +40,7 @@ static_assert(sizeof(const struct reason_indentifier_1_1) ==
|
|||
MEMBER_SIZE(struct nvme_telemetry_log, rsnident),
|
||||
"Size mismatch for reason_indentifier_1_1");
|
||||
|
||||
struct reason_indentifier_1_2
|
||||
{
|
||||
struct reason_indentifier_1_2 {
|
||||
uint16_t versionMajor;
|
||||
uint16_t versionMinor;
|
||||
uint32_t reasonCode; //! 0 denotes no issue. All other values denote a potential issue.
|
||||
|
@ -69,14 +66,21 @@ static void telemetry_log_reason_id_parse1_0_ext(const struct telemetry_log *tl,
|
|||
struct json_object *reserved;
|
||||
|
||||
ri = (struct reason_indentifier_1_0 *) tl->log->rsnident;
|
||||
json_object_object_add(reason_id, "FirmwareVersion", json_object_new_string_len(ri->FirmwareVersion, sizeof(ri->FirmwareVersion)));
|
||||
json_object_object_add(reason_id, "BootloaderVersion", json_object_new_string_len(ri->BootloaderVersion, sizeof(ri->BootloaderVersion)));
|
||||
json_object_object_add(reason_id, "SerialNumber", json_object_new_string_len(ri->SerialNumber, sizeof(ri->SerialNumber)));
|
||||
json_object_object_add(reason_id, "firmwareVersion",
|
||||
json_object_new_string_len(ri->FirmwareVersion,
|
||||
sizeof(ri->FirmwareVersion)));
|
||||
json_object_object_add(reason_id, "bootloaderVersion",
|
||||
json_object_new_string_len(ri->BootloaderVersion,
|
||||
sizeof(ri->BootloaderVersion)));
|
||||
json_object_object_add(reason_id, "serialNumber",
|
||||
json_object_new_string_len(ri->SerialNumber,
|
||||
sizeof(ri->SerialNumber)));
|
||||
|
||||
reserved = json_create_array();
|
||||
json_object_add_value_array(reason_id, "Reserved", reserved);
|
||||
for ( int i=0; i < sizeof(ri->Reserved); i++) {
|
||||
json_object_add_value_array(reason_id, "reserved", reserved);
|
||||
for (int i = 0; i < sizeof(ri->Reserved); i++) {
|
||||
struct json_object *val = json_object_new_int(ri->Reserved[i]);
|
||||
|
||||
json_object_array_add(reserved, val);
|
||||
}
|
||||
}
|
||||
|
@ -88,17 +92,27 @@ static void telemetry_log_reason_id_parse1_1_ext(const struct telemetry_log *tl,
|
|||
struct json_object *reserved;
|
||||
|
||||
ri = (struct reason_indentifier_1_1 *) tl->log->rsnident;
|
||||
json_object_object_add(reason_id, "FirmwareVersion", json_object_new_string_len(ri->FirmwareVersion, sizeof(ri->FirmwareVersion)));
|
||||
json_object_object_add(reason_id, "BootloaderVersion", json_object_new_string_len(ri->BootloaderVersion, sizeof(ri->BootloaderVersion)));
|
||||
json_object_object_add(reason_id, "SerialNumber", json_object_new_string_len(ri->SerialNumber, sizeof(ri->SerialNumber)));
|
||||
json_object_add_value_uint64(reason_id, "OemDataMapOffset", le64_to_cpu(ri->OemDataMapOffset));
|
||||
json_object_add_value_uint(reason_id, "TelemetryMajorVersion", le16_to_cpu(ri->TelemetryMajorVersion));
|
||||
json_object_add_value_uint(reason_id, "TelemetryMinorVersion", le16_to_cpu(ri->TelemetryMinorVersion));
|
||||
json_object_object_add(reason_id, "firmwareVersion",
|
||||
json_object_new_string_len(ri->FirmwareVersion,
|
||||
sizeof(ri->FirmwareVersion)));
|
||||
json_object_object_add(reason_id, "bootloaderVersion",
|
||||
json_object_new_string_len(ri->BootloaderVersion,
|
||||
sizeof(ri->BootloaderVersion)));
|
||||
json_object_object_add(reason_id, "serialNumber",
|
||||
json_object_new_string_len(ri->SerialNumber,
|
||||
sizeof(ri->SerialNumber)));
|
||||
json_object_add_value_uint64(reason_id, "oemDataMapOffset",
|
||||
le64_to_cpu(ri->OemDataMapOffset));
|
||||
json_object_add_value_uint(reason_id, "telemetryMajorVersion",
|
||||
le16_to_cpu(ri->TelemetryMajorVersion));
|
||||
json_object_add_value_uint(reason_id, "telemetryMinorVersion",
|
||||
le16_to_cpu(ri->TelemetryMinorVersion));
|
||||
|
||||
reserved = json_create_array();
|
||||
json_object_add_value_array(reason_id, "Reserved", reserved);
|
||||
json_object_add_value_array(reason_id, "reserved", reserved);
|
||||
for (int i = 0; i < sizeof(ri->Reserved); i++) {
|
||||
struct json_object *val = json_object_new_int(ri->Reserved[i]);
|
||||
|
||||
json_object_array_add(reserved, val);
|
||||
}
|
||||
}
|
||||
|
@ -112,23 +126,30 @@ static void telemetry_log_reason_id_parse1_2_ext(const struct telemetry_log *tl,
|
|||
|
||||
ri = (struct reason_indentifier_1_2 *) tl->log->rsnident;
|
||||
|
||||
json_object_object_add(reason_id, "SerialNumber", json_object_new_string_len(ri->SerialNumber, sizeof(ri->SerialNumber)));
|
||||
json_object_add_value_uint64(reason_id, "OemDataMapOffset", le64_to_cpu(ri->OemDataMapOffset));
|
||||
json_object_add_value_uint(reason_id, "TelemetryMajorVersion", le16_to_cpu(ri->TelemetryMajorVersion));
|
||||
json_object_add_value_uint(reason_id, "TelemetryMinorVersion", le16_to_cpu(ri->TelemetryMinorVersion));
|
||||
json_object_add_value_uint(reason_id, "ProductFamilyId", ri->ProductFamilyId);
|
||||
json_object_object_add(reason_id, "serialNumber",
|
||||
json_object_new_string_len(ri->SerialNumber,
|
||||
sizeof(ri->SerialNumber)));
|
||||
json_object_add_value_uint64(reason_id, "oemDataMapOffset",
|
||||
le64_to_cpu(ri->OemDataMapOffset));
|
||||
json_object_add_value_uint(reason_id, "telemetryMajorVersion",
|
||||
le16_to_cpu(ri->TelemetryMajorVersion));
|
||||
json_object_add_value_uint(reason_id, "telemetryMinorVersion",
|
||||
le16_to_cpu(ri->TelemetryMinorVersion));
|
||||
json_object_add_value_uint(reason_id, "productFamilyId", ri->ProductFamilyId);
|
||||
|
||||
reserved = json_create_array();
|
||||
json_object_add_value_array(reason_id, "Reserved2", reserved);
|
||||
json_object_add_value_array(reason_id, "reserved2", reserved);
|
||||
for (int i = 0; i < sizeof(ri->Reserved2); i++) {
|
||||
struct json_object *val = json_object_new_int(ri->Reserved2[i]);
|
||||
|
||||
json_object_array_add(reserved, val);
|
||||
}
|
||||
|
||||
dp_reserved = json_create_array();
|
||||
json_object_add_value_array(reason_id, "DualPortReserved", dp_reserved);
|
||||
json_object_add_value_array(reason_id, "dualPortReserved", dp_reserved);
|
||||
for (int i = 0; i < sizeof(ri->DualPortReserved); i++) {
|
||||
struct json_object *val = json_object_new_int(ri->DualPortReserved[i]);
|
||||
|
||||
json_object_array_add(dp_reserved, val);
|
||||
}
|
||||
}
|
||||
|
@ -137,23 +158,26 @@ static void solidigm_telemetry_log_reason_id_parse(const struct telemetry_log *t
|
|||
{
|
||||
const struct reason_indentifier_1_0 *ri1_0 =
|
||||
(struct reason_indentifier_1_0 *) tl->log->rsnident;
|
||||
__u16 version_major = le16_to_cpu(ri1_0->versionMajor);
|
||||
__u16 version_minor = le16_to_cpu(ri1_0->versionMinor);
|
||||
uint16_t version_major = le16_to_cpu(ri1_0->versionMajor);
|
||||
uint16_t version_minor = le16_to_cpu(ri1_0->versionMinor);
|
||||
|
||||
json_object_add_value_uint(reason_id, "versionMajor", version_major);
|
||||
json_object_add_value_uint(reason_id, "versionMinor", version_minor);
|
||||
json_object_add_value_uint(reason_id, "reasonCode", le32_to_cpu(ri1_0->reasonCode));
|
||||
json_object_add_value_object(reason_id, "DriveStatus", json_object_new_string_len(ri1_0->DriveStatus, sizeof(ri1_0->DriveStatus)));
|
||||
json_object_add_value_object(reason_id, "driveStatus",
|
||||
json_object_new_string_len(ri1_0->DriveStatus,
|
||||
sizeof(ri1_0->DriveStatus)));
|
||||
if (version_major == 1) {
|
||||
switch (version_minor) {
|
||||
case 0:
|
||||
telemetry_log_reason_id_parse1_0_ext(tl, reason_id);
|
||||
break;
|
||||
case 1:
|
||||
telemetry_log_reason_id_parse1_1_ext(tl, reason_id);
|
||||
break;
|
||||
default:
|
||||
telemetry_log_reason_id_parse1_2_ext(tl, reason_id);
|
||||
case 0:
|
||||
telemetry_log_reason_id_parse1_0_ext(tl, reason_id);
|
||||
break;
|
||||
case 1:
|
||||
telemetry_log_reason_id_parse1_1_ext(tl, reason_id);
|
||||
break;
|
||||
default:
|
||||
telemetry_log_reason_id_parse1_2_ext(tl, reason_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,4 +3,5 @@ sources += [
|
|||
'plugins/solidigm/solidigm-telemetry/header.c',
|
||||
'plugins/solidigm/solidigm-telemetry/config.c',
|
||||
'plugins/solidigm/solidigm-telemetry/data-area.c',
|
||||
'plugins/solidigm/solidigm-telemetry/nlog.c',
|
||||
]
|
||||
|
|
130
plugins/solidigm/solidigm-telemetry/nlog.c
Normal file
130
plugins/solidigm/solidigm-telemetry/nlog.c
Normal file
|
@ -0,0 +1,130 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright (c) 2023 Solidigm.
|
||||
*
|
||||
* Author: leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
|
||||
#include "nlog.h"
|
||||
#include "config.h"
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define LOG_ENTRY_HEADER_SIZE 1
|
||||
#define LOG_ENTRY_TIMESTAMP_SIZE 2
|
||||
#define LOG_ENTRY_NUM_ARGS_MAX 8
|
||||
#define LOG_ENTRY_MAX_SIZE (LOG_ENTRY_HEADER_SIZE + LOG_ENTRY_TIMESTAMP_SIZE + \
|
||||
LOG_ENTRY_NUM_ARGS_MAX)
|
||||
#define NUM_ARGS_MASK ((1 << ((int)log2(LOG_ENTRY_NUM_ARGS_MAX)+1)) - 1)
|
||||
#define MAX_HEADER_MISMATCH_TRACK 10
|
||||
|
||||
static int formats_find(struct json_object *formats, uint32_t val, struct json_object **format)
|
||||
{
|
||||
char hex_header[STR_HEX32_SIZE];
|
||||
|
||||
snprintf(hex_header, STR_HEX32_SIZE, "0x%08X", val);
|
||||
return json_object_object_get_ex(formats, hex_header, format);
|
||||
}
|
||||
|
||||
static uint32_t nlog_get_pos(const uint32_t *nlog, const uint32_t nlog_size, int pos)
|
||||
{
|
||||
return nlog[pos % nlog_size];
|
||||
}
|
||||
|
||||
static uint32_t nlog_get_events(const uint32_t *nlog, const uint32_t nlog_size, int start_offset,
|
||||
struct json_object *formats, struct json_object *events, uint32_t *tail_mismatches)
|
||||
{
|
||||
uint32_t event_count = 0;
|
||||
int last_bad_header_pos = nlog_size + 1; // invalid nlog offset
|
||||
uint32_t tail_count = 0;
|
||||
|
||||
for (int i = nlog_size - start_offset - 1; i >= -start_offset; i--) {
|
||||
struct json_object *format;
|
||||
uint32_t header = nlog_get_pos(nlog, nlog_size, i);
|
||||
uint32_t num_data;
|
||||
|
||||
if (header == 0 || !formats_find(formats, header, &format)) {
|
||||
if (event_count > 0) {
|
||||
//check if fould circular buffer tail
|
||||
if (i != (last_bad_header_pos - 1)) {
|
||||
if (tail_mismatches &&
|
||||
(tail_count < MAX_HEADER_MISMATCH_TRACK))
|
||||
tail_mismatches[tail_count] = header;
|
||||
tail_count++;
|
||||
}
|
||||
last_bad_header_pos = i;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
num_data = header & NUM_ARGS_MASK;
|
||||
if (events) {
|
||||
struct json_object *event = json_object_new_array();
|
||||
struct json_object *param = json_object_new_array();
|
||||
uint32_t val = nlog_get_pos(nlog, nlog_size, i - 1);
|
||||
|
||||
json_object_array_add(events, event);
|
||||
json_object_array_add(event, json_object_new_int64(val));
|
||||
val = nlog_get_pos(nlog, nlog_size, i - 2);
|
||||
json_object_array_add(event, json_object_new_int64(val));
|
||||
json_object_array_add(event, json_object_new_int64(header));
|
||||
json_object_array_add(event, param);
|
||||
for (uint32_t j = 0; j < num_data; j++) {
|
||||
val = nlog_get_pos(nlog, nlog_size, i - 3 - j);
|
||||
json_object_array_add(param, json_object_new_int64(val));
|
||||
}
|
||||
json_object_get(format);
|
||||
json_object_array_add(event, format);
|
||||
}
|
||||
i -= 2 + num_data;
|
||||
event_count++;
|
||||
}
|
||||
return tail_count;
|
||||
}
|
||||
|
||||
int solidigm_nlog_parse(const char *buffer, uint64_t buff_size, struct json_object *formats,
|
||||
struct json_object *metadata, struct json_object *output)
|
||||
{
|
||||
uint32_t smaller_tail_count = UINT32_MAX;
|
||||
int best_offset = 0;
|
||||
uint32_t offset_tail_mismatches[LOG_ENTRY_MAX_SIZE][MAX_HEADER_MISMATCH_TRACK];
|
||||
struct json_object *events = json_object_new_array();
|
||||
const uint32_t *nlog = (uint32_t *)buffer;
|
||||
const uint32_t nlog_size = buff_size / sizeof(uint32_t);
|
||||
|
||||
for (int i = 0; i < LOG_ENTRY_MAX_SIZE; i++) {
|
||||
uint32_t tail_count = nlog_get_events(nlog, nlog_size, i, formats, NULL,
|
||||
offset_tail_mismatches[i]);
|
||||
if (tail_count < smaller_tail_count) {
|
||||
best_offset = i;
|
||||
smaller_tail_count = tail_count;
|
||||
}
|
||||
if (tail_count == 0)
|
||||
break;
|
||||
}
|
||||
if (smaller_tail_count > 1) {
|
||||
const char *name = "";
|
||||
int media_bank = -1;
|
||||
char str_mismatches[(STR_HEX32_SIZE + 1) * MAX_HEADER_MISMATCH_TRACK];
|
||||
int pos = 0;
|
||||
int show_mismatch_num = smaller_tail_count < MAX_HEADER_MISMATCH_TRACK ?
|
||||
smaller_tail_count : MAX_HEADER_MISMATCH_TRACK;
|
||||
struct json_object *jobj;
|
||||
|
||||
if (json_object_object_get_ex(metadata, "objName", &jobj))
|
||||
name = json_object_get_string(jobj);
|
||||
if (json_object_object_get_ex(metadata, "mediaBankId", &jobj))
|
||||
media_bank = json_object_get_int(jobj);
|
||||
|
||||
for (int i = 0; i < show_mismatch_num; i++)
|
||||
pos += snprintf(&str_mismatches[pos], STR_HEX32_SIZE + 1, "0x%08X ",
|
||||
offset_tail_mismatches[best_offset][i]);
|
||||
|
||||
SOLIDIGM_LOG_WARNING("%s:%d with %d header mismatches ( %s). Configuration file may be missing format headers.",
|
||||
name, media_bank, smaller_tail_count, str_mismatches);
|
||||
}
|
||||
nlog_get_events(nlog, nlog_size, best_offset, formats, events, NULL);
|
||||
|
||||
json_object_object_add(output, "events", events);
|
||||
return 0;
|
||||
}
|
11
plugins/solidigm/solidigm-telemetry/nlog.h
Normal file
11
plugins/solidigm/solidigm-telemetry/nlog.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright (c) 2023 Solidigm.
|
||||
*
|
||||
* Author: leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
#include "telemetry-log.h"
|
||||
|
||||
int solidigm_nlog_parse(const char *buffer, uint64_t bufer_size,
|
||||
struct json_object *formats, struct json_object *metadata,
|
||||
struct json_object *output);
|
|
@ -21,37 +21,37 @@ static const __u32 OP_SCT_STATUS = 0xE0;
|
|||
static const __u32 OP_SCT_COMMAND_TRANSFER = 0xE0;
|
||||
static const __u32 OP_SCT_DATA_TRANSFER = 0xE1;
|
||||
|
||||
static const __u32 DW10_SCT_STATUS_COMMAND = 0x0;
|
||||
static const __u32 DW10_SCT_STATUS_COMMAND;
|
||||
static const __u32 DW10_SCT_COMMAND_TRANSFER = 0x1;
|
||||
|
||||
static const __u32 DW11_SCT_STATUS_COMMAND = 0x0;
|
||||
static const __u32 DW11_SCT_COMMAND_TRANSFER = 0x0;
|
||||
static const __u32 DW11_SCT_STATUS_COMMAND;
|
||||
static const __u32 DW11_SCT_COMMAND_TRANSFER;
|
||||
|
||||
static const __u16 INTERNAL_LOG_ACTION_CODE = 0xFFFB;
|
||||
static const __u16 CURRENT_LOG_FUNCTION_CODE = 0x0001;
|
||||
static const __u16 SAVED_LOG_FUNCTION_CODE = 0x0002;
|
||||
|
||||
/* A bitmask field for supported devices */
|
||||
typedef enum {
|
||||
MASK_0 = 1 << 0,
|
||||
MASK_1 = 1 << 1,
|
||||
enum {
|
||||
MASK_0 = 1 << 0,
|
||||
MASK_1 = 1 << 1,
|
||||
/*
|
||||
* Future devices can use the remaining 31 bits from this field
|
||||
* and should use 1 << 2, 1 << 3, etc.
|
||||
*/
|
||||
MASK_IGNORE = 0
|
||||
} DeviceMask;
|
||||
};
|
||||
|
||||
/* Internal device codes */
|
||||
typedef enum {
|
||||
enum {
|
||||
CODE_0 = 0x0D,
|
||||
CODE_1 = 0x10
|
||||
} DeviceCode;
|
||||
};
|
||||
|
||||
|
||||
static int nvme_sct_op(int fd, __u32 opcode, __u32 cdw10, __u32 cdw11, void* data, __u32 data_len )
|
||||
static int nvme_sct_op(int fd, __u32 opcode, __u32 cdw10, __u32 cdw11, void *data, __u32 data_len)
|
||||
{
|
||||
void *metadata = NULL;
|
||||
void *metadata = NULL;
|
||||
const __u32 cdw2 = 0;
|
||||
const __u32 cdw3 = 0;
|
||||
const __u32 cdw12 = 0;
|
||||
|
@ -63,26 +63,23 @@ static int nvme_sct_op(int fd, __u32 opcode, __u32 cdw10, __u32 cdw11, void* da
|
|||
const __u32 namespace_id = 0x0;
|
||||
const __u32 flags = 0;
|
||||
const __u32 rsvd = 0;
|
||||
int err = 0;
|
||||
|
||||
__u32 result;
|
||||
err = nvme_admin_passthru(fd, opcode, flags, rsvd,
|
||||
namespace_id, cdw2, cdw3, cdw10,
|
||||
cdw11, cdw12, cdw13, cdw14, cdw15,
|
||||
data_len, data, metadata_len, metadata,
|
||||
timeout, &result);
|
||||
return err;
|
||||
|
||||
return nvme_admin_passthru(fd, opcode, flags, rsvd, namespace_id, cdw2, cdw3, cdw10, cdw11,
|
||||
cdw12, cdw13, cdw14, cdw15, data_len, data, metadata_len,
|
||||
metadata, timeout, &result);
|
||||
}
|
||||
|
||||
static int nvme_get_sct_status(int fd, __u32 device_mask)
|
||||
{
|
||||
int err;
|
||||
void* data = NULL;
|
||||
void *data = NULL;
|
||||
size_t data_len = 512;
|
||||
unsigned char *status;
|
||||
__u32 supported = 0;
|
||||
|
||||
if (posix_memalign(&data, getpagesize(), data_len))
|
||||
return ENOMEM;
|
||||
return -ENOMEM;
|
||||
|
||||
memset(data, 0, data_len);
|
||||
err = nvme_sct_op(fd, OP_SCT_STATUS, DW10_SCT_STATUS_COMMAND, DW11_SCT_STATUS_COMMAND, data, data_len);
|
||||
|
@ -102,22 +99,19 @@ static int nvme_get_sct_status(int fd, __u32 device_mask)
|
|||
|
||||
/* Check if device is supported */
|
||||
if (device_mask != MASK_IGNORE) {
|
||||
__u32 supported = 0;
|
||||
switch (status[1]) {
|
||||
case CODE_0:
|
||||
supported = (device_mask & MASK_0);
|
||||
break;
|
||||
|
||||
case CODE_1:
|
||||
supported = (device_mask & MASK_1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
if (0 == supported) {
|
||||
fprintf(stderr, "%s: command unsupported on this device: (0x%x)\n",__func__, status[1]);
|
||||
if (!supported) {
|
||||
fprintf(stderr, "%s: command unsupported on this device: (0x%x)\n", __func__, status[1]);
|
||||
err = -1;
|
||||
errno = EINVAL;
|
||||
goto end;
|
||||
|
@ -142,7 +136,7 @@ static int nvme_sct_command_transfer_log(int fd, bool current)
|
|||
function_code = SAVED_LOG_FUNCTION_CODE;
|
||||
|
||||
if (posix_memalign(&data, getpagesize(), data_len))
|
||||
return ENOMEM;
|
||||
return -ENOMEM;
|
||||
|
||||
memset(data, 0, data_len);
|
||||
memcpy(data, &action_code, sizeof(action_code));
|
||||
|
@ -153,7 +147,7 @@ static int nvme_sct_command_transfer_log(int fd, bool current)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int nvme_sct_data_transfer(int fd, void* data, size_t data_len, size_t offset)
|
||||
static int nvme_sct_data_transfer(int fd, void *data, size_t data_len, size_t offset)
|
||||
{
|
||||
__u32 dw10, dw11, lba_count = (data_len) / 512;
|
||||
|
||||
|
@ -170,7 +164,7 @@ static int nvme_sct_data_transfer(int fd, void* data, size_t data_len, size_t of
|
|||
return nvme_sct_op(fd, OP_SCT_DATA_TRANSFER, dw10, dw11, data, data_len);
|
||||
}
|
||||
|
||||
static int d_raw_to_fd(const unsigned char *buf, unsigned len, int fd)
|
||||
static int d_raw_to_fd(const unsigned char *buf, unsigned int len, int fd)
|
||||
{
|
||||
int written = 0;
|
||||
int remaining = len;
|
||||
|
@ -207,26 +201,26 @@ static void progress_runner(float progress)
|
|||
fprintf(stdout, " ");
|
||||
}
|
||||
|
||||
fprintf(stdout, "] %d %%\r",(int)(progress * 100.0));
|
||||
fprintf(stdout, "] %d %%\r", (int)(progress * 100.0));
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static int nvme_get_internal_log(int fd, const char* const filename, bool current)
|
||||
static int nvme_get_internal_log(int fd, const char *const filename, bool current)
|
||||
{
|
||||
int err;
|
||||
int o_fd = -1;
|
||||
void* page_data = NULL;
|
||||
void *page_data = NULL;
|
||||
const size_t page_sector_len = 32;
|
||||
const size_t page_data_len = page_sector_len * 512; /* 32 sectors per page */
|
||||
uint32_t* area1_last_page;
|
||||
uint32_t* area2_last_page;
|
||||
uint32_t* area3_last_page;
|
||||
uint32_t *area1_last_page;
|
||||
uint32_t *area2_last_page;
|
||||
uint32_t *area3_last_page;
|
||||
uint32_t log_sectors = 0;
|
||||
size_t pages;
|
||||
|
||||
__u32 pages_chunk;
|
||||
/*
|
||||
* By trial and error it seems that the largest transfer chunk size
|
||||
* is 128 * 32 = 4k sectors = 2MB
|
||||
* is 128 * 32 = 4k sectors = 2MB
|
||||
*/
|
||||
const __u32 max_pages = 128;
|
||||
size_t i;
|
||||
|
@ -248,7 +242,7 @@ static int nvme_get_internal_log(int fd, const char* const filename, bool curren
|
|||
/* Read the header to get the last log page - offsets 8->11, 12->15, 16->19 */
|
||||
err = nvme_sct_data_transfer(fd, page_data, page_data_len, 0);
|
||||
if (err) {
|
||||
fprintf(stderr, "%s: SCT data transfer failed, page 0\n",__func__);
|
||||
fprintf(stderr, "%s: SCT data transfer failed, page 0\n", __func__);
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
@ -274,7 +268,7 @@ static int nvme_get_internal_log(int fd, const char* const filename, bool curren
|
|||
o_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if (o_fd < 0) {
|
||||
fprintf(stderr, "%s: couldn't output file %s\n", __func__, filename);
|
||||
err = EINVAL;
|
||||
err = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
err = d_raw_to_fd(page_data, page_data_len, o_fd);
|
||||
|
@ -286,7 +280,7 @@ static int nvme_get_internal_log(int fd, const char* const filename, bool curren
|
|||
|
||||
/* Now read the rest */
|
||||
for (i = 1; i < pages;) {
|
||||
__u32 pages_chunk = max_pages;
|
||||
pages_chunk = max_pages;
|
||||
if (pages_chunk + i >= pages)
|
||||
pages_chunk = pages - i;
|
||||
|
||||
|
@ -318,23 +312,21 @@ static int nvme_get_internal_log(int fd, const char* const filename, bool curren
|
|||
}
|
||||
progress = 1.0f;
|
||||
progress_runner(progress);
|
||||
fprintf(stdout,"\n");
|
||||
fprintf(stdout, "\n");
|
||||
err = nvme_get_sct_status(fd, MASK_IGNORE);
|
||||
if (err) {
|
||||
fprintf(stderr, "%s: bad SCT status\n", __func__);
|
||||
goto end;
|
||||
}
|
||||
end:
|
||||
if (o_fd >= 0) {
|
||||
if (o_fd >= 0)
|
||||
close(o_fd);
|
||||
}
|
||||
if (page_data) {
|
||||
if (page_data)
|
||||
free(page_data);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nvme_get_internal_log_file(int fd, const char* const filename, bool current)
|
||||
static int nvme_get_internal_log_file(int fd, const char *const filename, bool current)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -366,20 +358,20 @@ static void default_show_vendor_log_c0(struct nvme_dev *dev, __u32 nsid,
|
|||
{
|
||||
printf("Vendor Log Page Directory 0xC0 for NVME device:%s namespace-id:%x\n",
|
||||
dev->name, nsid);
|
||||
printf("Error Log : %u \n", smart->items[ERROR_LOG_C0]);
|
||||
printf("SMART Health Log : %u \n", smart->items[SMART_HEALTH_LOG_C0]);
|
||||
printf("Firmware Slot Info : %u \n", smart->items[FIRMWARE_SLOT_INFO_C0]);
|
||||
printf("Command Effects : %u \n", smart->items[COMMAND_EFFECTS_C0]);
|
||||
printf("Device Self Test : %u \n", smart->items[DEVICE_SELF_TEST_C0]);
|
||||
printf("Log Page Directory : %u \n", smart->items[LOG_PAGE_DIRECTORY_C0]);
|
||||
printf("SMART Attributes : %u \n", smart->items[SMART_ATTRIBUTES_C0]);
|
||||
printf("Error Log : %u\n", smart->items[ERROR_LOG_C0]);
|
||||
printf("SMART Health Log : %u\n", smart->items[SMART_HEALTH_LOG_C0]);
|
||||
printf("Firmware Slot Info : %u\n", smart->items[FIRMWARE_SLOT_INFO_C0]);
|
||||
printf("Command Effects : %u\n", smart->items[COMMAND_EFFECTS_C0]);
|
||||
printf("Device Self Test : %u\n", smart->items[DEVICE_SELF_TEST_C0]);
|
||||
printf("Log Page Directory : %u\n", smart->items[LOG_PAGE_DIRECTORY_C0]);
|
||||
printf("SMART Attributes : %u\n", smart->items[SMART_ATTRIBUTES_C0]);
|
||||
}
|
||||
|
||||
static int nvme_get_vendor_log(struct nvme_dev *dev, __u32 namespace_id,
|
||||
int log_page, const char* const filename)
|
||||
int log_page, const char *const filename)
|
||||
{
|
||||
int err;
|
||||
void* log = NULL;
|
||||
void *log = NULL;
|
||||
size_t log_len = 512;
|
||||
|
||||
if (posix_memalign(&log, getpagesize(), log_len)) {
|
||||
|
@ -389,9 +381,8 @@ static int nvme_get_vendor_log(struct nvme_dev *dev, __u32 namespace_id,
|
|||
|
||||
/* Check device supported */
|
||||
err = nvme_get_sct_status(dev_fd(dev), MASK_0 | MASK_1);
|
||||
if (err) {
|
||||
if (err)
|
||||
goto end;
|
||||
}
|
||||
err = nvme_get_nsid_log(dev_fd(dev), false, log_page, namespace_id,
|
||||
log_len, log);
|
||||
if (err) {
|
||||
|
@ -405,7 +396,7 @@ static int nvme_get_vendor_log(struct nvme_dev *dev, __u32 namespace_id,
|
|||
if (o_fd < 0) {
|
||||
fprintf(stderr, "%s: couldn't output file %s\n",
|
||||
__func__, filename);
|
||||
err = EINVAL;
|
||||
err = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
err = d_raw_to_fd(log, log_len, o_fd);
|
||||
|
@ -422,12 +413,11 @@ static int nvme_get_vendor_log(struct nvme_dev *dev, __u32 namespace_id,
|
|||
if (log_page == 0xc0)
|
||||
default_show_vendor_log_c0(dev, namespace_id, log);
|
||||
else
|
||||
d(log, log_len,16,1);
|
||||
d(log, log_len, 16, 1);
|
||||
}
|
||||
end:
|
||||
if (log) {
|
||||
if (log)
|
||||
free(log);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -442,7 +432,7 @@ static int vendor_log(int argc, char **argv, struct command *cmd, struct plugin
|
|||
|
||||
struct config {
|
||||
__u32 namespace_id;
|
||||
const char* output_file;
|
||||
const char *output_file;
|
||||
int log;
|
||||
};
|
||||
|
||||
|
@ -461,13 +451,13 @@ static int vendor_log(int argc, char **argv, struct command *cmd, struct plugin
|
|||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err) {
|
||||
fprintf(stderr,"%s: failed to parse arguments\n", __func__);
|
||||
return EINVAL;
|
||||
fprintf(stderr, "%s: failed to parse arguments\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((cfg.log != 0xC0) && (cfg.log != 0xCA)) {
|
||||
fprintf(stderr, "%s: invalid log page 0x%x - should be 0xC0 or 0xCA\n", __func__, cfg.log);
|
||||
err = EINVAL;
|
||||
err = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
@ -491,7 +481,7 @@ static int internal_log(int argc, char **argv, struct command *cmd, struct plugi
|
|||
int err;
|
||||
|
||||
struct config {
|
||||
const char* output_file;
|
||||
const char *output_file;
|
||||
bool prev_log;
|
||||
};
|
||||
|
||||
|
@ -501,15 +491,15 @@ static int internal_log(int argc, char **argv, struct command *cmd, struct plugi
|
|||
};
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_FILE("output-file", 'o', &cfg.output_file, output_file),
|
||||
OPT_FILE("output-file", 'o', &cfg.output_file, output_file),
|
||||
OPT_FLAG("prev-log", 'p', &cfg.prev_log, prev_log),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err) {
|
||||
fprintf(stderr,"%s: failed to parse arguments\n", __func__);
|
||||
return EINVAL;
|
||||
fprintf(stderr, "%s: failed to parse arguments\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cfg.prev_log)
|
||||
|
@ -520,7 +510,7 @@ static int internal_log(int argc, char **argv, struct command *cmd, struct plugi
|
|||
err = nvme_get_internal_log_file(dev_fd(dev), cfg.output_file,
|
||||
!cfg.prev_log);
|
||||
if (err < 0)
|
||||
fprintf(stderr, "%s: couldn't get fw log \n", __func__);
|
||||
fprintf(stderr, "%s: couldn't get fw log\n", __func__);
|
||||
if (err > 0)
|
||||
nvme_show_status(err);
|
||||
|
||||
|
@ -547,8 +537,8 @@ static int clear_correctable_errors(int argc, char **argv, struct command *cmd,
|
|||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err) {
|
||||
fprintf(stderr,"%s: failed to parse arguments\n", __func__);
|
||||
return EINVAL;
|
||||
fprintf(stderr, "%s: failed to parse arguments\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check device supported */
|
||||
|
@ -573,7 +563,7 @@ static int clear_correctable_errors(int argc, char **argv, struct command *cmd,
|
|||
};
|
||||
err = nvme_set_features(&args);
|
||||
if (err)
|
||||
fprintf(stderr, "%s: couldn't clear PCIe correctable errors \n",
|
||||
fprintf(stderr, "%s: couldn't clear PCIe correctable errors\n",
|
||||
__func__);
|
||||
end:
|
||||
if (err > 0)
|
||||
|
|
|
@ -21,7 +21,7 @@ static int getHealthValue(int argc, char **argv, struct command *cmd, struct plu
|
|||
{
|
||||
struct nvme_smart_log smart_log;
|
||||
char *desc = "Get nvme health percentage.";
|
||||
int percent_used = 0, healthvalue=0;
|
||||
int percent_used = 0, healthvalue = 0;
|
||||
struct nvme_dev *dev;
|
||||
int result;
|
||||
|
||||
|
@ -31,59 +31,55 @@ static int getHealthValue(int argc, char **argv, struct command *cmd, struct plu
|
|||
|
||||
result = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (result) {
|
||||
printf("\nDevice not found \n");;
|
||||
printf("\nDevice not found\n");
|
||||
return -1;
|
||||
}
|
||||
result = nvme_get_log_smart(dev_fd(dev), 0xffffffff, false, &smart_log);
|
||||
if (!result) {
|
||||
printf("Transcend NVME heath value: ");
|
||||
percent_used =smart_log.percent_used;
|
||||
|
||||
if(percent_used>100 || percent_used<0)
|
||||
{
|
||||
percent_used = smart_log.percent_used;
|
||||
|
||||
if (percent_used > 100 || percent_used < 0) {
|
||||
printf("0%%\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
healthvalue = 100 - percent_used;
|
||||
printf("%d%%\n",healthvalue);
|
||||
printf("%d%%\n", healthvalue);
|
||||
}
|
||||
|
||||
}
|
||||
dev_close(dev);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int getBadblock(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
|
||||
char *desc = "Get nvme bad block number.";
|
||||
struct nvme_dev *dev;
|
||||
int result;
|
||||
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
result = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (result) {
|
||||
printf("\nDevice not found \n");;
|
||||
printf("\nDevice not found\n");
|
||||
return -1;
|
||||
}
|
||||
unsigned char data[1]={0};
|
||||
unsigned char data[1] = {0};
|
||||
struct nvme_passthru_cmd nvmecmd;
|
||||
memset(&nvmecmd,0,sizeof(nvmecmd));
|
||||
nvmecmd.opcode=OP_BAD_BLOCK;
|
||||
nvmecmd.cdw10=DW10_BAD_BLOCK;
|
||||
nvmecmd.cdw12=DW12_BAD_BLOCK;
|
||||
|
||||
memset(&nvmecmd, 0, sizeof(nvmecmd));
|
||||
nvmecmd.opcode = OP_BAD_BLOCK;
|
||||
nvmecmd.cdw10 = DW10_BAD_BLOCK;
|
||||
nvmecmd.cdw12 = DW12_BAD_BLOCK;
|
||||
nvmecmd.addr = (__u64)(uintptr_t)data;
|
||||
nvmecmd.data_len = 0x1;
|
||||
result = nvme_submit_admin_passthru(dev_fd(dev), &nvmecmd, NULL);
|
||||
if(!result) {
|
||||
if (!result) {
|
||||
int badblock = data[0];
|
||||
printf("Transcend NVME badblock count: %d\n",badblock);
|
||||
|
||||
printf("Transcend NVME badblock count: %d\n", badblock);
|
||||
}
|
||||
dev_close(dev);
|
||||
return result;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#define CREATE_CMD
|
||||
#include "virtium-nvme.h"
|
||||
|
||||
#define MIN2(a, b) ( ((a) < (b))? (a) : (b))
|
||||
#define MIN2(a, b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
#define HOUR_IN_SECONDS 3600
|
||||
|
||||
|
@ -30,26 +30,26 @@
|
|||
static char vt_default_log_file_name[256];
|
||||
|
||||
struct vtview_log_header {
|
||||
char path[256];
|
||||
char test_name[256];
|
||||
long int time_stamp;
|
||||
struct nvme_id_ctrl raw_ctrl;
|
||||
struct nvme_firmware_slot raw_fw;
|
||||
char path[256];
|
||||
char test_name[256];
|
||||
long time_stamp;
|
||||
struct nvme_id_ctrl raw_ctrl;
|
||||
struct nvme_firmware_slot raw_fw;
|
||||
};
|
||||
|
||||
struct vtview_smart_log_entry {
|
||||
char path[256];
|
||||
long int time_stamp;
|
||||
char path[256];
|
||||
long time_stamp;
|
||||
struct nvme_id_ns raw_ns;
|
||||
struct nvme_id_ctrl raw_ctrl;
|
||||
struct nvme_smart_log raw_smart;
|
||||
};
|
||||
|
||||
struct vtview_save_log_settings {
|
||||
double run_time_hrs;
|
||||
double log_record_frequency_hrs;
|
||||
const char* output_file;
|
||||
const char* test_name;
|
||||
double run_time_hrs;
|
||||
double log_record_frequency_hrs;
|
||||
const char *output_file;
|
||||
const char *test_name;
|
||||
};
|
||||
|
||||
static void vt_initialize_header_buffer(struct vtview_log_header *pbuff)
|
||||
|
@ -72,7 +72,7 @@ static void vt_convert_data_buffer_to_hex_string(const unsigned char *bufPtr,
|
|||
memset(output, 0, (size * 2) + 1);
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if(isReverted)
|
||||
if (isReverted)
|
||||
pos = size - 1 - i;
|
||||
else
|
||||
pos = i;
|
||||
|
@ -86,7 +86,7 @@ static void vt_convert_data_buffer_to_hex_string(const unsigned char *bufPtr,
|
|||
* Log file name will be generated automatically if user leave log file option blank.
|
||||
* Log file name will be generated as vtView-Smart-log-date-time.txt
|
||||
*/
|
||||
static void vt_generate_vtview_log_file_name(char* fname)
|
||||
static void vt_generate_vtview_log_file_name(char *fname)
|
||||
{
|
||||
time_t current;
|
||||
struct tm tstamp;
|
||||
|
@ -112,17 +112,19 @@ static void vt_convert_smart_data_to_human_readable_format(struct vtview_smart_l
|
|||
char *curlocale;
|
||||
char *templocale;
|
||||
__u8 lba_index;
|
||||
|
||||
nvme_id_ns_flbas_to_lbaf_inuse(smart->raw_ns.flbas, &lba_index);
|
||||
|
||||
curlocale = setlocale(LC_ALL, NULL);
|
||||
templocale = strdup(curlocale);
|
||||
|
||||
if (NULL == templocale)
|
||||
if (!templocale)
|
||||
printf("Cannot malloc buffer\n");
|
||||
|
||||
setlocale(LC_ALL, "C");
|
||||
|
||||
unsigned long long int lba = 1ULL << smart->raw_ns.lbaf[lba_index].ds;
|
||||
unsigned long long lba = 1ULL << smart->raw_ns.lbaf[lba_index].ds;
|
||||
|
||||
capacity = le64_to_cpu(smart->raw_ns.nsze) * lba;
|
||||
|
||||
snprintf(tempbuff, sizeof(tempbuff), "log;%s;%lu;%s;%s;%-.*s;", smart->raw_ctrl.sn, smart->time_stamp, smart->path,
|
||||
|
@ -167,7 +169,8 @@ static void vt_convert_smart_data_to_human_readable_format(struct vtview_smart_l
|
|||
|
||||
for (i = 0; i < 8; i++) {
|
||||
__s32 temp = le16_to_cpu(smart->raw_smart.temp_sensor[i]);
|
||||
if (0 == temp) {
|
||||
|
||||
if (!temp) {
|
||||
snprintf(tempbuff, sizeof(tempbuff), "Temperature_Sensor_%d;NC;", i);
|
||||
strcat(text, tempbuff);
|
||||
continue;
|
||||
|
@ -217,7 +220,7 @@ static int vt_append_text_file(const char *text, const char *filename)
|
|||
FILE *f;
|
||||
|
||||
f = fopen(filename, "a");
|
||||
if(NULL == f) {
|
||||
if (!f) {
|
||||
printf("Cannot open %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
@ -247,11 +250,11 @@ static void vt_process_string(char *str, const size_t size)
|
|||
{
|
||||
size_t i;
|
||||
|
||||
if (size == 0)
|
||||
if (!size)
|
||||
return;
|
||||
|
||||
i = size - 1;
|
||||
while ((0 != i) && (' ' == str[i])) {
|
||||
while (i && (' ' == str[i])) {
|
||||
str[i] = 0;
|
||||
i--;
|
||||
}
|
||||
|
@ -262,11 +265,11 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi
|
|||
struct vtview_smart_log_entry smart;
|
||||
const char *filename;
|
||||
int ret = 0;
|
||||
unsigned nsid = 0;
|
||||
unsigned int nsid = 0;
|
||||
|
||||
memset(smart.path, 0, sizeof(smart.path));
|
||||
strncpy(smart.path, path, sizeof(smart.path) - 1);
|
||||
if(NULL == cfg->output_file)
|
||||
if (!cfg->output_file)
|
||||
filename = vt_default_log_file_name;
|
||||
else
|
||||
filename = cfg->output_file;
|
||||
|
@ -301,7 +304,7 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi
|
|||
vt_process_string(smart.raw_ctrl.mn, sizeof(smart.raw_ctrl.mn));
|
||||
|
||||
ret = vt_append_log(&smart, filename);
|
||||
return (ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vt_update_vtview_log_header(const int fd, const char *path, const struct vtview_save_log_settings *cfg)
|
||||
|
@ -318,9 +321,9 @@ static int vt_update_vtview_log_header(const int fd, const char *path, const str
|
|||
}
|
||||
strcpy(header.path, path);
|
||||
|
||||
if (NULL == cfg->test_name)
|
||||
if (!cfg->test_name) {
|
||||
strcpy(header.test_name, DEFAULT_TEST_NAME);
|
||||
else {
|
||||
} else {
|
||||
if (strlen(cfg->test_name) > sizeof(header.test_name)) {
|
||||
printf("test name too long\n");
|
||||
errno = EINVAL;
|
||||
|
@ -329,7 +332,7 @@ static int vt_update_vtview_log_header(const int fd, const char *path, const str
|
|||
strcpy(header.test_name, cfg->test_name);
|
||||
}
|
||||
|
||||
if(NULL == cfg->output_file)
|
||||
if (!cfg->output_file)
|
||||
filename = vt_default_log_file_name;
|
||||
else
|
||||
filename = cfg->output_file;
|
||||
|
@ -353,7 +356,7 @@ static int vt_update_vtview_log_header(const int fd, const char *path, const str
|
|||
vt_process_string(header.raw_ctrl.mn, sizeof(header.raw_ctrl.mn));
|
||||
|
||||
ret = vt_append_header(&header, filename);
|
||||
return (ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void vt_build_identify_lv2(unsigned int data, unsigned int start,
|
||||
|
@ -371,13 +374,13 @@ static void vt_build_identify_lv2(unsigned int data, unsigned int start,
|
|||
printf(" \"bit %u\":\"%ub %s\"\n", i, temp, table[pos]);
|
||||
printf(" %s", table[pos + 1]);
|
||||
|
||||
if((end - 1) != i || !isEnd)
|
||||
if ((end - 1) != i || !isEnd)
|
||||
printf(",\n");
|
||||
else
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if(isEnd)
|
||||
if (isEnd)
|
||||
printf(" },\n");
|
||||
}
|
||||
|
||||
|
@ -418,7 +421,7 @@ static void vt_build_power_state_descriptor(const struct nvme_id_ctrl *ctrl)
|
|||
unsigned int temp;
|
||||
|
||||
printf("%6d", i);
|
||||
buf = (unsigned char*) (&ctrl->psd[i]);
|
||||
buf = (unsigned char *) (&ctrl->psd[i]);
|
||||
vt_convert_data_buffer_to_hex_string(&buf[0], 4, true, s);
|
||||
printf("%9sh", s);
|
||||
|
||||
|
@ -469,36 +472,35 @@ static void vt_build_power_state_descriptor(const struct nvme_id_ctrl *ctrl)
|
|||
|
||||
}
|
||||
|
||||
static void vt_dump_hex_data(const unsigned char *pbuff, size_t pbuffsize) {
|
||||
|
||||
static void vt_dump_hex_data(const unsigned char *pbuff, size_t pbuffsize)
|
||||
{
|
||||
char textbuf[33];
|
||||
unsigned long int i, j;
|
||||
unsigned long i, j;
|
||||
|
||||
textbuf[32] = '\0';
|
||||
printf("[%08X] ", 0);
|
||||
for (i = 0; i < pbuffsize; i++) {
|
||||
printf("%02X ", pbuff[i]);
|
||||
|
||||
if (pbuff[i] >= ' ' && pbuff[i] <= '~')
|
||||
if (pbuff[i] >= ' ' && pbuff[i] <= '~')
|
||||
textbuf[i % 32] = pbuff[i];
|
||||
else
|
||||
else
|
||||
textbuf[i % 32] = '.';
|
||||
|
||||
if ((((i + 1) % 8) == 0) || ((i + 1) == pbuffsize)) {
|
||||
if (!(((i + 1) % 8)) || ((i + 1) == pbuffsize)) {
|
||||
printf(" ");
|
||||
if ((i + 1) % 32 == 0) {
|
||||
if (!((i + 1) % 32)) {
|
||||
printf(" %s\n", textbuf);
|
||||
if((i + 1) != pbuffsize)
|
||||
printf("[%08lX] ", (i + 1));
|
||||
}
|
||||
else if (i + 1 == pbuffsize) {
|
||||
if ((i + 1) != pbuffsize)
|
||||
printf("[%08lX] ", (i + 1));
|
||||
} else if (i + 1 == pbuffsize) {
|
||||
textbuf[(i + 1) % 32] = '\0';
|
||||
if(((i + 1) % 8) == 0)
|
||||
if (!((i + 1) % 8))
|
||||
printf(" ");
|
||||
|
||||
for (j = ((i + 1) % 32); j < 32; j++) {
|
||||
printf(" ");
|
||||
if(((j + 1) % 8) == 0)
|
||||
if (!((j + 1) % 8))
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
|
@ -515,174 +517,174 @@ static void vt_parse_detail_identify(const struct nvme_id_ctrl *ctrl)
|
|||
char s[1024] = "";
|
||||
|
||||
const char *CMICtable[6] = {"0 = the NVM subsystem contains only a single NVM subsystem port",
|
||||
"1 = the NVM subsystem may contain more than one subsystem ports",
|
||||
"0 = the NVM subsystem contains only a single controller",
|
||||
"1 = the NVM subsystem may contain two or more controllers (see section 1.4.1)",
|
||||
"0 = the controller is associated with a PCI Function or a Fabrics connection",
|
||||
"1 = the controller is associated with an SR-IOV Virtual Function"};
|
||||
"1 = the NVM subsystem may contain more than one subsystem ports",
|
||||
"0 = the NVM subsystem contains only a single controller",
|
||||
"1 = the NVM subsystem may contain two or more controllers (see section 1.4.1)",
|
||||
"0 = the controller is associated with a PCI Function or a Fabrics connection",
|
||||
"1 = the controller is associated with an SR-IOV Virtual Function"};
|
||||
|
||||
const char *OAEStable[20] = {"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"0 = does not support sending the Namespace Attribute Notices event nor the associated Changed Namespace List log page",
|
||||
"1 = supports sending the Namespace Attribute Notices & the associated Changed Namespace List log page",
|
||||
"0 = does not support sending Firmware Activation Notices event",
|
||||
"1 = supports sending Firmware Activation Notices"};
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"0 = does not support sending the Namespace Attribute Notices event nor the associated Changed Namespace List log page",
|
||||
"1 = supports sending the Namespace Attribute Notices & the associated Changed Namespace List log page",
|
||||
"0 = does not support sending Firmware Activation Notices event",
|
||||
"1 = supports sending Firmware Activation Notices"};
|
||||
|
||||
const char *CTRATTtable[4] = {"0 = does not support a 128-bit Host Identifier",
|
||||
"1 = supports a 128-bit Host Identifier",
|
||||
"0 = does not support Non-Operational Power State Permissive Mode",
|
||||
"1 = supports Non-Operational Power State Permissive Mode"};
|
||||
"1 = supports a 128-bit Host Identifier",
|
||||
"0 = does not support Non-Operational Power State Permissive Mode",
|
||||
"1 = supports Non-Operational Power State Permissive Mode"};
|
||||
|
||||
const char *OACStable[18] = {"0 = does not support the Security Send and Security Receive commands",
|
||||
"1 = supports the Security Send and Security Receive commands",
|
||||
"0 = does not support the Format NVM command",
|
||||
"1 = supports the Format NVM command",
|
||||
"0 = does not support the Firmware Commit and Firmware Image Download commands",
|
||||
"1 = supports the Firmware Commit and Firmware Image Download commands",
|
||||
"0 = does not support the Namespace Management capability",
|
||||
"1 = supports the Namespace Management capability",
|
||||
"0 = does not support the Device Self-test command",
|
||||
"1 = supports the Device Self-test command",
|
||||
"0 = does not support Directives",
|
||||
"1 = supports Directive Send & Directive Receive commands",
|
||||
"0 = does not support the NVMe-MI Send and NVMe-MI Receive commands",
|
||||
"1 = supports the NVMe-MI Send and NVMe-MI Receive commands",
|
||||
"0 = does not support the Virtualization Management command",
|
||||
"1 = supports the Virtualization Management command",
|
||||
"0 = does not support the Doorbell Buffer Config command",
|
||||
"1 = supports the Doorbell Buffer Config command"};
|
||||
"1 = supports the Security Send and Security Receive commands",
|
||||
"0 = does not support the Format NVM command",
|
||||
"1 = supports the Format NVM command",
|
||||
"0 = does not support the Firmware Commit and Firmware Image Download commands",
|
||||
"1 = supports the Firmware Commit and Firmware Image Download commands",
|
||||
"0 = does not support the Namespace Management capability",
|
||||
"1 = supports the Namespace Management capability",
|
||||
"0 = does not support the Device Self-test command",
|
||||
"1 = supports the Device Self-test command",
|
||||
"0 = does not support Directives",
|
||||
"1 = supports Directive Send & Directive Receive commands",
|
||||
"0 = does not support the NVMe-MI Send and NVMe-MI Receive commands",
|
||||
"1 = supports the NVMe-MI Send and NVMe-MI Receive commands",
|
||||
"0 = does not support the Virtualization Management command",
|
||||
"1 = supports the Virtualization Management command",
|
||||
"0 = does not support the Doorbell Buffer Config command",
|
||||
"1 = supports the Doorbell Buffer Config command"};
|
||||
|
||||
const char *FRMWtable[10] = {"0 = the 1st firmware slot (slot 1) is read/write",
|
||||
"1 = the 1st firmware slot (slot 1) is read only",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"0 = requires a reset for firmware to be activated",
|
||||
"1 = supports firmware activation without a reset"};
|
||||
"1 = the 1st firmware slot (slot 1) is read only",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"0 = requires a reset for firmware to be activated",
|
||||
"1 = supports firmware activation without a reset"};
|
||||
|
||||
const char *LPAtable[8] = {"0 = does not support the SMART / Health information log page on a per namespace basis",
|
||||
"1 = supports the SMART / Health information log page on a per namespace basis",
|
||||
"0 = does not support the Commands Supported & Effects log page",
|
||||
"1 = supports the Commands Supported Effects log page",
|
||||
"0 = does not support extended data for Get Log Page",
|
||||
"1 = supports extended data for Get Log Page (including extended Number of Dwords and Log Page Offset fields)",
|
||||
"0 = does not support the Telemetry Host-Initiated and Telemetry Controller-Initiated log pages and Telemetry Log Notices events",
|
||||
"1 = supports the Telemetry Host-Initiated and Telemetry Controller-Initiated log pages and sending Telemetry Log Notices" };
|
||||
"1 = supports the SMART / Health information log page on a per namespace basis",
|
||||
"0 = does not support the Commands Supported & Effects log page",
|
||||
"1 = supports the Commands Supported Effects log page",
|
||||
"0 = does not support extended data for Get Log Page",
|
||||
"1 = supports extended data for Get Log Page (including extended Number of Dwords and Log Page Offset fields)",
|
||||
"0 = does not support the Telemetry Host-Initiated and Telemetry Controller-Initiated log pages and Telemetry Log Notices events",
|
||||
"1 = supports the Telemetry Host-Initiated and Telemetry Controller-Initiated log pages and sending Telemetry Log Notices"};
|
||||
|
||||
const char *AVSCCtable[2] = {"0 = the format of all Admin Vendor Specific Commands are vendor specific",
|
||||
"1 = all Admin Vendor Specific Commands use the format defined in NVM Express specification"};
|
||||
"1 = all Admin Vendor Specific Commands use the format defined in NVM Express specification"};
|
||||
|
||||
const char *APSTAtable[2] = {"0 = does not support autonomous power state transitions",
|
||||
"1 = supports autonomous power state transitions"};
|
||||
"1 = supports autonomous power state transitions"};
|
||||
|
||||
const char *DSTOtable[2] = {"0 = the NVM subsystem supports one device self-test operation per controller at a time",
|
||||
"1 = the NVM subsystem supports only one device self-test operation in progress at a time"};
|
||||
"1 = the NVM subsystem supports only one device self-test operation in progress at a time"};
|
||||
|
||||
const char *HCTMAtable[2] = {"0 = does not support host controlled thermal management",
|
||||
"1 = supports host controlled thermal management. Supports Set Features & Get Features commands with the Feature Identifier field set to 10h"};
|
||||
"1 = supports host controlled thermal management. Supports Set Features & Get Features commands with the Feature Identifier field set to 10h"};
|
||||
|
||||
const char *SANICAPtable[6] = {"0 = does not support the Crypto Erase sanitize operation",
|
||||
"1 = supports the Crypto Erase sanitize operation",
|
||||
"0 = does not support the Block Erase sanitize operation",
|
||||
"1 = supports the Block Erase sanitize operation",
|
||||
"0 = does not support the Overwrite sanitize operation",
|
||||
"1 = supports the Overwrite sanitize operation"};
|
||||
"1 = supports the Crypto Erase sanitize operation",
|
||||
"0 = does not support the Block Erase sanitize operation",
|
||||
"1 = supports the Block Erase sanitize operation",
|
||||
"0 = does not support the Overwrite sanitize operation",
|
||||
"1 = supports the Overwrite sanitize operation"};
|
||||
|
||||
const char *ONCStable[14] = {"0 = does not support the Compare command",
|
||||
"1 = supports the Compare command",
|
||||
"0 = does not support the Write Uncorrectable command",
|
||||
"1 = supports the Write Uncorrectable command",
|
||||
"0 = does not support the Dataset Management command",
|
||||
"1 = supports the Dataset Management command",
|
||||
"0 = does not support the Write Zeroes command",
|
||||
"1 = supports the Write Zeroes command",
|
||||
"0 = does not support the Save field set to a non-zero value in the Set Features and the Get Features commands",
|
||||
"1 = supports the Save field set to a non-zero value in the Set Features and the Get Features commands", \
|
||||
"0 = does not support reservations",
|
||||
"1 = supports reservations",
|
||||
"0 = does not support the Timestamp feature (refer to section 5.21.1.14)",
|
||||
"1 = supports the Timestamp feature"};
|
||||
"1 = supports the Compare command",
|
||||
"0 = does not support the Write Uncorrectable command",
|
||||
"1 = supports the Write Uncorrectable command",
|
||||
"0 = does not support the Dataset Management command",
|
||||
"1 = supports the Dataset Management command",
|
||||
"0 = does not support the Write Zeroes command",
|
||||
"1 = supports the Write Zeroes command",
|
||||
"0 = does not support the Save field set to a non-zero value in the Set Features and the Get Features commands",
|
||||
"1 = supports the Save field set to a non-zero value in the Set Features and the Get Features commands",
|
||||
"0 = does not support reservations",
|
||||
"1 = supports reservations",
|
||||
"0 = does not support the Timestamp feature (refer to section 5.21.1.14)",
|
||||
"1 = supports the Timestamp feature"};
|
||||
|
||||
const char *FUSEStable[2] = {"0 = does not support the Compare and Write fused operation",
|
||||
"1 = supports the Compare and Write fused operation"};
|
||||
"1 = supports the Compare and Write fused operation"};
|
||||
|
||||
const char *FNAtable[6] = {"0 = supports format on a per namespace basis",
|
||||
"1 = all namespaces shall be configured with the same attributes and a format (excluding secure erase) of any namespace results in a format of all namespaces in an NVM subsystem",
|
||||
"0 = any secure erase performed as part of a format results in a secure erase of a particular namespace specified",
|
||||
"1 = any secure erase performed as part of a format operation results in a secure erase of all namespaces in the NVM subsystem",
|
||||
"0 = cryptographic erase is not supported",
|
||||
"1 = cryptographic erase is supported as part of the secure erase functionality"};
|
||||
"1 = all namespaces shall be configured with the same attributes and a format (excluding secure erase) of any namespace results in a format of all namespaces in an NVM subsystem",
|
||||
"0 = any secure erase performed as part of a format results in a secure erase of a particular namespace specified",
|
||||
"1 = any secure erase performed as part of a format operation results in a secure erase of all namespaces in the NVM subsystem",
|
||||
"0 = cryptographic erase is not supported",
|
||||
"1 = cryptographic erase is supported as part of the secure erase functionality"};
|
||||
|
||||
const char *VWCtable[2] = {"0 = a volatile write cache is not present",
|
||||
"1 = a volatile write cache is present"};
|
||||
"1 = a volatile write cache is present"};
|
||||
|
||||
const char *ICSVSCCtable[2] = {"0 = the format of all NVM Vendor Specific Commands are vendor specific",
|
||||
"1 = all NVM Vendor Specific Commands use the format defined in NVM Express specification"};
|
||||
"1 = all NVM Vendor Specific Commands use the format defined in NVM Express specification"};
|
||||
|
||||
const char *SGLSSubtable[4] = {"00b = SGLs are not supported",
|
||||
"01b = SGLs are supported. There is no alignment nor granularity requirement for Data Blocks",
|
||||
"10b = SGLs are supported. There is a Dword alignment and granularity requirement for Data Blocks",
|
||||
"11b = Reserved"};
|
||||
"01b = SGLs are supported. There is no alignment nor granularity requirement for Data Blocks",
|
||||
"10b = SGLs are supported. There is a Dword alignment and granularity requirement for Data Blocks",
|
||||
"11b = Reserved"};
|
||||
|
||||
const char *SGLStable[42] = {"Used",
|
||||
"Used",
|
||||
"Used",
|
||||
"Used",
|
||||
"0 = does not support the Keyed SGL Data Block descriptor",
|
||||
"1 = supports the Keyed SGL Data Block descriptor",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"0 = the SGL Bit Bucket descriptor is not supported",
|
||||
"1 = the SGL Bit Bucket descriptor is supported",
|
||||
"0 = use of a byte aligned contiguous physical buffer of metadata is not supported",
|
||||
"1 = use of a byte aligned contiguous physical buffer of metadata is supported",
|
||||
"0 = the SGL length shall be equal to the amount of data to be transferred",
|
||||
"1 = supports commands that contain a data or metadata SGL of a length larger than the amount of data to be transferred",
|
||||
"0 = use of Metadata Pointer (MPTR) that contains an address of an SGL segment containing exactly one SGL Descriptor that is Qword aligned is not supported",
|
||||
"1 = use of Metadata Pointer (MPTR) that contains an address of an SGL segment containing exactly one SGL Descriptor that is Qword aligned is supported",
|
||||
"0 = the Address field specifying an offset is not supported",
|
||||
"1 = supports the Address field in SGL Data Block, SGL Segment, and SGL Last Segment descriptor types specifying an offset"};
|
||||
"Used",
|
||||
"Used",
|
||||
"Used",
|
||||
"0 = does not support the Keyed SGL Data Block descriptor",
|
||||
"1 = supports the Keyed SGL Data Block descriptor",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"0 = the SGL Bit Bucket descriptor is not supported",
|
||||
"1 = the SGL Bit Bucket descriptor is supported",
|
||||
"0 = use of a byte aligned contiguous physical buffer of metadata is not supported",
|
||||
"1 = use of a byte aligned contiguous physical buffer of metadata is supported",
|
||||
"0 = the SGL length shall be equal to the amount of data to be transferred",
|
||||
"1 = supports commands that contain a data or metadata SGL of a length larger than the amount of data to be transferred",
|
||||
"0 = use of Metadata Pointer (MPTR) that contains an address of an SGL segment containing exactly one SGL Descriptor that is Qword aligned is not supported",
|
||||
"1 = use of Metadata Pointer (MPTR) that contains an address of an SGL segment containing exactly one SGL Descriptor that is Qword aligned is supported",
|
||||
"0 = the Address field specifying an offset is not supported",
|
||||
"1 = supports the Address field in SGL Data Block, SGL Segment, and SGL Last Segment descriptor types specifying an offset"};
|
||||
|
||||
buf = (unsigned char *)(ctrl);
|
||||
|
||||
|
@ -791,12 +793,12 @@ static void vt_parse_detail_identify(const struct nvme_id_ctrl *ctrl)
|
|||
vt_convert_data_buffer_to_hex_string(&buf[296], 16, true, s);
|
||||
printf(" \"Unallocated NVM Capacity\":\"%sh\",\n", s);
|
||||
|
||||
temp = le32_to_cpu(ctrl->rpmbs);
|
||||
temp = le32_to_cpu(ctrl->rpmbs);
|
||||
printf(" \"Replay Protected Memory Block Support\":{\n");
|
||||
vt_convert_data_buffer_to_hex_string(&buf[312], 4, true, s);
|
||||
printf(" \"Value\":\"%sh\",\n", s);
|
||||
printf(" \"Number of RPMB Units\":\"%u\",\n", (temp & 0x00000003));
|
||||
snprintf(s, sizeof(s), ((temp >> 3) & 0x00000007)? "Reserved" : "HMAC SHA-256");
|
||||
snprintf(s, sizeof(s), ((temp >> 3) & 0x00000007) ? "Reserved" : "HMAC SHA-256");
|
||||
printf(" \"Authentication Method\":\"%u: %s\",\n", ((temp >> 3) & 0x00000007), s);
|
||||
printf(" \"Total Size\":\"%u\",\n", ((temp >> 16) & 0x000000FF));
|
||||
printf(" \"Access Size\":\"%u\",\n", ((temp >> 24) & 0x000000FF));
|
||||
|
@ -917,18 +919,18 @@ static void vt_parse_detail_identify(const struct nvme_id_ctrl *ctrl)
|
|||
static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
int ret, err = 0;
|
||||
long int total_time = 0;
|
||||
long int freq_time = 0;
|
||||
long int cur_time = 0;
|
||||
long int remain_time = 0;
|
||||
long int start_time = 0;
|
||||
long int end_time = 0;
|
||||
long total_time = 0;
|
||||
long freq_time = 0;
|
||||
long cur_time = 0;
|
||||
long remain_time = 0;
|
||||
long start_time = 0;
|
||||
long end_time = 0;
|
||||
char path[256] = "";
|
||||
char *desc = "Save SMART data into log file with format that is easy to analyze (comma delimited). Maximum log file will be 4K.\n\n"
|
||||
"Typical usages:\n\n"
|
||||
"Temperature characterization: \n"
|
||||
"Temperature characterization:\n"
|
||||
"\tvirtium save-smart-to-vtview-log /dev/yourDevice --run-time=100 --record-frequency=0.25 --test-name=burn-in-at-(-40)\n\n"
|
||||
"Endurance testing : \n"
|
||||
"Endurance testing :\n"
|
||||
"\tvirtium save-smart-to-vtview-log /dev/yourDevice --run-time=100 --record-frequency=1 --test-name=Endurance-test-JEDEG-219-workload\n\n"
|
||||
"Just logging :\n"
|
||||
"\tvirtium save-smart-to-vtview-log /dev/yourDevice";
|
||||
|
@ -979,13 +981,13 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm
|
|||
if (ret) {
|
||||
err = EINVAL;
|
||||
dev_close(dev);
|
||||
return (err);
|
||||
return err;
|
||||
}
|
||||
|
||||
total_time = cfg.run_time_hrs * (float)HOUR_IN_SECONDS;
|
||||
freq_time = cfg.log_record_frequency_hrs * (float)HOUR_IN_SECONDS;
|
||||
|
||||
if(freq_time == 0)
|
||||
if (!freq_time)
|
||||
freq_time = 1;
|
||||
|
||||
start_time = time(NULL);
|
||||
|
@ -995,7 +997,7 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm
|
|||
|
||||
while (1) {
|
||||
cur_time = time(NULL);
|
||||
if(cur_time >= end_time)
|
||||
if (cur_time >= end_time)
|
||||
break;
|
||||
|
||||
ret = vt_add_entry_to_log(dev_fd(dev), path, &cfg);
|
||||
|
@ -1011,7 +1013,7 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm
|
|||
}
|
||||
|
||||
dev_close(dev);
|
||||
return (err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int vt_show_identify(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
|
@ -1037,7 +1039,7 @@ static int vt_show_identify(int argc, char **argv, struct command *cmd, struct p
|
|||
if (ret) {
|
||||
printf("Cannot read identify device\n");
|
||||
dev_close(dev);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
vt_process_string(ctrl.sn, sizeof(ctrl.sn));
|
||||
|
@ -1045,5 +1047,5 @@ static int vt_show_identify(int argc, char **argv, struct command *cmd, struct p
|
|||
vt_parse_detail_identify(&ctrl);
|
||||
|
||||
dev_close(dev);
|
||||
return (err);
|
||||
return err;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -38,7 +38,7 @@ int wdc_UtilsSnprintf(char *buffer, unsigned int sizeOfBuffer, const char *forma
|
|||
return res;
|
||||
}
|
||||
|
||||
void wdc_UtilsDeleteCharFromString(char* buffer, int buffSize, char charToRemove)
|
||||
void wdc_UtilsDeleteCharFromString(char *buffer, int buffSize, char charToRemove)
|
||||
{
|
||||
int i = 0;
|
||||
int count = 0;
|
||||
|
@ -62,7 +62,7 @@ int wdc_UtilsGetTime(PUtilsTimeInfo timeInfo)
|
|||
time_t currTime;
|
||||
struct tm currTimeInfo;
|
||||
|
||||
if(!timeInfo)
|
||||
if (!timeInfo)
|
||||
return WDC_STATUS_INVALID_PARAMETER;
|
||||
|
||||
tzset();
|
||||
|
@ -81,7 +81,7 @@ int wdc_UtilsGetTime(PUtilsTimeInfo timeInfo)
|
|||
#if defined(__GLIBC__) && !defined(__UCLIBC__) && !defined(__MUSL__)
|
||||
timeInfo->zone = -currTimeInfo.tm_gmtoff / 60;
|
||||
#else
|
||||
timeInfo->zone = -1 * (timezone / SECONDS_IN_MIN);
|
||||
timeInfo->zone = -1 * (timezone / SECONDS_IN_MIN);
|
||||
#endif
|
||||
|
||||
return WDC_STATUS_SUCCESS;
|
||||
|
@ -92,7 +92,7 @@ int wdc_UtilsCreateDir(char *path)
|
|||
int retStatus;
|
||||
int status = WDC_STATUS_SUCCESS;
|
||||
|
||||
if (!path )
|
||||
if (!path)
|
||||
return WDC_STATUS_INVALID_PARAMETER;
|
||||
|
||||
retStatus = mkdir(path, 0x999);
|
||||
|
@ -125,7 +125,7 @@ int wdc_WriteToFile(char *fileName, char *buffer, unsigned int bufferLen)
|
|||
status = WDC_STATUS_UNABLE_TO_WRITE_ALL_DATA;
|
||||
|
||||
end:
|
||||
if(file)
|
||||
if (file)
|
||||
fclose(file);
|
||||
return status;
|
||||
}
|
||||
|
@ -151,9 +151,7 @@ int wdc_UtilsStrCompare(char *pcSrc, char *pcDst)
|
|||
|
||||
void wdc_StrFormat(char *formatter, size_t fmt_sz, char *tofmt, size_t tofmtsz)
|
||||
{
|
||||
|
||||
fmt_sz = snprintf(formatter,fmt_sz, "%-*.*s",
|
||||
(int)tofmtsz, (int)tofmtsz, tofmt);
|
||||
fmt_sz = snprintf(formatter, fmt_sz, "%-*.*s", (int)tofmtsz, (int)tofmtsz, tofmt);
|
||||
/* trim() the obnoxious trailing white lines */
|
||||
while (fmt_sz) {
|
||||
if (formatter[fmt_sz - 1] != ' ' && formatter[fmt_sz - 1] != '\0') {
|
||||
|
|
|
@ -17,145 +17,145 @@
|
|||
|
||||
static void get_ymtc_smart_info(struct nvme_ymtc_smart_log *smart, int index, u8 *nm_val, u8 *raw_val)
|
||||
{
|
||||
memcpy(nm_val, smart->itemArr[index].nmVal, NM_SIZE);
|
||||
memcpy(raw_val, smart->itemArr[index].rawVal, RAW_SIZE);
|
||||
memcpy(nm_val, smart->itemArr[index].nmVal, NM_SIZE);
|
||||
memcpy(raw_val, smart->itemArr[index].rawVal, RAW_SIZE);
|
||||
}
|
||||
|
||||
static int show_ymtc_smart_log(struct nvme_dev *dev, __u32 nsid,
|
||||
struct nvme_ymtc_smart_log *smart)
|
||||
{
|
||||
struct nvme_id_ctrl ctrl;
|
||||
char fw_ver[10];
|
||||
int err = 0;
|
||||
struct nvme_id_ctrl ctrl;
|
||||
char fw_ver[10];
|
||||
int err = 0;
|
||||
|
||||
u8 *nm = malloc(NM_SIZE * sizeof(u8));
|
||||
u8 *raw = malloc(RAW_SIZE * sizeof(u8));
|
||||
u8 *nm = malloc(NM_SIZE * sizeof(u8));
|
||||
u8 *raw = malloc(RAW_SIZE * sizeof(u8));
|
||||
|
||||
if (!nm) {
|
||||
if (raw)
|
||||
free(raw);
|
||||
return -1;
|
||||
}
|
||||
if (!raw) {
|
||||
free(nm);
|
||||
return -1;
|
||||
}
|
||||
err = nvme_identify_ctrl(dev_fd(dev), &ctrl);
|
||||
if (err) {
|
||||
free(nm);
|
||||
free(raw);
|
||||
return err;
|
||||
}
|
||||
if (!nm) {
|
||||
if (raw)
|
||||
free(raw);
|
||||
return -1;
|
||||
}
|
||||
if (!raw) {
|
||||
free(nm);
|
||||
return -1;
|
||||
}
|
||||
err = nvme_identify_ctrl(dev_fd(dev), &ctrl);
|
||||
if (err) {
|
||||
free(nm);
|
||||
free(raw);
|
||||
return err;
|
||||
}
|
||||
|
||||
snprintf(fw_ver, sizeof(fw_ver), "%c.%c%c.%c%c%c%c",
|
||||
ctrl.fr[0], ctrl.fr[1], ctrl.fr[2], ctrl.fr[3],
|
||||
ctrl.fr[4], ctrl.fr[5], ctrl.fr[6]);
|
||||
snprintf(fw_ver, sizeof(fw_ver), "%c.%c%c.%c%c%c%c",
|
||||
ctrl.fr[0], ctrl.fr[1], ctrl.fr[2], ctrl.fr[3],
|
||||
ctrl.fr[4], ctrl.fr[5], ctrl.fr[6]);
|
||||
|
||||
/* Table Title */
|
||||
printf("Additional Smart Log for NVME device:%s namespace-id:%x\n",
|
||||
dev->name, nsid);
|
||||
/* Clumn Name*/
|
||||
printf("key normalized raw\n");
|
||||
/* 00 SI_VD_PROGRAM_FAIL */
|
||||
get_ymtc_smart_info(smart, SI_VD_PROGRAM_FAIL, nm, raw);
|
||||
printf("program_fail_count : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
|
||||
/* 01 SI_VD_ERASE_FAIL */
|
||||
get_ymtc_smart_info(smart, SI_VD_ERASE_FAIL, nm, raw);
|
||||
printf("erase_fail_count : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
|
||||
/* 02 SI_VD_WEARLEVELING_COUNT */
|
||||
get_ymtc_smart_info(smart, SI_VD_WEARLEVELING_COUNT, nm, raw);
|
||||
printf("wear_leveling : %3d%% min: %u, max: %u, avg: %u\n", *nm,
|
||||
*(uint16_t *)raw, *(uint16_t *)(raw+2), *(uint16_t *)(raw+4));
|
||||
/* 03 SI_VD_E2E_DECTECTION_COUNT */
|
||||
get_ymtc_smart_info(smart, SI_VD_E2E_DECTECTION_COUNT, nm, raw);
|
||||
printf("end_to_end_error_detection_count: %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
|
||||
/* 04 SI_VD_PCIE_CRC_ERR_COUNT */
|
||||
get_ymtc_smart_info(smart, SI_VD_PCIE_CRC_ERR_COUNT, nm, raw);
|
||||
printf("crc_error_count : %3d%% %"PRIu32"\n", *nm, *(uint32_t *)raw);
|
||||
/* 08 SI_VD_THERMAL_THROTTLE_STATUS */
|
||||
get_ymtc_smart_info(smart, SI_VD_THERMAL_THROTTLE_STATUS, nm, raw);
|
||||
printf("thermal_throttle_status : %3d%% %d%%, cnt: %"PRIu32"\n", *nm,
|
||||
*raw, *(uint32_t *)(raw+1));
|
||||
/* 11 SI_VD_TOTAL_WRITE */
|
||||
get_ymtc_smart_info(smart, SI_VD_TOTAL_WRITE, nm, raw);
|
||||
printf("nand_bytes_written : %3d%% sectors: %"PRIu64"\n", *nm, int48_to_long(raw));
|
||||
/* 12 SI_VD_HOST_WRITE */
|
||||
get_ymtc_smart_info(smart, SI_VD_HOST_WRITE, nm, raw);
|
||||
printf("host_bytes_written : %3d%% sectors: %"PRIu64"\n", *nm, int48_to_long(raw));
|
||||
/* 14 SI_VD_TOTAL_READ */
|
||||
get_ymtc_smart_info(smart, SI_VD_TOTAL_READ, nm, raw);
|
||||
printf("nand_bytes_read : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
|
||||
/* 15 SI_VD_TEMPT_SINCE_BORN */
|
||||
get_ymtc_smart_info(smart, SI_VD_TEMPT_SINCE_BORN, nm, raw);
|
||||
printf("tempt_since_born : %3d%% max: %u, min: %u, curr: %u\n", *nm,
|
||||
*(uint16_t *)raw-273, *(uint16_t *)(raw+2)-273, *(int16_t *)(raw+4)-273);
|
||||
/* 16 SI_VD_POWER_CONSUMPTION */
|
||||
get_ymtc_smart_info(smart, SI_VD_POWER_CONSUMPTION, nm, raw);
|
||||
printf("power_consumption : %3d%% max: %u, min: %u, curr: %u\n", *nm,
|
||||
*(uint16_t *)raw, *(uint16_t *)(raw+2), *(uint16_t *)(raw+4));
|
||||
/* 17 SI_VD_TEMPT_SINCE_BOOTUP */
|
||||
get_ymtc_smart_info(smart, SI_VD_TEMPT_SINCE_BOOTUP, nm, raw);
|
||||
printf("tempt_since_bootup : %3d%% max: %u, min: %u, curr: %u\n", *nm,
|
||||
*(uint16_t *)raw-273, *(uint16_t *)(raw+2)-273, *(uint16_t *)(raw+4)-273);
|
||||
/* 18 SI_VD_POWER_LOSS_PROTECTION */
|
||||
get_ymtc_smart_info(smart, SI_VD_POWER_LOSS_PROTECTION, nm, raw);
|
||||
printf("power_loss_protection : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
|
||||
/* 19 SI_VD_READ_FAIL */
|
||||
get_ymtc_smart_info(smart, SI_VD_READ_FAIL, nm, raw);
|
||||
printf("read_fail : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
|
||||
/* 20 SI_VD_THERMAL_THROTTLE_TIME */
|
||||
get_ymtc_smart_info(smart, SI_VD_THERMAL_THROTTLE_TIME, nm, raw);
|
||||
printf("thermal_throttle_time : %3d%% %u, time: %"PRIu32"\n", *nm,
|
||||
*raw, *(uint32_t *)(raw+1));
|
||||
/* 21 SI_VD_FLASH_MEDIA_ERROR */
|
||||
get_ymtc_smart_info(smart, SI_VD_FLASH_MEDIA_ERROR, nm, raw);
|
||||
printf("flash_error_media_count : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
|
||||
/* Table Title */
|
||||
printf("Additional Smart Log for NVME device:%s namespace-id:%x\n",
|
||||
dev->name, nsid);
|
||||
/* Clumn Name*/
|
||||
printf("key normalized raw\n");
|
||||
/* 00 SI_VD_PROGRAM_FAIL */
|
||||
get_ymtc_smart_info(smart, SI_VD_PROGRAM_FAIL, nm, raw);
|
||||
printf("program_fail_count : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
|
||||
/* 01 SI_VD_ERASE_FAIL */
|
||||
get_ymtc_smart_info(smart, SI_VD_ERASE_FAIL, nm, raw);
|
||||
printf("erase_fail_count : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
|
||||
/* 02 SI_VD_WEARLEVELING_COUNT */
|
||||
get_ymtc_smart_info(smart, SI_VD_WEARLEVELING_COUNT, nm, raw);
|
||||
printf("wear_leveling : %3d%% min: %u, max: %u, avg: %u\n", *nm,
|
||||
*(uint16_t *)raw, *(uint16_t *)(raw+2), *(uint16_t *)(raw+4));
|
||||
/* 03 SI_VD_E2E_DECTECTION_COUNT */
|
||||
get_ymtc_smart_info(smart, SI_VD_E2E_DECTECTION_COUNT, nm, raw);
|
||||
printf("end_to_end_error_detection_count: %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
|
||||
/* 04 SI_VD_PCIE_CRC_ERR_COUNT */
|
||||
get_ymtc_smart_info(smart, SI_VD_PCIE_CRC_ERR_COUNT, nm, raw);
|
||||
printf("crc_error_count : %3d%% %"PRIu32"\n", *nm, *(uint32_t *)raw);
|
||||
/* 08 SI_VD_THERMAL_THROTTLE_STATUS */
|
||||
get_ymtc_smart_info(smart, SI_VD_THERMAL_THROTTLE_STATUS, nm, raw);
|
||||
printf("thermal_throttle_status : %3d%% %d%%, cnt: %"PRIu32"\n", *nm,
|
||||
*raw, *(uint32_t *)(raw+1));
|
||||
/* 11 SI_VD_TOTAL_WRITE */
|
||||
get_ymtc_smart_info(smart, SI_VD_TOTAL_WRITE, nm, raw);
|
||||
printf("nand_bytes_written : %3d%% sectors: %"PRIu64"\n", *nm, int48_to_long(raw));
|
||||
/* 12 SI_VD_HOST_WRITE */
|
||||
get_ymtc_smart_info(smart, SI_VD_HOST_WRITE, nm, raw);
|
||||
printf("host_bytes_written : %3d%% sectors: %"PRIu64"\n", *nm, int48_to_long(raw));
|
||||
/* 14 SI_VD_TOTAL_READ */
|
||||
get_ymtc_smart_info(smart, SI_VD_TOTAL_READ, nm, raw);
|
||||
printf("nand_bytes_read : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
|
||||
/* 15 SI_VD_TEMPT_SINCE_BORN */
|
||||
get_ymtc_smart_info(smart, SI_VD_TEMPT_SINCE_BORN, nm, raw);
|
||||
printf("tempt_since_born : %3d%% max: %u, min: %u, curr: %u\n", *nm,
|
||||
*(uint16_t *)raw-273, *(uint16_t *)(raw+2)-273, *(int16_t *)(raw+4)-273);
|
||||
/* 16 SI_VD_POWER_CONSUMPTION */
|
||||
get_ymtc_smart_info(smart, SI_VD_POWER_CONSUMPTION, nm, raw);
|
||||
printf("power_consumption : %3d%% max: %u, min: %u, curr: %u\n", *nm,
|
||||
*(uint16_t *)raw, *(uint16_t *)(raw+2), *(uint16_t *)(raw+4));
|
||||
/* 17 SI_VD_TEMPT_SINCE_BOOTUP */
|
||||
get_ymtc_smart_info(smart, SI_VD_TEMPT_SINCE_BOOTUP, nm, raw);
|
||||
printf("tempt_since_bootup : %3d%% max: %u, min: %u, curr: %u\n", *nm,
|
||||
*(uint16_t *)raw-273, *(uint16_t *)(raw+2)-273, *(uint16_t *)(raw+4)-273);
|
||||
/* 18 SI_VD_POWER_LOSS_PROTECTION */
|
||||
get_ymtc_smart_info(smart, SI_VD_POWER_LOSS_PROTECTION, nm, raw);
|
||||
printf("power_loss_protection : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
|
||||
/* 19 SI_VD_READ_FAIL */
|
||||
get_ymtc_smart_info(smart, SI_VD_READ_FAIL, nm, raw);
|
||||
printf("read_fail : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
|
||||
/* 20 SI_VD_THERMAL_THROTTLE_TIME */
|
||||
get_ymtc_smart_info(smart, SI_VD_THERMAL_THROTTLE_TIME, nm, raw);
|
||||
printf("thermal_throttle_time : %3d%% %u, time: %"PRIu32"\n", *nm,
|
||||
*raw, *(uint32_t *)(raw+1));
|
||||
/* 21 SI_VD_FLASH_MEDIA_ERROR */
|
||||
get_ymtc_smart_info(smart, SI_VD_FLASH_MEDIA_ERROR, nm, raw);
|
||||
printf("flash_error_media_count : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
|
||||
|
||||
free(nm);
|
||||
free(raw);
|
||||
free(nm);
|
||||
free(raw);
|
||||
|
||||
return err;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
struct nvme_ymtc_smart_log smart_log;
|
||||
char *desc = "Get Ymtc vendor specific additional smart log (optionally, "\
|
||||
"for the specified namespace), and show it.";
|
||||
const char *namespace = "(optional) desired namespace";
|
||||
const char *raw = "dump output in binary format";
|
||||
struct nvme_dev *dev;
|
||||
struct config {
|
||||
__u32 namespace_id;
|
||||
bool raw_binary;
|
||||
};
|
||||
int err;
|
||||
struct nvme_ymtc_smart_log smart_log;
|
||||
char *desc =
|
||||
"Get Ymtc vendor specific additional smart log (optionally, for the specified namespace), and show it.";
|
||||
const char *namespace = "(optional) desired namespace";
|
||||
const char *raw = "dump output in binary format";
|
||||
struct nvme_dev *dev;
|
||||
struct config {
|
||||
__u32 namespace_id;
|
||||
bool raw_binary;
|
||||
};
|
||||
int err;
|
||||
|
||||
struct config cfg = {
|
||||
.namespace_id = NVME_NSID_ALL,
|
||||
};
|
||||
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_END()
|
||||
};
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace),
|
||||
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err)
|
||||
return err;
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = nvme_get_nsid_log(dev_fd(dev), false, 0xca, cfg.namespace_id,
|
||||
sizeof(smart_log), &smart_log);
|
||||
if (!err) {
|
||||
if (!cfg.raw_binary)
|
||||
err = show_ymtc_smart_log(dev, cfg.namespace_id, &smart_log);
|
||||
else
|
||||
d_raw((unsigned char *)&smart_log, sizeof(smart_log));
|
||||
}
|
||||
if (err > 0)
|
||||
nvme_show_status(err);
|
||||
err = nvme_get_nsid_log(dev_fd(dev), false, 0xca, cfg.namespace_id,
|
||||
sizeof(smart_log), &smart_log);
|
||||
if (!err) {
|
||||
if (!cfg.raw_binary)
|
||||
err = show_ymtc_smart_log(dev, cfg.namespace_id, &smart_log);
|
||||
else
|
||||
d_raw((unsigned char *)&smart_log, sizeof(smart_log));
|
||||
}
|
||||
if (err > 0)
|
||||
nvme_show_status(err);
|
||||
|
||||
dev_close(dev);
|
||||
return err;
|
||||
dev_close(dev);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -49,9 +49,8 @@ static int print_zns_list_ns(nvme_ns_t ns)
|
|||
return err;
|
||||
}
|
||||
|
||||
if (supported) {
|
||||
if (supported)
|
||||
nvme_show_list_item(ns);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -63,21 +62,17 @@ static int print_zns_list(nvme_root_t nvme_root)
|
|||
nvme_subsystem_t s;
|
||||
nvme_ctrl_t c;
|
||||
nvme_ns_t n;
|
||||
nvme_for_each_host(nvme_root, h)
|
||||
{
|
||||
nvme_for_each_subsystem(h, s)
|
||||
{
|
||||
nvme_subsystem_for_each_ns(s, n)
|
||||
{
|
||||
|
||||
nvme_for_each_host(nvme_root, h) {
|
||||
nvme_for_each_subsystem(h, s) {
|
||||
nvme_subsystem_for_each_ns(s, n) {
|
||||
err = print_zns_list_ns(n);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
nvme_subsystem_for_each_ctrl(s, c)
|
||||
{
|
||||
nvme_ctrl_for_each_ns(c, n)
|
||||
{
|
||||
nvme_subsystem_for_each_ctrl(s, c) {
|
||||
nvme_ctrl_for_each_ns(c, n) {
|
||||
err = print_zns_list_ns(n);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -114,9 +109,9 @@ static int list(int argc, char **argv, struct command *cmd,
|
|||
|
||||
static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "Send an ZNS specific Identify Controller command to "\
|
||||
"the given device and report information about the specified "\
|
||||
"controller in various formats.";
|
||||
const char *desc = "Send a ZNS specific Identify Controller command to\n"
|
||||
"the given device and report information about the specified\n"
|
||||
"controller in various formats.";
|
||||
|
||||
enum nvme_print_flags flags;
|
||||
struct nvme_zns_id_ctrl ctrl;
|
||||
|
@ -158,9 +153,9 @@ close_fd:
|
|||
|
||||
static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "Send an ZNS specific Identify Namespace command to "\
|
||||
"the given device and report information about the specified "\
|
||||
"namespace in varios formats.";
|
||||
const char *desc = "Send a ZNS specific Identify Namespace command to\n"
|
||||
"the given device and report information about the specified\n"
|
||||
"namespace in varios formats.";
|
||||
const char *vendor_specific = "dump binary vendor fields";
|
||||
const char *human_readable = "show identify in readable format";
|
||||
|
||||
|
@ -292,11 +287,11 @@ static int zns_mgmt_send(int argc, char **argv, struct command *cmd, struct plug
|
|||
printf("%s: Success, action:%d zone:%"PRIx64" all:%d zcapc:%u nsid:%d\n",
|
||||
command, zsa, (uint64_t)cfg.zslba, (int)cfg.select_all,
|
||||
zcapc, cfg.namespace_id);
|
||||
}
|
||||
else if (err > 0)
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
else
|
||||
} else {
|
||||
perror(desc);
|
||||
}
|
||||
free:
|
||||
free(command);
|
||||
close_dev:
|
||||
|
@ -337,8 +332,8 @@ static int get_zdes_bytes(int fd, __u32 nsid)
|
|||
static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "Zone Management Send";
|
||||
const char *zslba = "starting LBA of the zone for this command"\
|
||||
"(for flush action, last lba to flush)";
|
||||
const char *zslba =
|
||||
"starting LBA of the zone for this command(for flush action, last lba to flush)";
|
||||
const char *zsaso = "Zone Send Action Specific Option";
|
||||
const char *select_all = "send command to all zones";
|
||||
const char *zsa = "zone send action";
|
||||
|
@ -356,8 +351,8 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu
|
|||
bool zsaso;
|
||||
bool select_all;
|
||||
__u8 zsa;
|
||||
int data_len;
|
||||
char *file;
|
||||
int data_len;
|
||||
char *file;
|
||||
__u32 timeout;
|
||||
};
|
||||
|
||||
|
@ -394,13 +389,12 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu
|
|||
}
|
||||
|
||||
if (cfg.zsa == NVME_ZNS_ZSA_SET_DESC_EXT) {
|
||||
if(!cfg.data_len) {
|
||||
if (!cfg.data_len) {
|
||||
int data_len = get_zdes_bytes(dev_fd(dev),
|
||||
cfg.namespace_id);
|
||||
|
||||
if (data_len == 0) {
|
||||
fprintf(stderr,
|
||||
"Zone Descriptor Extensions are not supported\n");
|
||||
fprintf(stderr, "Zone Descriptor Extensions are not supported\n");
|
||||
goto close_dev;
|
||||
} else if (data_len < 0) {
|
||||
err = data_len;
|
||||
|
@ -429,8 +423,7 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu
|
|||
}
|
||||
} else {
|
||||
if (cfg.file || cfg.data_len) {
|
||||
fprintf(stderr,
|
||||
"data, data_len only valid with set extended descriptor\n");
|
||||
fprintf(stderr, "data, data_len only valid with set extended descriptor\n");
|
||||
err = -EINVAL;
|
||||
goto close_dev;
|
||||
}
|
||||
|
@ -451,10 +444,8 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu
|
|||
};
|
||||
err = nvme_zns_mgmt_send(&args);
|
||||
if (!err)
|
||||
printf("zone-mgmt-send: Success, action:%d zone:%"PRIx64" "
|
||||
"all:%d nsid:%d\n",
|
||||
cfg.zsa, (uint64_t)cfg.zslba, (int)cfg.select_all,
|
||||
cfg.namespace_id);
|
||||
printf("zone-mgmt-send: Success, action:%d zone:%"PRIx64" all:%d nsid:%d\n",
|
||||
cfg.zsa, (uint64_t)cfg.zslba, (int)cfg.select_all, cfg.namespace_id);
|
||||
else if (err > 0)
|
||||
nvme_show_status(err);
|
||||
else
|
||||
|
@ -542,7 +533,7 @@ static int open_zone(int argc, char **argv, struct command *cmd, struct plugin *
|
|||
err = nvme_zns_mgmt_send(&args);
|
||||
if (!err)
|
||||
printf("zns-open-zone: Success zone slba:%"PRIx64" nsid:%d\n",
|
||||
(uint64_t)cfg.zslba, cfg.namespace_id);
|
||||
(uint64_t)cfg.zslba, cfg.namespace_id);
|
||||
else
|
||||
nvme_show_status(err);
|
||||
close_dev:
|
||||
|
@ -656,7 +647,7 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug
|
|||
err = nvme_zns_mgmt_send(&args);
|
||||
if (!err)
|
||||
printf("set-zone-desc: Success, zone:%"PRIx64" nsid:%d\n",
|
||||
(uint64_t)cfg.zslba, cfg.namespace_id);
|
||||
(uint64_t)cfg.zslba, cfg.namespace_id);
|
||||
else if (err > 0)
|
||||
nvme_show_status(err);
|
||||
else
|
||||
|
@ -723,7 +714,7 @@ static int zrwa_flush_zone(int argc, char **argv, struct command *cmd, struct pl
|
|||
err = nvme_zns_mgmt_send(&args);
|
||||
if (!err)
|
||||
printf("zrwa-flush-zone: Success, lba:%"PRIx64" nsid:%d\n",
|
||||
(uint64_t)cfg.lba, cfg.namespace_id);
|
||||
(uint64_t)cfg.lba, cfg.namespace_id);
|
||||
else
|
||||
nvme_show_status(err);
|
||||
close_dev:
|
||||
|
@ -737,7 +728,7 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu
|
|||
const char *zslba = "starting LBA of the zone";
|
||||
const char *zra = "Zone Receive Action";
|
||||
const char *zrasf = "Zone Receive Action Specific Field(Reporting Options)";
|
||||
const char *partial = "Zone Receive Action Specific Features(Partial Report)";
|
||||
const char *partial = "Zone Receive Action Specific Features(Partial Report)";
|
||||
const char *data_len = "length of data in bytes";
|
||||
|
||||
enum nvme_print_flags flags;
|
||||
|
@ -816,7 +807,7 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu
|
|||
err = nvme_zns_mgmt_recv(&args);
|
||||
if (!err)
|
||||
printf("zone-mgmt-recv: Success, action:%d zone:%"PRIx64" nsid:%d\n",
|
||||
cfg.zra, (uint64_t)cfg.zslba, cfg.namespace_id);
|
||||
cfg.zra, (uint64_t)cfg.zslba, cfg.namespace_id);
|
||||
else if (err > 0)
|
||||
nvme_show_status(err);
|
||||
else
|
||||
|
@ -921,9 +912,8 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
|
|||
if (!err) {
|
||||
/* get zsze field from zns id ns data - needed for offset calculation */
|
||||
nvme_id_ns_flbas_to_lbaf_inuse(id_ns.flbas, &lbaf);
|
||||
zsze = le64_to_cpu(id_zns.lbafe[lbaf].zsze);
|
||||
}
|
||||
else {
|
||||
zsze = le64_to_cpu(id_zns.lbafe[lbaf].zsze);
|
||||
} else {
|
||||
nvme_show_status(err);
|
||||
goto close_dev;
|
||||
}
|
||||
|
@ -942,17 +932,15 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
|
|||
if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
goto free_buff;
|
||||
}
|
||||
else if (err < 0) {
|
||||
} else if (err < 0) {
|
||||
perror("zns report-zones");
|
||||
goto free_buff;
|
||||
}
|
||||
|
||||
total_nr_zones = le64_to_cpu(buff->nr_zones);
|
||||
|
||||
if (cfg.num_descs == -1) {
|
||||
if (cfg.num_descs == -1)
|
||||
cfg.num_descs = total_nr_zones;
|
||||
}
|
||||
|
||||
nr_zones = cfg.num_descs;
|
||||
if (nr_zones < nr_zones_chunks)
|
||||
|
@ -994,15 +982,20 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
|
|||
}
|
||||
|
||||
if (!err)
|
||||
nvme_show_zns_report_zones(report, nr_zones_chunks,
|
||||
zdes, log_len, flags, zone_list);
|
||||
nvme_show_zns_report_zones(report, nr_zones_chunks,
|
||||
zdes, log_len, zone_list, flags);
|
||||
|
||||
nr_zones_retrieved += nr_zones_chunks;
|
||||
offset = le64_to_cpu(report->entries[nr_zones_chunks-1].zslba) + zsze;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & JSON)
|
||||
json_nvme_finish_zone_list(total_nr_zones, zone_list);
|
||||
if (flags & JSON) {
|
||||
struct print_ops *ops;
|
||||
|
||||
ops = nvme_get_json_print_ops(flags);
|
||||
if (ops)
|
||||
ops->zns_finish_zone_list(total_nr_zones, zone_list);
|
||||
}
|
||||
|
||||
nvme_free(report, huge);
|
||||
|
||||
|
@ -1015,9 +1008,9 @@ close_dev:
|
|||
|
||||
static int zone_append(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "The zone append command is used to write to a zone "\
|
||||
"using the slba of the zone, and the write will be appended from the "\
|
||||
"write pointer of the zone";
|
||||
const char *desc = "The zone append command is used to write to a zone\n"
|
||||
"using the slba of the zone, and the write will be appended from the\n"
|
||||
"write pointer of the zone";
|
||||
const char *zslba = "starting LBA of the zone";
|
||||
const char *data = "file containing data to write";
|
||||
const char *metadata = "file with metadata to be written";
|
||||
|
@ -1116,7 +1109,7 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin
|
|||
|
||||
meta_size = ns.lbaf[lba_index].ms;
|
||||
if (meta_size && !(meta_size == 8 && (cfg.prinfo & 0x8)) &&
|
||||
(!cfg.metadata_size || cfg.metadata_size % meta_size)) {
|
||||
(!cfg.metadata_size || cfg.metadata_size % meta_size)) {
|
||||
fprintf(stderr,
|
||||
"Metadata size:%#"PRIx64" not aligned to metadata size:%#x\n",
|
||||
(uint64_t)cfg.metadata_size, meta_size);
|
||||
|
@ -1125,7 +1118,7 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin
|
|||
}
|
||||
|
||||
if (cfg.prinfo > 0xf) {
|
||||
fprintf(stderr, "Invalid value for prinfo:%#x\n", cfg.prinfo);
|
||||
fprintf(stderr, "Invalid value for prinfo:%#x\n", cfg.prinfo);
|
||||
errno = EINVAL;
|
||||
goto close_dev;
|
||||
}
|
||||
|
@ -1208,7 +1201,7 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin
|
|||
gettimeofday(&end_time, NULL);
|
||||
if (cfg.latency)
|
||||
printf(" latency: zone append: %llu us\n",
|
||||
elapsed_utime(start_time, end_time));
|
||||
elapsed_utime(start_time, end_time));
|
||||
|
||||
if (!err)
|
||||
printf("Success appended data to LBA %"PRIx64"\n", (uint64_t)result);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue