#include <err.h>
#include "libnvme_test_common.h"
static bool
pev_action(nvme_t *nvme, nvme_ctrl_t *ctrl, nvme_pev_log_lsp_t pev, bool exp,
const char *desc)
{
nvme_log_disc_t *disc;
nvme_log_req_t *req;
uint8_t *buf;
size_t buflen = 512;
bool ret = true, lret;
if ((buf = calloc(buflen, sizeof (uint8_t))) == NULL) {
err(EXIT_FAILURE, "INTERNAL TEST FAILURE: failed to allocate "
"%zu bytes for internal buffer", buflen);
}
if (!nvme_log_req_init_by_name(ctrl, "pev", 0, &disc, &req)) {
libnvme_test_ctrl_fatal(ctrl, "%s: failed to initialize "
"persistent event log request", desc);
}
if (!nvme_log_req_set_output(req, buf, buflen)) {
libnvme_test_ctrl_warn(ctrl, "%s: failed to set output buffer",
desc);
ret = false;
goto done;
}
if (!nvme_log_req_set_lsp(req, pev)) {
libnvme_test_ctrl_warn(ctrl, "%s: failed to set lsp to 0x%x",
desc, pev);
ret = false;
goto done;
}
lret = nvme_log_req_exec(req);
if (exp && !lret) {
libnvme_test_ctrl_warn(ctrl, "%s: log request failed, but "
"expected success", desc);
ret = false;
} else if (!exp && lret) {
warnx("TEST FAILED: %s: log request succeeded, but expected "
"failure", desc);
ret = false;
} else if (!lret) {
nvme_err_t err;
uint32_t sct, sc;
err = nvme_ctrl_err(ctrl);
nvme_ctrl_deverr(ctrl, &sct, &sc);
if (err != NVME_ERR_CONTROLLER) {
warnx("TEST FAILED: %s: found controller error %s "
"(0x%x), but expected %s (0x%x)", desc,
nvme_errtostr(nvme, err), err,
nvme_errtostr(nvme, NVME_ERR_CONTROLLER),
NVME_ERR_CONTROLLER);
ret = false;
} else if (sct != NVME_CQE_SCT_GENERIC) {
warnx("TEST FAILED: %s: found device sct %s (0x%x), "
"but expected %s (0x%x)", desc,
nvme_scttostr(ctrl, sct), sct,
nvme_scttostr(ctrl, NVME_CQE_SCT_GENERIC),
NVME_CQE_SCT_GENERIC);
ret = false;
} else if (sc != NVME_CQE_SC_GEN_CMD_SEQ_ERR) {
warnx("TEST FAILED: %s: found device sc %s (0x%x), "
"but expected %s (0x%x)", desc,
nvme_sctostr(ctrl, NVME_CSI_NVM, sct, sc), sc,
nvme_sctostr(ctrl, NVME_CSI_NVM, sct,
NVME_CQE_SC_GEN_CMD_SEQ_ERR),
NVME_CQE_SC_GEN_CMD_SEQ_ERR);
ret = false;
}
} else if (pev == NVME_PEV_LSP_READ ||
pev == NVME_PEV_LSP_EST_CTX_READ) {
if (*buf != NVME_LOGPAGE_PEV) {
warnx("TEST FAILED: %s: returned data does not have "
"correct LID in byte 0, found 0x%x, expected 0x%x",
desc, *buf, NVME_LOGPAGE_PEV);
ret = false;
}
}
if (ret) {
(void) printf("TEST PASSED: %s\n", desc);
}
done:
nvme_log_disc_free(disc);
nvme_log_req_fini(req);
free(buf);
return (ret);
}
int
main(void)
{
int ret = EXIT_SUCCESS;
nvme_t *nvme;
nvme_ctrl_t *ctrl;
libnvme_test_init(&nvme, &ctrl);
if (!pev_action(nvme, ctrl, NVME_PEV_LSP_REL_CTX, true,
"initial release context works")) {
ret = EXIT_FAILURE;
}
if (!pev_action(nvme, ctrl, NVME_PEV_LSP_REL_CTX, true,
"second release context works")) {
ret = EXIT_FAILURE;
}
if (!pev_action(nvme, ctrl, NVME_PEV_LSP_READ, false,
"read without context fails")) {
ret = EXIT_FAILURE;
}
if (!pev_action(nvme, ctrl, NVME_PEV_LSP_EST_CTX_READ, true,
"establish context and read works")) {
ret = EXIT_FAILURE;
}
if (!pev_action(nvme, ctrl, NVME_PEV_LSP_EST_CTX_READ, false,
"second establish context and read fails")) {
ret = EXIT_FAILURE;
}
if (!pev_action(nvme, ctrl, NVME_PEV_LSP_READ, true,
"read with context works")) {
ret = EXIT_FAILURE;
}
if (!pev_action(nvme, ctrl, NVME_PEV_LSP_REL_CTX, true,
"release after read works")) {
ret = EXIT_FAILURE;
}
if (ret == EXIT_SUCCESS) {
(void) printf("All tests passed successfully\n");
}
return (ret);
}