1
0
Fork 0

Adding upstream version 1.14.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-16 11:30:13 +01:00
parent ac60c09ef6
commit 2066c5b305
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
305 changed files with 20664 additions and 6099 deletions

View file

@ -3,6 +3,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include "linux/nvme_ioctl.h"
@ -19,9 +20,23 @@
#include "memblaze-utils.h"
enum {
MB_FEAT_POWER_MGMT = 0xc6,
// feature id
MB_FEAT_POWER_MGMT = 0x02,
MB_FEAT_HIGH_LATENCY = 0xE1,
// log id
GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM = 0xC1,
GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM = 0xC2,
GLP_ID_VU_GET_HIGH_LATENCY_LOG = 0xC3,
MB_FEAT_CLEAR_ERRORLOG = 0xF7,
};
#define LOG_PAGE_SIZE (0x1000)
#define DO_PRINT_FLAG (1)
#define NOT_PRINT_FLAG (0)
#define FID_C1_LOG_FILENAME "log_c1.csv"
#define FID_C2_LOG_FILENAME "log_c2.csv"
#define FID_C3_LOG_FILENAME "log_c3.csv"
/*
* Return -1 if @fw1 < @fw2
* Return 0 if @fw1 == @fw2
@ -53,18 +68,26 @@ static int compare_fw_version(const char *fw1, const char *fw2)
#define MEMBLAZE_FORMAT (0)
#define INTEL_FORMAT (1)
// 2.83 = raisin
#define IS_RAISIN(str) (!strcmp(str, "2.83"))
// 2.13 = papaya
#define IS_PAPAYA(str) (!strcmp(str, "2.13"))
#define STR_VER_SIZE 5
// 2.83 = raisin
#define IS_RAISIN(str) (!strcmp(str, "2.83"))
// 2.94 = kumquat
#define IS_KUMQUAT(str) (!strcmp(str, "2.94"))
// 0.60 = loquat
#define IS_LOQUAT(str) (!strcmp(str, "0.60"))
#define STR_VER_SIZE (5)
int getlogpage_format_type(char *fw_ver)
{
char fw_ver_local[STR_VER_SIZE];
strncpy(fw_ver_local, fw_ver, STR_VER_SIZE);
*(fw_ver_local + STR_VER_SIZE - 1) = '\0';
if ( IS_RAISIN(fw_ver_local) )
if ( IS_RAISIN(fw_ver_local)
|| IS_KUMQUAT(fw_ver_local)
|| IS_LOQUAT(fw_ver_local)
)
{
return INTEL_FORMAT;
}
@ -128,7 +151,7 @@ static __u64 raw_2_u64(const __u8 *buf, size_t len)
#define STR17_04 ", min: "
#define STR17_05 ", curr: "
#define STR18_01 "power_loss_protection"
#define STR19_01 "read_fail"
#define STR19_01 "read_fail_count"
#define STR20_01 "thermal_throttle_time"
#define STR21_01 "flash_media_error"
@ -380,7 +403,42 @@ static int show_memblaze_smart_log(int fd, __u32 nsid, const char *devname,
return err;
}
static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
int parse_params(char *str, int number, ...)
{
va_list argp;
int *param;
char *c;
int value;
va_start(argp, number);
while (number > 0) {
c = strtok(str, ",");
if ( c == NULL) {
printf("No enough parameters. abort...\n");
exit(EINVAL);
}
if (isalnum(*c) == 0) {
printf("%s is not a valid number\n", c);
return 1;
}
value = atoi(c);
param = va_arg(argp, int *);
*param = value;
if (str) {
str = strchr(str, ',');
if (str) { str++; }
}
number--;
}
va_end(argp);
return 0;
}
static int mb_get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
struct nvme_memblaze_smart_log smart_log;
int err, fd;
@ -408,7 +466,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
return fd;
err = nvme_get_log(fd, cfg.namespace_id, 0xca, false,
sizeof(smart_log), &smart_log);
NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log);
if (!err) {
if (!cfg.raw_binary)
err = show_memblaze_smart_log(fd, cfg.namespace_id, devicename, &smart_log);
@ -423,213 +481,262 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
static char *mb_feature_to_string(int feature)
{
switch (feature) {
case MB_FEAT_POWER_MGMT: return "Memblaze power management";
default: return "Unknown";
}
switch (feature) {
case MB_FEAT_POWER_MGMT: return "Memblaze power management";
case MB_FEAT_HIGH_LATENCY: return "Memblaze high latency log";
case MB_FEAT_CLEAR_ERRORLOG: return "Memblaze clear error log";
default: return "Unknown";
}
}
static int get_additional_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin)
static int mb_get_powermanager_status(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 "\
"behaviour 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"\
"0xc6: Memblaze power management\n"\
" (value 0 - 25w, 1 - 20w, 2 - 15w)";
const char *raw = "show feature in binary format";
const char *namespace_id = "identifier of desired namespace";
const char *feature_id = "hexadecimal feature name";
const char *sel = "[0-3]: curr./default/saved/supp.";
const char *data_len = "buffer len (if) data is returned";
const char *cdw11 = "dword 11 for interrupt vector config";
const char *human_readable = "show infos in readable format";
int err, fd;
__u32 result;
void *buf = NULL;
const char *desc = "Get Memblaze power management ststus\n (value 0 - 25w, 1 - 20w, 2 - 15w)";
int err, fd;
__u32 result;
__u32 feature_id = MB_FEAT_POWER_MGMT;
struct config {
__u32 namespace_id;
__u32 feature_id;
__u8 sel;
__u32 cdw11;
__u32 data_len;
int raw_binary;
int human_readable;
};
OPT_ARGS(opts) = {
OPT_END()
};
struct config cfg = {
.namespace_id = 1,
.feature_id = 0,
.sel = 0,
.cdw11 = 0,
.data_len = 0,
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) return fd;
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_UINT("cdw11", 'c', &cfg.cdw11, cdw11),
OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable),
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
return fd;
if (cfg.sel > 7) {
fprintf(stderr, "invalid 'select' param:%d\n", cfg.sel);
return EINVAL;
}
if (!cfg.feature_id) {
fprintf(stderr, "feature-id required param\n");
return EINVAL;
}
if (cfg.data_len) {
if (posix_memalign(&buf, getpagesize(), cfg.data_len))
exit(ENOMEM);
memset(buf, 0, cfg.data_len);
}
err = nvme_get_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.sel, cfg.cdw11,
cfg.data_len, buf, &result);
if (!err) {
printf("get-feature:0x%02x (%s), %s value: %#08x\n", cfg.feature_id,
mb_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);
}
}
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
if (buf)
free(buf);
return err;
err = nvme_get_feature(fd, 0, feature_id, 0, 0, 0, NULL, &result);
if (err < 0) {
perror("get-feature");
}
if (!err) {
printf("get-feature:0x%02x (%s), %s value: %#08x\n", feature_id,
mb_feature_to_string(feature_id),
nvme_select_to_string(0), result);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
return err;
}
static int set_additional_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin)
static int mb_set_powermanager_status(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"\
"0xc6: Memblaze power management\n"\
" (value 0 - 25w, 1 - 20w, 2 - 15w)";
const char *namespace_id = "desired namespace";
const char *feature_id = "hex feature name (required)";
const char *data_len = "buffer length if data required";
const char *data = "optional file for feature data (default stdin)";
const char *value = "new value of feature (required)";
const char *save = "specifies that the controller shall save the attribute";
int err, fd;
__u32 result;
void *buf = NULL;
int ffd = STDIN_FILENO;
const char *desc = "Set Memblaze power management status\n (value 0 - 25w, 1 - 20w, 2 - 15w)";
const char *value = "new value of feature (required)";
const char *save = "specifies that the controller shall save the attribute";
int err, fd;
__u32 result;
struct config {
char *file;
__u32 namespace_id;
__u32 feature_id;
__u32 value;
__u32 data_len;
int save;
};
struct config {
__u32 feature_id;
__u32 value;
int save;
};
struct config cfg = {
.file = "",
.namespace_id = 0,
.feature_id = 0,
.value = 0,
.data_len = 0,
.save = 0,
};
struct config cfg = {
.feature_id = MB_FEAT_POWER_MGMT,
.value = 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_END()
};
OPT_ARGS(opts) = {
OPT_UINT("value", 'v', &cfg.value, value),
OPT_FLAG("save", 's', &cfg.save, save),
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
return fd;
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) return fd;
if (!cfg.feature_id) {
fprintf(stderr, "feature-id required param\n");
return EINVAL;
}
err = nvme_set_feature(fd, 0, cfg.feature_id, cfg.value, 0, cfg.save, 0, NULL, &result);
if (err < 0) {
perror("set-feature");
}
if (!err) {
printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id,
mb_feature_to_string(cfg.feature_id), cfg.value);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
if (cfg.data_len) {
if (posix_memalign(&buf, getpagesize(), cfg.data_len))
exit(ENOMEM);
memset(buf, 0, cfg.data_len);
}
if (buf) {
if (strlen(cfg.file)) {
ffd = open(cfg.file, O_RDONLY);
if (ffd <= 0) {
fprintf(stderr, "no firmware file provided\n");
err = EINVAL;
goto free;
}
}
if (read(ffd, (void *)buf, cfg.data_len) < 0) {
fprintf(stderr, "failed to read data buffer from input file\n");
err = EINVAL;
goto free;
}
}
err = nvme_set_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.value,
0, cfg.save, cfg.data_len, buf, &result);
if (err < 0) {
perror("set-feature");
goto free;
}
if (!err) {
printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id,
mb_feature_to_string(cfg.feature_id), cfg.value);
if (buf)
d(buf, cfg.data_len, 16, 1);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
free:
if (buf)
free(buf);
return err;
return err;
}
#define P2MIN (1)
#define P2MAX (5000)
#define MB_FEAT_HIGH_LATENCY_VALUE_SHIFT (15)
static int mb_set_high_latency_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Set Memblaze high latency log\n"\
" input parameter p1,p2\n"\
" p1 value: 0 is disable, 1 is enable\n"\
" p2 value: 1 .. 5000 ms";
const char *param = "input parameters";
int err, fd;
__u32 result;
int param1 = 0, param2 = 0;
struct config {
__u32 feature_id;
char * param;
__u32 value;
};
struct config cfg = {
.feature_id = MB_FEAT_HIGH_LATENCY,
.param = "0,0",
.value = 0,
};
OPT_ARGS(opts) = {
OPT_LIST("param", 'p', &cfg.param, param),
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) return fd;
if (parse_params(cfg.param, 2, &param1, &param2)) {
printf("setfeature: invalid formats %s\n", cfg.param);
exit(EINVAL);
}
if ((param1 == 1) && (param2 < P2MIN || param2 > P2MAX)) {
printf("setfeature: invalid high io latency threshold %d\n", param2);
exit(EINVAL);
}
cfg.value = (param1 << MB_FEAT_HIGH_LATENCY_VALUE_SHIFT) | param2;
err = nvme_set_feature(fd, 0, cfg.feature_id, cfg.value, 0, 0, 0, NULL, &result);
if (err < 0) {
perror("set-feature");
}
if (!err) {
printf("set-feature:0x%02X (%s), value:%#08x\n", cfg.feature_id,
mb_feature_to_string(cfg.feature_id), cfg.value);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
return err;
}
static int glp_high_latency_show_bar(FILE *fdi, int print)
{
fPRINT_PARAM1("Memblaze High Latency Log\n");
fPRINT_PARAM1("---------------------------------------------------------------------------------------------\n");
fPRINT_PARAM1("Timestamp Type QID CID NSID StartLBA NumLBA Latency\n");
fPRINT_PARAM1("---------------------------------------------------------------------------------------------\n");
return 0;
}
/* High latency log page definiton
* Total 32 bytes
*/
typedef struct
{
__u8 port;
__u8 revision;
__u16 rsvd;
__u8 opcode;
__u8 sqe;
__u16 cid;
__u32 nsid;
__u32 latency;
__u64 sLBA;
__u16 numLBA;
__u16 timestampH;
__u32 timestampL;
} log_page_high_latency_t; /* total 32 bytes */
static int find_deadbeef(char *buf)
{
if (((*(buf + 0) & 0xff) == 0xef) && ((*(buf + 1) & 0xff) == 0xbe) && \
((*(buf + 2) & 0xff) == 0xad) && ((*(buf + 3) & 0xff) == 0xde))
{
return 1;
}
return 0;
}
#define TIME_STR_SIZE (44)
static int glp_high_latency(FILE *fdi, char *buf, int buflen, int print)
{
log_page_high_latency_t *logEntry;
char string[TIME_STR_SIZE];
int i, entrySize;
__u64 timestamp;
time_t tt = 0;
struct tm *t = NULL;
int millisec = 0;
if (find_deadbeef(buf)) return 0;
entrySize = sizeof(log_page_high_latency_t);
for (i = 0; i < buflen; i += entrySize)
{
logEntry = (log_page_high_latency_t *)(buf + i);
if (logEntry->latency == 0 && logEntry->revision == 0)
{
return 1;
}
if (0 == logEntry->timestampH) // generate host time string
{
snprintf(string, sizeof(string), "%d", logEntry->timestampL);
}
else // sort
{
timestamp = logEntry->timestampH - 1;
timestamp = timestamp << 32;
timestamp += logEntry->timestampL;
tt = timestamp / 1000;
millisec = timestamp % 1000;
t = gmtime(&tt);
snprintf(string, sizeof(string), "%4d%02d%02d--%02d:%02d:%02d.%03d UTC",
1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, millisec);
}
fprintf(fdi, "%-32s %-7x %-6x %-6x %-8x %4x%08x %-8x %-d\n",
string, logEntry->opcode, logEntry->sqe, logEntry->cid, logEntry->nsid,
(__u32)(logEntry->sLBA >> 32), (__u32)logEntry->sLBA, logEntry->numLBA, logEntry->latency);
if (print)
{
printf("%-32s %-7x %-6x %-6x %-8x %4x%08x %-8x %-d\n",
string, logEntry->opcode, logEntry->sqe, logEntry->cid, logEntry->nsid,
(__u32)(logEntry->sLBA >> 32), (__u32)logEntry->sLBA, logEntry->numLBA, logEntry->latency);
}
}
return 1;
}
static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Get Memblaze high latency log";
int err, fd;
char buf[LOG_PAGE_SIZE];
FILE *fdi = NULL;
fdi = fopen(FID_C3_LOG_FILENAME, "w+");
OPT_ARGS(opts) = {
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) return fd;
glp_high_latency_show_bar(fdi, DO_PRINT_FLAG);
err = nvme_get_log(fd, NVME_NSID_ALL, GLP_ID_VU_GET_HIGH_LATENCY_LOG, 0, NVME_NO_LOG_LSP, sizeof(buf), &buf);
while ( 1) {
if (!glp_high_latency(fdi, buf, LOG_PAGE_SIZE, DO_PRINT_FLAG)) break;
err = nvme_get_log(fd, NVME_NSID_ALL, GLP_ID_VU_GET_HIGH_LATENCY_LOG, 0, NVME_NO_LOG_LSP, sizeof(buf), &buf);
if ( err) {
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
break;
}
}
if (NULL != fdi) fclose(fdi);
return err;
}
static int memblaze_fw_commit(int fd, int select)
{
struct nvme_admin_cmd cmd = {
@ -641,7 +748,7 @@ static int memblaze_fw_commit(int fd, int select)
return nvme_submit_admin_passthru(fd, &cmd);
}
static int memblaze_selective_download(int argc, char **argv, struct command *cmd, struct plugin *plugin)
static int mb_selective_download(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc =
"This performs a selective firmware download, which allows the user to "
@ -757,3 +864,287 @@ out:
return err;
}
static void ioLatencyHistogramOutput(FILE *fd, int index, int start, int end, char *unit0,
char *unit1, unsigned int *pHistogram, int print)
{
int len;
char string[64], subString0[12], subString1[12];
len = snprintf(subString0, sizeof(subString0), "%d%s", start, unit0);
if (end != 0x7FFFFFFF)
{
len = snprintf(subString1, sizeof(subString1), "%d%s", end, unit1);
}
else
{
len = snprintf(subString1, sizeof(subString1), "%s", "+INF");
}
len = snprintf(string, sizeof(string), "%-11d %-11s %-11s %-11u\n", index, subString0, subString1,
pHistogram[index]);
fwrite(string, 1, len, fd);
if (print)
{
printf("%s", string);
}
}
int io_latency_histogram(char *file, char *buf, int print, int logid)
{
FILE *fdi = fopen(file, "w+");
int i, index;
char unit[2][3];
unsigned int *revision = (unsigned int *)buf;
if (logid == GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM)
{
fPRINT_PARAM1("Memblaze IO Read Command Latency Histogram\n");
}
else if (logid == GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM)
{
fPRINT_PARAM1("Memblaze IO Write Command Latency Histogram\n");
}
fPRINT_PARAM2("Major Revision : %d\n", revision[1]);
fPRINT_PARAM2("Minor Revision : %d\n", revision[0]);
buf += 8;
if (revision[1] == 1 && revision[0] == 0)
{
fPRINT_PARAM1("--------------------------------------------------\n");
fPRINT_PARAM1("Bucket Start End Value \n");
fPRINT_PARAM1("--------------------------------------------------\n");
index = 0;
strcpy(unit[0], "us");
strcpy(unit[1], "us");
for (i = 0; i < 32; i++, index++)
{
if (i == 31)
{
strcpy(unit[1], "ms");
ioLatencyHistogramOutput(fdi, index, i * 32, 1, unit[0], unit[1], (unsigned int *)buf, print);
}
else
{
ioLatencyHistogramOutput(fdi, index, i * 32, (i + 1) * 32, unit[0], unit[1], (unsigned int *)buf,
print);
}
}
strcpy(unit[0], "ms");
strcpy(unit[1], "ms");
for (i = 1; i < 32; i++, index++)
{
ioLatencyHistogramOutput(fdi, index, i, i + 1, unit[0], unit[1], (unsigned int *)buf, print);
}
for (i = 1; i < 32; i++, index++)
{
if (i == 31)
{
strcpy(unit[1], "s");
ioLatencyHistogramOutput(fdi, index, i * 32, 1, unit[0], unit[1], (unsigned int *)buf, print);
}
else
{
ioLatencyHistogramOutput(fdi, index, i * 32, (i + 1) * 32, unit[0], unit[1], (unsigned int *)buf,
print);
}
}
strcpy(unit[0], "s");
strcpy(unit[1], "s");
for (i = 1; i < 4; i++, index++)
{
ioLatencyHistogramOutput(fdi, index, i, i + 1, unit[0], unit[1], (unsigned int *)buf, print);
}
ioLatencyHistogramOutput(fdi, index, i, 0x7FFFFFFF, unit[0], unit[1], (unsigned int *)buf, print);
}
else
{
fPRINT_PARAM1("Unsupported io latency histogram revision\n");
}
fclose(fdi);
return 1;
}
static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
char stats[LOG_PAGE_SIZE];
int err = 0;
int fd;
char f1[] = FID_C1_LOG_FILENAME;
char f2[] = FID_C2_LOG_FILENAME;
const char *desc = "Get Latency Statistics log and show it.";
const char *write = "Get write statistics (read default)";
struct config {
int write;
};
struct config cfg = {
.write = 0,
};
OPT_ARGS(opts) = {
OPT_FLAG("write", 'w', &cfg.write, write),
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) return fd;
err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1, false, NVME_NO_LOG_LSP, sizeof(stats), &stats);
if (!err)
io_latency_histogram(cfg.write ? f2 : f1, stats, DO_PRINT_FLAG,
cfg.write ? GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM : GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM);
else
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
close(fd);
return err;
}
#define OP 0xFC
#define FID 0x68
static int memblaze_clear_error_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
int err, fd;
char *desc = "Clear Memblaze devices error log.";
//const char *value = "new value of feature (required)";
//const char *save = "specifies that the controller shall save the attribute";
__u32 result;
struct config {
__u32 feature_id;
__u32 value;
int save;
};
struct config cfg = {
.feature_id = 0xf7,
.value = 0x534d0001,
.save = 0,
};
OPT_ARGS(opts) = {
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
return fd;
err = nvme_set_feature(fd, 0, cfg.feature_id, cfg.value, 0, cfg.save, 0, NULL, &result);
if (err < 0) {
perror("set-feature");
}
if (!err) {
printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id, mb_feature_to_string(cfg.feature_id), cfg.value);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
/*
struct nvme_admin_cmd admin_cmd = {
.opcode = OP,
.cdw10 = FID,
};
err = nvme_submit_admin_passthru(fd, &admin_cmd);
if (!err) {
printf("OP(0x%2X) FID(0x%2X) Clear error log success.\n", OP, FID);
} else {
printf("NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
};
*/
return err;
}
static int mb_set_lat_stats(int argc, char **argv,
struct command *command, struct plugin *plugin)
{
int err, fd;
const char *desc = (
"Enable/Disable Latency Statistics Tracking.\n"
"No argument prints current status.");
const char *enable_desc = "Enable LST";
const char *disable_desc = "Disable LST";
const __u32 nsid = 0;
const __u8 fid = 0xe2;
const __u8 sel = 0;
const __u32 cdw11 = 0x0;
const __u32 cdw12 = 0x0;
const __u32 data_len = 32;
const __u32 save = 0;
__u32 result;
void *buf = NULL;
struct config {
bool enable, disable;
};
struct config cfg = {
.enable = false,
.disable = false,
};
const struct argconfig_commandline_options command_line_options[] = {
{"enable", 'e', "", CFG_NONE, &cfg.enable, no_argument, enable_desc},
{"disable", 'd', "", CFG_NONE, &cfg.disable, no_argument, disable_desc},
{NULL}
};
fd = parse_and_open(argc, argv, desc, command_line_options);
enum Option {
None = -1,
True = 1,
False = 0,
};
enum Option option = None;
if (cfg.enable && cfg.disable)
printf("Cannot enable and disable simultaneously.");
else if (cfg.enable || cfg.disable)
option = cfg.enable;
if (fd < 0)
return fd;
switch (option) {
case None:
err = nvme_get_feature(fd, nsid, fid, sel, cdw11, data_len, buf,
&result);
if (!err) {
printf(
"Latency Statistics Tracking (FID 0x%X) is currently (%i).\n",
fid, result);
} else {
printf("Could not read feature id 0xE2.\n");
return err;
}
break;
case True:
case False:
err = nvme_set_feature(fd, nsid, fid, option, cdw12, save,
data_len, buf, &result);
if (err > 0) {
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
} else if (err < 0) {
perror("Enable latency tracking");
fprintf(stderr, "Command failed while parsing.\n");
} else {
printf("Successfully set enable bit for FID (0x%X) to %i.\n",
fid, option);
}
break;
default:
printf("%d not supported.\n", option);
return EINVAL;
}
return fd;
}