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)
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 */
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),