1533affcbSRobert Mustacchi /*
2533affcbSRobert Mustacchi * This file and its contents are supplied under the terms of the
3533affcbSRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4533affcbSRobert Mustacchi * You may only use this file in accordance with the terms of version
5533affcbSRobert Mustacchi * 1.0 of the CDDL.
6533affcbSRobert Mustacchi *
7533affcbSRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8533affcbSRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9533affcbSRobert Mustacchi * http://www.illumos.org/license/CDDL.
10533affcbSRobert Mustacchi */
11533affcbSRobert Mustacchi
12533affcbSRobert Mustacchi /*
13533affcbSRobert Mustacchi * Copyright 2024 Oxide Computer Company
14533affcbSRobert Mustacchi */
15533affcbSRobert Mustacchi
16533affcbSRobert Mustacchi /*
17533affcbSRobert Mustacchi * libnvme error manipulation and translation. This maintains the error objects
18533affcbSRobert Mustacchi * that we have on handles and provides translations between the kernel's errors
19533affcbSRobert Mustacchi * and those that we might generate ourselves. Information errors are instead
20533affcbSRobert Mustacchi * contained in the corresponding files that own controller and namespace
21533affcbSRobert Mustacchi * information libnvme_ctrl_info.c and libnvme_ns_info.c respectively.
22533affcbSRobert Mustacchi */
23533affcbSRobert Mustacchi
24533affcbSRobert Mustacchi #include <string.h>
25533affcbSRobert Mustacchi #include <stdarg.h>
26533affcbSRobert Mustacchi #include <sys/debug.h>
27533affcbSRobert Mustacchi #include <sys/sysmacros.h>
28533affcbSRobert Mustacchi #include <upanic.h>
29533affcbSRobert Mustacchi
30533affcbSRobert Mustacchi #include "libnvme_impl.h"
31533affcbSRobert Mustacchi
32533affcbSRobert Mustacchi /*
33533affcbSRobert Mustacchi * The following sets of functions provide translations of error types. Note,
34533affcbSRobert Mustacchi * the kernel headers need to be updated for newer NVMe specs at which point
35533affcbSRobert Mustacchi * these should be updated.
36533affcbSRobert Mustacchi */
37533affcbSRobert Mustacchi const char *
nvme_scttostr(nvme_ctrl_t * ctrl __unused,uint32_t sc)38533affcbSRobert Mustacchi nvme_scttostr(nvme_ctrl_t *ctrl __unused, uint32_t sc)
39533affcbSRobert Mustacchi {
40533affcbSRobert Mustacchi switch (sc) {
41533affcbSRobert Mustacchi case NVME_CQE_SCT_GENERIC:
42533affcbSRobert Mustacchi return ("generic command status");
43533affcbSRobert Mustacchi case NVME_CQE_SCT_SPECIFIC:
44533affcbSRobert Mustacchi return ("command specific status");
45533affcbSRobert Mustacchi case NVME_CQE_SCT_INTEGRITY:
46533affcbSRobert Mustacchi return ("media and data integrity errors");
47533affcbSRobert Mustacchi case NVME_CQE_SCT_VENDOR:
48533affcbSRobert Mustacchi return ("vendor specific");
49533affcbSRobert Mustacchi default:
50533affcbSRobert Mustacchi return ("unknown status type");
51533affcbSRobert Mustacchi }
52533affcbSRobert Mustacchi }
53533affcbSRobert Mustacchi
54533affcbSRobert Mustacchi static const char *
nvme_sctostr_gen_gen(uint32_t sct)55533affcbSRobert Mustacchi nvme_sctostr_gen_gen(uint32_t sct)
56533affcbSRobert Mustacchi {
57533affcbSRobert Mustacchi switch (sct) {
58533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_SUCCESS:
59533affcbSRobert Mustacchi return ("successful completion");
60533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_INV_OPC:
61533affcbSRobert Mustacchi return ("invalid command opcode");
62533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_INV_FLD:
63533affcbSRobert Mustacchi return ("invalid field in command");
64533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_ID_CNFL:
65533affcbSRobert Mustacchi return ("command id conflict");
66533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_DATA_XFR_ERR:
67533affcbSRobert Mustacchi return ("data transfer error");
68533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_ABORT_PWRLOSS:
69533affcbSRobert Mustacchi return ("commands aborted due to power loss notification");
70533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_INTERNAL_ERR:
71533affcbSRobert Mustacchi return ("internal error");
72533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_ABORT_REQUEST:
73533affcbSRobert Mustacchi return ("command abort requested");
74533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_ABORT_SQ_DEL:
75533affcbSRobert Mustacchi return ("command aborted due to sq deletion");
76533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_ABORT_FUSE_FAIL:
77533affcbSRobert Mustacchi return ("command aborted due to failed fused command");
78533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_ABORT_FUSE_MISS:
79533affcbSRobert Mustacchi return ("command aborted due to missing fused command");
80533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_INV_NS:
81533affcbSRobert Mustacchi return ("invalid namespace or format");
82533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_CMD_SEQ_ERR:
83533affcbSRobert Mustacchi return ("command sequence error");
84533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_INV_SGL_LAST:
85533affcbSRobert Mustacchi return ("invalid sgl last segment descriptor");
86533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_INV_SGL_NUM:
87533affcbSRobert Mustacchi return ("invalid number of sgl descriptors");
88533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_INV_DSGL_LEN:
89533affcbSRobert Mustacchi return ("data sgl length invalid");
90533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_INV_MSGL_LEN:
91533affcbSRobert Mustacchi return ("metadata sgl length invalid");
92533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_INV_SGL_DESC:
93533affcbSRobert Mustacchi return ("sgl descriptor type invalid");
94533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_INV_USE_CMB:
95533affcbSRobert Mustacchi return ("invalid use of controller memory buffer");
96533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_INV_PRP_OFF:
97533affcbSRobert Mustacchi return ("prp offset invalid");
98533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_AWU_EXCEEDED:
99533affcbSRobert Mustacchi return ("atomic write unit exceeded");
100*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_OP_DENIED:
101*e7efdd31SRobert Mustacchi return ("operation denied");
102*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_INV_SGL_OFF:
103*e7efdd31SRobert Mustacchi return ("sgl offset invalid");
104*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_INV_SGL_ST:
105*e7efdd31SRobert Mustacchi return ("sgl sub type invalid");
106*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_INCON_HOSTID:
107*e7efdd31SRobert Mustacchi return ("host identifier inconsistent format");
108*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_KA_EXP:
109*e7efdd31SRobert Mustacchi return ("keep alive timer expired");
110*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_INV_KA_TO:
111*e7efdd31SRobert Mustacchi return ("keep alive timeout invalid");
112*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_ABORT_PREEMPT:
113*e7efdd31SRobert Mustacchi return ("command aborted due to preempt and abort");
114*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_SANITIZE_FAIL:
115*e7efdd31SRobert Mustacchi return ("sanitize failed");
116*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_SANITIZING:
117*e7efdd31SRobert Mustacchi return ("sanitize in progress");
118*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_INV_SGL_GRAN:
119*e7efdd31SRobert Mustacchi return ("sgl data block granularity invalid");
120*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_NO_CMD_Q_CMD:
121*e7efdd31SRobert Mustacchi return ("command not supported for queue in cmb");
122*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_NS_RDONLY:
123*e7efdd31SRobert Mustacchi return ("namespace is write protected");
124*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_CMD_INTR:
125*e7efdd31SRobert Mustacchi return ("command interrupted");
126*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_TRANSIENT:
127*e7efdd31SRobert Mustacchi return ("transient transport error");
128*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_CMD_LOCK:
129*e7efdd31SRobert Mustacchi return ("command prohibited by command and feature lockdown");
130*e7efdd31SRobert Mustacchi case NVME_CQE_SC_ADM_MEDIA_NR:
131*e7efdd31SRobert Mustacchi return ("admin command media not ready");
132533affcbSRobert Mustacchi default:
133533affcbSRobert Mustacchi return ("unknown status code");
134533affcbSRobert Mustacchi }
135533affcbSRobert Mustacchi }
136533affcbSRobert Mustacchi
137533affcbSRobert Mustacchi static const char *
nvme_sctostr_gen_csi(nvme_csi_t csi,uint32_t sct)138533affcbSRobert Mustacchi nvme_sctostr_gen_csi(nvme_csi_t csi, uint32_t sct)
139533affcbSRobert Mustacchi {
140*e7efdd31SRobert Mustacchi /*
141*e7efdd31SRobert Mustacchi * These errors are allowed for all command sets.
142*e7efdd31SRobert Mustacchi */
143533affcbSRobert Mustacchi switch (sct) {
144533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_NVM_CAP_EXC:
145533affcbSRobert Mustacchi return ("capacity exceeded");
146533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_NVM_NS_NOTRDY:
147533affcbSRobert Mustacchi return ("namespace not ready");
148533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_NVM_RSV_CNFLCT:
149533affcbSRobert Mustacchi return ("reservation conflict");
150*e7efdd31SRobert Mustacchi default:
151*e7efdd31SRobert Mustacchi break;
152*e7efdd31SRobert Mustacchi }
153*e7efdd31SRobert Mustacchi
154*e7efdd31SRobert Mustacchi switch (csi) {
155*e7efdd31SRobert Mustacchi case NVME_CSI_NVM:
156*e7efdd31SRobert Mustacchi case NVME_CSI_ZNS:
157*e7efdd31SRobert Mustacchi switch (sct) {
158*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_NVM_LBA_RANGE:
159*e7efdd31SRobert Mustacchi return ("lba out of range");
160533affcbSRobert Mustacchi case NVME_CQE_SC_GEN_NVM_FORMATTING:
161533affcbSRobert Mustacchi return ("format in progress");
162533affcbSRobert Mustacchi default:
163*e7efdd31SRobert Mustacchi break;
164533affcbSRobert Mustacchi }
165*e7efdd31SRobert Mustacchi break;
166*e7efdd31SRobert Mustacchi case NVME_CSI_KV:
167*e7efdd31SRobert Mustacchi switch (sct) {
168*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_KEY_INV_VAL:
169*e7efdd31SRobert Mustacchi return ("invalid value size");
170*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_KEY_INV_KEY:
171*e7efdd31SRobert Mustacchi return ("invalid key size");
172*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_KEY_ENOENT:
173*e7efdd31SRobert Mustacchi return ("kv key does not exist");
174*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_KEY_UNRECOV:
175*e7efdd31SRobert Mustacchi return ("unrecovered error");
176*e7efdd31SRobert Mustacchi case NVME_CQE_SC_GEN_KEY_EXISTS:
177*e7efdd31SRobert Mustacchi return ("key exists");
178*e7efdd31SRobert Mustacchi default:
179*e7efdd31SRobert Mustacchi break;
180*e7efdd31SRobert Mustacchi }
181*e7efdd31SRobert Mustacchi break;
182*e7efdd31SRobert Mustacchi default:
183*e7efdd31SRobert Mustacchi break;
184*e7efdd31SRobert Mustacchi }
185*e7efdd31SRobert Mustacchi
186*e7efdd31SRobert Mustacchi return ("unknown command set specific general status code");
187533affcbSRobert Mustacchi }
188533affcbSRobert Mustacchi
189533affcbSRobert Mustacchi static const char *
nvme_sctostr_cmd_gen(uint32_t sct)190533affcbSRobert Mustacchi nvme_sctostr_cmd_gen(uint32_t sct)
191533affcbSRobert Mustacchi {
192533affcbSRobert Mustacchi switch (sct) {
193533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_INV_CQ :
194533affcbSRobert Mustacchi return ("completion queue invalid");
195533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_INV_QID :
196533affcbSRobert Mustacchi return ("invalid queue identifier");
197533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_MAX_QSZ_EXC:
198533affcbSRobert Mustacchi return ("max queue size exceeded");
199533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_ABRT_CMD_EXC:
200533affcbSRobert Mustacchi return ("abort command limit exceeded");
201533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_ASYNC_EVREQ_EXC:
202533affcbSRobert Mustacchi return ("asynchronous event request limit");
203533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_INV_FW_SLOT:
204533affcbSRobert Mustacchi return ("invalid firmware slot");
205533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_INV_FW_IMG:
206533affcbSRobert Mustacchi return ("invalid firmware image");
207533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_INV_INT_VECT:
208533affcbSRobert Mustacchi return ("invalid interrupt vector");
209533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_INV_LOG_PAGE:
210533affcbSRobert Mustacchi return ("invalid log page");
211533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_INV_FORMAT:
212533affcbSRobert Mustacchi return ("invalid format");
213533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_FW_RESET:
214533affcbSRobert Mustacchi return ("firmware activation requires conventional reset");
215533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_INV_Q_DEL:
216533affcbSRobert Mustacchi return ("invalid queue deletion");
217533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_FEAT_SAVE:
218533affcbSRobert Mustacchi return ("feature identifier not saveable");
219533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_FEAT_CHG:
220533affcbSRobert Mustacchi return ("feature not changeable");
221533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_FEAT_NS_SPEC:
222533affcbSRobert Mustacchi return ("feature not namespace spec");
223533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_FW_NSSR :
224533affcbSRobert Mustacchi return ("firmware activation requires nvm subsystem reset");
225533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_FW_NEXT_RESET:
226533affcbSRobert Mustacchi return ("firmware activation requires controller level reset");
227533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_FW_MTFA :
228533affcbSRobert Mustacchi return ("firmware activation requires maximum time violation");
229533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_FW_PROHIBITED:
230533affcbSRobert Mustacchi return ("firmware activation prohibited");
231533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_FW_OVERLAP:
232533affcbSRobert Mustacchi return ("overlapping range");
233*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_NS_INSUF_CAP:
234*e7efdd31SRobert Mustacchi return ("namespace insufficient capacity");
235*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_NS_NO_ID:
236*e7efdd31SRobert Mustacchi return ("namespace identifier unavailable");
237*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_NS_ATTACHED:
238*e7efdd31SRobert Mustacchi return ("namespace already attached");
239*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_NS_PRIV:
240*e7efdd31SRobert Mustacchi return ("namespace is private");
241*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_NS_NOT_ATTACH:
242*e7efdd31SRobert Mustacchi return ("namespace is not attached");
243*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_THIN_ENOTSUP:
244*e7efdd31SRobert Mustacchi return ("thin provisioning not supported");
245*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_INV_CTRL_LIST:
246*e7efdd31SRobert Mustacchi return ("controller list invalid");
247*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_SELF_TESTING:
248*e7efdd31SRobert Mustacchi return ("device self-test in progress");
249*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_NO_BP_WRITE:
250*e7efdd31SRobert Mustacchi return ("boot partition write protected");
251*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_INV_CTRL_ID:
252*e7efdd31SRobert Mustacchi return ("invalid controller identifier");
253*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_INV_SEC_CTRL:
254*e7efdd31SRobert Mustacchi return ("invalid secondary controller state");
255*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_INV_CTRL_NRSRC:
256*e7efdd31SRobert Mustacchi return ("invalid number of controller resources");
257*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_INV_RSRC_ID:
258*e7efdd31SRobert Mustacchi return ("Invalid resource identifier");
259*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_NO_SAN_PMR:
260*e7efdd31SRobert Mustacchi return ("sanitize prohibited while persistent memory region "
261*e7efdd31SRobert Mustacchi "is enabled");
262*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_INV_ANA_GID:
263*e7efdd31SRobert Mustacchi return ("ana group identifier invalid");
264*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_ANA_ATTACH:
265*e7efdd31SRobert Mustacchi return ("ana attach failed");
266*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_INSUF_CAP:
267*e7efdd31SRobert Mustacchi return ("insufficient capacity");
268*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_NS_ATTACH_LIM:
269*e7efdd31SRobert Mustacchi return ("namespace attachment limit exceeded");
270*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_LOCKDOWN_UNSUP:
271*e7efdd31SRobert Mustacchi return ("prohibition of command execution not supported");
272*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_UNSUP_IO_CMD:
273*e7efdd31SRobert Mustacchi return ("I/O command set not supported");
274*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_DIS_IO_CMD:
275*e7efdd31SRobert Mustacchi return ("I/O command set not enabled");
276*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_INV_CMD_COMBO:
277*e7efdd31SRobert Mustacchi return ("I/O command set combination rejected");
278*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_INV_IO_CMD:
279*e7efdd31SRobert Mustacchi return ("Invalid I/O command set");
280*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_UNAVAIL_ID:
281*e7efdd31SRobert Mustacchi return ("identifier unavailable");
282533affcbSRobert Mustacchi default:
283533affcbSRobert Mustacchi return ("unknown generic command status code");
284533affcbSRobert Mustacchi }
285533affcbSRobert Mustacchi }
286533affcbSRobert Mustacchi
287*e7efdd31SRobert Mustacchi /*
288*e7efdd31SRobert Mustacchi * The NVMe 2.0c spec that introduces many of the zoned related errors has
289*e7efdd31SRobert Mustacchi * footnotes to suggest some of these are command set specific, but does not
290*e7efdd31SRobert Mustacchi * mark any of them. For the moment we basically assume that they're valid
291*e7efdd31SRobert Mustacchi * everywhere due to the fact that they don't overlap.
292*e7efdd31SRobert Mustacchi */
293533affcbSRobert Mustacchi static const char *
nvme_sctostr_cmd_csi(nvme_csi_t csi,uint32_t sct)294533affcbSRobert Mustacchi nvme_sctostr_cmd_csi(nvme_csi_t csi, uint32_t sct)
295533affcbSRobert Mustacchi {
296533affcbSRobert Mustacchi switch (sct) {
297533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_NVM_CNFL_ATTR:
298533affcbSRobert Mustacchi return ("conflicting attributes");
299533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_NVM_INV_PROT:
300533affcbSRobert Mustacchi return ("invalid protection");
301533affcbSRobert Mustacchi case NVME_CQE_SC_SPC_NVM_READONLY:
302533affcbSRobert Mustacchi return ("write to read only range");
303*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_ZONE_BDRY_ERR:
304*e7efdd31SRobert Mustacchi return ("zoned boundary error");
305*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_ZONE_FULL:
306*e7efdd31SRobert Mustacchi return ("zone is full");
307*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_ZONE_RDONLY:
308*e7efdd31SRobert Mustacchi return ("zone is read only");
309*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_ZONE_OFFLINE:
310*e7efdd31SRobert Mustacchi return ("zone is offline");
311*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_ZONE_INV_WRITE:
312*e7efdd31SRobert Mustacchi return ("zone invalid write");
313*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_ZONE_ACT:
314*e7efdd31SRobert Mustacchi return ("too many active zones");
315*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_ZONE_OPEN:
316*e7efdd31SRobert Mustacchi return ("too many open zones");
317*e7efdd31SRobert Mustacchi case NVME_CQE_SC_SPC_INV_ZONE_TRANS:
318*e7efdd31SRobert Mustacchi return ("invalid zone state transition");
319533affcbSRobert Mustacchi default:
320533affcbSRobert Mustacchi return ("unknown command specific, I/O command set specific "
321533affcbSRobert Mustacchi "status code");
322533affcbSRobert Mustacchi }
323533affcbSRobert Mustacchi }
324533affcbSRobert Mustacchi
325533affcbSRobert Mustacchi static const char *
nvme_sctostr_media(nvme_csi_t csi,uint32_t sct)326533affcbSRobert Mustacchi nvme_sctostr_media(nvme_csi_t csi, uint32_t sct)
327533affcbSRobert Mustacchi {
328533affcbSRobert Mustacchi if (sct >= NVME_CQE_SC_VEND_MIN) {
329533affcbSRobert Mustacchi return ("vendor specific media and data integrity status code");
330533affcbSRobert Mustacchi }
331533affcbSRobert Mustacchi
332533affcbSRobert Mustacchi /*
333533affcbSRobert Mustacchi * Unlike NVMe 1.x, NVMe 2.x declares the following command set
334533affcbSRobert Mustacchi * independent.
335533affcbSRobert Mustacchi */
336533affcbSRobert Mustacchi switch (sct) {
337533affcbSRobert Mustacchi case NVME_CQE_SC_INT_NVM_WRITE:
338533affcbSRobert Mustacchi return ("write fault");
339533affcbSRobert Mustacchi case NVME_CQE_SC_INT_NVM_READ:
340533affcbSRobert Mustacchi return ("unrecovered read error");
341533affcbSRobert Mustacchi case NVME_CQE_SC_INT_NVM_GUARD:
342533affcbSRobert Mustacchi return ("guard check error");
343533affcbSRobert Mustacchi case NVME_CQE_SC_INT_NVM_APPL_TAG:
344533affcbSRobert Mustacchi return ("application tag check err");
345533affcbSRobert Mustacchi case NVME_CQE_SC_INT_NVM_REF_TAG:
346533affcbSRobert Mustacchi return ("reference tag check err");
347533affcbSRobert Mustacchi case NVME_CQE_SC_INT_NVM_ACCESS:
348533affcbSRobert Mustacchi return ("access denied");
349*e7efdd31SRobert Mustacchi case NVME_CQE_SC_INT_NVM_TAG:
350*e7efdd31SRobert Mustacchi return ("end-to-end storage tag check error");
351*e7efdd31SRobert Mustacchi default:
352*e7efdd31SRobert Mustacchi break;
353533affcbSRobert Mustacchi }
354533affcbSRobert Mustacchi
355533affcbSRobert Mustacchi /*
356533affcbSRobert Mustacchi * The only command-set specific values are currently defined for the
357533affcbSRobert Mustacchi * NVM command set.
358533affcbSRobert Mustacchi */
359533affcbSRobert Mustacchi if (csi != NVME_CSI_NVM) {
360533affcbSRobert Mustacchi return ("unknown media and data integrity status code");
361533affcbSRobert Mustacchi }
362533affcbSRobert Mustacchi
363533affcbSRobert Mustacchi switch (sct) {
364533affcbSRobert Mustacchi case NVME_CQE_SC_INT_NVM_COMPARE:
365533affcbSRobert Mustacchi return ("compare failure");
366*e7efdd31SRobert Mustacchi case NVME_CQE_SC_INT_NVM_DEALLOC:
367*e7efdd31SRobert Mustacchi return ("deallocated or unwritten logical block");
368533affcbSRobert Mustacchi default:
369533affcbSRobert Mustacchi return ("unknown media and data integrity status code");
370533affcbSRobert Mustacchi }
371533affcbSRobert Mustacchi }
372533affcbSRobert Mustacchi
373*e7efdd31SRobert Mustacchi static const char *
nvme_sctostr_path(uint32_t sct)374*e7efdd31SRobert Mustacchi nvme_sctostr_path(uint32_t sct)
375*e7efdd31SRobert Mustacchi {
376*e7efdd31SRobert Mustacchi switch (sct) {
377*e7efdd31SRobert Mustacchi case NVME_CQE_SC_PATH_INT_ERR:
378*e7efdd31SRobert Mustacchi return ("internal path error");
379*e7efdd31SRobert Mustacchi case NVME_CQE_SC_PATH_AA_PLOSS:
380*e7efdd31SRobert Mustacchi return ("asymmetric access persistent loss");
381*e7efdd31SRobert Mustacchi case NVME_CQE_SC_PATH_AA_INACC:
382*e7efdd31SRobert Mustacchi return ("asymmetric access inaccessible");
383*e7efdd31SRobert Mustacchi case NVME_CQE_SC_PATH_AA_TRANS:
384*e7efdd31SRobert Mustacchi return ("asymmetric access transition");
385*e7efdd31SRobert Mustacchi case NVME_CQE_SC_PATH_CTRL_ERR:
386*e7efdd31SRobert Mustacchi return ("controller pathing error");
387*e7efdd31SRobert Mustacchi case NVME_CQE_SC_PATH_HOST_ERR:
388*e7efdd31SRobert Mustacchi return ("host pathing error");
389*e7efdd31SRobert Mustacchi case NVME_CQE_SC_PATH_HOST_ABRT:
390*e7efdd31SRobert Mustacchi return ("command aborted by host");
391*e7efdd31SRobert Mustacchi default:
392*e7efdd31SRobert Mustacchi return ("unknown path related status code");
393*e7efdd31SRobert Mustacchi }
394*e7efdd31SRobert Mustacchi }
395*e7efdd31SRobert Mustacchi
396533affcbSRobert Mustacchi const char *
nvme_sctostr(nvme_ctrl_t * ctrl __unused,nvme_csi_t csi,uint32_t sct,uint32_t sc)397533affcbSRobert Mustacchi nvme_sctostr(nvme_ctrl_t *ctrl __unused, nvme_csi_t csi, uint32_t sct,
398533affcbSRobert Mustacchi uint32_t sc)
399533affcbSRobert Mustacchi {
400533affcbSRobert Mustacchi switch (sct) {
401533affcbSRobert Mustacchi case NVME_CQE_SCT_GENERIC:
402533affcbSRobert Mustacchi if (sc <= NVME_CQE_SC_GEN_MAX) {
403533affcbSRobert Mustacchi return (nvme_sctostr_gen_gen(sc));
404533affcbSRobert Mustacchi } else if (sc <= NVME_CQE_SC_CSI_MAX) {
405533affcbSRobert Mustacchi return (nvme_sctostr_gen_csi(csi, sc));
406533affcbSRobert Mustacchi } else {
407533affcbSRobert Mustacchi return ("generic vendor specific status code");
408533affcbSRobert Mustacchi }
409533affcbSRobert Mustacchi case NVME_CQE_SCT_SPECIFIC:
410533affcbSRobert Mustacchi if (sc <= NVME_CQE_SC_GEN_MAX) {
411533affcbSRobert Mustacchi return (nvme_sctostr_cmd_gen(sc));
412533affcbSRobert Mustacchi } else if (sc <= NVME_CQE_SC_CSI_MAX) {
413533affcbSRobert Mustacchi return (nvme_sctostr_cmd_csi(csi, sc));
414533affcbSRobert Mustacchi } else {
415533affcbSRobert Mustacchi return ("command specific vendor specific status code");
416533affcbSRobert Mustacchi }
417533affcbSRobert Mustacchi case NVME_CQE_SCT_INTEGRITY:
418533affcbSRobert Mustacchi return (nvme_sctostr_media(csi, sc));
419*e7efdd31SRobert Mustacchi case NVME_CQE_SCT_PATH:
420*e7efdd31SRobert Mustacchi return (nvme_sctostr_path(sc));
421533affcbSRobert Mustacchi case NVME_CQE_SCT_VENDOR:
422533affcbSRobert Mustacchi return ("vendor specific");
423533affcbSRobert Mustacchi default:
424533affcbSRobert Mustacchi return ("unknown status code");
425533affcbSRobert Mustacchi }
426533affcbSRobert Mustacchi }
427533affcbSRobert Mustacchi
428533affcbSRobert Mustacchi nvme_err_t
nvme_err(nvme_t * nvme)429533affcbSRobert Mustacchi nvme_err(nvme_t *nvme)
430533affcbSRobert Mustacchi {
431533affcbSRobert Mustacchi return (nvme->nh_err.ne_err);
432533affcbSRobert Mustacchi }
433533affcbSRobert Mustacchi
434533affcbSRobert Mustacchi int32_t
nvme_syserr(nvme_t * nvme)435533affcbSRobert Mustacchi nvme_syserr(nvme_t *nvme)
436533affcbSRobert Mustacchi {
437533affcbSRobert Mustacchi return (nvme->nh_err.ne_syserr);
438533affcbSRobert Mustacchi }
439533affcbSRobert Mustacchi
440533affcbSRobert Mustacchi const char *
nvme_errmsg(nvme_t * nvme)441533affcbSRobert Mustacchi nvme_errmsg(nvme_t *nvme)
442533affcbSRobert Mustacchi {
443533affcbSRobert Mustacchi return (nvme->nh_err.ne_errmsg);
444533affcbSRobert Mustacchi }
445533affcbSRobert Mustacchi
446533affcbSRobert Mustacchi size_t
nvme_errlen(nvme_t * nvme)447533affcbSRobert Mustacchi nvme_errlen(nvme_t *nvme)
448533affcbSRobert Mustacchi {
449533affcbSRobert Mustacchi return (nvme->nh_err.ne_errlen);
450533affcbSRobert Mustacchi }
451533affcbSRobert Mustacchi
452533affcbSRobert Mustacchi const char *
nvme_errtostr(nvme_t * nvme,nvme_err_t err)453533affcbSRobert Mustacchi nvme_errtostr(nvme_t *nvme, nvme_err_t err)
454533affcbSRobert Mustacchi {
455533affcbSRobert Mustacchi switch (err) {
456533affcbSRobert Mustacchi case NVME_ERR_OK:
457533affcbSRobert Mustacchi return ("NVME_ERR_OK");
458533affcbSRobert Mustacchi case NVME_ERR_CONTROLLER:
459533affcbSRobert Mustacchi return ("NVME_ERR_CONTROLLER");
460533affcbSRobert Mustacchi case NVME_ERR_NO_MEM:
461533affcbSRobert Mustacchi return ("NVME_ERR_NO_MEM");
462533affcbSRobert Mustacchi case NVME_ERR_NO_DMA_MEM:
463533affcbSRobert Mustacchi return ("NVME_ERR_NO_DMA_MEM");
464533affcbSRobert Mustacchi case NVME_ERR_LIBDEVINFO:
465533affcbSRobert Mustacchi return ("NVME_ERR_LIBDEVINFO");
466533affcbSRobert Mustacchi case NVME_ERR_INTERNAL:
467533affcbSRobert Mustacchi return ("NVME_ERR_INTERNAL");
468533affcbSRobert Mustacchi case NVME_ERR_BAD_PTR:
469533affcbSRobert Mustacchi return ("NVME_ERR_BAD_PTR");
470533affcbSRobert Mustacchi case NVME_ERR_BAD_FLAG:
471533affcbSRobert Mustacchi return ("NVME_ERR_BAD_FLAG");
472533affcbSRobert Mustacchi case NVME_ERR_BAD_DEVI:
473533affcbSRobert Mustacchi return ("NVME_ERR_BAD_DEVI");
474533affcbSRobert Mustacchi case NVME_ERR_BAD_DEVI_PROP:
475533affcbSRobert Mustacchi return ("NVME_ERR_BAD_DEVI_PROP");
476533affcbSRobert Mustacchi case NVME_ERR_ILLEGAL_INSTANCE:
477533affcbSRobert Mustacchi return ("NVME_ERR_ILLEGAL_INSTANCE");
478533affcbSRobert Mustacchi case NVME_ERR_BAD_CONTROLLER:
479533affcbSRobert Mustacchi return ("NVME_ERR_BAD_CONTROLLER");
480533affcbSRobert Mustacchi case NVME_ERR_PRIVS:
481533affcbSRobert Mustacchi return ("NVME_ERR_PRIVS");
482533affcbSRobert Mustacchi case NVME_ERR_OPEN_DEV:
483533affcbSRobert Mustacchi return ("NVME_ERR_OPEN_DEV");
484533affcbSRobert Mustacchi case NVME_ERR_BAD_RESTORE:
485533affcbSRobert Mustacchi return ("NVME_ERR_BAD_RESTORE");
486533affcbSRobert Mustacchi case NVME_ERR_NS_RANGE:
487533affcbSRobert Mustacchi return ("NVME_ERR_NS_RANGE");
488533affcbSRobert Mustacchi case NVME_ERR_NS_UNUSE:
489533affcbSRobert Mustacchi return ("NVME_ERR_NS_UNUSE");
490533affcbSRobert Mustacchi case NVME_ERR_LOG_CSI_RANGE:
491533affcbSRobert Mustacchi return ("NVME_ERR_LOG_CSI_RANGE");
492533affcbSRobert Mustacchi case NVME_ERR_LOG_LID_RANGE:
493533affcbSRobert Mustacchi return ("NVME_ERR_LOG_LID_RANGE");
494533affcbSRobert Mustacchi case NVME_ERR_LOG_LSP_RANGE:
495533affcbSRobert Mustacchi return ("NVME_ERR_LOG_LSP_RANGE");
496533affcbSRobert Mustacchi case NVME_ERR_LOG_LSI_RANGE:
497533affcbSRobert Mustacchi return ("NVME_ERR_LOG_LSI_RANGE");
498533affcbSRobert Mustacchi case NVME_ERR_LOG_RAE_RANGE:
499533affcbSRobert Mustacchi return ("NVME_ERR_LOG_RAE_RANGE");
500533affcbSRobert Mustacchi case NVME_ERR_LOG_SIZE_RANGE:
501533affcbSRobert Mustacchi return ("NVME_ERR_LOG_SIZE_RANGE");
502533affcbSRobert Mustacchi case NVME_ERR_LOG_OFFSET_RANGE:
503533affcbSRobert Mustacchi return ("NVME_ERR_LOG_OFFSET_RANGE");
504533affcbSRobert Mustacchi case NVME_ERR_LOG_CSI_UNSUP:
505533affcbSRobert Mustacchi return ("NVME_ERR_LOG_CSI_UNSUP");
506533affcbSRobert Mustacchi case NVME_ERR_LOG_LSP_UNSUP:
507533affcbSRobert Mustacchi return ("NVME_ERR_LOG_LSP_UNSUP");
508533affcbSRobert Mustacchi case NVME_ERR_LOG_LSI_UNSUP:
509533affcbSRobert Mustacchi return ("NVME_ERR_LOG_LSI_UNSUP");
510533affcbSRobert Mustacchi case NVME_ERR_LOG_RAE_UNSUP:
511533affcbSRobert Mustacchi return ("NVME_ERR_LOG_RAE_UNSUP");
512533affcbSRobert Mustacchi case NVME_ERR_LOG_OFFSET_UNSUP:
513533affcbSRobert Mustacchi return ("NVME_ERR_LOG_OFFSET_UNSUP");
514533affcbSRobert Mustacchi case NVME_ERR_LOG_LSP_UNUSE:
515533affcbSRobert Mustacchi return ("NVME_ERR_LOG_LSP_UNUSE");
516533affcbSRobert Mustacchi case NVME_ERR_LOG_LSI_UNUSE:
517533affcbSRobert Mustacchi return ("NVME_ERR_LOG_LSI_UNUSE");
518533affcbSRobert Mustacchi case NVME_ERR_LOG_RAE_UNUSE:
519533affcbSRobert Mustacchi return ("NVME_ERR_LOG_RAE_UNUSE");
520533affcbSRobert Mustacchi case NVME_ERR_LOG_SCOPE_MISMATCH:
521533affcbSRobert Mustacchi return ("NVME_ERR_LOG_SCOPE_MISMATCH");
522533affcbSRobert Mustacchi case NVME_ERR_LOG_REQ_MISSING_FIELDS:
523533affcbSRobert Mustacchi return ("NVME_ERR_LOG_REQ_MISSING_FIELDS");
524533affcbSRobert Mustacchi case NVME_ERR_LOG_NAME_UNKNOWN:
525533affcbSRobert Mustacchi return ("NVME_ERR_LOG_NAME_UNKNOWN");
526533affcbSRobert Mustacchi case NVME_ERR_LOG_UNSUP_BY_DEV:
527533affcbSRobert Mustacchi return ("NVME_ERR_LOG_UNSUP_BY_DEV");
528533affcbSRobert Mustacchi case NVME_ERR_IDENTIFY_UNKNOWN:
529533affcbSRobert Mustacchi return ("NVME_ERR_IDENTIFY_UNKNOWN");
530533affcbSRobert Mustacchi case NVME_ERR_IDENTIFY_UNSUP_BY_DEV:
531533affcbSRobert Mustacchi return ("NVME_ERR_IDENTIFY_UNSUP_BY_DEV");
532533affcbSRobert Mustacchi case NVME_ERR_IDENTIFY_CTRLID_RANGE:
533533affcbSRobert Mustacchi return ("NVME_ERR_IDENTIFY_CTRLID_RANGE");
534533affcbSRobert Mustacchi case NVME_ERR_IDENTIFY_OUTPUT_RANGE:
535533affcbSRobert Mustacchi return ("NVME_ERR_IDENTIFY_OUTPUT_RANGE");
536533affcbSRobert Mustacchi case NVME_ERR_IDENTIFY_CTRLID_UNSUP:
537533affcbSRobert Mustacchi return ("NVME_ERR_IDENTIFY_CTRLID_UNSUP");
538533affcbSRobert Mustacchi case NVME_ERR_IDENTIFY_CTRLID_UNUSE:
539533affcbSRobert Mustacchi return ("NVME_ERR_IDENTIFY_CTRLID_UNUSE");
540533affcbSRobert Mustacchi case NVME_ERR_IDENTIFY_REQ_MISSING_FIELDS:
541533affcbSRobert Mustacchi return ("NVME_ERR_IDENTIFY_REQ_MISSING_FIELDS");
542533affcbSRobert Mustacchi case NVME_ERR_VUC_UNSUP_BY_DEV:
543533affcbSRobert Mustacchi return ("NVME_ERR_VUC_UNSUP_BY_DEV");
544533affcbSRobert Mustacchi case NVME_ERR_VUC_TIMEOUT_RANGE:
545533affcbSRobert Mustacchi return ("NVME_ERR_VUC_TIMEOUT_RANGE");
546533affcbSRobert Mustacchi case NVME_ERR_VUC_OPCODE_RANGE:
547533affcbSRobert Mustacchi return ("NVME_ERR_VUC_OPCODE_RANGE");
548533affcbSRobert Mustacchi case NVME_ERR_VUC_IMPACT_RANGE:
549533affcbSRobert Mustacchi return ("NVME_ERR_VUC_IMPACT_RANGE");
550533affcbSRobert Mustacchi case NVME_ERR_VUC_NDT_RANGE:
551533affcbSRobert Mustacchi return ("NVME_ERR_VUC_NDT_RANGE");
552533affcbSRobert Mustacchi case NVME_ERR_VUC_CANNOT_RW:
553533affcbSRobert Mustacchi return ("NVME_ERR_VUC_CANNOT_RW");
554533affcbSRobert Mustacchi case NVME_ERR_VUC_NO_RESULTS:
555533affcbSRobert Mustacchi return ("NVME_ERR_VUC_NO_RESULTS");
556533affcbSRobert Mustacchi case NVME_ERR_VUC_UNKNOWN:
557533affcbSRobert Mustacchi return ("NVME_ERR_VUC_UNKNOWN");
558533affcbSRobert Mustacchi case NVME_ERR_VUC_REQ_MISSING_FIELDS:
559533affcbSRobert Mustacchi return ("NVME_ERR_VUC_REQ_MISSING_FIELDS");
560533affcbSRobert Mustacchi case NVME_ERR_VU_FUNC_UNSUP_BY_DEV:
561533affcbSRobert Mustacchi return ("NVME_ERR_VU_FUNC_UNSUP_BY_DEV");
562533affcbSRobert Mustacchi case NVME_ERR_WDC_E6_OFFSET_RANGE:
563533affcbSRobert Mustacchi return ("NVME_ERR_WDC_E6_OFFSET_RANGE");
564533affcbSRobert Mustacchi case NVME_ERR_FW_UNSUP_BY_DEV:
565533affcbSRobert Mustacchi return ("NVME_ERR_FW_UNSUP_BY_DEV");
566533affcbSRobert Mustacchi case NVME_ERR_KERN_FW_IMPOS:
567533affcbSRobert Mustacchi return ("NVME_ERR_KERN_FW_IMPOS");
568533affcbSRobert Mustacchi case NVME_ERR_FW_LOAD_LEN_RANGE:
569533affcbSRobert Mustacchi return ("NVME_ERR_FW_LOAD_LEN_RANGE");
570533affcbSRobert Mustacchi case NVME_ERR_FW_LOAD_OFFSET_RANGE:
571533affcbSRobert Mustacchi return ("NVME_ERR_FW_LOAD_OFFSET_RANGE");
572533affcbSRobert Mustacchi case NVME_ERR_FW_COMMIT_SLOT_RANGE:
573533affcbSRobert Mustacchi return ("NVME_ERR_FW_COMMIT_SLOT_RANGE");
574533affcbSRobert Mustacchi case NVME_ERR_FW_COMMIT_ACTION_RANGE:
575533affcbSRobert Mustacchi return ("NVME_ERR_FW_COMMIT_ACTION_RANGE");
576533affcbSRobert Mustacchi case NVME_ERR_FW_COMMIT_REQ_MISSING_FIELDS:
577533affcbSRobert Mustacchi return ("NVME_ERR_FW_COMMIT_REQ_MISSING_FIELDS");
578533affcbSRobert Mustacchi case NVME_ERR_FW_SLOT_RO:
579533affcbSRobert Mustacchi return ("NVME_ERR_FW_SLOT_RO");
580533affcbSRobert Mustacchi case NVME_ERR_FORMAT_UNSUP_BY_DEV:
581533affcbSRobert Mustacchi return ("NVME_ERR_FORMAT_UNSUP_BY_DEV");
582533affcbSRobert Mustacchi case NVME_ERR_CRYPTO_SE_UNSUP_BY_DEV:
583533affcbSRobert Mustacchi return ("NVME_ERR_CRYPTO_SE_UNSUP_BY_DEV");
584533affcbSRobert Mustacchi case NVME_ERR_NS_FORMAT_UNSUP_BY_DEV:
585533affcbSRobert Mustacchi return ("NVME_ERR_NS_FORMAT_UNSUP_BY_DEV");
586533affcbSRobert Mustacchi case NVME_ERR_KERN_FORMAT_UNSUP:
587533affcbSRobert Mustacchi return ("NVME_ERR_KERN_FORMAT_UNSUP");
588533affcbSRobert Mustacchi case NVME_ERR_FORMAT_LBAF_RANGE:
589533affcbSRobert Mustacchi return ("NVME_ERR_FORMAT_LBAF_RANGE");
590533affcbSRobert Mustacchi case NVME_ERR_FORMAT_SES_RANGE:
591533affcbSRobert Mustacchi return ("NVME_ERR_FORMAT_SES_RANGE");
592533affcbSRobert Mustacchi case NVME_ERR_FORMAT_PARAM_UNSUP:
593533affcbSRobert Mustacchi return ("NVME_ERR_FORMAT_PARAM_UNSUP");
594533affcbSRobert Mustacchi case NVME_ERR_FORMAT_REQ_MISSING_FIELDS:
595533affcbSRobert Mustacchi return ("NVME_ERR_FORMAT_REQ_MISSING_FIELDS");
596533affcbSRobert Mustacchi case NVME_ERR_WDC_E6_REQ_MISSING_FIELDS:
597533affcbSRobert Mustacchi return ("NVME_ERR_WDC_E6_REQ_MISSING_FIELDS");
598533affcbSRobert Mustacchi case NVME_ERR_FEAT_NAME_UNKNOWN:
599533affcbSRobert Mustacchi return ("NVME_ERR_FEAT_NAME_UNKNOWN");
600533affcbSRobert Mustacchi case NVME_ERR_FEAT_UNSUP_BY_DEV:
601533affcbSRobert Mustacchi return ("NVME_ERR_FEAT_UNSUP_BY_DEV");
602533affcbSRobert Mustacchi case NVME_ERR_FEAT_FID_RANGE:
603533affcbSRobert Mustacchi return ("NVME_ERR_FEAT_FID_RANGE");
604533affcbSRobert Mustacchi case NVME_ERR_FEAT_SEL_RANGE:
605533affcbSRobert Mustacchi return ("NVME_ERR_FEAT_SEL_RANGE");
606533affcbSRobert Mustacchi case NVME_ERR_FEAT_CDW11_RANGE:
607533affcbSRobert Mustacchi return ("NVME_ERR_FEAT_CDW11_RANGE");
608533affcbSRobert Mustacchi case NVME_ERR_FEAT_DATA_RANGE:
609533affcbSRobert Mustacchi return ("NVME_ERR_FEAT_DATA_RANGE");
610533affcbSRobert Mustacchi case NVME_ERR_FEAT_SEL_UNSUP:
611533affcbSRobert Mustacchi return ("NVME_ERR_FEAT_SEL_UNSUP");
612533affcbSRobert Mustacchi case NVME_ERR_FEAT_CDW11_UNUSE:
613533affcbSRobert Mustacchi return ("NVME_ERR_FEAT_CDW11_UNUSE");
614533affcbSRobert Mustacchi case NVME_ERR_FEAT_DATA_UNUSE:
615533affcbSRobert Mustacchi return ("NVME_ERR_FEAT_DATA_UNUSE");
616533affcbSRobert Mustacchi case NVME_ERR_FEAT_NO_RESULTS:
617533affcbSRobert Mustacchi return ("NVME_ERR_FEAT_NO_RESULTS");
618533affcbSRobert Mustacchi case NVME_ERR_GET_FEAT_REQ_MISSING_FIELDS:
619533affcbSRobert Mustacchi return ("NVME_ERR_GET_FEAT_REQ_MISSING_FIELDS");
620533affcbSRobert Mustacchi case NVME_ERR_NEED_CTRL_WRLOCK:
621533affcbSRobert Mustacchi return ("NVME_ERR_NEED_CTRL_WRLOCK");
622533affcbSRobert Mustacchi case NVME_ERR_NEED_NS_WRLOCK:
623533affcbSRobert Mustacchi return ("NVME_ERR_NEED_NS_WRLOCK");
624533affcbSRobert Mustacchi case NVME_ERR_CTRL_LOCKED:
625533affcbSRobert Mustacchi return ("NVME_ERR_CTRL_LOCKED");
626533affcbSRobert Mustacchi case NVME_ERR_NS_LOCKED:
627533affcbSRobert Mustacchi return ("NVME_ERR_NS_LOCKED");
628533affcbSRobert Mustacchi case NVME_ERR_LOCK_PROG:
629533affcbSRobert Mustacchi return ("NVME_ERR_LOCK_PROG");
630533affcbSRobert Mustacchi case NVME_ERR_LOCK_ORDER:
631533affcbSRobert Mustacchi return ("NVME_ERR_LOCK_ORDER");
632533affcbSRobert Mustacchi case NVME_ERR_LOCK_WAIT_INTR:
633533affcbSRobert Mustacchi return ("NVME_ERR_LOCK_WAIT_INTR");
634533affcbSRobert Mustacchi case NVME_ERR_LOCK_WOULD_BLOCK:
635533affcbSRobert Mustacchi return ("NVME_ERR_LOCK_WOULD_BLOCK");
636533affcbSRobert Mustacchi case NVME_ERR_DETACH_KERN:
637533affcbSRobert Mustacchi return ("NVME_ERR_DETACH_KERN");
638533affcbSRobert Mustacchi case NVME_ERR_ATTACH_KERN:
639533affcbSRobert Mustacchi return ("NVME_ERR_ATTACH_KERN");
640533affcbSRobert Mustacchi case NVME_ERR_ATTACH_UNSUP_KERN:
641533affcbSRobert Mustacchi return ("NVME_ERR_ATTACH_UNSUP_KERN");
642533affcbSRobert Mustacchi case NVME_ERR_NS_BLKDEV_ATTACH:
643533affcbSRobert Mustacchi return ("NVME_ERR_NS_BLKDEV_ATTACH");
644533affcbSRobert Mustacchi case NVME_ERR_NO_KERN_MEM:
645533affcbSRobert Mustacchi return ("NVME_ERR_NO_KERN_MEM");
646533affcbSRobert Mustacchi case NVME_ERR_CTRL_DEAD:
647533affcbSRobert Mustacchi return ("NVME_ERR_CTRL_DEAD");
648533affcbSRobert Mustacchi case NVME_ERR_CTRL_GONE:
649533affcbSRobert Mustacchi return ("NVME_ERR_CTRL_GONE");
650533affcbSRobert Mustacchi default:
651533affcbSRobert Mustacchi return ("unknown error");
652533affcbSRobert Mustacchi }
653533affcbSRobert Mustacchi }
654533affcbSRobert Mustacchi
655533affcbSRobert Mustacchi nvme_err_t
nvme_ctrl_err(nvme_ctrl_t * ctrl)656533affcbSRobert Mustacchi nvme_ctrl_err(nvme_ctrl_t *ctrl)
657533affcbSRobert Mustacchi {
658533affcbSRobert Mustacchi return (ctrl->nc_err.ne_err);
659533affcbSRobert Mustacchi }
660533affcbSRobert Mustacchi
661533affcbSRobert Mustacchi int32_t
nvme_ctrl_syserr(nvme_ctrl_t * ctrl)662533affcbSRobert Mustacchi nvme_ctrl_syserr(nvme_ctrl_t *ctrl)
663533affcbSRobert Mustacchi {
664533affcbSRobert Mustacchi return (ctrl->nc_err.ne_syserr);
665533affcbSRobert Mustacchi }
666533affcbSRobert Mustacchi
667533affcbSRobert Mustacchi const char *
nvme_ctrl_errmsg(nvme_ctrl_t * ctrl)668533affcbSRobert Mustacchi nvme_ctrl_errmsg(nvme_ctrl_t *ctrl)
669533affcbSRobert Mustacchi {
670533affcbSRobert Mustacchi return (ctrl->nc_err.ne_errmsg);
671533affcbSRobert Mustacchi }
672533affcbSRobert Mustacchi
673533affcbSRobert Mustacchi size_t
nvme_ctrl_errlen(nvme_ctrl_t * ctrl)674533affcbSRobert Mustacchi nvme_ctrl_errlen(nvme_ctrl_t *ctrl)
675533affcbSRobert Mustacchi {
676533affcbSRobert Mustacchi return (ctrl->nc_err.ne_errlen);
677533affcbSRobert Mustacchi }
678533affcbSRobert Mustacchi
679533affcbSRobert Mustacchi void
nvme_ctrl_deverr(nvme_ctrl_t * ctrl,uint32_t * sct,uint32_t * sc)680533affcbSRobert Mustacchi nvme_ctrl_deverr(nvme_ctrl_t *ctrl, uint32_t *sct, uint32_t *sc)
681533affcbSRobert Mustacchi {
682533affcbSRobert Mustacchi if (sct != NULL) {
683533affcbSRobert Mustacchi *sct = ctrl->nc_err.ne_ctrl_sct;
684533affcbSRobert Mustacchi }
685533affcbSRobert Mustacchi
686533affcbSRobert Mustacchi if (sc != NULL) {
687533affcbSRobert Mustacchi *sc = ctrl->nc_err.ne_ctrl_sc;
688533affcbSRobert Mustacchi }
689533affcbSRobert Mustacchi }
690533affcbSRobert Mustacchi
691533affcbSRobert Mustacchi const char *
nvme_ctrl_errtostr(nvme_ctrl_t * ctrl,nvme_err_t err)692533affcbSRobert Mustacchi nvme_ctrl_errtostr(nvme_ctrl_t *ctrl, nvme_err_t err)
693533affcbSRobert Mustacchi {
694533affcbSRobert Mustacchi return (nvme_errtostr(ctrl->nc_nvme, err));
695533affcbSRobert Mustacchi }
696533affcbSRobert Mustacchi
697533affcbSRobert Mustacchi static void
nvme_error_common(nvme_err_data_t * ep,nvme_err_t err,int32_t sys,const char * fmt,va_list ap)698533affcbSRobert Mustacchi nvme_error_common(nvme_err_data_t *ep, nvme_err_t err, int32_t sys,
699533affcbSRobert Mustacchi const char *fmt, va_list ap)
700533affcbSRobert Mustacchi {
701533affcbSRobert Mustacchi int ret;
702533affcbSRobert Mustacchi
703533affcbSRobert Mustacchi ep->ne_err = err;
704533affcbSRobert Mustacchi ep->ne_syserr = sys;
705533affcbSRobert Mustacchi ep->ne_ctrl_sct = 0;
706533affcbSRobert Mustacchi ep->ne_ctrl_sc = 0;
707533affcbSRobert Mustacchi ret = vsnprintf(ep->ne_errmsg,
708533affcbSRobert Mustacchi sizeof (ep->ne_errmsg), fmt, ap);
709533affcbSRobert Mustacchi if (ret >= sizeof (ep->ne_errmsg)) {
710533affcbSRobert Mustacchi ep->ne_errlen = sizeof (ep->ne_errmsg) - 1;
711533affcbSRobert Mustacchi } else if (ret <= 0) {
712533affcbSRobert Mustacchi ep->ne_errlen = 0;
713533affcbSRobert Mustacchi ep->ne_errmsg[0] = '\0';
714533affcbSRobert Mustacchi } else {
715533affcbSRobert Mustacchi ep->ne_errlen = (size_t)ret;
716533affcbSRobert Mustacchi }
717533affcbSRobert Mustacchi }
718533affcbSRobert Mustacchi
719533affcbSRobert Mustacchi bool
nvme_error(nvme_t * nvme,nvme_err_t err,int32_t sys,const char * fmt,...)720533affcbSRobert Mustacchi nvme_error(nvme_t *nvme, nvme_err_t err, int32_t sys, const char *fmt, ...)
721533affcbSRobert Mustacchi {
722533affcbSRobert Mustacchi va_list ap;
723533affcbSRobert Mustacchi
724533affcbSRobert Mustacchi va_start(ap, fmt);
725533affcbSRobert Mustacchi nvme_error_common(&nvme->nh_err, err, sys, fmt, ap);
726533affcbSRobert Mustacchi va_end(ap);
727533affcbSRobert Mustacchi
728533affcbSRobert Mustacchi return (false);
729533affcbSRobert Mustacchi }
730533affcbSRobert Mustacchi
731533affcbSRobert Mustacchi bool
nvme_ctrl_error(nvme_ctrl_t * ctrl,nvme_err_t err,int32_t sys,const char * fmt,...)732533affcbSRobert Mustacchi nvme_ctrl_error(nvme_ctrl_t *ctrl, nvme_err_t err, int32_t sys,
733533affcbSRobert Mustacchi const char *fmt, ...)
734533affcbSRobert Mustacchi {
735533affcbSRobert Mustacchi va_list ap;
736533affcbSRobert Mustacchi
737533affcbSRobert Mustacchi va_start(ap, fmt);
738533affcbSRobert Mustacchi nvme_error_common(&ctrl->nc_err, err, sys, fmt, ap);
739533affcbSRobert Mustacchi va_end(ap);
740533affcbSRobert Mustacchi
741533affcbSRobert Mustacchi return (false);
742533affcbSRobert Mustacchi }
743533affcbSRobert Mustacchi
744533affcbSRobert Mustacchi static bool
nvme_success_common(nvme_err_data_t * err)745533affcbSRobert Mustacchi nvme_success_common(nvme_err_data_t *err)
746533affcbSRobert Mustacchi {
747533affcbSRobert Mustacchi err->ne_err = NVME_ERR_OK;
748533affcbSRobert Mustacchi err->ne_syserr = 0;
749533affcbSRobert Mustacchi err->ne_ctrl_sct = 0;
750533affcbSRobert Mustacchi err->ne_ctrl_sc = 0;
751533affcbSRobert Mustacchi err->ne_errmsg[0] = '\0';
752533affcbSRobert Mustacchi err->ne_errlen = 0;
753533affcbSRobert Mustacchi
754533affcbSRobert Mustacchi return (true);
755533affcbSRobert Mustacchi }
756533affcbSRobert Mustacchi
757533affcbSRobert Mustacchi bool
nvme_success(nvme_t * nvme)758533affcbSRobert Mustacchi nvme_success(nvme_t *nvme)
759533affcbSRobert Mustacchi {
760533affcbSRobert Mustacchi return (nvme_success_common(&nvme->nh_err));
761533affcbSRobert Mustacchi }
762533affcbSRobert Mustacchi
763533affcbSRobert Mustacchi bool
nvme_ctrl_success(nvme_ctrl_t * ctrl)764533affcbSRobert Mustacchi nvme_ctrl_success(nvme_ctrl_t *ctrl)
765533affcbSRobert Mustacchi {
766533affcbSRobert Mustacchi return (nvme_success_common(&ctrl->nc_err));
767533affcbSRobert Mustacchi }
768533affcbSRobert Mustacchi
769533affcbSRobert Mustacchi void
nvme_err_save(const nvme_t * nvme,nvme_err_data_t * out)770533affcbSRobert Mustacchi nvme_err_save(const nvme_t *nvme, nvme_err_data_t *out)
771533affcbSRobert Mustacchi {
772533affcbSRobert Mustacchi *out = nvme->nh_err;
773533affcbSRobert Mustacchi }
774533affcbSRobert Mustacchi
775533affcbSRobert Mustacchi void
nvme_err_set(nvme_t * nvme,const nvme_err_data_t * err)776533affcbSRobert Mustacchi nvme_err_set(nvme_t *nvme, const nvme_err_data_t *err)
777533affcbSRobert Mustacchi {
778533affcbSRobert Mustacchi nvme->nh_err = *err;
779533affcbSRobert Mustacchi }
780533affcbSRobert Mustacchi
781533affcbSRobert Mustacchi void
nvme_ctrl_err_save(const nvme_ctrl_t * ctrl,nvme_err_data_t * out)782533affcbSRobert Mustacchi nvme_ctrl_err_save(const nvme_ctrl_t *ctrl, nvme_err_data_t *out)
783533affcbSRobert Mustacchi {
784533affcbSRobert Mustacchi *out = ctrl->nc_err;
785533affcbSRobert Mustacchi }
786533affcbSRobert Mustacchi
787533affcbSRobert Mustacchi void
nvme_ctrl_err_set(nvme_ctrl_t * ctrl,const nvme_err_data_t * err)788533affcbSRobert Mustacchi nvme_ctrl_err_set(nvme_ctrl_t *ctrl, const nvme_err_data_t *err)
789533affcbSRobert Mustacchi {
790533affcbSRobert Mustacchi ctrl->nc_err = *err;
791533affcbSRobert Mustacchi }
792533affcbSRobert Mustacchi
793533affcbSRobert Mustacchi /*
794533affcbSRobert Mustacchi * This table deals with mapping a kernel error to a library error and provides
795533affcbSRobert Mustacchi * a short description of what it is. Note, we do not expect all kernel errors
796533affcbSRobert Mustacchi * to occur and we may want to revisit which of these end up indicating a
797533affcbSRobert Mustacchi * programmer error that we caused somehow.
798533affcbSRobert Mustacchi */
799533affcbSRobert Mustacchi typedef struct {
800533affcbSRobert Mustacchi nvme_ioctl_errno_t kl_kern;
801533affcbSRobert Mustacchi nvme_err_t kl_lib;
802533affcbSRobert Mustacchi const char *kl_desc;
803533affcbSRobert Mustacchi } nvme_ktolmap_t;
804533affcbSRobert Mustacchi
805533affcbSRobert Mustacchi /*
806533affcbSRobert Mustacchi * Please keep this table ordered based on the nvme_ioctl_error_t enumeration
807533affcbSRobert Mustacchi * order. This is not required for correctness, but helps when scanning for
808533affcbSRobert Mustacchi * missing entries. Please document why certain entries are skipped.
809533affcbSRobert Mustacchi */
810533affcbSRobert Mustacchi static const nvme_ktolmap_t nvme_ktolmap[] = {
811533affcbSRobert Mustacchi /*
812533affcbSRobert Mustacchi * NVME_IOCTL_E_OK and NVME_IOCTL_E_CTRL_ERROR should already have been
813533affcbSRobert Mustacchi * dealt with and shouldn't be included here.
814533affcbSRobert Mustacchi */
815533affcbSRobert Mustacchi { NVME_IOCTL_E_CTRL_DEAD, NVME_ERR_CTRL_DEAD, "the controller is no "
816533affcbSRobert Mustacchi "longer usable by the system" },
817533affcbSRobert Mustacchi { NVME_IOCTL_E_CTRL_GONE, NVME_ERR_CTRL_GONE, "the controller has been "
818533affcbSRobert Mustacchi "physically removed from the system" },
819533affcbSRobert Mustacchi { NVME_IOCTL_E_NS_RANGE, NVME_ERR_NS_RANGE, "invalid namespace "
820533affcbSRobert Mustacchi "requested" },
821533affcbSRobert Mustacchi { NVME_IOCTL_E_NS_UNUSE, NVME_ERR_NS_UNUSE, "a namespace ID may not be "
822533affcbSRobert Mustacchi "specified in this context" },
823533affcbSRobert Mustacchi /*
824533affcbSRobert Mustacchi * We have purposefully skipped NVME_IOCTL_E_MINOR_WRONG_NS and
825533affcbSRobert Mustacchi * NVME_IOCTL_E_NOT_CTRL as the library should not ever use the
826533affcbSRobert Mustacchi * namespace minor.
827533affcbSRobert Mustacchi */
828533affcbSRobert Mustacchi { NVME_IOCTL_E_NO_BCAST_NS, NVME_ERR_NS_RANGE, "the broadcast "
829533affcbSRobert Mustacchi "namespace may not be used in this context" },
830533affcbSRobert Mustacchi { NVME_IOCTL_E_NEED_CTRL_WRLOCK, NVME_ERR_NEED_CTRL_WRLOCK, "operation "
831533affcbSRobert Mustacchi "requires a controller write lock, but it is not owned" },
832533affcbSRobert Mustacchi { NVME_IOCTL_E_NEED_NS_WRLOCK, NVME_ERR_NEED_NS_WRLOCK, "operation "
833533affcbSRobert Mustacchi "requires a namespace write lock, but it is not owned" },
834533affcbSRobert Mustacchi { NVME_IOCTL_E_CTRL_LOCKED, NVME_ERR_CTRL_LOCKED, "controller locked" },
835533affcbSRobert Mustacchi { NVME_IOCTL_E_NS_LOCKED, NVME_ERR_NS_LOCKED, "namespace locked" },
836533affcbSRobert Mustacchi /*
837533affcbSRobert Mustacchi * We have purposefully skipped NVME_IOCTL_E_UNKNOWN_LOG_PAGE as in
838533affcbSRobert Mustacchi * theory the library and kernel should be in sync with the set of known
839533affcbSRobert Mustacchi * log pages. If it is out of sync due to someone distributing the two
840533affcbSRobert Mustacchi * weirdly or a bad build, we'd rather that end up as an internal error
841533affcbSRobert Mustacchi * rather than a first class error for users.
842533affcbSRobert Mustacchi */
843533affcbSRobert Mustacchi { NVME_IOCTL_E_UNSUP_LOG_PAGE, NVME_ERR_LOG_UNSUP_BY_DEV, "controller "
844533affcbSRobert Mustacchi "does not support the specified log page" },
845533affcbSRobert Mustacchi { NVME_IOCTL_E_BAD_LOG_SCOPE, NVME_ERR_LOG_SCOPE_MISMATCH, "log page "
846533affcbSRobert Mustacchi "does not work with the requested scope" },
847533affcbSRobert Mustacchi { NVME_IOCTL_E_LOG_CSI_RANGE, NVME_ERR_LOG_CSI_RANGE, "invalid command "
848533affcbSRobert Mustacchi "set interface value" },
849533affcbSRobert Mustacchi { NVME_IOCTL_E_LOG_LID_RANGE, NVME_ERR_LOG_LID_RANGE, "invalid log "
850533affcbSRobert Mustacchi "identifier value" },
851533affcbSRobert Mustacchi { NVME_IOCTL_E_LOG_LSP_RANGE, NVME_ERR_LOG_LSP_RANGE, "invalid log "
852533affcbSRobert Mustacchi "specific parameter value" },
853533affcbSRobert Mustacchi { NVME_IOCTL_E_LOG_LSI_RANGE, NVME_ERR_LOG_LSI_RANGE, "invalid log "
854533affcbSRobert Mustacchi "specific identifier value" },
855533affcbSRobert Mustacchi { NVME_IOCTL_E_LOG_RAE_RANGE, NVME_ERR_LOG_SIZE_RANGE, "invalid retain "
856533affcbSRobert Mustacchi "asynchronous event value" },
857533affcbSRobert Mustacchi { NVME_IOCTL_E_LOG_SIZE_RANGE, NVME_ERR_LOG_SIZE_RANGE, "invalid log "
858533affcbSRobert Mustacchi "length value" },
859533affcbSRobert Mustacchi { NVME_IOCTL_E_LOG_OFFSET_RANGE, NVME_ERR_LOG_OFFSET_RANGE, "invalid "
860533affcbSRobert Mustacchi "log offset value" },
861533affcbSRobert Mustacchi { NVME_IOCTL_E_LOG_CSI_UNSUP, NVME_ERR_LOG_CSI_UNSUP,
862533affcbSRobert Mustacchi "the controller does not support specifying the csi" },
863533affcbSRobert Mustacchi { NVME_IOCTL_E_LOG_LSP_UNSUP, NVME_ERR_LOG_LSP_UNSUP,
864533affcbSRobert Mustacchi "the controller does not support specifying the lsp" },
865533affcbSRobert Mustacchi { NVME_IOCTL_E_LOG_LSI_UNSUP, NVME_ERR_LOG_LSI_UNSUP,
866533affcbSRobert Mustacchi "or controller do not support specifying the lsi" },
867533affcbSRobert Mustacchi { NVME_IOCTL_E_LOG_RAE_UNSUP, NVME_ERR_LOG_RAE_UNSUP,
868533affcbSRobert Mustacchi "the controller does not support retaining an asynchronous event" },
869533affcbSRobert Mustacchi { NVME_IOCTL_E_LOG_OFFSET_UNSUP, NVME_ERR_LOG_OFFSET_UNSUP,
870533affcbSRobert Mustacchi "the controller do not support specifying a a read offset" },
871533affcbSRobert Mustacchi { NVME_IOCTL_E_LOG_LSP_UNUSE, NVME_ERR_LOG_LSP_UNUSE, "the log page "
872533affcbSRobert Mustacchi "does not allow the lsp to be used" },
873533affcbSRobert Mustacchi { NVME_IOCTL_E_LOG_LSI_UNUSE, NVME_ERR_LOG_LSI_UNUSE, "the log page "
874533affcbSRobert Mustacchi "does not allow the lsi to be used" },
875533affcbSRobert Mustacchi { NVME_IOCTL_E_LOG_RAE_UNUSE, NVME_ERR_LOG_RAE_UNUSE, "the log page "
876533affcbSRobert Mustacchi "does not allow rae to be set" },
877533affcbSRobert Mustacchi { NVME_IOCTL_E_NO_DMA_MEM, NVME_ERR_NO_DMA_MEM, "the kernel failed to "
878533affcbSRobert Mustacchi "allocate sufficient DMA resources" },
879533affcbSRobert Mustacchi { NVME_IOCTL_E_NO_KERN_MEM, NVME_ERR_NO_KERN_MEM, "the kernel failed "
880533affcbSRobert Mustacchi "to allocate sufficient memory for this operation" },
881533affcbSRobert Mustacchi { NVME_IOCTL_E_BAD_PRP, NVME_ERR_INTERNAL, "a driver error occurred "
882533affcbSRobert Mustacchi "while filling out the command's DMA resources" },
883533affcbSRobert Mustacchi { NVME_IOCTL_E_BAD_USER_DATA, NVME_ERR_BAD_PTR, "the kernel "
884533affcbSRobert Mustacchi "detected an invalid user buffer while trying to read/write the "
885533affcbSRobert Mustacchi "passed in data buffer" },
886533affcbSRobert Mustacchi { NVME_IOCTL_E_UNKNOWN_IDENTIFY, NVME_ERR_IDENTIFY_UNKNOWN, "unknown "
887533affcbSRobert Mustacchi "identify command requested" },
888533affcbSRobert Mustacchi { NVME_IOCTL_E_UNSUP_IDENTIFY, NVME_ERR_IDENTIFY_UNSUP_BY_DEV,
889533affcbSRobert Mustacchi "controller does not support the requested identify command" },
890533affcbSRobert Mustacchi { NVME_IOCTL_E_IDENTIFY_CTRLID_RANGE, NVME_ERR_IDENTIFY_CTRLID_RANGE,
891533affcbSRobert Mustacchi "invalid controller id value" },
892533affcbSRobert Mustacchi { NVME_IOCTL_E_IDENTIFY_CTRLID_UNSUP, NVME_ERR_IDENTIFY_CTRLID_UNSUP,
893533affcbSRobert Mustacchi "the controller does not support specifying the controller ID" },
894533affcbSRobert Mustacchi { NVME_IOCTL_E_IDENTIFY_CTRLID_UNUSE, NVME_ERR_IDENTIFY_CTRLID_UNUSE,
895533affcbSRobert Mustacchi "this specific identify request does not allow setting the "
896533affcbSRobert Mustacchi "controller id" },
897533affcbSRobert Mustacchi { NVME_IOCTL_E_CTRL_VUC_UNSUP, NVME_ERR_VUC_UNSUP_BY_DEV,
898533affcbSRobert Mustacchi "the controller does not support standard NVMe vendor unique "
899533affcbSRobert Mustacchi "commands" },
900533affcbSRobert Mustacchi /*
901533affcbSRobert Mustacchi * The following indicate bad values for given NVMe vendor unique
902533affcbSRobert Mustacchi * command fields. Note, we do not include an entry for
903533affcbSRobert Mustacchi * NVME_IOCTL_E_VUC_FLAGS_RANGE because these flags are entirely owned
904533affcbSRobert Mustacchi * by the library.
905533affcbSRobert Mustacchi */
906533affcbSRobert Mustacchi { NVME_IOCTL_E_VUC_TIMEOUT_RANGE, NVME_ERR_VUC_TIMEOUT_RANGE, "invalid "
907533affcbSRobert Mustacchi "command timeout value" },
908533affcbSRobert Mustacchi { NVME_IOCTL_E_VUC_OPCODE_RANGE, NVME_ERR_VUC_OPCODE_RANGE, "invalid "
909533affcbSRobert Mustacchi "vendor unique opcode specified" },
910533affcbSRobert Mustacchi { NVME_IOCTL_E_VUC_IMPACT_RANGE, NVME_ERR_VUC_IMPACT_RANGE, "invalid "
911533affcbSRobert Mustacchi "vendor unique impact specified" },
912533affcbSRobert Mustacchi { NVME_IOCTL_E_VUC_NDT_RANGE, NVME_ERR_VUC_NDT_RANGE, "invalid "
913533affcbSRobert Mustacchi "data transfer size specified" },
914533affcbSRobert Mustacchi /*
915533affcbSRobert Mustacchi * We skip NVME_IOCTL_E_INCONSIST_VUC_FLAGS_NDT and
916533affcbSRobert Mustacchi * NVME_IOCTL_E_INCONSIST_VUC_BUF_NDT because these are solely under the
917533affcbSRobert Mustacchi * library control and would indicate a programming error at our end.
918533affcbSRobert Mustacchi * The user shouldn't be able to cause this.
919533affcbSRobert Mustacchi */
920533affcbSRobert Mustacchi { NVME_IOCTL_E_BLKDEV_DETACH, NVME_ERR_DETACH_KERN, "the kernel failed "
921533affcbSRobert Mustacchi "to detach the requested namespace" },
922533affcbSRobert Mustacchi { NVME_IOCTL_E_BLKDEV_ATTACH, NVME_ERR_ATTACH_KERN, "the kernel failed "
923533affcbSRobert Mustacchi "to attach the requested namespace" },
924533affcbSRobert Mustacchi { NVME_IOCTL_E_UNSUP_ATTACH_NS, NVME_ERR_ATTACH_UNSUP_KERN,
925533affcbSRobert Mustacchi "the namespace is not supported by the kernel" },
926533affcbSRobert Mustacchi { NVME_IOCTL_E_CTRL_FORMAT_UNSUP, NVME_ERR_FORMAT_UNSUP_BY_DEV, "the "
927533affcbSRobert Mustacchi "controller does not support formatting namespaces" },
928533affcbSRobert Mustacchi { NVME_IOCTL_E_CTRL_CRYPTO_SE_UNSUP, NVME_ERR_CRYPTO_SE_UNSUP_BY_DEV,
929533affcbSRobert Mustacchi "the controller does not support cryptographic secure erase" },
930533affcbSRobert Mustacchi { NVME_IOCTL_E_CTRL_NS_FORMAT_UNSUP, NVME_ERR_NS_FORMAT_UNSUP_BY_DEV,
931533affcbSRobert Mustacchi "the controller cannot format a single namespace" },
932533affcbSRobert Mustacchi { NVME_IOCTL_E_CTRL_NS_SE_UNSUP, NVME_ERR_NS_FORMAT_UNSUP_BY_DEV,
933533affcbSRobert Mustacchi "the controller cannot secure erase a single namespace" },
934533affcbSRobert Mustacchi { NVME_IOCTL_E_FORMAT_LBAF_RANGE, NVME_ERR_FORMAT_LBAF_RANGE,
935533affcbSRobert Mustacchi "invalid LBA format value" },
936533affcbSRobert Mustacchi { NVME_IOCTL_E_FORMAT_SES_RANGE, NVME_ERR_FORMAT_SES_RANGE,
937533affcbSRobert Mustacchi "invalid secure erase settings value" },
938533affcbSRobert Mustacchi { NVME_IOCTL_E_UNSUP_LBAF_META, NVME_ERR_KERN_FORMAT_UNSUP, "cannot "
939533affcbSRobert Mustacchi "format due to the use of unsupported metadata sectors" },
940533affcbSRobert Mustacchi { NVME_IOCTL_E_CTRL_FW_UNSUP, NVME_ERR_FW_UNSUP_BY_DEV, "the "
941533affcbSRobert Mustacchi "controller does not support firmware commands" },
942533affcbSRobert Mustacchi { NVME_IOCTL_E_FW_LOAD_IMPOS_GRAN, NVME_ERR_KERN_FW_IMPOS, "controller "
943533affcbSRobert Mustacchi "reported firmware upgrade granularity does not work with the "
944533affcbSRobert Mustacchi "calculated maximum DMA transfer size" },
945533affcbSRobert Mustacchi { NVME_IOCTL_E_FW_LOAD_LEN_RANGE, NVME_ERR_FW_LOAD_LEN_RANGE,
946533affcbSRobert Mustacchi "invalid firmware load length value" },
947533affcbSRobert Mustacchi { NVME_IOCTL_E_FW_LOAD_OFFSET_RANGE, NVME_ERR_FW_LOAD_OFFSET_RANGE,
948533affcbSRobert Mustacchi "invalid firmware load offset value" },
949533affcbSRobert Mustacchi { NVME_IOCTL_E_FW_COMMIT_SLOT_RANGE, NVME_ERR_FW_COMMIT_SLOT_RANGE,
950533affcbSRobert Mustacchi "invalid firmware commit slot value" },
951533affcbSRobert Mustacchi { NVME_IOCTL_E_FW_COMMIT_ACTION_RANGE, NVME_ERR_FW_COMMIT_ACTION_RANGE,
952533affcbSRobert Mustacchi "invalid firmware commit action value" },
953533affcbSRobert Mustacchi { NVME_IOCTL_E_RO_FW_SLOT, NVME_ERR_FW_SLOT_RO, "cannot write to read-"
954533affcbSRobert Mustacchi "only slot" },
955533affcbSRobert Mustacchi /*
956533affcbSRobert Mustacchi * We have purposefully skipped NVME_IOCTL_E_UNKNOWN_FEATURE for the
957533affcbSRobert Mustacchi * same reasons we did with NVME_IOCTL_E_UNKNOWN_LOG above.
958533affcbSRobert Mustacchi */
959533affcbSRobert Mustacchi { NVME_IOCTL_E_UNSUP_FEATURE, NVME_ERR_FEAT_UNSUP_BY_DEV, "the "
960533affcbSRobert Mustacchi "controller does not supported the requested feature" },
961533affcbSRobert Mustacchi { NVME_IOCTL_E_GET_FEAT_SEL_RANGE, NVME_ERR_FEAT_SEL_RANGE, "invalid "
962533affcbSRobert Mustacchi "feature selector value" },
963533affcbSRobert Mustacchi { NVME_IOCTL_E_GET_FEAT_CDW11_RANGE, NVME_ERR_FEAT_CDW11_RANGE,
964533affcbSRobert Mustacchi "invalid feature-specific cdw11 value" },
965533affcbSRobert Mustacchi { NVME_IOCTL_E_GET_FEAT_DATA_RANGE, NVME_ERR_FEAT_DATA_RANGE, "invalid "
966533affcbSRobert Mustacchi "feature data, likely a size mismatch" },
967533affcbSRobert Mustacchi { NVME_IOCTL_E_GET_FEAT_SEL_UNSUP, NVME_ERR_FEAT_SEL_UNSUP, "the "
968533affcbSRobert Mustacchi "controller does not support specifying a feature selector" },
969533affcbSRobert Mustacchi { NVME_IOCTL_E_GET_FEAT_CDW11_UNUSE, NVME_ERR_FEAT_CDW11_UNUSE,
970533affcbSRobert Mustacchi "the feature does not support specifying a cdw11 argument" },
971533affcbSRobert Mustacchi { NVME_IOCTL_E_GET_FEAT_DATA_UNUSE, NVME_ERR_FEAT_DATA_UNUSE,
972533affcbSRobert Mustacchi "the feature does not support specifying a data buffer" },
973533affcbSRobert Mustacchi /*
974533affcbSRobert Mustacchi * We skip the NVME_IOCTL_E_BAD_LOCK_ENTITY,
975533affcbSRobert Mustacchi * NVME_IOCTL_E_BAD_LOCK_LEVEL, and NVME_IOCTL_E_BAD_LOCK_FLAGS
976533affcbSRobert Mustacchi * arguments as these are all generally passed by the library and not
977533affcbSRobert Mustacchi * really under direct user control. Therefore if there is a problem,
978533affcbSRobert Mustacchi * that should be an internal error.
979533affcbSRobert Mustacchi *
980533affcbSRobert Mustacchi * Similarly we skip NVME_IOCTL_E_NS_CANNOT_LOCK_CTRL and
981533affcbSRobert Mustacchi * NVME_IOCTL_E_NS_CANNOT_UNLOCK_CTRL because the library does not
982533affcbSRobert Mustacchi * utilize namespace minors and these can only apply to those.
983533affcbSRobert Mustacchi */
984533affcbSRobert Mustacchi { NVME_IOCTL_E_LOCK_ALREADY_HELD, NVME_ERR_LOCK_PROG, "fatal "
985533affcbSRobert Mustacchi "programmer error: recursive lock attempt" },
986533affcbSRobert Mustacchi { NVME_IOCTL_E_LOCK_NO_CTRL_WITH_NS, NVME_ERR_LOCK_ORDER,
987533affcbSRobert Mustacchi "control locks cannot be acquired while holding a namespace lock" },
988533affcbSRobert Mustacchi { NVME_IOCTL_LOCK_NO_NS_WITH_CTRL_WRLOCK, NVME_ERR_LOCK_ORDER,
989533affcbSRobert Mustacchi "no namespace locks may be acquired while holding a controller "
990533affcbSRobert Mustacchi "write lock" },
991533affcbSRobert Mustacchi { NVME_IOCTL_E_LOCK_NO_2ND_NS, NVME_ERR_LOCK_ORDER, "only a single "
992533affcbSRobert Mustacchi "namespace lock can be held at any time" },
993533affcbSRobert Mustacchi { NVME_IOCTL_E_LOCK_WAIT_SIGNAL, NVME_ERR_LOCK_WAIT_INTR, "signal "
994533affcbSRobert Mustacchi "received while blocking" },
995533affcbSRobert Mustacchi { NVME_IOCTL_E_LOCK_WOULD_BLOCK, NVME_ERR_LOCK_WOULD_BLOCK, "lock not "
996533affcbSRobert Mustacchi "available and no blocking allowed" },
997533affcbSRobert Mustacchi { NVME_IOCTL_E_LOCK_PENDING, NVME_ERR_LOCK_ORDER, "a handle may only "
998533affcbSRobert Mustacchi "block on one lock at a time" },
999533affcbSRobert Mustacchi { NVME_IOCTL_E_LOCK_NOT_HELD, NVME_ERR_LOCK_PROG, "fatal "
1000533affcbSRobert Mustacchi "programmer error: asked to unlock lock that was not held" },
1001533affcbSRobert Mustacchi /*
1002533affcbSRobert Mustacchi * This error is almost a can't happen due to the library construction
1003533affcbSRobert Mustacchi * and should result in the above error, but if this does happen, we
1004533affcbSRobert Mustacchi * treat this as a fatal lock error regardless.
1005533affcbSRobert Mustacchi */
1006533affcbSRobert Mustacchi { NVME_IOCTL_E_LOCK_WRONG_NS, NVME_ERR_LOCK_PROG, "fatal "
1007533affcbSRobert Mustacchi "programmer error: asked to unlock namespace lock that was not "
1008533affcbSRobert Mustacchi "held" },
1009533affcbSRobert Mustacchi { NVME_IOCTL_E_NS_BLKDEV_ATTACH, NVME_ERR_NS_BLKDEV_ATTACH, "cannot "
1010533affcbSRobert Mustacchi "execute request while namespace is attached" },
1011533affcbSRobert Mustacchi /*
1012533affcbSRobert Mustacchi * We purposefully skip NVME_IOCTL_E_BD_ADDR_OVER right now because
1013533affcbSRobert Mustacchi * there is nothing that a user can do about this. This is a
1014533affcbSRobert Mustacchi * libnvme/kernel interface issue.
1015533affcbSRobert Mustacchi */
1016533affcbSRobert Mustacchi };
1017533affcbSRobert Mustacchi
1018533affcbSRobert Mustacchi /*
1019533affcbSRobert Mustacchi * Translate a kernel ioctl error into the library's error. We handle the
1020533affcbSRobert Mustacchi * controller error separately. Otherwise, everything else is done based upon
1021533affcbSRobert Mustacchi * our translation table.
1022533affcbSRobert Mustacchi */
1023533affcbSRobert Mustacchi bool
nvme_ioctl_error(nvme_ctrl_t * ctrl,const nvme_ioctl_common_t * ioc,const char * desc)1024533affcbSRobert Mustacchi nvme_ioctl_error(nvme_ctrl_t *ctrl, const nvme_ioctl_common_t *ioc,
1025533affcbSRobert Mustacchi const char *desc)
1026533affcbSRobert Mustacchi {
1027533affcbSRobert Mustacchi int ret;
1028533affcbSRobert Mustacchi nvme_err_data_t *err = &ctrl->nc_err;
1029533affcbSRobert Mustacchi VERIFY3U(ioc->nioc_drv_err, !=, NVME_IOCTL_E_OK);
1030533affcbSRobert Mustacchi
1031533affcbSRobert Mustacchi err->ne_syserr = 0;
1032533affcbSRobert Mustacchi err->ne_ctrl_sct = 0;
1033533affcbSRobert Mustacchi err->ne_ctrl_sc = 0;
1034533affcbSRobert Mustacchi
1035533affcbSRobert Mustacchi if (ioc->nioc_drv_err == NVME_IOCTL_E_CTRL_ERROR) {
1036533affcbSRobert Mustacchi const char *sct, *sc;
1037533affcbSRobert Mustacchi err->ne_err = NVME_ERR_CONTROLLER;
1038533affcbSRobert Mustacchi err->ne_ctrl_sct = ioc->nioc_ctrl_sct;
1039533affcbSRobert Mustacchi err->ne_ctrl_sc = ioc->nioc_ctrl_sc;
1040533affcbSRobert Mustacchi sct = nvme_scttostr(ctrl, ioc->nioc_ctrl_sct);
1041533affcbSRobert Mustacchi sc = nvme_sctostr(ctrl, NVME_CSI_NVM, ioc->nioc_ctrl_sct,
1042533affcbSRobert Mustacchi ioc->nioc_ctrl_sc);
1043533affcbSRobert Mustacchi ret = snprintf(err->ne_errmsg, sizeof (err->ne_errmsg),
1044533affcbSRobert Mustacchi "failed to execute %s command: received controller error "
1045533affcbSRobert Mustacchi "sct/sc %s/%s (0x%x/0x%x)", desc, sct, sc,
1046533affcbSRobert Mustacchi ioc->nioc_ctrl_sct, ioc->nioc_ctrl_sc);
1047533affcbSRobert Mustacchi } else {
1048533affcbSRobert Mustacchi const nvme_ktolmap_t *map = NULL;
1049533affcbSRobert Mustacchi for (size_t i = 0; i < ARRAY_SIZE(nvme_ktolmap); i++) {
1050533affcbSRobert Mustacchi if (nvme_ktolmap[i].kl_kern == ioc->nioc_drv_err) {
1051533affcbSRobert Mustacchi map = &nvme_ktolmap[i];
1052533affcbSRobert Mustacchi break;
1053533affcbSRobert Mustacchi }
1054533affcbSRobert Mustacchi }
1055533affcbSRobert Mustacchi
1056533affcbSRobert Mustacchi if (map != NULL) {
1057533affcbSRobert Mustacchi err->ne_err = map->kl_lib;
1058533affcbSRobert Mustacchi ret = snprintf(err->ne_errmsg, sizeof (err->ne_errmsg),
1059533affcbSRobert Mustacchi "failed to execute %s command: %s", desc,
1060533affcbSRobert Mustacchi map->kl_desc);
1061533affcbSRobert Mustacchi } else {
1062533affcbSRobert Mustacchi err->ne_err = NVME_ERR_INTERNAL;
1063533affcbSRobert Mustacchi ret = snprintf(err->ne_errmsg, sizeof (err->ne_errmsg),
1064533affcbSRobert Mustacchi "failed to execute %s command: failed to map "
1065533affcbSRobert Mustacchi "kernel error 0x%x to a known cause", desc,
1066533affcbSRobert Mustacchi ioc->nioc_drv_err);
1067533affcbSRobert Mustacchi }
1068533affcbSRobert Mustacchi }
1069533affcbSRobert Mustacchi
1070533affcbSRobert Mustacchi if (ret >= sizeof (err->ne_errmsg)) {
1071533affcbSRobert Mustacchi err->ne_errlen = sizeof (err->ne_errmsg) - 1;
1072533affcbSRobert Mustacchi } else if (ret <= 0) {
1073533affcbSRobert Mustacchi err->ne_errlen = 0;
1074533affcbSRobert Mustacchi err->ne_errmsg[0] = '\0';
1075533affcbSRobert Mustacchi } else {
1076533affcbSRobert Mustacchi err->ne_errlen = (size_t)ret;
1077533affcbSRobert Mustacchi }
1078533affcbSRobert Mustacchi
1079533affcbSRobert Mustacchi return (false);
1080533affcbSRobert Mustacchi }
1081533affcbSRobert Mustacchi
1082533affcbSRobert Mustacchi /*
1083533affcbSRobert Mustacchi * Evaluate the set of ioctl errors that we see and translate and/or abort a few
1084533affcbSRobert Mustacchi * of the expected values. Most things will end up being translated into a
1085533affcbSRobert Mustacchi * generic internal error as we expect a rather tight error set at this point.
1086533affcbSRobert Mustacchi *
1087533affcbSRobert Mustacchi * We choose to panic on EFAULT because we are responsible for all such EFAULT
1088533affcbSRobert Mustacchi * errors. These are structure that are coming from the library. This is not
1089533affcbSRobert Mustacchi * something that the user could have passed us (their buffers will trigger
1090533affcbSRobert Mustacchi * an explicit nvme_ioctl_errno_t). Therefore, something has gone very wrong
1091533affcbSRobert Mustacchi * with our stack or we just corrupted some memory.
1092533affcbSRobert Mustacchi *
1093533affcbSRobert Mustacchi * The same is true with EBADF. In this case, that'd happen either because our
1094533affcbSRobert Mustacchi * controller fd was bandit'd away by someone or somehow we lost FREAD or FWRITE
1095533affcbSRobert Mustacchi * on the fd. That should not be possible assuming everyone is acting in good
1096533affcbSRobert Mustacchi * faith, so we treat this as a sign that something quite bad has happened and
1097533affcbSRobert Mustacchi * we shouldn't continue.
1098533affcbSRobert Mustacchi */
1099533affcbSRobert Mustacchi bool
nvme_ioctl_syserror(nvme_ctrl_t * ctrl,int err,const char * desc)1100533affcbSRobert Mustacchi nvme_ioctl_syserror(nvme_ctrl_t *ctrl, int err, const char *desc)
1101533affcbSRobert Mustacchi {
1102533affcbSRobert Mustacchi switch (err) {
1103533affcbSRobert Mustacchi case EFAULT:
1104533affcbSRobert Mustacchi case EBADF: {
1105533affcbSRobert Mustacchi const char *base = "fatal libnvme internal programming error: "
1106533affcbSRobert Mustacchi "failed to issue ioctl";
1107533affcbSRobert Mustacchi char msg[1024];
1108533affcbSRobert Mustacchi int ret;
1109533affcbSRobert Mustacchi const char *up;
1110533affcbSRobert Mustacchi size_t ulen;
1111533affcbSRobert Mustacchi
1112533affcbSRobert Mustacchi ret = snprintf(msg, sizeof (msg), "%s %s: %s (controller %p)",
1113533affcbSRobert Mustacchi base, desc, strerror(err), ctrl);
1114533affcbSRobert Mustacchi if (ret >= sizeof (msg)) {
1115533affcbSRobert Mustacchi ulen = sizeof (msg);
1116533affcbSRobert Mustacchi up = msg;
1117533affcbSRobert Mustacchi } else if (ret <= 0) {
1118533affcbSRobert Mustacchi up = base;
1119533affcbSRobert Mustacchi ulen = strlen(base) + 1;
1120533affcbSRobert Mustacchi } else {
1121533affcbSRobert Mustacchi ulen = (size_t)ret;
1122533affcbSRobert Mustacchi up = msg;
1123533affcbSRobert Mustacchi }
1124533affcbSRobert Mustacchi
1125533affcbSRobert Mustacchi upanic(up, ulen);
1126533affcbSRobert Mustacchi }
1127533affcbSRobert Mustacchi case EPERM:
1128533affcbSRobert Mustacchi return (nvme_ctrl_error(ctrl, NVME_ERR_PRIVS, err,
1129533affcbSRobert Mustacchi "failed to issue %s ioctl due to missing privileges",
1130533affcbSRobert Mustacchi desc));
1131533affcbSRobert Mustacchi default:
1132533affcbSRobert Mustacchi return (nvme_ctrl_error(ctrl, NVME_ERR_INTERNAL, err,
1133533affcbSRobert Mustacchi "failed to issue %s ioctl due to unexpected system "
1134533affcbSRobert Mustacchi "error: %s", desc, strerror(err)));
1135533affcbSRobert Mustacchi }
1136533affcbSRobert Mustacchi }
1137533affcbSRobert Mustacchi
1138533affcbSRobert Mustacchi /*
1139533affcbSRobert Mustacchi * Generate the standard warning about which fields are unused.
1140533affcbSRobert Mustacchi */
1141533affcbSRobert Mustacchi bool
nvme_field_miss_err(nvme_ctrl_t * ctrl,const nvme_field_info_t * fields,size_t nfields,nvme_err_t err,const char * desc,uint32_t val)1142533affcbSRobert Mustacchi nvme_field_miss_err(nvme_ctrl_t *ctrl, const nvme_field_info_t *fields,
1143533affcbSRobert Mustacchi size_t nfields, nvme_err_t err, const char *desc, uint32_t val)
1144533affcbSRobert Mustacchi {
1145533affcbSRobert Mustacchi char buf[512];
1146533affcbSRobert Mustacchi bool comma = false;
1147533affcbSRobert Mustacchi
1148533affcbSRobert Mustacchi VERIFY3U(val, !=, 0);
1149533affcbSRobert Mustacchi buf[0] = '\0';
1150533affcbSRobert Mustacchi for (size_t i = 0; i < nfields; i++) {
1151533affcbSRobert Mustacchi if ((val & (1 << i)) == 0) {
1152533affcbSRobert Mustacchi continue;
1153533affcbSRobert Mustacchi }
1154533affcbSRobert Mustacchi
1155533affcbSRobert Mustacchi if (comma) {
1156533affcbSRobert Mustacchi (void) strlcat(buf, ",", sizeof (buf));
1157533affcbSRobert Mustacchi }
1158533affcbSRobert Mustacchi (void) strlcat(buf, fields[i].nlfi_spec, sizeof (buf));
1159533affcbSRobert Mustacchi comma = true;
1160533affcbSRobert Mustacchi }
1161533affcbSRobert Mustacchi
1162533affcbSRobert Mustacchi return (nvme_ctrl_error(ctrl, err, 0, "cannot execute %s request due "
1163533affcbSRobert Mustacchi "to missing fields: %s", desc, buf));
1164533affcbSRobert Mustacchi }
1165533affcbSRobert Mustacchi
1166533affcbSRobert Mustacchi bool
nvme_field_check_one(nvme_ctrl_t * ctrl,uint64_t val,const char * req,const nvme_field_check_t * check,uint32_t allow)1167533affcbSRobert Mustacchi nvme_field_check_one(nvme_ctrl_t *ctrl, uint64_t val, const char *req,
1168533affcbSRobert Mustacchi const nvme_field_check_t *check, uint32_t allow)
1169533affcbSRobert Mustacchi {
1170533affcbSRobert Mustacchi const nvme_field_info_t *field = &check->chk_fields[check->chk_index];
1171533affcbSRobert Mustacchi nvme_valid_ctrl_data_t data;
1172533affcbSRobert Mustacchi nvme_field_error_t err;
1173533affcbSRobert Mustacchi char msg[256];
1174533affcbSRobert Mustacchi
1175533affcbSRobert Mustacchi if (allow != 0 && (allow & (1 << check->chk_index)) == 0) {
1176533affcbSRobert Mustacchi VERIFY3U(check->chk_field_unuse, !=, 0);
1177533affcbSRobert Mustacchi return (nvme_ctrl_error(ctrl, check->chk_field_unuse, 0,
1178533affcbSRobert Mustacchi "field %s (%s) cannot be set in this %s request",
1179533affcbSRobert Mustacchi field->nlfi_human, field->nlfi_spec, req));
1180533affcbSRobert Mustacchi }
1181533affcbSRobert Mustacchi
1182533affcbSRobert Mustacchi data.vcd_vers = &ctrl->nc_vers;
1183533affcbSRobert Mustacchi data.vcd_id = &ctrl->nc_info;
1184533affcbSRobert Mustacchi
1185533affcbSRobert Mustacchi err = nvme_field_validate(field, &data, val, msg, sizeof (msg));
1186533affcbSRobert Mustacchi switch (err) {
1187533affcbSRobert Mustacchi case NVME_FIELD_ERR_OK:
1188533affcbSRobert Mustacchi break;
1189533affcbSRobert Mustacchi case NVME_FIELD_ERR_UNSUP_VERSION:
1190533affcbSRobert Mustacchi case NVME_FIELD_ERR_UNSUP_FIELD:
1191533affcbSRobert Mustacchi VERIFY3U(check->chk_field_unsup, !=, 0);
1192533affcbSRobert Mustacchi return (nvme_ctrl_error(ctrl, check->chk_field_unsup, 0, "%s",
1193533affcbSRobert Mustacchi msg));
1194533affcbSRobert Mustacchi case NVME_FIELD_ERR_BAD_VALUE:
1195533affcbSRobert Mustacchi VERIFY3U(check->chk_field_range, !=, 0);
1196533affcbSRobert Mustacchi return (nvme_ctrl_error(ctrl, check->chk_field_range, 0, "%s",
1197533affcbSRobert Mustacchi msg));
1198533affcbSRobert Mustacchi }
1199533affcbSRobert Mustacchi
1200533affcbSRobert Mustacchi return (true);
1201533affcbSRobert Mustacchi }
1202