1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (C) 2012-2014 Intel Corporation
5 * All rights reserved.
6 *
7 * Copyright (c) 2023 Chelsio Communications, Inc.
8 */
9
10 #include <sys/types.h>
11 #include <sys/sbuf.h>
12 #ifndef _KERNEL
13 #include <sys/time.h>
14 #include <stdio.h>
15 #endif
16
17 #include <dev/nvme/nvme.h>
18
19 #include <cam/ctl/ctl_io.h>
20 #include <cam/ctl/ctl_nvme_all.h>
21
22 /* XXX: This duplicates lists in nvme_qpair.c. */
23
24 #define OPC_ENTRY(x) [NVME_OPC_ ## x] = #x
25
26 static const char *admin_opcode[256] = {
27 OPC_ENTRY(DELETE_IO_SQ),
28 OPC_ENTRY(CREATE_IO_SQ),
29 OPC_ENTRY(GET_LOG_PAGE),
30 OPC_ENTRY(DELETE_IO_CQ),
31 OPC_ENTRY(CREATE_IO_CQ),
32 OPC_ENTRY(IDENTIFY),
33 OPC_ENTRY(ABORT),
34 OPC_ENTRY(SET_FEATURES),
35 OPC_ENTRY(GET_FEATURES),
36 OPC_ENTRY(ASYNC_EVENT_REQUEST),
37 OPC_ENTRY(NAMESPACE_MANAGEMENT),
38 OPC_ENTRY(FIRMWARE_ACTIVATE),
39 OPC_ENTRY(FIRMWARE_IMAGE_DOWNLOAD),
40 OPC_ENTRY(DEVICE_SELF_TEST),
41 OPC_ENTRY(NAMESPACE_ATTACHMENT),
42 OPC_ENTRY(KEEP_ALIVE),
43 OPC_ENTRY(DIRECTIVE_SEND),
44 OPC_ENTRY(DIRECTIVE_RECEIVE),
45 OPC_ENTRY(VIRTUALIZATION_MANAGEMENT),
46 OPC_ENTRY(NVME_MI_SEND),
47 OPC_ENTRY(NVME_MI_RECEIVE),
48 OPC_ENTRY(CAPACITY_MANAGEMENT),
49 OPC_ENTRY(LOCKDOWN),
50 OPC_ENTRY(DOORBELL_BUFFER_CONFIG),
51 OPC_ENTRY(FABRICS_COMMANDS),
52 OPC_ENTRY(FORMAT_NVM),
53 OPC_ENTRY(SECURITY_SEND),
54 OPC_ENTRY(SECURITY_RECEIVE),
55 OPC_ENTRY(SANITIZE),
56 OPC_ENTRY(GET_LBA_STATUS),
57 };
58
59 static const char *nvm_opcode[256] = {
60 OPC_ENTRY(FLUSH),
61 OPC_ENTRY(WRITE),
62 OPC_ENTRY(READ),
63 OPC_ENTRY(WRITE_UNCORRECTABLE),
64 OPC_ENTRY(COMPARE),
65 OPC_ENTRY(WRITE_ZEROES),
66 OPC_ENTRY(DATASET_MANAGEMENT),
67 OPC_ENTRY(VERIFY),
68 OPC_ENTRY(RESERVATION_REGISTER),
69 OPC_ENTRY(RESERVATION_REPORT),
70 OPC_ENTRY(RESERVATION_ACQUIRE),
71 OPC_ENTRY(RESERVATION_RELEASE),
72 OPC_ENTRY(COPY),
73 };
74
75 void
ctl_nvme_command_string(struct ctl_nvmeio * ctnio,struct sbuf * sb)76 ctl_nvme_command_string(struct ctl_nvmeio *ctnio, struct sbuf *sb)
77 {
78 const char *s, *type;
79
80 if (ctnio->io_hdr.io_type == CTL_IO_NVME_ADMIN) {
81 s = admin_opcode[ctnio->cmd.opc];
82 type = "ADMIN";
83 } else {
84 s = nvm_opcode[ctnio->cmd.opc];
85 type = "NVM";
86 }
87 if (s == NULL)
88 sbuf_printf(sb, "%s:0x%02x", type, ctnio->cmd.opc);
89 else
90 sbuf_printf(sb, "%s", s);
91 }
92
93 #define SC_ENTRY(x) [NVME_SC_ ## x] = #x
94
95 static const char *generic_status[256] = {
96 SC_ENTRY(SUCCESS),
97 SC_ENTRY(INVALID_OPCODE),
98 SC_ENTRY(INVALID_FIELD),
99 SC_ENTRY(COMMAND_ID_CONFLICT),
100 SC_ENTRY(DATA_TRANSFER_ERROR),
101 SC_ENTRY(ABORTED_POWER_LOSS),
102 SC_ENTRY(INTERNAL_DEVICE_ERROR),
103 SC_ENTRY(ABORTED_BY_REQUEST),
104 SC_ENTRY(ABORTED_SQ_DELETION),
105 SC_ENTRY(ABORTED_FAILED_FUSED),
106 SC_ENTRY(ABORTED_MISSING_FUSED),
107 SC_ENTRY(INVALID_NAMESPACE_OR_FORMAT),
108 SC_ENTRY(COMMAND_SEQUENCE_ERROR),
109 SC_ENTRY(INVALID_SGL_SEGMENT_DESCR),
110 SC_ENTRY(INVALID_NUMBER_OF_SGL_DESCR),
111 SC_ENTRY(DATA_SGL_LENGTH_INVALID),
112 SC_ENTRY(METADATA_SGL_LENGTH_INVALID),
113 SC_ENTRY(SGL_DESCRIPTOR_TYPE_INVALID),
114 SC_ENTRY(INVALID_USE_OF_CMB),
115 SC_ENTRY(PRP_OFFET_INVALID),
116 SC_ENTRY(ATOMIC_WRITE_UNIT_EXCEEDED),
117 SC_ENTRY(OPERATION_DENIED),
118 SC_ENTRY(SGL_OFFSET_INVALID),
119 SC_ENTRY(HOST_ID_INCONSISTENT_FORMAT),
120 SC_ENTRY(KEEP_ALIVE_TIMEOUT_EXPIRED),
121 SC_ENTRY(KEEP_ALIVE_TIMEOUT_INVALID),
122 SC_ENTRY(ABORTED_DUE_TO_PREEMPT),
123 SC_ENTRY(SANITIZE_FAILED),
124 SC_ENTRY(SANITIZE_IN_PROGRESS),
125 SC_ENTRY(SGL_DATA_BLOCK_GRAN_INVALID),
126 SC_ENTRY(NOT_SUPPORTED_IN_CMB),
127 SC_ENTRY(NAMESPACE_IS_WRITE_PROTECTED),
128 SC_ENTRY(COMMAND_INTERRUPTED),
129 SC_ENTRY(TRANSIENT_TRANSPORT_ERROR),
130
131 SC_ENTRY(LBA_OUT_OF_RANGE),
132 SC_ENTRY(CAPACITY_EXCEEDED),
133 SC_ENTRY(NAMESPACE_NOT_READY),
134 SC_ENTRY(RESERVATION_CONFLICT),
135 SC_ENTRY(FORMAT_IN_PROGRESS),
136 };
137
138 static const char *command_specific_status[256] = {
139 SC_ENTRY(COMPLETION_QUEUE_INVALID),
140 SC_ENTRY(INVALID_QUEUE_IDENTIFIER),
141 SC_ENTRY(MAXIMUM_QUEUE_SIZE_EXCEEDED),
142 SC_ENTRY(ABORT_COMMAND_LIMIT_EXCEEDED),
143 SC_ENTRY(ASYNC_EVENT_REQUEST_LIMIT_EXCEEDED),
144 SC_ENTRY(INVALID_FIRMWARE_SLOT),
145 SC_ENTRY(INVALID_FIRMWARE_IMAGE),
146 SC_ENTRY(INVALID_INTERRUPT_VECTOR),
147 SC_ENTRY(INVALID_LOG_PAGE),
148 SC_ENTRY(INVALID_FORMAT),
149 SC_ENTRY(FIRMWARE_REQUIRES_RESET),
150 SC_ENTRY(INVALID_QUEUE_DELETION),
151 SC_ENTRY(FEATURE_NOT_SAVEABLE),
152 SC_ENTRY(FEATURE_NOT_CHANGEABLE),
153 SC_ENTRY(FEATURE_NOT_NS_SPECIFIC),
154 SC_ENTRY(FW_ACT_REQUIRES_NVMS_RESET),
155 SC_ENTRY(FW_ACT_REQUIRES_RESET),
156 SC_ENTRY(FW_ACT_REQUIRES_TIME),
157 SC_ENTRY(FW_ACT_PROHIBITED),
158 SC_ENTRY(OVERLAPPING_RANGE),
159 SC_ENTRY(NS_INSUFFICIENT_CAPACITY),
160 SC_ENTRY(NS_ID_UNAVAILABLE),
161 SC_ENTRY(NS_ALREADY_ATTACHED),
162 SC_ENTRY(NS_IS_PRIVATE),
163 SC_ENTRY(NS_NOT_ATTACHED),
164 SC_ENTRY(THIN_PROV_NOT_SUPPORTED),
165 SC_ENTRY(CTRLR_LIST_INVALID),
166 SC_ENTRY(SELF_TEST_IN_PROGRESS),
167 SC_ENTRY(BOOT_PART_WRITE_PROHIB),
168 SC_ENTRY(INVALID_CTRLR_ID),
169 SC_ENTRY(INVALID_SEC_CTRLR_STATE),
170 SC_ENTRY(INVALID_NUM_OF_CTRLR_RESRC),
171 SC_ENTRY(INVALID_RESOURCE_ID),
172 SC_ENTRY(SANITIZE_PROHIBITED_WPMRE),
173 SC_ENTRY(ANA_GROUP_ID_INVALID),
174 SC_ENTRY(ANA_ATTACH_FAILED),
175
176 SC_ENTRY(CONFLICTING_ATTRIBUTES),
177 SC_ENTRY(INVALID_PROTECTION_INFO),
178 SC_ENTRY(ATTEMPTED_WRITE_TO_RO_PAGE),
179 };
180
181 static const char *media_error_status[256] = {
182 SC_ENTRY(WRITE_FAULTS),
183 SC_ENTRY(UNRECOVERED_READ_ERROR),
184 SC_ENTRY(GUARD_CHECK_ERROR),
185 SC_ENTRY(APPLICATION_TAG_CHECK_ERROR),
186 SC_ENTRY(REFERENCE_TAG_CHECK_ERROR),
187 SC_ENTRY(COMPARE_FAILURE),
188 SC_ENTRY(ACCESS_DENIED),
189 SC_ENTRY(DEALLOCATED_OR_UNWRITTEN),
190 };
191
192 static const char *path_related_status[256] = {
193 SC_ENTRY(INTERNAL_PATH_ERROR),
194 SC_ENTRY(ASYMMETRIC_ACCESS_PERSISTENT_LOSS),
195 SC_ENTRY(ASYMMETRIC_ACCESS_INACCESSIBLE),
196 SC_ENTRY(ASYMMETRIC_ACCESS_TRANSITION),
197 SC_ENTRY(CONTROLLER_PATHING_ERROR),
198 SC_ENTRY(HOST_PATHING_ERROR),
199 SC_ENTRY(COMMAND_ABORTED_BY_HOST),
200 };
201
202 void
ctl_nvme_status_string(struct ctl_nvmeio * ctnio,struct sbuf * sb)203 ctl_nvme_status_string(struct ctl_nvmeio *ctnio, struct sbuf *sb)
204 {
205 const char *s, *type;
206 uint16_t status;
207
208 status = le16toh(ctnio->cpl.status);
209 switch (NVME_STATUS_GET_SCT(status)) {
210 case NVME_SCT_GENERIC:
211 s = generic_status[NVME_STATUS_GET_SC(status)];
212 type = "GENERIC";
213 break;
214 case NVME_SCT_COMMAND_SPECIFIC:
215 s = command_specific_status[NVME_STATUS_GET_SC(status)];
216 type = "COMMAND SPECIFIC";
217 break;
218 case NVME_SCT_MEDIA_ERROR:
219 s = media_error_status[NVME_STATUS_GET_SC(status)];
220 type = "MEDIA ERROR";
221 break;
222 case NVME_SCT_PATH_RELATED:
223 s = path_related_status[NVME_STATUS_GET_SC(status)];
224 type = "PATH RELATED";
225 break;
226 case NVME_SCT_VENDOR_SPECIFIC:
227 s = NULL;
228 type = "VENDOR SPECIFIC";
229 break;
230 default:
231 s = "RESERVED";
232 type = NULL;
233 break;
234 }
235
236 if (s == NULL)
237 sbuf_printf(sb, "%s:0x%02x", type, NVME_STATUS_GET_SC(status));
238 else
239 sbuf_printf(sb, "%s", s);
240 if (NVME_STATUS_GET_M(status) != 0)
241 sbuf_printf(sb, " M");
242 if (NVME_STATUS_GET_DNR(status) != 0)
243 sbuf_printf(sb, " DNR");
244 }
245