Skip to content

Commit eeea64a

Browse files
Tomasz Bursztykacarlescufi
Tomasz Bursztyka
authored andcommitted
drivers/nvme: Add debug information in case of request error
This will provide a detailed error status report. As for most of the original code of the driver, this is a backport of the work done by Jim Harris in FreeBSD. Signed-off-by: Tomasz Bursztyka <[email protected]>
1 parent 68dd265 commit eeea64a

File tree

4 files changed

+182
-2
lines changed

4 files changed

+182
-2
lines changed

drivers/disk/nvme/nvme_cmd.c

+168
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,174 @@ static void request_timeout(struct k_work *work);
2626

2727
static K_WORK_DELAYABLE_DEFINE(request_timer, request_timeout);
2828

29+
#ifdef CONFIG_NVME_LOG_LEVEL_DBG
30+
struct nvme_status_string {
31+
uint16_t sc;
32+
const char *str;
33+
};
34+
35+
static struct nvme_status_string generic_status[] = {
36+
{ NVME_SC_SUCCESS, "SUCCESS" },
37+
{ NVME_SC_INVALID_OPCODE, "INVALID OPCODE" },
38+
{ NVME_SC_INVALID_FIELD, "INVALID_FIELD" },
39+
{ NVME_SC_COMMAND_ID_CONFLICT, "COMMAND ID CONFLICT" },
40+
{ NVME_SC_DATA_TRANSFER_ERROR, "DATA TRANSFER ERROR" },
41+
{ NVME_SC_ABORTED_POWER_LOSS, "ABORTED - POWER LOSS" },
42+
{ NVME_SC_INTERNAL_DEVICE_ERROR, "INTERNAL DEVICE ERROR" },
43+
{ NVME_SC_ABORTED_BY_REQUEST, "ABORTED - BY REQUEST" },
44+
{ NVME_SC_ABORTED_SQ_DELETION, "ABORTED - SQ DELETION" },
45+
{ NVME_SC_ABORTED_FAILED_FUSED, "ABORTED - FAILED FUSED" },
46+
{ NVME_SC_ABORTED_MISSING_FUSED, "ABORTED - MISSING FUSED" },
47+
{ NVME_SC_INVALID_NAMESPACE_OR_FORMAT, "INVALID NAMESPACE OR FORMAT" },
48+
{ NVME_SC_COMMAND_SEQUENCE_ERROR, "COMMAND SEQUENCE ERROR" },
49+
{ NVME_SC_INVALID_SGL_SEGMENT_DESCR, "INVALID SGL SEGMENT DESCRIPTOR" },
50+
{ NVME_SC_INVALID_NUMBER_OF_SGL_DESCR, "INVALID NUMBER OF SGL DESCRIPTORS" },
51+
{ NVME_SC_DATA_SGL_LENGTH_INVALID, "DATA SGL LENGTH INVALID" },
52+
{ NVME_SC_METADATA_SGL_LENGTH_INVALID, "METADATA SGL LENGTH INVALID" },
53+
{ NVME_SC_SGL_DESCRIPTOR_TYPE_INVALID, "SGL DESCRIPTOR TYPE INVALID" },
54+
{ NVME_SC_INVALID_USE_OF_CMB, "INVALID USE OF CONTROLLER MEMORY BUFFER" },
55+
{ NVME_SC_PRP_OFFSET_INVALID, "PRP OFFSET INVALID" },
56+
{ NVME_SC_ATOMIC_WRITE_UNIT_EXCEEDED, "ATOMIC WRITE UNIT EXCEEDED" },
57+
{ NVME_SC_OPERATION_DENIED, "OPERATION DENIED" },
58+
{ NVME_SC_SGL_OFFSET_INVALID, "SGL OFFSET INVALID" },
59+
{ NVME_SC_HOST_ID_INCONSISTENT_FORMAT, "HOST IDENTIFIER INCONSISTENT FORMAT" },
60+
{ NVME_SC_KEEP_ALIVE_TIMEOUT_EXPIRED, "KEEP ALIVE TIMEOUT EXPIRED" },
61+
{ NVME_SC_KEEP_ALIVE_TIMEOUT_INVALID, "KEEP ALIVE TIMEOUT INVALID" },
62+
{ NVME_SC_ABORTED_DUE_TO_PREEMPT, "COMMAND ABORTED DUE TO PREEMPT AND ABORT" },
63+
{ NVME_SC_SANITIZE_FAILED, "SANITIZE FAILED" },
64+
{ NVME_SC_SANITIZE_IN_PROGRESS, "SANITIZE IN PROGRESS" },
65+
{ NVME_SC_SGL_DATA_BLOCK_GRAN_INVALID, "SGL_DATA_BLOCK_GRANULARITY_INVALID" },
66+
{ NVME_SC_NOT_SUPPORTED_IN_CMB, "COMMAND NOT SUPPORTED FOR QUEUE IN CMB" },
67+
{ NVME_SC_NAMESPACE_IS_WRITE_PROTECTED, "NAMESPACE IS WRITE PROTECTED" },
68+
{ NVME_SC_COMMAND_INTERRUPTED, "COMMAND INTERRUPTED" },
69+
{ NVME_SC_TRANSIENT_TRANSPORT_ERROR, "TRANSIENT TRANSPORT ERROR" },
70+
{ NVME_SC_LBA_OUT_OF_RANGE, "LBA OUT OF RANGE" },
71+
{ NVME_SC_CAPACITY_EXCEEDED, "CAPACITY EXCEEDED" },
72+
{ NVME_SC_NAMESPACE_NOT_READY, "NAMESPACE NOT READY" },
73+
{ NVME_SC_RESERVATION_CONFLICT, "RESERVATION CONFLICT" },
74+
{ NVME_SC_FORMAT_IN_PROGRESS, "FORMAT IN PROGRESS" },
75+
{ 0xFFFF, "GENERIC" }
76+
};
77+
78+
static struct nvme_status_string command_specific_status[] = {
79+
{ NVME_SC_COMPLETION_QUEUE_INVALID, "INVALID COMPLETION QUEUE" },
80+
{ NVME_SC_INVALID_QUEUE_IDENTIFIER, "INVALID QUEUE IDENTIFIER" },
81+
{ NVME_SC_MAXIMUM_QUEUE_SIZE_EXCEEDED, "MAX QUEUE SIZE EXCEEDED" },
82+
{ NVME_SC_ABORT_COMMAND_LIMIT_EXCEEDED, "ABORT CMD LIMIT EXCEEDED" },
83+
{ NVME_SC_ASYNC_EVENT_REQUEST_LIMIT_EXCEEDED, "ASYNC LIMIT EXCEEDED" },
84+
{ NVME_SC_INVALID_FIRMWARE_SLOT, "INVALID FIRMWARE SLOT" },
85+
{ NVME_SC_INVALID_FIRMWARE_IMAGE, "INVALID FIRMWARE IMAGE" },
86+
{ NVME_SC_INVALID_INTERRUPT_VECTOR, "INVALID INTERRUPT VECTOR" },
87+
{ NVME_SC_INVALID_LOG_PAGE, "INVALID LOG PAGE" },
88+
{ NVME_SC_INVALID_FORMAT, "INVALID FORMAT" },
89+
{ NVME_SC_FIRMWARE_REQUIRES_RESET, "FIRMWARE REQUIRES RESET" },
90+
{ NVME_SC_INVALID_QUEUE_DELETION, "INVALID QUEUE DELETION" },
91+
{ NVME_SC_FEATURE_NOT_SAVEABLE, "FEATURE IDENTIFIER NOT SAVEABLE" },
92+
{ NVME_SC_FEATURE_NOT_CHANGEABLE, "FEATURE NOT CHANGEABLE" },
93+
{ NVME_SC_FEATURE_NOT_NS_SPECIFIC, "FEATURE NOT NAMESPACE SPECIFIC" },
94+
{ NVME_SC_FW_ACT_REQUIRES_NVMS_RESET, "FIRMWARE ACTIVATION REQUIRES NVM SUBSYSTEM RESET" },
95+
{ NVME_SC_FW_ACT_REQUIRES_RESET, "FIRMWARE ACTIVATION REQUIRES RESET" },
96+
{ NVME_SC_FW_ACT_REQUIRES_TIME, "FIRMWARE ACTIVATION REQUIRES MAXIMUM TIME VIOLATION" },
97+
{ NVME_SC_FW_ACT_PROHIBITED, "FIRMWARE ACTIVATION PROHIBITED" },
98+
{ NVME_SC_OVERLAPPING_RANGE, "OVERLAPPING RANGE" },
99+
{ NVME_SC_NS_INSUFFICIENT_CAPACITY, "NAMESPACE INSUFFICIENT CAPACITY" },
100+
{ NVME_SC_NS_ID_UNAVAILABLE, "NAMESPACE IDENTIFIER UNAVAILABLE" },
101+
{ NVME_SC_NS_ALREADY_ATTACHED, "NAMESPACE ALREADY ATTACHED" },
102+
{ NVME_SC_NS_IS_PRIVATE, "NAMESPACE IS PRIVATE" },
103+
{ NVME_SC_NS_NOT_ATTACHED, "NS NOT ATTACHED" },
104+
{ NVME_SC_THIN_PROV_NOT_SUPPORTED, "THIN PROVISIONING NOT SUPPORTED" },
105+
{ NVME_SC_CTRLR_LIST_INVALID, "CONTROLLER LIST INVALID" },
106+
{ NVME_SC_SELF_TEST_IN_PROGRESS, "DEVICE SELF-TEST IN PROGRESS" },
107+
{ NVME_SC_BOOT_PART_WRITE_PROHIB, "BOOT PARTITION WRITE PROHIBITED" },
108+
{ NVME_SC_INVALID_CTRLR_ID, "INVALID CONTROLLER IDENTIFIER" },
109+
{ NVME_SC_INVALID_SEC_CTRLR_STATE, "INVALID SECONDARY CONTROLLER STATE" },
110+
{ NVME_SC_INVALID_NUM_OF_CTRLR_RESRC, "INVALID NUMBER OF CONTROLLER RESOURCES" },
111+
{ NVME_SC_INVALID_RESOURCE_ID, "INVALID RESOURCE IDENTIFIER" },
112+
{ NVME_SC_SANITIZE_PROHIBITED_WPMRE,
113+
"SANITIZE PROHIBITED WRITE PERSISTENT MEMORY REGION ENABLED" },
114+
{ NVME_SC_ANA_GROUP_ID_INVALID, "ANA GROUP IDENTIFIED INVALID" },
115+
{ NVME_SC_ANA_ATTACH_FAILED, "ANA ATTACH FAILED" },
116+
{ NVME_SC_CONFLICTING_ATTRIBUTES, "CONFLICTING ATTRIBUTES" },
117+
{ NVME_SC_INVALID_PROTECTION_INFO, "INVALID PROTECTION INFO" },
118+
{ NVME_SC_ATTEMPTED_WRITE_TO_RO_PAGE, "WRITE TO RO PAGE" },
119+
{ 0xFFFF, "COMMAND SPECIFIC" }
120+
};
121+
122+
static struct nvme_status_string media_error_status[] = {
123+
{ NVME_SC_WRITE_FAULTS, "WRITE FAULTS" },
124+
{ NVME_SC_UNRECOVERED_READ_ERROR, "UNRECOVERED READ ERROR" },
125+
{ NVME_SC_GUARD_CHECK_ERROR, "GUARD CHECK ERROR" },
126+
{ NVME_SC_APPLICATION_TAG_CHECK_ERROR, "APPLICATION TAG CHECK ERROR" },
127+
{ NVME_SC_REFERENCE_TAG_CHECK_ERROR, "REFERENCE TAG CHECK ERROR" },
128+
{ NVME_SC_COMPARE_FAILURE, "COMPARE FAILURE" },
129+
{ NVME_SC_ACCESS_DENIED, "ACCESS DENIED" },
130+
{ NVME_SC_DEALLOCATED_OR_UNWRITTEN, "DEALLOCATED OR UNWRITTEN LOGICAL BLOCK" },
131+
{ 0xFFFF, "MEDIA ERROR" }
132+
};
133+
134+
static struct nvme_status_string path_related_status[] = {
135+
{ NVME_SC_INTERNAL_PATH_ERROR, "INTERNAL PATH ERROR" },
136+
{ NVME_SC_ASYMMETRIC_ACCESS_PERSISTENT_LOSS, "ASYMMETRIC ACCESS PERSISTENT LOSS" },
137+
{ NVME_SC_ASYMMETRIC_ACCESS_INACCESSIBLE, "ASYMMETRIC ACCESS INACCESSIBLE" },
138+
{ NVME_SC_ASYMMETRIC_ACCESS_TRANSITION, "ASYMMETRIC ACCESS TRANSITION" },
139+
{ NVME_SC_CONTROLLER_PATHING_ERROR, "CONTROLLER PATHING ERROR" },
140+
{ NVME_SC_HOST_PATHING_ERROR, "HOST PATHING ERROR" },
141+
{ NVME_SC_COMMAND_ABORTED_BY_HOST, "COMMAND ABORTED BY HOST" },
142+
{ 0xFFFF, "PATH RELATED" },
143+
};
144+
145+
static const char *get_status_string(uint16_t sct, uint16_t sc)
146+
{
147+
struct nvme_status_string *entry;
148+
149+
switch (sct) {
150+
case NVME_SCT_GENERIC:
151+
entry = generic_status;
152+
break;
153+
case NVME_SCT_COMMAND_SPECIFIC:
154+
entry = command_specific_status;
155+
break;
156+
case NVME_SCT_MEDIA_ERROR:
157+
entry = media_error_status;
158+
break;
159+
case NVME_SCT_PATH_RELATED:
160+
entry = path_related_status;
161+
break;
162+
case NVME_SCT_VENDOR_SPECIFIC:
163+
return "VENDOR SPECIFIC";
164+
default:
165+
return "RESERVED";
166+
}
167+
168+
while (entry->sc != 0xFFFF) {
169+
if (entry->sc == sc) {
170+
return entry->str;
171+
}
172+
173+
entry++;
174+
}
175+
return entry->str;
176+
}
177+
178+
void nvme_completion_print(const struct nvme_completion *cpl)
179+
{
180+
uint8_t sct, sc, crd, m, dnr, p;
181+
182+
sct = NVME_STATUS_GET_SCT(cpl->status);
183+
sc = NVME_STATUS_GET_SC(cpl->status);
184+
crd = NVME_STATUS_GET_CRD(cpl->status);
185+
m = NVME_STATUS_GET_M(cpl->status);
186+
dnr = NVME_STATUS_GET_DNR(cpl->status);
187+
p = NVME_STATUS_GET_P(cpl->status);
188+
189+
LOG_DBG("%s (%02x/%02x) crd:%x m:%x dnr:%x p:%d "
190+
"sqid:%d cid:%d cdw0:%x\n",
191+
get_status_string(sct, sc), sct, sc, crd, m, dnr, p,
192+
cpl->sqid, cpl->cid, cpl->cdw0);
193+
}
194+
195+
#endif /* CONFIG_NVME_LOG_LEVEL_DBG */
196+
29197
void nvme_cmd_init(void)
30198
{
31199
int idx;

drivers/disk/nvme/nvme_cmd.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ enum nvme_path_related_status_code {
197197
NVME_SC_ASYMMETRIC_ACCESS_TRANSITION = 0x03,
198198
NVME_SC_CONTROLLER_PATHING_ERROR = 0x60,
199199
NVME_SC_HOST_PATHING_ERROR = 0x70,
200-
NVME_SC_COMMAND_ABOTHED_BY_HOST = 0x71,
200+
NVME_SC_COMMAND_ABORTED_BY_HOST = 0x71,
201201
};
202202

203203
/* admin opcodes */
@@ -377,6 +377,12 @@ void nvme_cmd_init(void);
377377

378378
void nvme_completion_poll_cb(void *arg, const struct nvme_completion *cpl);
379379

380+
#ifdef CONFIG_NVME_LOG_LEVEL_DBG
381+
void nvme_completion_print(const struct nvme_completion *cpl);
382+
#else
383+
#define nvme_completion_print(...)
384+
#endif /* CONFIG_NVME_LOG_LEVEL_DBG */
385+
380386
void nvme_cmd_request_free(struct nvme_request *request);
381387

382388
struct nvme_request *nvme_cmd_request_alloc(void);

drivers/disk/nvme/nvme_controller.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ static int nvme_controller_setup_io_queues(const struct device *dev)
183183
if (nvme_cpl_status_is_error(&status)) {
184184
LOG_ERR("Could not set IO num queues to %u",
185185
nvme_ctrlr->num_io_queues);
186+
nvme_completion_print(&status.cpl);
186187
return -EIO;
187188
}
188189

@@ -225,6 +226,7 @@ static int nvme_controller_setup_io_queues(const struct device *dev)
225226
nvme_completion_poll(&status);
226227
if (nvme_cpl_status_is_error(&status)) {
227228
LOG_ERR("IO CQ creation failed");
229+
nvme_completion_print(&status.cpl);
228230
return -EIO;
229231
}
230232

@@ -240,6 +242,7 @@ static int nvme_controller_setup_io_queues(const struct device *dev)
240242
nvme_completion_poll(&status);
241243
if (nvme_cpl_status_is_error(&status)) {
242244
LOG_ERR("IO CQ creation failed");
245+
nvme_completion_print(&status.cpl);
243246
return -EIO;
244247
}
245248
}
@@ -372,9 +375,9 @@ static int nvme_controller_identify(struct nvme_controller *nvme_ctrlr)
372375
nvme_ctrlr_cmd_identify_controller(nvme_ctrlr,
373376
nvme_completion_poll_cb, &status);
374377
nvme_completion_poll(&status);
375-
376378
if (nvme_cpl_status_is_error(&status)) {
377379
LOG_ERR("Could not identify the controller");
380+
nvme_completion_print(&status.cpl);
378381
return -EIO;
379382
}
380383

drivers/disk/nvme/nvme_disk.c

+3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ static int nvme_disk_read(struct disk_info *disk,
5757
if (nvme_cpl_status_is_error(&status)) {
5858
LOG_WRN("Reading at sector %u (count %d) on disk %s failed",
5959
start_sector, num_sector, ns->name);
60+
nvme_completion_print(&status.cpl);
6061
ret = -EIO;
6162
}
6263
out:
@@ -100,6 +101,7 @@ static int nvme_disk_write(struct disk_info *disk,
100101
if (nvme_cpl_status_is_error(&status)) {
101102
LOG_WRN("Writing at sector %u (count %d) on disk %s failed",
102103
start_sector, num_sector, ns->name);
104+
nvme_completion_print(&status.cpl);
103105
ret = -EIO;
104106
}
105107
out:
@@ -128,6 +130,7 @@ static int nvme_disk_flush(struct nvme_namespace *ns)
128130
nvme_completion_poll(&status);
129131
if (nvme_cpl_status_is_error(&status)) {
130132
LOG_ERR("Flushing disk %s failed", ns->name);
133+
nvme_completion_print(&status.cpl);
131134
return -EIO;
132135
}
133136

0 commit comments

Comments
 (0)