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 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 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