blob: 8c4a2079f729f5cbe6ac8ca40953a5812b9d38fd [file] [log] [blame]
Lorenz Brunfba5da02022-12-15 11:20:47 +00001package nvme
2
3import "fmt"
4
5// Figure 31 in the spec
6var genericStatusCodeDesc = map[uint8]string{
7 0x00: "successful completion",
8 0x01: "invalid command opcode",
9 0x02: "invalid field in command",
10 0x03: "command ID conflict",
11 0x04: "data transfer error",
12 0x05: "command aborted due power loss notification",
13 0x06: "internal error",
14 0x07: "command abort requested",
15 0x08: "command abort due to SQ deletion",
16 0x09: "command abort due to failed fused command",
17 0x0a: "command abort due to missing fused command",
18 0x0b: "invalid namespace or format",
19 0x0c: "command sequence error",
20 0x0d: "invalid SGL segment descriptor",
21 0x0e: "invalid number of SGL descriptors",
22 0x0f: "data SGL length invalid",
23 0x10: "metadata SGL length invalid",
24 0x11: "SGL descriptor type invalid",
25 0x12: "invalid use of controller memory buffer",
26 0x13: "PRP offset invalid",
27 0x14: "atomic write unit exceeded",
28 0x15: "operation denied",
29 0x16: "SGL offset invalid",
30 0x18: "host identifer inconsistent format",
31 0x19: "keep alive timeout expired",
32 0x1a: "keep alive timeout invalid",
33 0x1b: "command aborted due to preempt and abort",
34 0x1c: "sanitize failed",
35 0x1d: "sanitize in progress",
36 0x1e: "SGL data block granularity invalid",
37 0x1f: "command not supported for queue in CMB",
38
39 // Figure 32
40 0x80: "LBA out of range",
41 0x81: "capacity exceeded",
42 0x82: "namespace not ready",
43 0x83: "reservation conflict",
44 0x84: "format in progress",
45}
46
47// Figure 33 in the spec
48var commandSpecificStatusCodeDesc = map[uint8]string{
49 0x00: "completion queue invalid",
50 0x01: "invalid queue identifier",
51 0x02: "invalid queue size",
52 0x03: "abort command limit exceeded",
53 0x05: "asynchronous event request limit exceeded",
54 0x06: "invalid firmware slot",
55 0x07: "invalid firmware image",
56 0x08: "invalid interrupt vector",
57 0x09: "invalid log page",
58 0x0a: "invalid format",
59 0x0b: "firmware activation requires conventional reset",
60 0x0c: "invalid queue deletion",
61 0x0d: "feature identifier not saveable",
62 0x0e: "feature not changeable",
63 0x0f: "feature not namespace-specific",
64 0x10: "firmware activation requires NVM subsystem reset",
65 0x11: "firmware activation requires reset",
66 0x12: "firmware activation requires maximum time violation",
67 0x13: "firmware activation prohibited",
68 0x14: "overlapping range",
69 0x15: "namespace insufficient capacity",
70 0x16: "namespace identifier unavailable",
71 0x18: "namespace already attached",
72 0x19: "namespace is private",
73 0x1a: "namespace is not attached",
74 0x1b: "thin provisioning not supported",
75 0x1c: "controller list invalid",
76 0x1d: "device self-test in progress",
77 0x1e: "boot partition write prohibited",
78 0x1f: "invalid controller identifier",
79 0x20: "invalid secondary controller state",
80 0x21: "invalid number of controller resources",
81 0x22: "invalid resource identifier",
82
83 // Figure 34
84 0x80: "conflicting attributes",
85 0x81: "invalid protection information",
86 0x82: "attempted to write to read-only range",
87}
88
89// Figure 36
90var mediaAndDataIntegrityStatusCodeDesc = map[uint8]string{
91 0x80: "write fault",
92 0x81: "unrecovered read error",
93 0x82: "end-to-end guard check error",
94 0x83: "end-to-end application tag check error",
95 0x84: "end-to-end reference tag check error",
96 0x85: "compare failure",
97 0x86: "access denied",
98 0x87: "deallocated or unwritten logical block",
99}
100
101const (
102 StatusCodeTypeGeneric = 0x0
103 StatusCodeTypeCommandSpecific = 0x1
104 StatusCodeTypeMediaAndDataIntegrity = 0x2
105)
106
107// Error represents an error returned by the NVMe device in the form of a
108// NVMe Status Field (see also Figure 29 in the spec).
109type Error struct {
110 DoNotRetry bool
111 More bool
112 StatusCodeType uint8
113 StatusCode uint8
114}
115
116func (e Error) Error() string {
117 switch e.StatusCodeType {
118 case StatusCodeTypeGeneric:
119 if errStr, ok := genericStatusCodeDesc[e.StatusCode]; ok {
120 return errStr
121 }
122 return fmt.Sprintf("unknown error with generic code 0x%x", e.StatusCode)
123 case StatusCodeTypeCommandSpecific:
124 if errStr, ok := commandSpecificStatusCodeDesc[e.StatusCode]; ok {
125 return errStr
126 }
127 return fmt.Sprintf("unknown error with command-specific code 0x%x", e.StatusCode)
128 case StatusCodeTypeMediaAndDataIntegrity:
129 if errStr, ok := mediaAndDataIntegrityStatusCodeDesc[e.StatusCode]; ok {
130 return errStr
131 }
132 return fmt.Sprintf("unknown error with media and data integrity code 0x%x", e.StatusCode)
133 default:
134 return fmt.Sprintf("unknown error with unknown type 0x%x and code 0x%x", e.StatusCodeType, e.StatusCode)
135 }
136}