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