1604 lines
45 KiB
C
1604 lines
45 KiB
C
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
#include <libnvme.h>
|
|
|
|
#include <errno.h>
|
|
#include <inttypes.h>
|
|
|
|
#include "mock.h"
|
|
#include "util.h"
|
|
|
|
#define TEST_FD 0xFD
|
|
#define TEST_TIMEOUT 1234
|
|
#define TEST_NSID 0x89ABCDEF
|
|
#define TEST_CDW11 0x11111111
|
|
#define TEST_CDW12 0x12121212
|
|
#define TEST_CDW13 0x13131313
|
|
#define TEST_CDW15 0x15151515
|
|
#define TEST_UUIDX 0b1001110
|
|
#define TEST_FID 0xFE
|
|
#define TEST_RESULT 0x12345678
|
|
#define TEST_SEL NVME_GET_FEATURES_SEL_SAVED
|
|
#define TEST_SC NVME_SC_INVALID_FIELD
|
|
|
|
static void test_set_features(void)
|
|
{
|
|
uint32_t result = 0;
|
|
uint8_t data[256];
|
|
struct nvme_set_features_args args = {
|
|
.result = &result,
|
|
.data = data,
|
|
.args_size = sizeof(args),
|
|
.fd = TEST_FD,
|
|
.timeout = TEST_TIMEOUT,
|
|
.nsid = TEST_NSID,
|
|
.cdw11 = TEST_CDW11,
|
|
.cdw12 = TEST_CDW12,
|
|
.cdw13 = TEST_CDW13,
|
|
.cdw15 = TEST_CDW15,
|
|
.data_len = sizeof(data),
|
|
.save = true,
|
|
.uuidx = TEST_UUIDX,
|
|
.fid = TEST_FID,
|
|
};
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.nsid = TEST_NSID,
|
|
.in_data = data,
|
|
.data_len = sizeof(data),
|
|
.cdw10 = (uint32_t)1 << 31 /* SAVE */
|
|
| TEST_FID,
|
|
.cdw11 = TEST_CDW11,
|
|
.cdw12 = TEST_CDW12,
|
|
.cdw13 = TEST_CDW13,
|
|
.cdw14 = TEST_UUIDX,
|
|
.cdw15 = TEST_CDW15,
|
|
.timeout_ms = TEST_TIMEOUT,
|
|
.result = TEST_RESULT,
|
|
};
|
|
int err;
|
|
|
|
arbitrary(data, sizeof(data));
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features(&args);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_features(void)
|
|
{
|
|
uint32_t result = 0;
|
|
uint8_t data[256], get_data[sizeof(data)] = {};
|
|
struct nvme_get_features_args args = {
|
|
.result = &result,
|
|
.data = get_data,
|
|
.args_size = sizeof(args),
|
|
.fd = TEST_FD,
|
|
.timeout = TEST_TIMEOUT,
|
|
.nsid = TEST_NSID,
|
|
.sel = TEST_SEL,
|
|
.cdw11 = TEST_CDW11,
|
|
.data_len = sizeof(data),
|
|
.fid = TEST_FID,
|
|
.uuidx = TEST_UUIDX,
|
|
};
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.nsid = TEST_NSID,
|
|
.data_len = sizeof(data),
|
|
.cdw10 = TEST_SEL << 8 | TEST_FID,
|
|
.cdw11 = TEST_CDW11,
|
|
.cdw14 = TEST_UUIDX,
|
|
.timeout_ms = TEST_TIMEOUT,
|
|
.out_data = data,
|
|
.result = TEST_RESULT,
|
|
};
|
|
int err;
|
|
|
|
arbitrary(data, sizeof(data));
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features(&args);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
cmp(get_data, data, sizeof(data), "incorrect data");
|
|
}
|
|
|
|
static void test_set_features_data(void)
|
|
{
|
|
uint8_t data[128];
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.nsid = TEST_NSID,
|
|
.in_data = data,
|
|
.data_len = sizeof(data),
|
|
.cdw10 = TEST_FID,
|
|
.cdw11 = TEST_CDW11,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
arbitrary(data, sizeof(data));
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_data(
|
|
TEST_FD, TEST_FID, TEST_NSID, TEST_CDW11, false,
|
|
sizeof(data), data, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_features_data(void)
|
|
{
|
|
uint8_t data[128], get_data[sizeof(data)] = {};
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.nsid = TEST_NSID,
|
|
.data_len = sizeof(data),
|
|
.cdw10 = NVME_GET_FEATURES_SEL_CURRENT << 8 | TEST_FID,
|
|
.out_data = data,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
arbitrary(data, sizeof(data));
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_data(
|
|
TEST_FD, TEST_FID, TEST_NSID, sizeof(data), get_data, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
cmp(get_data, data, sizeof(data), "incorrect data");
|
|
}
|
|
|
|
static void test_set_features_simple(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.nsid = TEST_NSID,
|
|
.cdw10 = (uint32_t)1 << 31 /* SAVE */
|
|
| TEST_FID,
|
|
.cdw11 = TEST_CDW11,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_simple(
|
|
TEST_FD, TEST_FID, TEST_NSID, TEST_CDW11, true, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_features_simple(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.nsid = TEST_NSID,
|
|
.cdw10 = NVME_GET_FEATURES_SEL_CURRENT << 8 | TEST_FID,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_simple(TEST_FD, TEST_FID, TEST_NSID, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_arbitration(void)
|
|
{
|
|
uint8_t HPW = 0xAA, MPW = 0xBB, LPW = 0xCC, AB = 0b111;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.cdw10 = NVME_FEAT_FID_ARBITRATION,
|
|
.cdw11 = (uint32_t)HPW << 24 | MPW << 16 | LPW << 8 | AB,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_arbitration(
|
|
TEST_FD, AB, LPW, MPW, HPW, false, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_arbitration(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_ARBITRATION,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_arbitration(TEST_FD, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_power_mgmt(void)
|
|
{
|
|
uint8_t PS = 0b10101, WH = 0b101;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.cdw10 = (uint32_t)1 << 31 /* SAVE */
|
|
| NVME_FEAT_FID_POWER_MGMT,
|
|
.cdw11 = WH << 5 | PS,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_power_mgmt(TEST_FD, PS, WH, true, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_power_mgmt(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_POWER_MGMT,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_power_mgmt(TEST_FD, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_lba_range(void)
|
|
{
|
|
uint8_t NUM = 64;
|
|
struct nvme_lba_range_type range_types;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.nsid = TEST_NSID,
|
|
.in_data = &range_types,
|
|
.data_len = sizeof(range_types),
|
|
.cdw10 = NVME_FEAT_FID_LBA_RANGE,
|
|
.cdw11 = NUM - 1,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
arbitrary(&range_types, sizeof(range_types));
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_lba_range(
|
|
TEST_FD, TEST_NSID, NUM, false, &range_types, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_lba_range(void)
|
|
{
|
|
struct nvme_lba_range_type range_types, get_range_types = {};
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.nsid = TEST_NSID,
|
|
.data_len = sizeof(range_types),
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_LBA_RANGE,
|
|
.out_data = &range_types,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
arbitrary(&range_types, sizeof(range_types));
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_lba_range2(
|
|
TEST_FD, TEST_SEL, TEST_NSID, &get_range_types, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
cmp(&get_range_types, &range_types, sizeof(range_types),
|
|
"incorrect LBA range types");
|
|
}
|
|
|
|
static void test_set_temp_thresh(void)
|
|
{
|
|
uint16_t TMPTH = 0xFEDC;
|
|
uint8_t TMPSEL = 0x8;
|
|
enum nvme_feat_tmpthresh_thsel THSEL =
|
|
NVME_FEATURE_TEMPTHRESH_THSEL_UNDER;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.cdw10 = (uint32_t)1 << 31 /* SAVE */
|
|
| NVME_FEAT_FID_TEMP_THRESH,
|
|
.cdw11 = THSEL << 20 | TMPSEL << 16 | TMPTH,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_temp_thresh(
|
|
TEST_FD, TMPTH, TMPSEL, THSEL, true, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_temp_thresh(void)
|
|
{
|
|
/*
|
|
* nvme_get_features_temp_thresh() doesn't support
|
|
* specifying TMPSEL and THSEL
|
|
*/
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_TEMP_THRESH,
|
|
.cdw11 = NVME_FEATURE_TEMPTHRESH_THSEL_OVER << 20,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_temp_thresh(TEST_FD, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_err_recovery(void)
|
|
{
|
|
uint16_t TLER = 0xCDEF;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.nsid = TEST_NSID,
|
|
.cdw10 = NVME_FEAT_FID_ERR_RECOVERY,
|
|
.cdw11 = 1 << 16 /* DULBE */
|
|
| TLER,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_err_recovery(
|
|
TEST_FD, TEST_NSID, TLER, true, false, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_err_recovery(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.nsid = TEST_NSID,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_ERR_RECOVERY,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_err_recovery2(
|
|
TEST_FD, TEST_SEL, TEST_NSID, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_volatile_wc(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.cdw10 = (uint32_t)1 << 31 /* SAVE */
|
|
| NVME_FEAT_FID_VOLATILE_WC,
|
|
.cdw11 = 1 << 0, /* WCE */
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_volatile_wc(TEST_FD, true, true, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_volatile_wc(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8
|
|
| NVME_FEAT_FID_VOLATILE_WC,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_volatile_wc(TEST_FD, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_num_queues(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_NUM_QUEUES,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_num_queues(TEST_FD, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_irq_coalesce(void)
|
|
{
|
|
uint8_t THR = 0xAB, TIME = 0xCD;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.cdw10 = NVME_FEAT_FID_IRQ_COALESCE,
|
|
.cdw11 = TIME << 8 | THR,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_irq_coalesce(
|
|
TEST_FD, THR, TIME, false, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_irq_coalesce(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_IRQ_COALESCE,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_irq_coalesce(TEST_FD, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_irq_config(void)
|
|
{
|
|
uint16_t IV = 0x1234;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.cdw10 = (uint32_t)1 << 31 /* SAVE */
|
|
| NVME_FEAT_FID_IRQ_CONFIG,
|
|
.cdw11 = 1 << 16 /* CD */
|
|
| IV,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_irq_config(TEST_FD, IV, true, true, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_irq_config(void)
|
|
{
|
|
uint16_t IV = 0x5678;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_IRQ_CONFIG,
|
|
.cdw11 = IV,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_irq_config(TEST_FD, TEST_SEL, IV, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_write_atomic(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.cdw10 = NVME_FEAT_FID_WRITE_ATOMIC,
|
|
.cdw11 = 1 << 0, /* DN */
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_write_atomic(TEST_FD, true, false, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_write_atomic(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_WRITE_ATOMIC,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_write_atomic(TEST_FD, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_async_event(void)
|
|
{
|
|
uint32_t EVENTS = 0x87654321;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.cdw10 = (uint32_t)1 << 31 /* SAVE */
|
|
| NVME_FEAT_FID_ASYNC_EVENT,
|
|
.cdw11 = EVENTS,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_async_event(TEST_FD, EVENTS, true, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_async_event(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_ASYNC_EVENT,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_async_event(TEST_FD, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_auto_pst(void)
|
|
{
|
|
struct nvme_feat_auto_pst apst;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.in_data = &apst,
|
|
.data_len = sizeof(apst),
|
|
.cdw10 = NVME_FEAT_FID_AUTO_PST,
|
|
.cdw11 = 1 << 0, /* APSTE */
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
arbitrary(&apst, sizeof(apst));
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_auto_pst(TEST_FD, true, false, &apst, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_auto_pst(void)
|
|
{
|
|
struct nvme_feat_auto_pst apst, get_apst = {};
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.data_len = sizeof(apst),
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_AUTO_PST,
|
|
.out_data = &apst,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
arbitrary(&apst, sizeof(apst));
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_auto_pst(TEST_FD, TEST_SEL, &get_apst, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
cmp(&get_apst, &apst, sizeof(apst), "incorrect apst");
|
|
}
|
|
|
|
static void test_get_host_mem_buf(void)
|
|
{
|
|
struct nvme_host_mem_buf_attrs attrs, get_attrs = {};
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.data_len = sizeof(attrs),
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_HOST_MEM_BUF,
|
|
.out_data = &attrs,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
arbitrary(&attrs, sizeof(attrs));
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_host_mem_buf2(
|
|
TEST_FD, TEST_SEL, &get_attrs, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
cmp(&get_attrs, &attrs, sizeof(attrs), "incorrect attrs");
|
|
}
|
|
|
|
static void test_set_timestamp(void)
|
|
{
|
|
struct nvme_timestamp ts = {.timestamp = {1, 2, 3, 4, 5, 6}};
|
|
uint64_t timestamp = ts.timestamp[0]
|
|
| (uint64_t) ts.timestamp[1] << 8
|
|
| (uint64_t) ts.timestamp[2] << 16
|
|
| (uint64_t) ts.timestamp[3] << 24
|
|
| (uint64_t) ts.timestamp[4] << 32
|
|
| (uint64_t) ts.timestamp[5] << 40;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.in_data = &ts,
|
|
.data_len = sizeof(ts),
|
|
.cdw10 = (uint32_t)1 << 31 /* SAVE */
|
|
| NVME_FEAT_FID_TIMESTAMP,
|
|
};
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_timestamp(TEST_FD, true, timestamp);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
}
|
|
|
|
static void test_get_timestamp(void)
|
|
{
|
|
struct nvme_timestamp ts, get_ts = {};
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.data_len = sizeof(ts),
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_TIMESTAMP,
|
|
.out_data = &ts,
|
|
};
|
|
int err;
|
|
|
|
arbitrary(&ts, sizeof(ts));
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_timestamp(TEST_FD, TEST_SEL, &get_ts);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
cmp(&get_ts, &ts, sizeof(ts), "incorrect timestamp");
|
|
}
|
|
|
|
static void test_get_kato(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_KATO,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_kato(TEST_FD, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_hctm(void)
|
|
{
|
|
uint16_t TMT2 = 0x4321, TMT1 = 0x8765;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.cdw10 = NVME_FEAT_FID_HCTM,
|
|
.cdw11 = (uint32_t)TMT1 << 16 | TMT2,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_hctm(TEST_FD, TMT2, TMT1, false, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_hctm(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_HCTM,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_hctm(TEST_FD, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_nopsc(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.cdw10 = (uint32_t)1 << 31 /* SAVE */
|
|
| NVME_FEAT_FID_NOPSC,
|
|
.cdw11 = 1 << 0 /* NOPPME */,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_nopsc(TEST_FD, true, true, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_nopsc(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_NOPSC,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_nopsc(TEST_FD, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_rrl(void)
|
|
{
|
|
uint8_t RRL = 0xA;
|
|
uint16_t NVMSETID = 0x1234;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.cdw10 = NVME_FEAT_FID_RRL,
|
|
.cdw11 = NVMSETID,
|
|
.cdw12 = RRL,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_rrl(TEST_FD, RRL, NVMSETID, false, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_rrl(void)
|
|
{
|
|
/* nvme_get_features_rrl() doesn't support specifying the NVMSETID */
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_RRL,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_rrl(TEST_FD, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_plm_config(void)
|
|
{
|
|
uint16_t NVMSETID = 0xFEDC;
|
|
struct nvme_plm_config config;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.in_data = &config,
|
|
.data_len = sizeof(config),
|
|
.cdw10 = (uint32_t)1 << 31 /* SAVE */
|
|
| NVME_FEAT_FID_PLM_CONFIG,
|
|
.cdw11 = NVMSETID,
|
|
.cdw12 = 1 << 0 /* Predictable Latency Enable */,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
arbitrary(&config, sizeof(config));
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_plm_config(
|
|
TEST_FD, true, NVMSETID, true, &config, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_plm_config(void)
|
|
{
|
|
uint16_t NVMSETID = 0xABCD;
|
|
struct nvme_plm_config config, get_config = {};
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.data_len = sizeof(config),
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_PLM_CONFIG,
|
|
.cdw11 = NVMSETID,
|
|
.out_data = &config,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
arbitrary(&config, sizeof(config));
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_plm_config(
|
|
TEST_FD, TEST_SEL, NVMSETID, &get_config, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
cmp(&get_config, &config, sizeof(config), "incorrect PLM config");
|
|
}
|
|
|
|
static void test_set_plm_window(void)
|
|
{
|
|
enum nvme_feat_plm_window_select SEL = NVME_FEATURE_PLM_NDWIN;
|
|
uint16_t NVMSETID = 0x4321;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.cdw10 = NVME_FEAT_FID_PLM_WINDOW,
|
|
.cdw11 = NVMSETID,
|
|
.cdw12 = SEL,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_plm_window(
|
|
TEST_FD, SEL, NVMSETID, false, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_plm_window(void)
|
|
{
|
|
uint16_t NVMSETID = 0x8765;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_PLM_WINDOW,
|
|
.cdw11 = NVMSETID,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_plm_window(
|
|
TEST_FD, TEST_SEL, NVMSETID, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_lba_sts_interval(void)
|
|
{
|
|
uint16_t LSIRI = 0x1234, LSIPI = 0x5678;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.cdw10 = (uint32_t)1 << 31 /* SAVE */
|
|
| NVME_FEAT_FID_LBA_STS_INTERVAL,
|
|
.cdw11 = LSIPI << 16 | LSIRI,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_lba_sts_interval(
|
|
TEST_FD, LSIRI, LSIPI, true, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_lba_sts_interval(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_LBA_STS_INTERVAL,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_lba_sts_interval(TEST_FD, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_host_behavior(void)
|
|
{
|
|
/* nvme_set_features_host_behavior() ignores SAVE */
|
|
struct nvme_feat_host_behavior behavior;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.in_data = &behavior,
|
|
.data_len = sizeof(behavior),
|
|
.cdw10 = NVME_FEAT_FID_HOST_BEHAVIOR,
|
|
};
|
|
int err;
|
|
|
|
arbitrary(&behavior, sizeof(behavior));
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_host_behavior(TEST_FD, true, &behavior);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
}
|
|
|
|
static void test_get_host_behavior(void)
|
|
{
|
|
struct nvme_feat_host_behavior behavior, get_behavior = {};
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.data_len = sizeof(behavior),
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_HOST_BEHAVIOR,
|
|
.out_data = &behavior,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
arbitrary(&behavior, sizeof(behavior));
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_host_behavior(
|
|
TEST_FD, TEST_SEL, &get_behavior, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
cmp(&get_behavior, &behavior, sizeof(behavior), "incorrect behavior");
|
|
}
|
|
|
|
static void test_set_sanitize(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.cdw10 = NVME_FEAT_FID_SANITIZE,
|
|
.cdw11 = 1 << 0, /* NODRM */
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_sanitize(TEST_FD, true, false, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_sanitize(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_SANITIZE,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_sanitize(TEST_FD, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_endurance_evt_cfg(void)
|
|
{
|
|
uint16_t ENDGID = 0x9876;
|
|
uint8_t EGWARN = 0xCD;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.cdw10 = (uint32_t)1 << 31 /* SAVE */
|
|
| NVME_FEAT_FID_ENDURANCE_EVT_CFG,
|
|
.cdw11 = EGWARN << 16 | ENDGID,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_endurance_evt_cfg(
|
|
TEST_FD, ENDGID, EGWARN, true, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_endurance_event_cfg(void)
|
|
{
|
|
uint16_t ENDGID = 0x6789;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_ENDURANCE_EVT_CFG,
|
|
.cdw11 = ENDGID,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_endurance_event_cfg(
|
|
TEST_FD, TEST_SEL, ENDGID, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_iocs_profile(void)
|
|
{
|
|
uint16_t IOCSI = 0b101100111;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.cdw10 = NVME_FEAT_FID_IOCS_PROFILE,
|
|
.cdw11 = IOCSI,
|
|
};
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_iocs_profile(TEST_FD, IOCSI, false);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
}
|
|
|
|
static void test_get_iocs_profile(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_IOCS_PROFILE,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_iocs_profile(TEST_FD, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_sw_progress(void)
|
|
{
|
|
uint8_t PBSLC = 0xBA;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.cdw10 = (uint32_t)1 << 31 /* SAVE */
|
|
| NVME_FEAT_FID_SW_PROGRESS,
|
|
.cdw11 = PBSLC,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_sw_progress(TEST_FD, PBSLC, true, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_sw_progress(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_SW_PROGRESS,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_sw_progress(TEST_FD, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_host_id(void)
|
|
{
|
|
uint8_t hostid[8];
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.in_data = hostid,
|
|
.data_len = sizeof(hostid),
|
|
.cdw10 = (uint32_t)1 << 31 /* SAVE */
|
|
| NVME_FEAT_FID_HOST_ID,
|
|
.result = TEST_RESULT,
|
|
};
|
|
int err;
|
|
|
|
arbitrary(hostid, sizeof(hostid));
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_host_id(TEST_FD, false, true, hostid);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
}
|
|
|
|
static void test_set_host_id_extended(void)
|
|
{
|
|
uint8_t hostid[16];
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.in_data = hostid,
|
|
.data_len = sizeof(hostid),
|
|
.cdw10 = NVME_FEAT_FID_HOST_ID,
|
|
.cdw11 = 1 << 0, /* EXHID */
|
|
.result = TEST_RESULT,
|
|
};
|
|
int err;
|
|
|
|
arbitrary(hostid, sizeof(hostid));
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_host_id(TEST_FD, true, false, hostid);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
}
|
|
|
|
static void test_get_host_id(void)
|
|
{
|
|
uint8_t hostid[8], get_hostid[sizeof(hostid)] = {};
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.data_len = sizeof(hostid),
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_HOST_ID,
|
|
.out_data = hostid,
|
|
.result = TEST_RESULT,
|
|
};
|
|
int err;
|
|
|
|
arbitrary(hostid, sizeof(hostid));
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_host_id(
|
|
TEST_FD, TEST_SEL, false, sizeof(hostid), get_hostid);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
cmp(get_hostid, hostid, sizeof(hostid), "incorrect host identifier");
|
|
}
|
|
|
|
static void test_get_host_id_extended(void)
|
|
{
|
|
uint8_t hostid[16], get_hostid[sizeof(hostid)] = {};
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.data_len = sizeof(hostid),
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_HOST_ID,
|
|
.cdw11 = 1 << 0, /* EXHID */
|
|
.out_data = hostid,
|
|
.result = TEST_RESULT,
|
|
};
|
|
int err;
|
|
|
|
arbitrary(hostid, sizeof(hostid));
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_host_id(
|
|
TEST_FD, TEST_SEL, true, sizeof(hostid), get_hostid);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
cmp(get_hostid, hostid, sizeof(hostid), "incorrect host identifier");
|
|
}
|
|
|
|
static void test_set_resv_mask(void)
|
|
{
|
|
uint32_t MASK = 0x23456789;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.nsid = TEST_NSID,
|
|
.cdw10 = (uint32_t)1 << 31 /* SAVE */
|
|
| NVME_FEAT_FID_RESV_MASK,
|
|
.cdw11 = MASK,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_resv_mask2(
|
|
TEST_FD, TEST_NSID, MASK, true, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_resv_mask(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.nsid = TEST_NSID,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_RESV_MASK,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_resv_mask2(
|
|
TEST_FD, TEST_SEL, TEST_NSID, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_resv_persist(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.nsid = TEST_NSID,
|
|
.cdw10 = NVME_FEAT_FID_RESV_PERSIST,
|
|
.cdw11 = 1 << 0, /* PTPL */
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_resv_persist2(
|
|
TEST_FD, TEST_NSID, true, false, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_resv_persist(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.nsid = TEST_NSID,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_RESV_PERSIST,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_resv_persist2(
|
|
TEST_FD, TEST_SEL, TEST_NSID, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_write_protect(void)
|
|
{
|
|
/* nvme_set_features_write_protect() ignores SAVE */
|
|
enum nvme_feat_nswpcfg_state STATE =
|
|
NVME_FEAT_NS_WRITE_PROTECT_PERMANENT;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.nsid = TEST_NSID,
|
|
.cdw10 = NVME_FEAT_FID_WRITE_PROTECT,
|
|
.cdw11 = STATE,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_write_protect2(
|
|
TEST_FD, TEST_NSID, STATE, true, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "set features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_write_protect(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.nsid = TEST_NSID,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_WRITE_PROTECT,
|
|
.result = TEST_RESULT,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_write_protect(
|
|
TEST_FD, TEST_NSID, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == 0, "get features returned error %d, errno %m", err);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
/*
|
|
* All set_features functions tail-call nvme_set_features(),
|
|
* so testing errors in any of them will do
|
|
*/
|
|
|
|
static void test_set_status_code_error(void)
|
|
{
|
|
uint32_t EVENTS = 0x12345678;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.cdw10 = NVME_FEAT_FID_ASYNC_EVENT,
|
|
.cdw11 = EVENTS,
|
|
.result = TEST_RESULT,
|
|
.err = TEST_SC,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_async_event(TEST_FD, EVENTS, false, &result);
|
|
end_mock_cmds();
|
|
check(err == TEST_SC, "got error %d, expected %d", err, TEST_SC);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_set_kernel_error(void)
|
|
{
|
|
uint32_t MASK = 0x87654321;
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_set_features,
|
|
.nsid = TEST_NSID,
|
|
.cdw10 = NVME_FEAT_FID_RESV_MASK,
|
|
.cdw11 = MASK,
|
|
.result = TEST_RESULT,
|
|
.err = -EIO,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_set_features_resv_mask2(
|
|
TEST_FD, TEST_NSID, MASK, false, &result);
|
|
end_mock_cmds();
|
|
check(err == -1, "got error %d, expected -1", err);
|
|
check(errno == EIO, "unexpected error %m");
|
|
check(!result, "result unexpectedly set to %" PRIu32, result);
|
|
}
|
|
|
|
/*
|
|
* All get_features functions tail-call nvme_get_features(),
|
|
* so testing errors in any of them will do
|
|
*/
|
|
|
|
static void test_get_status_code_error(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_KATO,
|
|
.result = TEST_RESULT,
|
|
.err = TEST_SC,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_kato(TEST_FD, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == TEST_SC, "got error %d, expected %d", err, TEST_SC);
|
|
check(result == TEST_RESULT,
|
|
"got result %" PRIu32 ", expected %" PRIu32, result, TEST_RESULT);
|
|
}
|
|
|
|
static void test_get_kernel_error(void)
|
|
{
|
|
struct mock_cmd mock_admin_cmd = {
|
|
.opcode = nvme_admin_get_features,
|
|
.cdw10 = TEST_SEL << 8 | NVME_FEAT_FID_NUM_QUEUES,
|
|
.result = TEST_RESULT,
|
|
.err = -EBUSY,
|
|
};
|
|
uint32_t result = 0;
|
|
int err;
|
|
|
|
set_mock_admin_cmds(&mock_admin_cmd, 1);
|
|
err = nvme_get_features_num_queues(TEST_FD, TEST_SEL, &result);
|
|
end_mock_cmds();
|
|
check(err == -1, "got error %d, expected -1", err);
|
|
check(errno == EBUSY, "unexpected error %m");
|
|
check(!result, "result unexpectedly set to %" PRIu32, result);
|
|
}
|
|
|
|
static void run_test(const char *test_name, void (*test_fn)(void))
|
|
{
|
|
printf("Running test %s...", test_name);
|
|
fflush(stdout);
|
|
test_fn();
|
|
puts(" OK");
|
|
}
|
|
|
|
#define RUN_TEST(name) run_test(#name, test_ ## name)
|
|
|
|
int main(void)
|
|
{
|
|
set_mock_fd(TEST_FD);
|
|
RUN_TEST(set_features);
|
|
RUN_TEST(get_features);
|
|
RUN_TEST(set_features_data);
|
|
RUN_TEST(get_features_data);
|
|
RUN_TEST(set_features_simple);
|
|
RUN_TEST(get_features_simple);
|
|
RUN_TEST(set_arbitration);
|
|
RUN_TEST(get_arbitration);
|
|
RUN_TEST(set_power_mgmt);
|
|
RUN_TEST(get_power_mgmt);
|
|
RUN_TEST(set_lba_range);
|
|
RUN_TEST(get_lba_range);
|
|
RUN_TEST(set_temp_thresh);
|
|
RUN_TEST(get_temp_thresh);
|
|
RUN_TEST(set_err_recovery);
|
|
RUN_TEST(get_err_recovery);
|
|
RUN_TEST(set_volatile_wc);
|
|
RUN_TEST(get_volatile_wc);
|
|
RUN_TEST(get_num_queues);
|
|
RUN_TEST(set_irq_coalesce);
|
|
RUN_TEST(get_irq_coalesce);
|
|
RUN_TEST(set_irq_config);
|
|
RUN_TEST(get_irq_config);
|
|
RUN_TEST(set_write_atomic);
|
|
RUN_TEST(get_write_atomic);
|
|
RUN_TEST(set_async_event);
|
|
RUN_TEST(get_async_event);
|
|
RUN_TEST(set_auto_pst);
|
|
RUN_TEST(get_auto_pst);
|
|
RUN_TEST(get_host_mem_buf);
|
|
RUN_TEST(set_timestamp);
|
|
RUN_TEST(get_timestamp);
|
|
RUN_TEST(get_kato);
|
|
RUN_TEST(set_hctm);
|
|
RUN_TEST(get_hctm);
|
|
RUN_TEST(set_nopsc);
|
|
RUN_TEST(get_nopsc);
|
|
RUN_TEST(set_rrl);
|
|
RUN_TEST(get_rrl);
|
|
RUN_TEST(set_plm_config);
|
|
RUN_TEST(get_plm_config);
|
|
RUN_TEST(set_plm_window);
|
|
RUN_TEST(get_plm_window);
|
|
RUN_TEST(set_lba_sts_interval);
|
|
RUN_TEST(get_lba_sts_interval);
|
|
RUN_TEST(set_host_behavior);
|
|
RUN_TEST(get_host_behavior);
|
|
RUN_TEST(set_sanitize);
|
|
RUN_TEST(get_sanitize);
|
|
RUN_TEST(set_endurance_evt_cfg);
|
|
RUN_TEST(get_endurance_event_cfg);
|
|
RUN_TEST(set_iocs_profile);
|
|
RUN_TEST(get_iocs_profile);
|
|
RUN_TEST(set_sw_progress);
|
|
RUN_TEST(get_sw_progress);
|
|
RUN_TEST(set_host_id);
|
|
RUN_TEST(set_host_id_extended);
|
|
RUN_TEST(get_host_id);
|
|
RUN_TEST(get_host_id_extended);
|
|
RUN_TEST(set_resv_mask);
|
|
RUN_TEST(get_resv_mask);
|
|
RUN_TEST(set_resv_persist);
|
|
RUN_TEST(get_resv_persist);
|
|
RUN_TEST(set_write_protect);
|
|
RUN_TEST(get_write_protect);
|
|
RUN_TEST(set_status_code_error);
|
|
RUN_TEST(set_kernel_error);
|
|
RUN_TEST(get_status_code_error);
|
|
RUN_TEST(get_kernel_error);
|
|
}
|