xref: /illumos-gate/usr/src/test/nvme-tests/tests/libnvme/pev.c (revision 1c02c6c85edfeb48df1fe18511a8779bf9d6c6ed)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2024 Oxide Computer Company
14  */
15 
16 /*
17  * Test various aspects of reading the persistent event log from a device and
18  * verify that we properly handle certain error conditions. In particular, we
19  * want to verify the following:
20  *
21  * 1) Issuing a reset context while it's already reset is fine.
22  * 2) Issuing a read without establish fails
23  * 3) Issuing an establish context with one fails
24  * 4) Otherwise basic read / establish / release works
25  *
26  * Because this requires device specific behavior is it not part of the default
27  * non-destructive run.
28  */
29 
30 #include <err.h>
31 
32 #include "libnvme_test_common.h"
33 
34 static bool
pev_action(nvme_t * nvme,nvme_ctrl_t * ctrl,nvme_pev_log_lsp_t pev,bool exp,const char * desc)35 pev_action(nvme_t *nvme, nvme_ctrl_t *ctrl, nvme_pev_log_lsp_t pev, bool exp,
36     const char *desc)
37 {
38 	nvme_log_disc_t *disc;
39 	nvme_log_req_t *req;
40 	uint8_t *buf;
41 	size_t buflen = 512;
42 	bool ret = true, lret;
43 
44 	if ((buf = calloc(buflen, sizeof (uint8_t))) == NULL) {
45 		err(EXIT_FAILURE, "INTERNAL TEST FAILURE: failed to allocate "
46 		    "%zu bytes for internal buffer", buflen);
47 	}
48 
49 	if (!nvme_log_req_init_by_name(ctrl, "pev", 0, &disc, &req)) {
50 		libnvme_test_ctrl_fatal(ctrl, "%s: failed to initialize "
51 		    "persistent event log request", desc);
52 	}
53 
54 	if (!nvme_log_req_set_output(req, buf, buflen)) {
55 		libnvme_test_ctrl_warn(ctrl, "%s: failed to set output buffer",
56 		    desc);
57 		ret = false;
58 		goto done;
59 	}
60 
61 	if (!nvme_log_req_set_lsp(req, pev)) {
62 		libnvme_test_ctrl_warn(ctrl, "%s: failed to set lsp to 0x%x",
63 		    desc, pev);
64 		ret = false;
65 		goto done;
66 	}
67 
68 	lret = nvme_log_req_exec(req);
69 	if (exp && !lret) {
70 		libnvme_test_ctrl_warn(ctrl, "%s: log request failed, but "
71 		    "expected success", desc);
72 		ret = false;
73 	} else if (!exp && lret) {
74 		warnx("TEST FAILED: %s: log request succeeded, but expected "
75 		    "failure", desc);
76 		ret = false;
77 	} else if (!lret) {
78 		nvme_err_t err;
79 		uint32_t sct, sc;
80 
81 		err = nvme_ctrl_err(ctrl);
82 		nvme_ctrl_deverr(ctrl, &sct, &sc);
83 
84 		if (err != NVME_ERR_CONTROLLER) {
85 			warnx("TEST FAILED: %s: found controller error %s "
86 			    "(0x%x), but expected %s (0x%x)", desc,
87 			    nvme_errtostr(nvme, err), err,
88 			    nvme_errtostr(nvme, NVME_ERR_CONTROLLER),
89 			    NVME_ERR_CONTROLLER);
90 			ret = false;
91 		} else if (sct != NVME_CQE_SCT_GENERIC) {
92 			warnx("TEST FAILED: %s: found device sct %s (0x%x), "
93 			    "but expected %s (0x%x)", desc,
94 			    nvme_scttostr(ctrl, sct), sct,
95 			    nvme_scttostr(ctrl, NVME_CQE_SCT_GENERIC),
96 			    NVME_CQE_SCT_GENERIC);
97 			ret = false;
98 		} else if (sc != NVME_CQE_SC_GEN_CMD_SEQ_ERR) {
99 			warnx("TEST FAILED: %s: found device sc %s (0x%x), "
100 			    "but expected %s (0x%x)", desc,
101 			    nvme_sctostr(ctrl, NVME_CSI_NVM, sct, sc), sc,
102 			    nvme_sctostr(ctrl, NVME_CSI_NVM, sct,
103 			    NVME_CQE_SC_GEN_CMD_SEQ_ERR),
104 			    NVME_CQE_SC_GEN_CMD_SEQ_ERR);
105 			ret = false;
106 		}
107 	} else if (pev == NVME_PEV_LSP_READ ||
108 	    pev == NVME_PEV_LSP_EST_CTX_READ) {
109 		if (*buf != NVME_LOGPAGE_PEV) {
110 			warnx("TEST FAILED: %s: returned data does not have "
111 			    "correct LID in byte 0, found 0x%x, expected 0x%x",
112 			    desc, *buf, NVME_LOGPAGE_PEV);
113 			ret = false;
114 		}
115 	}
116 
117 	if (ret) {
118 		(void) printf("TEST PASSED: %s\n", desc);
119 	}
120 done:
121 	nvme_log_disc_free(disc);
122 	nvme_log_req_fini(req);
123 	free(buf);
124 	return (ret);
125 }
126 
127 int
main(void)128 main(void)
129 {
130 	int ret = EXIT_SUCCESS;
131 	nvme_t *nvme;
132 	nvme_ctrl_t *ctrl;
133 
134 	libnvme_test_init(&nvme, &ctrl);
135 	if (!pev_action(nvme, ctrl, NVME_PEV_LSP_REL_CTX, true,
136 	    "initial release context works")) {
137 		ret = EXIT_FAILURE;
138 	}
139 
140 	if (!pev_action(nvme, ctrl, NVME_PEV_LSP_REL_CTX, true,
141 	    "second release context works")) {
142 		ret = EXIT_FAILURE;
143 	}
144 
145 	if (!pev_action(nvme, ctrl, NVME_PEV_LSP_READ, false,
146 	    "read without context fails")) {
147 		ret = EXIT_FAILURE;
148 	}
149 
150 	if (!pev_action(nvme, ctrl, NVME_PEV_LSP_EST_CTX_READ, true,
151 	    "establish context and read works")) {
152 		ret = EXIT_FAILURE;
153 	}
154 
155 	if (!pev_action(nvme, ctrl, NVME_PEV_LSP_EST_CTX_READ, false,
156 	    "second establish context and read fails")) {
157 		ret = EXIT_FAILURE;
158 	}
159 
160 	if (!pev_action(nvme, ctrl, NVME_PEV_LSP_READ, true,
161 	    "read with context works")) {
162 		ret = EXIT_FAILURE;
163 	}
164 
165 	if (!pev_action(nvme, ctrl, NVME_PEV_LSP_REL_CTX, true,
166 	    "release after read works")) {
167 		ret = EXIT_FAILURE;
168 	}
169 
170 	if (ret == EXIT_SUCCESS) {
171 		(void) printf("All tests passed successfully\n");
172 	}
173 
174 	return (ret);
175 }
176