xref: /illumos-gate/usr/src/lib/libnvme/common/libnvme_error.c (revision e7efdd31faad970f4a4f8741f27ba4e6c36656c0)
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