diff options
Diffstat (limited to 'include/linux/lightnvm.h')
-rw-r--r-- | include/linux/lightnvm.h | 197 |
1 files changed, 58 insertions, 139 deletions
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index 69c9057e1ab8..034117b3be5f 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h | |||
@@ -50,15 +50,21 @@ enum { | |||
50 | NVM_IO_DUAL_ACCESS = 0x1, | 50 | NVM_IO_DUAL_ACCESS = 0x1, |
51 | NVM_IO_QUAD_ACCESS = 0x2, | 51 | NVM_IO_QUAD_ACCESS = 0x2, |
52 | 52 | ||
53 | /* NAND Access Modes */ | ||
53 | NVM_IO_SUSPEND = 0x80, | 54 | NVM_IO_SUSPEND = 0x80, |
54 | NVM_IO_SLC_MODE = 0x100, | 55 | NVM_IO_SLC_MODE = 0x100, |
55 | NVM_IO_SCRAMBLE_DISABLE = 0x200, | 56 | NVM_IO_SCRAMBLE_DISABLE = 0x200, |
57 | |||
58 | /* Block Types */ | ||
59 | NVM_BLK_T_FREE = 0x0, | ||
60 | NVM_BLK_T_BAD = 0x1, | ||
61 | NVM_BLK_T_DEV = 0x2, | ||
62 | NVM_BLK_T_HOST = 0x4, | ||
56 | }; | 63 | }; |
57 | 64 | ||
58 | struct nvm_id_group { | 65 | struct nvm_id_group { |
59 | u8 mtype; | 66 | u8 mtype; |
60 | u8 fmtype; | 67 | u8 fmtype; |
61 | u16 res16; | ||
62 | u8 num_ch; | 68 | u8 num_ch; |
63 | u8 num_lun; | 69 | u8 num_lun; |
64 | u8 num_pln; | 70 | u8 num_pln; |
@@ -74,9 +80,9 @@ struct nvm_id_group { | |||
74 | u32 tbet; | 80 | u32 tbet; |
75 | u32 tbem; | 81 | u32 tbem; |
76 | u32 mpos; | 82 | u32 mpos; |
83 | u32 mccap; | ||
77 | u16 cpar; | 84 | u16 cpar; |
78 | u8 res[913]; | 85 | }; |
79 | } __packed; | ||
80 | 86 | ||
81 | struct nvm_addr_format { | 87 | struct nvm_addr_format { |
82 | u8 ch_offset; | 88 | u8 ch_offset; |
@@ -91,19 +97,15 @@ struct nvm_addr_format { | |||
91 | u8 pg_len; | 97 | u8 pg_len; |
92 | u8 sect_offset; | 98 | u8 sect_offset; |
93 | u8 sect_len; | 99 | u8 sect_len; |
94 | u8 res[4]; | ||
95 | }; | 100 | }; |
96 | 101 | ||
97 | struct nvm_id { | 102 | struct nvm_id { |
98 | u8 ver_id; | 103 | u8 ver_id; |
99 | u8 vmnt; | 104 | u8 vmnt; |
100 | u8 cgrps; | 105 | u8 cgrps; |
101 | u8 res[5]; | ||
102 | u32 cap; | 106 | u32 cap; |
103 | u32 dom; | 107 | u32 dom; |
104 | struct nvm_addr_format ppaf; | 108 | struct nvm_addr_format ppaf; |
105 | u8 ppat; | ||
106 | u8 resv[224]; | ||
107 | struct nvm_id_group groups[4]; | 109 | struct nvm_id_group groups[4]; |
108 | } __packed; | 110 | } __packed; |
109 | 111 | ||
@@ -123,39 +125,28 @@ struct nvm_tgt_instance { | |||
123 | #define NVM_VERSION_MINOR 0 | 125 | #define NVM_VERSION_MINOR 0 |
124 | #define NVM_VERSION_PATCH 0 | 126 | #define NVM_VERSION_PATCH 0 |
125 | 127 | ||
126 | #define NVM_SEC_BITS (8) | ||
127 | #define NVM_PL_BITS (6) | ||
128 | #define NVM_PG_BITS (16) | ||
129 | #define NVM_BLK_BITS (16) | 128 | #define NVM_BLK_BITS (16) |
130 | #define NVM_LUN_BITS (10) | 129 | #define NVM_PG_BITS (16) |
130 | #define NVM_SEC_BITS (8) | ||
131 | #define NVM_PL_BITS (8) | ||
132 | #define NVM_LUN_BITS (8) | ||
131 | #define NVM_CH_BITS (8) | 133 | #define NVM_CH_BITS (8) |
132 | 134 | ||
133 | struct ppa_addr { | 135 | struct ppa_addr { |
136 | /* Generic structure for all addresses */ | ||
134 | union { | 137 | union { |
135 | /* Channel-based PPA format in nand 4x2x2x2x8x10 */ | ||
136 | struct { | ||
137 | u64 ch : 4; | ||
138 | u64 sec : 2; /* 4 sectors per page */ | ||
139 | u64 pl : 2; /* 4 planes per LUN */ | ||
140 | u64 lun : 2; /* 4 LUNs per channel */ | ||
141 | u64 pg : 8; /* 256 pages per block */ | ||
142 | u64 blk : 10;/* 1024 blocks per plane */ | ||
143 | u64 resved : 36; | ||
144 | } chnl; | ||
145 | |||
146 | /* Generic structure for all addresses */ | ||
147 | struct { | 138 | struct { |
139 | u64 blk : NVM_BLK_BITS; | ||
140 | u64 pg : NVM_PG_BITS; | ||
148 | u64 sec : NVM_SEC_BITS; | 141 | u64 sec : NVM_SEC_BITS; |
149 | u64 pl : NVM_PL_BITS; | 142 | u64 pl : NVM_PL_BITS; |
150 | u64 pg : NVM_PG_BITS; | ||
151 | u64 blk : NVM_BLK_BITS; | ||
152 | u64 lun : NVM_LUN_BITS; | 143 | u64 lun : NVM_LUN_BITS; |
153 | u64 ch : NVM_CH_BITS; | 144 | u64 ch : NVM_CH_BITS; |
154 | } g; | 145 | } g; |
155 | 146 | ||
156 | u64 ppa; | 147 | u64 ppa; |
157 | }; | 148 | }; |
158 | } __packed; | 149 | }; |
159 | 150 | ||
160 | struct nvm_rq { | 151 | struct nvm_rq { |
161 | struct nvm_tgt_instance *ins; | 152 | struct nvm_tgt_instance *ins; |
@@ -191,18 +182,18 @@ static inline void *nvm_rq_to_pdu(struct nvm_rq *rqdata) | |||
191 | struct nvm_block; | 182 | struct nvm_block; |
192 | 183 | ||
193 | typedef int (nvm_l2p_update_fn)(u64, u32, __le64 *, void *); | 184 | typedef int (nvm_l2p_update_fn)(u64, u32, __le64 *, void *); |
194 | typedef int (nvm_bb_update_fn)(u32, void *, unsigned int, void *); | 185 | typedef int (nvm_bb_update_fn)(struct ppa_addr, int, u8 *, void *); |
195 | typedef int (nvm_id_fn)(struct request_queue *, struct nvm_id *); | 186 | typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *); |
196 | typedef int (nvm_get_l2p_tbl_fn)(struct request_queue *, u64, u32, | 187 | typedef int (nvm_get_l2p_tbl_fn)(struct nvm_dev *, u64, u32, |
197 | nvm_l2p_update_fn *, void *); | 188 | nvm_l2p_update_fn *, void *); |
198 | typedef int (nvm_op_bb_tbl_fn)(struct request_queue *, int, unsigned int, | 189 | typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, int, |
199 | nvm_bb_update_fn *, void *); | 190 | nvm_bb_update_fn *, void *); |
200 | typedef int (nvm_op_set_bb_fn)(struct request_queue *, struct nvm_rq *, int); | 191 | typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct nvm_rq *, int); |
201 | typedef int (nvm_submit_io_fn)(struct request_queue *, struct nvm_rq *); | 192 | typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *); |
202 | typedef int (nvm_erase_blk_fn)(struct request_queue *, struct nvm_rq *); | 193 | typedef int (nvm_erase_blk_fn)(struct nvm_dev *, struct nvm_rq *); |
203 | typedef void *(nvm_create_dma_pool_fn)(struct request_queue *, char *); | 194 | typedef void *(nvm_create_dma_pool_fn)(struct nvm_dev *, char *); |
204 | typedef void (nvm_destroy_dma_pool_fn)(void *); | 195 | typedef void (nvm_destroy_dma_pool_fn)(void *); |
205 | typedef void *(nvm_dev_dma_alloc_fn)(struct request_queue *, void *, gfp_t, | 196 | typedef void *(nvm_dev_dma_alloc_fn)(struct nvm_dev *, void *, gfp_t, |
206 | dma_addr_t *); | 197 | dma_addr_t *); |
207 | typedef void (nvm_dev_dma_free_fn)(void *, void*, dma_addr_t); | 198 | typedef void (nvm_dev_dma_free_fn)(void *, void*, dma_addr_t); |
208 | 199 | ||
@@ -210,7 +201,7 @@ struct nvm_dev_ops { | |||
210 | nvm_id_fn *identity; | 201 | nvm_id_fn *identity; |
211 | nvm_get_l2p_tbl_fn *get_l2p_tbl; | 202 | nvm_get_l2p_tbl_fn *get_l2p_tbl; |
212 | nvm_op_bb_tbl_fn *get_bb_tbl; | 203 | nvm_op_bb_tbl_fn *get_bb_tbl; |
213 | nvm_op_set_bb_fn *set_bb; | 204 | nvm_op_set_bb_fn *set_bb_tbl; |
214 | 205 | ||
215 | nvm_submit_io_fn *submit_io; | 206 | nvm_submit_io_fn *submit_io; |
216 | nvm_erase_blk_fn *erase_block; | 207 | nvm_erase_blk_fn *erase_block; |
@@ -220,7 +211,7 @@ struct nvm_dev_ops { | |||
220 | nvm_dev_dma_alloc_fn *dev_dma_alloc; | 211 | nvm_dev_dma_alloc_fn *dev_dma_alloc; |
221 | nvm_dev_dma_free_fn *dev_dma_free; | 212 | nvm_dev_dma_free_fn *dev_dma_free; |
222 | 213 | ||
223 | uint8_t max_phys_sect; | 214 | unsigned int max_phys_sect; |
224 | }; | 215 | }; |
225 | 216 | ||
226 | struct nvm_lun { | 217 | struct nvm_lun { |
@@ -229,7 +220,9 @@ struct nvm_lun { | |||
229 | int lun_id; | 220 | int lun_id; |
230 | int chnl_id; | 221 | int chnl_id; |
231 | 222 | ||
223 | unsigned int nr_inuse_blocks; /* Number of used blocks */ | ||
232 | unsigned int nr_free_blocks; /* Number of unused blocks */ | 224 | unsigned int nr_free_blocks; /* Number of unused blocks */ |
225 | unsigned int nr_bad_blocks; /* Number of bad blocks */ | ||
233 | struct nvm_block *blocks; | 226 | struct nvm_block *blocks; |
234 | 227 | ||
235 | spinlock_t lock; | 228 | spinlock_t lock; |
@@ -263,8 +256,7 @@ struct nvm_dev { | |||
263 | int blks_per_lun; | 256 | int blks_per_lun; |
264 | int sec_size; | 257 | int sec_size; |
265 | int oob_size; | 258 | int oob_size; |
266 | int addr_mode; | 259 | struct nvm_addr_format ppaf; |
267 | struct nvm_addr_format addr_format; | ||
268 | 260 | ||
269 | /* Calculated/Cached values. These do not reflect the actual usable | 261 | /* Calculated/Cached values. These do not reflect the actual usable |
270 | * blocks at run-time. | 262 | * blocks at run-time. |
@@ -290,118 +282,45 @@ struct nvm_dev { | |||
290 | char name[DISK_NAME_LEN]; | 282 | char name[DISK_NAME_LEN]; |
291 | }; | 283 | }; |
292 | 284 | ||
293 | /* fallback conversion */ | 285 | static inline struct ppa_addr generic_to_dev_addr(struct nvm_dev *dev, |
294 | static struct ppa_addr __generic_to_linear_addr(struct nvm_dev *dev, | 286 | struct ppa_addr r) |
295 | struct ppa_addr r) | ||
296 | { | 287 | { |
297 | struct ppa_addr l; | 288 | struct ppa_addr l; |
298 | 289 | ||
299 | l.ppa = r.g.sec + | 290 | l.ppa = ((u64)r.g.blk) << dev->ppaf.blk_offset; |
300 | r.g.pg * dev->sec_per_pg + | 291 | l.ppa |= ((u64)r.g.pg) << dev->ppaf.pg_offset; |
301 | r.g.blk * (dev->pgs_per_blk * | 292 | l.ppa |= ((u64)r.g.sec) << dev->ppaf.sect_offset; |
302 | dev->sec_per_pg) + | 293 | l.ppa |= ((u64)r.g.pl) << dev->ppaf.pln_offset; |
303 | r.g.lun * (dev->blks_per_lun * | 294 | l.ppa |= ((u64)r.g.lun) << dev->ppaf.lun_offset; |
304 | dev->pgs_per_blk * | 295 | l.ppa |= ((u64)r.g.ch) << dev->ppaf.ch_offset; |
305 | dev->sec_per_pg) + | ||
306 | r.g.ch * (dev->blks_per_lun * | ||
307 | dev->pgs_per_blk * | ||
308 | dev->luns_per_chnl * | ||
309 | dev->sec_per_pg); | ||
310 | 296 | ||
311 | return l; | 297 | return l; |
312 | } | 298 | } |
313 | 299 | ||
314 | /* fallback conversion */ | 300 | static inline struct ppa_addr dev_to_generic_addr(struct nvm_dev *dev, |
315 | static struct ppa_addr __linear_to_generic_addr(struct nvm_dev *dev, | 301 | struct ppa_addr r) |
316 | struct ppa_addr r) | ||
317 | { | 302 | { |
318 | struct ppa_addr l; | 303 | struct ppa_addr l; |
319 | int secs, pgs, blks, luns; | ||
320 | sector_t ppa = r.ppa; | ||
321 | |||
322 | l.ppa = 0; | ||
323 | |||
324 | div_u64_rem(ppa, dev->sec_per_pg, &secs); | ||
325 | l.g.sec = secs; | ||
326 | 304 | ||
327 | sector_div(ppa, dev->sec_per_pg); | 305 | /* |
328 | div_u64_rem(ppa, dev->sec_per_blk, &pgs); | 306 | * (r.ppa << X offset) & X len bitmask. X eq. blk, pg, etc. |
329 | l.g.pg = pgs; | 307 | */ |
330 | 308 | l.g.blk = (r.ppa >> dev->ppaf.blk_offset) & | |
331 | sector_div(ppa, dev->pgs_per_blk); | 309 | (((1 << dev->ppaf.blk_len) - 1)); |
332 | div_u64_rem(ppa, dev->blks_per_lun, &blks); | 310 | l.g.pg |= (r.ppa >> dev->ppaf.pg_offset) & |
333 | l.g.blk = blks; | 311 | (((1 << dev->ppaf.pg_len) - 1)); |
334 | 312 | l.g.sec |= (r.ppa >> dev->ppaf.sect_offset) & | |
335 | sector_div(ppa, dev->blks_per_lun); | 313 | (((1 << dev->ppaf.sect_len) - 1)); |
336 | div_u64_rem(ppa, dev->luns_per_chnl, &luns); | 314 | l.g.pl |= (r.ppa >> dev->ppaf.pln_offset) & |
337 | l.g.lun = luns; | 315 | (((1 << dev->ppaf.pln_len) - 1)); |
338 | 316 | l.g.lun |= (r.ppa >> dev->ppaf.lun_offset) & | |
339 | sector_div(ppa, dev->luns_per_chnl); | 317 | (((1 << dev->ppaf.lun_len) - 1)); |
340 | l.g.ch = ppa; | 318 | l.g.ch |= (r.ppa >> dev->ppaf.ch_offset) & |
341 | 319 | (((1 << dev->ppaf.ch_len) - 1)); | |
342 | return l; | ||
343 | } | ||
344 | |||
345 | static struct ppa_addr __generic_to_chnl_addr(struct ppa_addr r) | ||
346 | { | ||
347 | struct ppa_addr l; | ||
348 | |||
349 | l.ppa = 0; | ||
350 | |||
351 | l.chnl.sec = r.g.sec; | ||
352 | l.chnl.pl = r.g.pl; | ||
353 | l.chnl.pg = r.g.pg; | ||
354 | l.chnl.blk = r.g.blk; | ||
355 | l.chnl.lun = r.g.lun; | ||
356 | l.chnl.ch = r.g.ch; | ||
357 | |||
358 | return l; | ||
359 | } | ||
360 | |||
361 | static struct ppa_addr __chnl_to_generic_addr(struct ppa_addr r) | ||
362 | { | ||
363 | struct ppa_addr l; | ||
364 | |||
365 | l.ppa = 0; | ||
366 | |||
367 | l.g.sec = r.chnl.sec; | ||
368 | l.g.pl = r.chnl.pl; | ||
369 | l.g.pg = r.chnl.pg; | ||
370 | l.g.blk = r.chnl.blk; | ||
371 | l.g.lun = r.chnl.lun; | ||
372 | l.g.ch = r.chnl.ch; | ||
373 | 320 | ||
374 | return l; | 321 | return l; |
375 | } | 322 | } |
376 | 323 | ||
377 | static inline struct ppa_addr addr_to_generic_mode(struct nvm_dev *dev, | ||
378 | struct ppa_addr gppa) | ||
379 | { | ||
380 | switch (dev->addr_mode) { | ||
381 | case NVM_ADDRMODE_LINEAR: | ||
382 | return __linear_to_generic_addr(dev, gppa); | ||
383 | case NVM_ADDRMODE_CHANNEL: | ||
384 | return __chnl_to_generic_addr(gppa); | ||
385 | default: | ||
386 | BUG(); | ||
387 | } | ||
388 | return gppa; | ||
389 | } | ||
390 | |||
391 | static inline struct ppa_addr generic_to_addr_mode(struct nvm_dev *dev, | ||
392 | struct ppa_addr gppa) | ||
393 | { | ||
394 | switch (dev->addr_mode) { | ||
395 | case NVM_ADDRMODE_LINEAR: | ||
396 | return __generic_to_linear_addr(dev, gppa); | ||
397 | case NVM_ADDRMODE_CHANNEL: | ||
398 | return __generic_to_chnl_addr(gppa); | ||
399 | default: | ||
400 | BUG(); | ||
401 | } | ||
402 | return gppa; | ||
403 | } | ||
404 | |||
405 | static inline int ppa_empty(struct ppa_addr ppa_addr) | 324 | static inline int ppa_empty(struct ppa_addr ppa_addr) |
406 | { | 325 | { |
407 | return (ppa_addr.ppa == ADDR_EMPTY); | 326 | return (ppa_addr.ppa == ADDR_EMPTY); |
@@ -468,7 +387,7 @@ typedef int (nvmm_end_io_fn)(struct nvm_rq *, int); | |||
468 | typedef int (nvmm_erase_blk_fn)(struct nvm_dev *, struct nvm_block *, | 387 | typedef int (nvmm_erase_blk_fn)(struct nvm_dev *, struct nvm_block *, |
469 | unsigned long); | 388 | unsigned long); |
470 | typedef struct nvm_lun *(nvmm_get_lun_fn)(struct nvm_dev *, int); | 389 | typedef struct nvm_lun *(nvmm_get_lun_fn)(struct nvm_dev *, int); |
471 | typedef void (nvmm_free_blocks_print_fn)(struct nvm_dev *); | 390 | typedef void (nvmm_lun_info_print_fn)(struct nvm_dev *); |
472 | 391 | ||
473 | struct nvmm_type { | 392 | struct nvmm_type { |
474 | const char *name; | 393 | const char *name; |
@@ -492,7 +411,7 @@ struct nvmm_type { | |||
492 | nvmm_get_lun_fn *get_lun; | 411 | nvmm_get_lun_fn *get_lun; |
493 | 412 | ||
494 | /* Statistics */ | 413 | /* Statistics */ |
495 | nvmm_free_blocks_print_fn *free_blocks_print; | 414 | nvmm_lun_info_print_fn *lun_info_print; |
496 | struct list_head list; | 415 | struct list_head list; |
497 | }; | 416 | }; |
498 | 417 | ||