xref: /spdk/include/spdk/nvme_ocssd_spec.h (revision a6dbe3721eb3b5990707fc3e378c95e505dd8ab5)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2018 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 /**
7  * \file
8  * Open-Channel specification definitions
9  */
10 
11 #ifndef SPDK_NVME_OCSSD_SPEC_H
12 #define SPDK_NVME_OCSSD_SPEC_H
13 
14 #include "spdk/stdinc.h"
15 
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19 
20 #include "spdk/assert.h"
21 #include "spdk/nvme_spec.h"
22 
23 /** A maximum number of LBAs that can be issued by vector I/O commands */
24 #define SPDK_NVME_OCSSD_MAX_LBAL_ENTRIES	64
25 
26 struct spdk_ocssd_dev_lba_fmt {
27 	/**  Contiguous number of bits assigned to Group addressing */
28 	uint8_t grp_len;
29 
30 	/** Contiguous number of bits assigned to PU addressing */
31 	uint8_t pu_len;
32 
33 	/** Contiguous number of bits assigned to Chunk addressing */
34 	uint8_t chk_len;
35 
36 	/** Contiguous number of bits assigned to logical blocks within Chunk */
37 	uint8_t lbk_len;
38 
39 	uint8_t reserved[4];
40 };
41 SPDK_STATIC_ASSERT(sizeof(struct spdk_ocssd_dev_lba_fmt) == 8, "Incorrect size");
42 
43 struct spdk_ocssd_geometry_data {
44 	/** Major Version Number */
45 	uint8_t		mjr;
46 
47 	/** Minor Version Number */
48 	uint8_t		mnr;
49 
50 	uint8_t		reserved1[6];
51 
52 	/** LBA format */
53 	struct spdk_ocssd_dev_lba_fmt	lbaf;
54 
55 	/** Media and Controller Capabilities */
56 	struct {
57 		/* Supports the Vector Chunk Copy I/O Command */
58 		uint32_t	vec_chk_cpy	: 1;
59 
60 		/* Supports multiple resets when a chunk is in its free state */
61 		uint32_t	multi_reset	: 1;
62 
63 		uint32_t	reserved	: 30;
64 	} mccap;
65 
66 	uint8_t		reserved2[12];
67 
68 	/** Wear-level Index Delta Threshold */
69 	uint8_t		wit;
70 
71 	uint8_t		reserved3[31];
72 
73 	/** Number of Groups */
74 	uint16_t	num_grp;
75 
76 	/** Number of parallel units per group */
77 	uint16_t	num_pu;
78 
79 	/** Number of chunks per parallel unit */
80 	uint32_t	num_chk;
81 
82 	/** Chunk Size */
83 	uint32_t	clba;
84 
85 	uint8_t		reserved4[52];
86 
87 	/** Minimum Write Size */
88 	uint32_t	ws_min;
89 
90 	/** Optimal Write Size */
91 	uint32_t	ws_opt;
92 
93 	/** Cache Minimum Write Size Units */
94 	uint32_t	mw_cunits;
95 
96 	/** Maximum Open Chunks */
97 	uint32_t	maxoc;
98 
99 	/** Maximum Open Chunks per PU */
100 	uint32_t	maxocpu;
101 
102 	uint8_t		reserved5[44];
103 
104 	/** tRD Typical */
105 	uint32_t	trdt;
106 
107 	/** tRD Max */
108 	uint32_t	trdm;
109 
110 	/** tWR Typical */
111 	uint32_t	twrt;
112 
113 	/** tWR Max */
114 	uint32_t	twrm;
115 
116 	/** tCRS Typical */
117 	uint32_t	tcrst;
118 
119 	/** tCRS Max */
120 	uint32_t	tcrsm;
121 
122 	/** bytes 216-255: reserved for performance related metrics */
123 	uint8_t		reserved6[40];
124 
125 	uint8_t		reserved7[3071 - 255];
126 
127 	/** bytes 3072-4095: Vendor Specific */
128 	uint8_t		vs[4095 - 3071];
129 };
130 SPDK_STATIC_ASSERT(sizeof(struct spdk_ocssd_geometry_data) == 4096, "Incorrect size");
131 
132 struct spdk_ocssd_chunk_information_entry {
133 	/** Chunk State */
134 	struct {
135 		/** if set to 1 chunk is free */
136 		uint8_t free		: 1;
137 
138 		/** if set to 1 chunk is closed */
139 		uint8_t closed		: 1;
140 
141 		/** if set to 1 chunk is open */
142 		uint8_t open		: 1;
143 
144 		/** if set to 1 chunk is offline */
145 		uint8_t offline		: 1;
146 
147 		uint8_t reserved	: 4;
148 	} cs;
149 
150 	/** Chunk Type */
151 	struct {
152 		/** If set to 1 chunk must be written sequentially */
153 		uint8_t seq_write		: 1;
154 
155 		/** If set to 1 chunk allows random writes */
156 		uint8_t rnd_write		: 1;
157 
158 		uint8_t reserved1		: 2;
159 
160 		/**
161 		 * If set to 1 chunk deviates from the chunk size reported
162 		 * in identify geometry command.
163 		 */
164 		uint8_t size_deviate		: 1;
165 
166 		uint8_t reserved2		: 3;
167 	} ct;
168 
169 	/** Wear-level Index */
170 	uint8_t wli;
171 
172 	uint8_t reserved[5];
173 
174 	/** Starting LBA */
175 	uint64_t slba;
176 
177 	/** Number of blocks in chunk */
178 	uint64_t cnlb;
179 
180 	/** Write Pointer */
181 	uint64_t wp;
182 };
183 SPDK_STATIC_ASSERT(sizeof(struct spdk_ocssd_chunk_information_entry) == 32, "Incorrect size");
184 
185 struct spdk_ocssd_chunk_notification_entry {
186 
187 	/**
188 	 * This is a 64-bit incrementing notification count, indicating a
189 	 * unique identifier for this notification. The counter begins at 1h
190 	 * and is incremented for each unique event
191 	 */
192 	uint64_t		nc;
193 
194 	/** This field points to the chunk that has its state updated */
195 	uint64_t		lba;
196 
197 	/**
198 	 * This field indicates the namespace id that the event is associated
199 	 * with
200 	 */
201 	uint32_t		nsid;
202 
203 	/** Field that indicate the state of the block */
204 	struct {
205 
206 		/**
207 		 * If set to 1, then the error rate of the chunk has been
208 		 * changed to low
209 		 */
210 		uint8_t error_rate_low : 1;
211 
212 		/**
213 		 * If set to 1, then the error rate of the chunk has been
214 		 * changed to medium
215 		 */
216 		uint8_t error_rate_medium : 1;
217 
218 		/**
219 		 * If set to 1, then the error rate of the chunk has been
220 		 * changed to high
221 		 */
222 		uint8_t error_rate_high : 1;
223 
224 		/**
225 		 * If set to 1, then the error rate of the chunk has been
226 		 * changed to unrecoverable
227 		 */
228 		uint8_t unrecoverable : 1;
229 
230 		/**
231 		 * If set to 1, then the chunk has been refreshed by the
232 		 * device
233 		 */
234 		uint8_t refreshed : 1;
235 
236 		uint8_t rsvd : 3;
237 
238 		/**
239 		 * If set to 1 then the chunk's wear-level index is outside
240 		 * the average wear-level index threshold defined by the
241 		 * controller
242 		 */
243 		uint8_t wit_exceeded : 1;
244 
245 		uint8_t rsvd2 : 7;
246 	} state;
247 
248 	/**
249 	 * The address provided is covering either logical block, chunk, or
250 	 * parallel unit
251 	 */
252 	struct {
253 
254 		/** If set to 1, the LBA covers the logical block */
255 		uint8_t lblk : 1;
256 
257 		/** If set to 1, the LBA covers the respecting chunk */
258 		uint8_t chunk : 1;
259 
260 		/**
261 		 * If set to 1, the LBA covers the respecting parallel unit
262 		 * including all chunks
263 		 */
264 		uint8_t pu : 1;
265 
266 		uint8_t rsvd : 5;
267 	} mask;
268 
269 	uint8_t			rsvd[9];
270 
271 	/**
272 	 * This field indicates the number of logical chunks to be written.
273 	 * This is a 0's based value. This field is only valid if mask bit 0 is
274 	 * set. The number of blocks addressed shall not be outside the boundary
275 	 * of the specified chunk.
276 	 */
277 	uint16_t		nlb;
278 
279 	uint8_t			rsvd2[30];
280 };
281 SPDK_STATIC_ASSERT(sizeof(struct spdk_ocssd_chunk_notification_entry) == 64, "Incorrect size");
282 
283 /**
284  * Vector completion queue entry
285  */
286 struct spdk_ocssd_vector_cpl {
287 	/* dword 0,1 */
288 	uint64_t		lba_status;	/* completion status bit array */
289 
290 	/* dword 2 */
291 	uint16_t		sqhd;	/* submission queue head pointer */
292 	uint16_t		sqid;	/* submission queue identifier */
293 
294 	/* dword 3 */
295 	uint16_t		cid;	/* command identifier */
296 	struct spdk_nvme_status	status;
297 };
298 SPDK_STATIC_ASSERT(sizeof(struct spdk_ocssd_vector_cpl) == 16, "Incorrect size");
299 
300 /**
301  * OCSSD admin command set opcodes
302  */
303 enum spdk_ocssd_admin_opcode {
304 	SPDK_OCSSD_OPC_GEOMETRY	= 0xE2
305 };
306 
307 /**
308  * OCSSD I/O command set opcodes
309  */
310 enum spdk_ocssd_io_opcode {
311 	SPDK_OCSSD_OPC_VECTOR_RESET	= 0x90,
312 	SPDK_OCSSD_OPC_VECTOR_WRITE	= 0x91,
313 	SPDK_OCSSD_OPC_VECTOR_READ	= 0x92,
314 	SPDK_OCSSD_OPC_VECTOR_COPY	= 0x93
315 };
316 
317 /**
318  * Log page identifiers for SPDK_NVME_OPC_GET_LOG_PAGE
319  */
320 enum spdk_ocssd_log_page {
321 	/** Chunk Information */
322 	SPDK_OCSSD_LOG_CHUNK_INFO		= 0xCA,
323 
324 	/** Chunk Notification Log */
325 	SPDK_OCSSD_LOG_CHUNK_NOTIFICATION	= 0xD0,
326 };
327 
328 /**
329  * OCSSD feature identifiers
330  * Defines OCSSD specific features that may be configured with Set Features and
331  * retrieved with Get Features.
332  */
333 enum spdk_ocssd_feat {
334 	/**  Media Feedback feature identifier */
335 	SPDK_OCSSD_FEAT_MEDIA_FEEDBACK	= 0xCA
336 };
337 
338 /**
339  * OCSSD media error status codes extension.
340  * Additional error codes for status code type “2h” (media errors)
341  */
342 enum spdk_ocssd_media_error_status_code {
343 	/**
344 	 * The chunk was either marked offline by the reset or the state
345 	 * of the chunk is already offline.
346 	 */
347 	SPDK_OCSSD_SC_OFFLINE_CHUNK			= 0xC0,
348 
349 	/**
350 	 * Invalid reset if chunk state is either “Free” or “Open”
351 	 */
352 	SPDK_OCSSD_SC_INVALID_RESET			= 0xC1,
353 
354 	/**
355 	 * Write failed, chunk remains open.
356 	 * Host should proceed to write to next write unit.
357 	 */
358 	SPDK_OCSSD_SC_WRITE_FAIL_WRITE_NEXT_UNIT	= 0xF0,
359 
360 	/**
361 	 * The writes ended prematurely. The chunk state is set to closed.
362 	 * The host can read up to the value of the write pointer.
363 	 */
364 	SPDK_OCSSD_SC_WRITE_FAIL_CHUNK_EARLY_CLOSE	= 0xF1,
365 
366 	/**
367 	 * The write corresponds to a write out of order within an open
368 	 * chunk or the write is to a closed or offline chunk.
369 	 */
370 	SPDK_OCSSD_SC_OUT_OF_ORDER_WRITE		= 0xF2,
371 
372 	/**
373 	 * The data retrieved is nearing its limit for reading.
374 	 * The limit is vendor specific, and only provides a hint
375 	 * to the host that should refresh its data in the future.
376 	 */
377 	SPDK_OCSSD_SC_READ_HIGH_ECC			= 0xD0,
378 };
379 
380 #define SPDK_OCSSD_IO_FLAGS_LIMITED_RETRY (1U << 31)
381 
382 #ifdef __cplusplus
383 }
384 #endif
385 
386 #endif
387