Merging upstream version 2.5.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
3d70d3c76b
commit
ee6621a5b2
507 changed files with 19440 additions and 17258 deletions
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue