summaryrefslogtreecommitdiffstats
path: root/test/mi.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/mi.c')
-rw-r--r--test/mi.c119
1 files changed, 99 insertions, 20 deletions
diff --git a/test/mi.c b/test/mi.c
index c21f9db..5bbb2f0 100644
--- a/test/mi.c
+++ b/test/mi.c
@@ -442,8 +442,8 @@ static void test_admin_id(nvme_mi_ep_t ep)
assert(rc == 0);
}
-/* test: simple NVMe error response */
-static int test_admin_err_resp_cb(struct nvme_mi_ep *ep,
+/* test: simple NVMe error response, error reported in the MI header */
+static int test_admin_err_mi_resp_cb(struct nvme_mi_ep *ep,
struct nvme_mi_req *req,
struct nvme_mi_resp *resp,
void *data)
@@ -481,19 +481,85 @@ static int test_admin_err_resp_cb(struct nvme_mi_ep *ep,
return 0;
}
-static void test_admin_err_resp(nvme_mi_ep_t ep)
+static void test_admin_err_mi_resp(nvme_mi_ep_t ep)
{
struct nvme_id_ctrl id;
nvme_mi_ctrl_t ctrl;
int rc;
- test_set_transport_callback(ep, test_admin_err_resp_cb, NULL);
+ test_set_transport_callback(ep, test_admin_err_mi_resp_cb, NULL);
ctrl = nvme_mi_init_ctrl(ep, 1);
assert(ctrl);
rc = nvme_mi_admin_identify_ctrl(ctrl, &id);
assert(rc != 0);
+ assert(nvme_status_get_type(rc) == NVME_STATUS_TYPE_MI);
+ assert(nvme_status_get_value(rc) == NVME_MI_RESP_INTERNAL_ERR);
+}
+
+/* test: NVMe Admin error, with the error reported in the Admin response */
+static int test_admin_err_nvme_resp_cb(struct nvme_mi_ep *ep,
+ struct nvme_mi_req *req,
+ struct nvme_mi_resp *resp,
+ void *data)
+{
+ __u8 ror, mt, *hdr;
+
+ assert(req->hdr->type == NVME_MI_MSGTYPE_NVME);
+
+ ror = req->hdr->nmp >> 7;
+ mt = req->hdr->nmp >> 3 & 0x7;
+ assert(ror == NVME_MI_ROR_REQ);
+ assert(mt == NVME_MI_MT_ADMIN);
+
+ /* do we have enough for a mi header? */
+ assert(req->hdr_len == sizeof(struct nvme_mi_admin_req_hdr));
+
+ /* inspect response as raw bytes */
+ hdr = (__u8 *)req->hdr;
+ assert(hdr[4] == nvme_admin_identify);
+
+ /* we need at least 8 bytes for error information */
+ assert(resp->hdr_len >= sizeof(struct nvme_mi_admin_resp_hdr));
+
+ /* create error response */
+ hdr = (__u8 *)resp->hdr;
+ hdr[4] = 0; /* MI status: success */
+ hdr[5] = 0;
+ hdr[6] = 0;
+ hdr[7] = 0;
+
+ hdr[16] = 0; /* cdw3: SC: internal, SCT: generic, DNR */
+ hdr[17] = 0;
+ hdr[18] = 0x0c;
+ hdr[19] = 0x80;
+
+ resp->hdr_len = sizeof(struct nvme_mi_admin_resp_hdr);
+ resp->data_len = 0;
+
+ test_transport_resp_calc_mic(resp);
+
+ return 0;
+}
+
+static void test_admin_err_nvme_resp(nvme_mi_ep_t ep)
+{
+ struct nvme_id_ctrl id;
+ nvme_mi_ctrl_t ctrl;
+ int rc;
+
+ test_set_transport_callback(ep, test_admin_err_nvme_resp_cb, NULL);
+
+ ctrl = nvme_mi_init_ctrl(ep, 1);
+ assert(ctrl);
+
+ rc = nvme_mi_admin_identify_ctrl(ctrl, &id);
+ assert(rc != 0);
+ assert(nvme_status_get_type(rc) == NVME_STATUS_TYPE_NVME);
+ assert(nvme_status_get_value(rc) ==
+ (NVME_SC_INTERNAL | (NVME_SCT_GENERIC << NVME_SCT_SHIFT)
+ | NVME_SC_DNR));
}
/* invalid Admin command transfers */
@@ -509,8 +575,11 @@ static int test_admin_invalid_formats_cb(struct nvme_mi_ep *ep,
static void test_admin_invalid_formats(nvme_mi_ep_t ep)
{
+ struct {
+ struct nvme_mi_admin_req_hdr hdr;
+ uint8_t data[4];
+ } req = { 0 };
struct nvme_mi_admin_resp_hdr resp = { 0 };
- struct nvme_mi_admin_req_hdr req = { 0 };
nvme_mi_ctrl_t ctrl;
size_t len;
int rc;
@@ -522,37 +591,37 @@ static void test_admin_invalid_formats(nvme_mi_ep_t ep)
/* unaligned req size */
len = 0;
- rc = nvme_mi_admin_xfer(ctrl, &req, 1, &resp, 0, &len);
+ rc = nvme_mi_admin_xfer(ctrl, &req.hdr, 1, &resp, 0, &len);
assert(rc != 0);
/* unaligned resp size */
len = 1;
- rc = nvme_mi_admin_xfer(ctrl, &req, 0, &resp, 0, &len);
+ rc = nvme_mi_admin_xfer(ctrl, &req.hdr, 0, &resp, 0, &len);
assert(rc != 0);
/* unaligned resp offset */
len = 4;
- rc = nvme_mi_admin_xfer(ctrl, &req, 0, &resp, 1, &len);
+ rc = nvme_mi_admin_xfer(ctrl, &req.hdr, 0, &resp, 1, &len);
assert(rc != 0);
/* resp too large */
len = 4096 + 4;
- rc = nvme_mi_admin_xfer(ctrl, &req, 0, &resp, 0, &len);
+ rc = nvme_mi_admin_xfer(ctrl, &req.hdr, 0, &resp, 0, &len);
assert(rc != 0);
/* resp offset too large */
len = 4;
- rc = nvme_mi_admin_xfer(ctrl, &req, 0, &resp, (off_t)1 << 32, &len);
+ rc = nvme_mi_admin_xfer(ctrl, &req.hdr, 0, &resp, (off_t)1 << 32, &len);
assert(rc != 0);
/* resp offset with no len */
len = 0;
- rc = nvme_mi_admin_xfer(ctrl, &req, 0, &resp, 4, &len);
+ rc = nvme_mi_admin_xfer(ctrl, &req.hdr, 0, &resp, 4, &len);
assert(rc != 0);
/* req and resp payloads */
len = 4;
- rc = nvme_mi_admin_xfer(ctrl, &req, 4, &resp, 0, &len);
+ rc = nvme_mi_admin_xfer(ctrl, &req.hdr, 4, &resp, 0, &len);
assert(rc != 0);
}
@@ -930,7 +999,7 @@ static int test_admin_set_features_cb(struct nvme_mi_ep *ep,
static void test_set_features(nvme_mi_ep_t ep)
{
struct nvme_set_features_args args = { 0 };
- struct nvme_timestamp tstamp;
+ struct nvme_timestamp tstamp = { 0 };
nvme_mi_ctrl_t ctrl;
uint32_t res;
int rc, i;
@@ -1141,7 +1210,7 @@ static int test_admin_id_nsid_ctrl_list_cb(struct nvme_mi_ep *ep,
assert(req->data_len == 0);
cns = hdr[45] << 8 | hdr[44];
- assert(cns == NVME_IDENTIFY_CNS_CTRL_LIST);
+ assert(cns == NVME_IDENTIFY_CNS_NS_CTRL_LIST);
nsid = hdr[11] << 24 | hdr[10] << 16 | hdr[9] << 8 | hdr[8];
assert(nsid == 0x01020304);
@@ -1273,7 +1342,7 @@ static int test_admin_ns_mgmt_cb(struct nvme_mi_ep *ep,
static void test_admin_ns_mgmt_create(struct nvme_mi_ep *ep)
{
- struct nvme_id_ns nsid;
+ struct nvme_id_ns nsid = { 0 };
nvme_mi_ctrl_t ctrl;
__u32 ns;
int rc;
@@ -1287,7 +1356,7 @@ static void test_admin_ns_mgmt_create(struct nvme_mi_ep *ep)
assert(!rc);
assert(ns == 0x01020304);
- nsid.nsze = 42;
+ nsid.nsze = cpu_to_le64(42);
rc = nvme_mi_admin_ns_mgmt_create(ctrl, &nsid, 0, &ns);
assert(rc);
}
@@ -1710,6 +1779,7 @@ static int test_admin_get_log_split_cb(struct nvme_mi_ep *ep,
struct nvme_mi_resp *resp,
void *data)
{
+ uint32_t log_page_offset_lower;
struct log_data *ldata = data;
uint32_t len, off;
__u8 *rq_hdr;
@@ -1724,19 +1794,25 @@ static int test_admin_get_log_split_cb(struct nvme_mi_ep *ep,
off = rq_hdr[31] << 24 | rq_hdr[30] << 16 | rq_hdr[29] << 8 | rq_hdr[28];
len = rq_hdr[35] << 24 | rq_hdr[34] << 16 | rq_hdr[33] << 8 | rq_hdr[32];
+ /* From the MI message's Command Dword 12 */
+ log_page_offset_lower = rq_hdr[55] << 24 | rq_hdr[54] << 16 | rq_hdr[53] << 8 | rq_hdr[52];
+
/* we should have a full-sized start and middle, and a short end */
switch (ldata->n) {
case 0:
+ assert(log_page_offset_lower == 0);
assert(len == 4096);
assert(off == 0);
break;
case 1:
+ assert(log_page_offset_lower == 4096);
assert(len == 4096);
- assert(off == 4096);
+ assert(off == 0);
break;
case 2:
+ assert(log_page_offset_lower == 8192);
assert(len == 4);
- assert(off == 4096 * 2);
+ assert(off == 0);
break;
default:
assert(0);
@@ -1755,8 +1831,8 @@ static int test_admin_get_log_split_cb(struct nvme_mi_ep *ep,
static void test_admin_get_log_split(struct nvme_mi_ep *ep)
{
+ struct nvme_get_log_args args = { 0 };
unsigned char buf[4096 * 2 + 4];
- struct nvme_get_log_args args;
struct log_data ldata;
nvme_mi_ctrl_t ctrl;
int rc;
@@ -1770,6 +1846,8 @@ static void test_admin_get_log_split(struct nvme_mi_ep *ep)
args.lid = 1;
args.log = buf;
args.len = sizeof(buf);
+ args.lpo = 0;
+ args.ot = false;
rc = nvme_mi_admin_get_log(ctrl, &args);
@@ -1792,7 +1870,8 @@ struct test {
DEFINE_TEST(scan_ctrl_list),
DEFINE_TEST(invalid_crc),
DEFINE_TEST(admin_id),
- DEFINE_TEST(admin_err_resp),
+ DEFINE_TEST(admin_err_mi_resp),
+ DEFINE_TEST(admin_err_nvme_resp),
DEFINE_TEST(admin_invalid_formats),
DEFINE_TEST(resp_req),
DEFINE_TEST(resp_hdr_small),