aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/lightnvm.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/lightnvm.h')
-rw-r--r--include/linux/lightnvm.h197
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
58struct nvm_id_group { 65struct 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
81struct nvm_addr_format { 87struct 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
97struct nvm_id { 102struct 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
133struct ppa_addr { 135struct 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
160struct nvm_rq { 151struct 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)
191struct nvm_block; 182struct nvm_block;
192 183
193typedef int (nvm_l2p_update_fn)(u64, u32, __le64 *, void *); 184typedef int (nvm_l2p_update_fn)(u64, u32, __le64 *, void *);
194typedef int (nvm_bb_update_fn)(u32, void *, unsigned int, void *); 185typedef int (nvm_bb_update_fn)(struct ppa_addr, int, u8 *, void *);
195typedef int (nvm_id_fn)(struct request_queue *, struct nvm_id *); 186typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *);
196typedef int (nvm_get_l2p_tbl_fn)(struct request_queue *, u64, u32, 187typedef int (nvm_get_l2p_tbl_fn)(struct nvm_dev *, u64, u32,
197 nvm_l2p_update_fn *, void *); 188 nvm_l2p_update_fn *, void *);
198typedef int (nvm_op_bb_tbl_fn)(struct request_queue *, int, unsigned int, 189typedef 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 *);
200typedef int (nvm_op_set_bb_fn)(struct request_queue *, struct nvm_rq *, int); 191typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct nvm_rq *, int);
201typedef int (nvm_submit_io_fn)(struct request_queue *, struct nvm_rq *); 192typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
202typedef int (nvm_erase_blk_fn)(struct request_queue *, struct nvm_rq *); 193typedef int (nvm_erase_blk_fn)(struct nvm_dev *, struct nvm_rq *);
203typedef void *(nvm_create_dma_pool_fn)(struct request_queue *, char *); 194typedef void *(nvm_create_dma_pool_fn)(struct nvm_dev *, char *);
204typedef void (nvm_destroy_dma_pool_fn)(void *); 195typedef void (nvm_destroy_dma_pool_fn)(void *);
205typedef void *(nvm_dev_dma_alloc_fn)(struct request_queue *, void *, gfp_t, 196typedef void *(nvm_dev_dma_alloc_fn)(struct nvm_dev *, void *, gfp_t,
206 dma_addr_t *); 197 dma_addr_t *);
207typedef void (nvm_dev_dma_free_fn)(void *, void*, dma_addr_t); 198typedef 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
226struct nvm_lun { 217struct 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 */ 285static inline struct ppa_addr generic_to_dev_addr(struct nvm_dev *dev,
294static 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 */ 300static inline struct ppa_addr dev_to_generic_addr(struct nvm_dev *dev,
315static 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
345static 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
361static 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
377static 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
391static 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
405static inline int ppa_empty(struct ppa_addr ppa_addr) 324static 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);
468typedef int (nvmm_erase_blk_fn)(struct nvm_dev *, struct nvm_block *, 387typedef int (nvmm_erase_blk_fn)(struct nvm_dev *, struct nvm_block *,
469 unsigned long); 388 unsigned long);
470typedef struct nvm_lun *(nvmm_get_lun_fn)(struct nvm_dev *, int); 389typedef struct nvm_lun *(nvmm_get_lun_fn)(struct nvm_dev *, int);
471typedef void (nvmm_free_blocks_print_fn)(struct nvm_dev *); 390typedef void (nvmm_lun_info_print_fn)(struct nvm_dev *);
472 391
473struct nvmm_type { 392struct 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