Blame view

include/linux/lightnvm.h 9.9 KB
cd9e9808d   Matias Bjørling   lightnvm: Support...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  #ifndef NVM_H
  #define NVM_H
  
  enum {
  	NVM_IO_OK = 0,
  	NVM_IO_REQUEUE = 1,
  	NVM_IO_DONE = 2,
  	NVM_IO_ERR = 3,
  
  	NVM_IOTYPE_NONE = 0,
  	NVM_IOTYPE_GC = 1,
  };
  
  #ifdef CONFIG_NVM
  
  #include <linux/blkdev.h>
  #include <linux/types.h>
  #include <linux/file.h>
  #include <linux/dmapool.h>
  
  enum {
  	/* HW Responsibilities */
  	NVM_RSP_L2P	= 1 << 0,
  	NVM_RSP_ECC	= 1 << 1,
  
  	/* Physical Adressing Mode */
  	NVM_ADDRMODE_LINEAR	= 0,
  	NVM_ADDRMODE_CHANNEL	= 1,
  
  	/* Plane programming mode for LUN */
  	NVM_PLANE_SINGLE	= 0,
  	NVM_PLANE_DOUBLE	= 1,
  	NVM_PLANE_QUAD		= 2,
  
  	/* Status codes */
  	NVM_RSP_SUCCESS		= 0x0,
  	NVM_RSP_NOT_CHANGEABLE	= 0x1,
  	NVM_RSP_ERR_FAILWRITE	= 0x40ff,
  	NVM_RSP_ERR_EMPTYPAGE	= 0x42ff,
  
  	/* Device opcodes */
  	NVM_OP_HBREAD		= 0x02,
  	NVM_OP_HBWRITE		= 0x81,
  	NVM_OP_PWRITE		= 0x91,
  	NVM_OP_PREAD		= 0x92,
  	NVM_OP_ERASE		= 0x90,
  
  	/* PPA Command Flags */
  	NVM_IO_SNGL_ACCESS	= 0x0,
  	NVM_IO_DUAL_ACCESS	= 0x1,
  	NVM_IO_QUAD_ACCESS	= 0x2,
57b4bd06f   Matias Bjørling   lightnvm: comment...
52
  	/* NAND Access Modes */
cd9e9808d   Matias Bjørling   lightnvm: Support...
53
54
55
  	NVM_IO_SUSPEND		= 0x80,
  	NVM_IO_SLC_MODE		= 0x100,
  	NVM_IO_SCRAMBLE_DISABLE	= 0x200,
57b4bd06f   Matias Bjørling   lightnvm: comment...
56
57
58
59
60
61
  
  	/* Block Types */
  	NVM_BLK_T_FREE		= 0x0,
  	NVM_BLK_T_BAD		= 0x1,
  	NVM_BLK_T_DEV		= 0x2,
  	NVM_BLK_T_HOST		= 0x4,
cd9e9808d   Matias Bjørling   lightnvm: Support...
62
63
64
65
66
  };
  
  struct nvm_id_group {
  	u8	mtype;
  	u8	fmtype;
cd9e9808d   Matias Bjørling   lightnvm: Support...
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  	u8	num_ch;
  	u8	num_lun;
  	u8	num_pln;
  	u16	num_blk;
  	u16	num_pg;
  	u16	fpg_sz;
  	u16	csecs;
  	u16	sos;
  	u32	trdt;
  	u32	trdm;
  	u32	tprt;
  	u32	tprm;
  	u32	tbet;
  	u32	tbem;
  	u32	mpos;
12be5edf6   Matias Bjørling   lightnvm: expose ...
82
  	u32	mccap;
cd9e9808d   Matias Bjørling   lightnvm: Support...
83
  	u16	cpar;
73387e7be   Matias Bjørling   lightnvm: remove ...
84
  };
cd9e9808d   Matias Bjørling   lightnvm: Support...
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  
  struct nvm_addr_format {
  	u8	ch_offset;
  	u8	ch_len;
  	u8	lun_offset;
  	u8	lun_len;
  	u8	pln_offset;
  	u8	pln_len;
  	u8	blk_offset;
  	u8	blk_len;
  	u8	pg_offset;
  	u8	pg_len;
  	u8	sect_offset;
  	u8	sect_len;
cd9e9808d   Matias Bjørling   lightnvm: Support...
99
100
101
102
103
104
  };
  
  struct nvm_id {
  	u8	ver_id;
  	u8	vmnt;
  	u8	cgrps;
cd9e9808d   Matias Bjørling   lightnvm: Support...
105
106
107
  	u32	cap;
  	u32	dom;
  	struct nvm_addr_format ppaf;
cd9e9808d   Matias Bjørling   lightnvm: Support...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
  	struct nvm_id_group groups[4];
  } __packed;
  
  struct nvm_target {
  	struct list_head list;
  	struct nvm_tgt_type *type;
  	struct gendisk *disk;
  };
  
  struct nvm_tgt_instance {
  	struct nvm_tgt_type *tt;
  };
  
  #define ADDR_EMPTY (~0ULL)
  
  #define NVM_VERSION_MAJOR 1
  #define NVM_VERSION_MINOR 0
  #define NVM_VERSION_PATCH 0
cd9e9808d   Matias Bjørling   lightnvm: Support...
126
  #define NVM_BLK_BITS (16)
7386af270   Matias Bjørling   lightnvm: remove ...
127
128
129
130
  #define NVM_PG_BITS  (16)
  #define NVM_SEC_BITS (8)
  #define NVM_PL_BITS  (8)
  #define NVM_LUN_BITS (8)
cd9e9808d   Matias Bjørling   lightnvm: Support...
131
132
133
  #define NVM_CH_BITS  (8)
  
  struct ppa_addr {
7386af270   Matias Bjørling   lightnvm: remove ...
134
  	/* Generic structure for all addresses */
cd9e9808d   Matias Bjørling   lightnvm: Support...
135
  	union {
cd9e9808d   Matias Bjørling   lightnvm: Support...
136
  		struct {
7386af270   Matias Bjørling   lightnvm: remove ...
137
138
  			u64 blk		: NVM_BLK_BITS;
  			u64 pg		: NVM_PG_BITS;
b7ceb7d50   Matias Bjørling   lightnvm: refacto...
139
140
  			u64 sec		: NVM_SEC_BITS;
  			u64 pl		: NVM_PL_BITS;
b7ceb7d50   Matias Bjørling   lightnvm: refacto...
141
142
  			u64 lun		: NVM_LUN_BITS;
  			u64 ch		: NVM_CH_BITS;
cd9e9808d   Matias Bjørling   lightnvm: Support...
143
  		} g;
b7ceb7d50   Matias Bjørling   lightnvm: refacto...
144
  		u64 ppa;
cd9e9808d   Matias Bjørling   lightnvm: Support...
145
  	};
7386af270   Matias Bjørling   lightnvm: remove ...
146
  };
cd9e9808d   Matias Bjørling   lightnvm: Support...
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
  
  struct nvm_rq {
  	struct nvm_tgt_instance *ins;
  	struct nvm_dev *dev;
  
  	struct bio *bio;
  
  	union {
  		struct ppa_addr ppa_addr;
  		dma_addr_t dma_ppa_list;
  	};
  
  	struct ppa_addr *ppa_list;
  
  	void *metadata;
  	dma_addr_t dma_metadata;
  
  	uint8_t opcode;
  	uint16_t nr_pages;
  	uint16_t flags;
  };
  
  static inline struct nvm_rq *nvm_rq_from_pdu(void *pdu)
  {
  	return pdu - sizeof(struct nvm_rq);
  }
  
  static inline void *nvm_rq_to_pdu(struct nvm_rq *rqdata)
  {
  	return rqdata + 1;
  }
  
  struct nvm_block;
  
  typedef int (nvm_l2p_update_fn)(u64, u32, __le64 *, void *);
114504698   Matias Bjørling   lightnvm: update ...
182
  typedef int (nvm_bb_update_fn)(struct ppa_addr, int, u8 *, void *);
16f26c3aa   Matias Bjørling   lightnvm: replace...
183
184
  typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *);
  typedef int (nvm_get_l2p_tbl_fn)(struct nvm_dev *, u64, u32,
cd9e9808d   Matias Bjørling   lightnvm: Support...
185
  				nvm_l2p_update_fn *, void *);
08236c6bb   Matias Bjørling   lightnvm: unconve...
186
  typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, int,
cd9e9808d   Matias Bjørling   lightnvm: Support...
187
  				nvm_bb_update_fn *, void *);
16f26c3aa   Matias Bjørling   lightnvm: replace...
188
189
190
191
  typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct nvm_rq *, int);
  typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
  typedef int (nvm_erase_blk_fn)(struct nvm_dev *, struct nvm_rq *);
  typedef void *(nvm_create_dma_pool_fn)(struct nvm_dev *, char *);
cd9e9808d   Matias Bjørling   lightnvm: Support...
192
  typedef void (nvm_destroy_dma_pool_fn)(void *);
16f26c3aa   Matias Bjørling   lightnvm: replace...
193
  typedef void *(nvm_dev_dma_alloc_fn)(struct nvm_dev *, void *, gfp_t,
cd9e9808d   Matias Bjørling   lightnvm: Support...
194
195
196
197
198
199
200
  								dma_addr_t *);
  typedef void (nvm_dev_dma_free_fn)(void *, void*, dma_addr_t);
  
  struct nvm_dev_ops {
  	nvm_id_fn		*identity;
  	nvm_get_l2p_tbl_fn	*get_l2p_tbl;
  	nvm_op_bb_tbl_fn	*get_bb_tbl;
114504698   Matias Bjørling   lightnvm: update ...
201
  	nvm_op_set_bb_fn	*set_bb_tbl;
cd9e9808d   Matias Bjørling   lightnvm: Support...
202
203
204
205
206
207
208
209
  
  	nvm_submit_io_fn	*submit_io;
  	nvm_erase_blk_fn	*erase_block;
  
  	nvm_create_dma_pool_fn	*create_dma_pool;
  	nvm_destroy_dma_pool_fn	*destroy_dma_pool;
  	nvm_dev_dma_alloc_fn	*dev_dma_alloc;
  	nvm_dev_dma_free_fn	*dev_dma_free;
aedf17f45   Matias Bjørling   lightnvm: change ...
210
  	unsigned int		max_phys_sect;
cd9e9808d   Matias Bjørling   lightnvm: Support...
211
212
213
214
215
216
217
  };
  
  struct nvm_lun {
  	int id;
  
  	int lun_id;
  	int chnl_id;
0b59733b9   Javier Gonzalez   lightnvm: keep tr...
218
  	unsigned int nr_inuse_blocks;	/* Number of used blocks */
cd9e9808d   Matias Bjørling   lightnvm: Support...
219
  	unsigned int nr_free_blocks;	/* Number of unused blocks */
0b59733b9   Javier Gonzalez   lightnvm: keep tr...
220
  	unsigned int nr_bad_blocks;	/* Number of bad blocks */
cd9e9808d   Matias Bjørling   lightnvm: Support...
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  	struct nvm_block *blocks;
  
  	spinlock_t lock;
  };
  
  struct nvm_block {
  	struct list_head list;
  	struct nvm_lun *lun;
  	unsigned long id;
  
  	void *priv;
  	int type;
  };
  
  struct nvm_dev {
  	struct nvm_dev_ops *ops;
  
  	struct list_head devices;
  	struct list_head online_targets;
  
  	/* Media manager */
  	struct nvmm_type *mt;
  	void *mp;
  
  	/* Device information */
  	int nr_chnls;
  	int nr_planes;
  	int luns_per_chnl;
  	int sec_per_pg; /* only sectors for a single page */
  	int pgs_per_blk;
  	int blks_per_lun;
  	int sec_size;
  	int oob_size;
7386af270   Matias Bjørling   lightnvm: remove ...
254
  	struct nvm_addr_format ppaf;
cd9e9808d   Matias Bjørling   lightnvm: Support...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
  
  	/* Calculated/Cached values. These do not reflect the actual usable
  	 * blocks at run-time.
  	 */
  	int max_rq_size;
  	int plane_mode; /* drive device in single, double or quad mode */
  
  	int sec_per_pl; /* all sectors across planes */
  	int sec_per_blk;
  	int sec_per_lun;
  
  	unsigned long total_pages;
  	unsigned long total_blocks;
  	int nr_luns;
  	unsigned max_pages_per_blk;
  
  	void *ppalist_pool;
  
  	struct nvm_id identity;
  
  	/* Backend device */
  	struct request_queue *q;
  	char name[DISK_NAME_LEN];
  };
7386af270   Matias Bjørling   lightnvm: remove ...
279
280
  static inline struct ppa_addr generic_to_dev_addr(struct nvm_dev *dev,
  						struct ppa_addr r)
cd9e9808d   Matias Bjørling   lightnvm: Support...
281
282
  {
  	struct ppa_addr l;
7386af270   Matias Bjørling   lightnvm: remove ...
283
284
285
286
287
288
  	l.ppa = ((u64)r.g.blk) << dev->ppaf.blk_offset;
  	l.ppa |= ((u64)r.g.pg) << dev->ppaf.pg_offset;
  	l.ppa |= ((u64)r.g.sec) << dev->ppaf.sect_offset;
  	l.ppa |= ((u64)r.g.pl) << dev->ppaf.pln_offset;
  	l.ppa |= ((u64)r.g.lun) << dev->ppaf.lun_offset;
  	l.ppa |= ((u64)r.g.ch) << dev->ppaf.ch_offset;
cd9e9808d   Matias Bjørling   lightnvm: Support...
289
290
291
  
  	return l;
  }
7386af270   Matias Bjørling   lightnvm: remove ...
292
293
  static inline struct ppa_addr dev_to_generic_addr(struct nvm_dev *dev,
  						struct ppa_addr r)
cd9e9808d   Matias Bjørling   lightnvm: Support...
294
295
  {
  	struct ppa_addr l;
7386af270   Matias Bjørling   lightnvm: remove ...
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
  	/*
  	 * (r.ppa << X offset) & X len bitmask. X eq. blk, pg, etc.
  	 */
  	l.g.blk = (r.ppa >> dev->ppaf.blk_offset) &
  					(((1 << dev->ppaf.blk_len) - 1));
  	l.g.pg |= (r.ppa >> dev->ppaf.pg_offset) &
  					(((1 << dev->ppaf.pg_len) - 1));
  	l.g.sec |= (r.ppa >> dev->ppaf.sect_offset) &
  					(((1 << dev->ppaf.sect_len) - 1));
  	l.g.pl |= (r.ppa >> dev->ppaf.pln_offset) &
  					(((1 << dev->ppaf.pln_len) - 1));
  	l.g.lun |= (r.ppa >> dev->ppaf.lun_offset) &
  					(((1 << dev->ppaf.lun_len) - 1));
  	l.g.ch |= (r.ppa >> dev->ppaf.ch_offset) &
  					(((1 << dev->ppaf.ch_len) - 1));
cd9e9808d   Matias Bjørling   lightnvm: Support...
311
312
313
  
  	return l;
  }
cd9e9808d   Matias Bjørling   lightnvm: Support...
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
  static inline int ppa_empty(struct ppa_addr ppa_addr)
  {
  	return (ppa_addr.ppa == ADDR_EMPTY);
  }
  
  static inline void ppa_set_empty(struct ppa_addr *ppa_addr)
  {
  	ppa_addr->ppa = ADDR_EMPTY;
  }
  
  static inline struct ppa_addr block_to_ppa(struct nvm_dev *dev,
  							struct nvm_block *blk)
  {
  	struct ppa_addr ppa;
  	struct nvm_lun *lun = blk->lun;
  
  	ppa.ppa = 0;
  	ppa.g.blk = blk->id % dev->blks_per_lun;
  	ppa.g.lun = lun->lun_id;
  	ppa.g.ch = lun->chnl_id;
  
  	return ppa;
  }
dece16353   Jens Axboe   block: change ->m...
337
  typedef blk_qc_t (nvm_tgt_make_rq_fn)(struct request_queue *, struct bio *);
cd9e9808d   Matias Bjørling   lightnvm: Support...
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
  typedef sector_t (nvm_tgt_capacity_fn)(void *);
  typedef int (nvm_tgt_end_io_fn)(struct nvm_rq *, int);
  typedef void *(nvm_tgt_init_fn)(struct nvm_dev *, struct gendisk *, int, int);
  typedef void (nvm_tgt_exit_fn)(void *);
  
  struct nvm_tgt_type {
  	const char *name;
  	unsigned int version[3];
  
  	/* target entry points */
  	nvm_tgt_make_rq_fn *make_rq;
  	nvm_tgt_capacity_fn *capacity;
  	nvm_tgt_end_io_fn *end_io;
  
  	/* module-specific init/teardown */
  	nvm_tgt_init_fn *init;
  	nvm_tgt_exit_fn *exit;
  
  	/* For internal use */
  	struct list_head list;
  };
  
  extern int nvm_register_target(struct nvm_tgt_type *);
  extern void nvm_unregister_target(struct nvm_tgt_type *);
  
  extern void *nvm_dev_dma_alloc(struct nvm_dev *, gfp_t, dma_addr_t *);
  extern void nvm_dev_dma_free(struct nvm_dev *, void *, dma_addr_t);
  
  typedef int (nvmm_register_fn)(struct nvm_dev *);
  typedef void (nvmm_unregister_fn)(struct nvm_dev *);
  typedef struct nvm_block *(nvmm_get_blk_fn)(struct nvm_dev *,
  					      struct nvm_lun *, unsigned long);
  typedef void (nvmm_put_blk_fn)(struct nvm_dev *, struct nvm_block *);
  typedef int (nvmm_open_blk_fn)(struct nvm_dev *, struct nvm_block *);
  typedef int (nvmm_close_blk_fn)(struct nvm_dev *, struct nvm_block *);
  typedef void (nvmm_flush_blk_fn)(struct nvm_dev *, struct nvm_block *);
  typedef int (nvmm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
  typedef int (nvmm_end_io_fn)(struct nvm_rq *, int);
  typedef int (nvmm_erase_blk_fn)(struct nvm_dev *, struct nvm_block *,
  								unsigned long);
  typedef struct nvm_lun *(nvmm_get_lun_fn)(struct nvm_dev *, int);
2fde0e482   Javier Gonzalez   lightnvm: add fre...
379
  typedef void (nvmm_lun_info_print_fn)(struct nvm_dev *);
cd9e9808d   Matias Bjørling   lightnvm: Support...
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
  
  struct nvmm_type {
  	const char *name;
  	unsigned int version[3];
  
  	nvmm_register_fn *register_mgr;
  	nvmm_unregister_fn *unregister_mgr;
  
  	/* Block administration callbacks */
  	nvmm_get_blk_fn *get_blk;
  	nvmm_put_blk_fn *put_blk;
  	nvmm_open_blk_fn *open_blk;
  	nvmm_close_blk_fn *close_blk;
  	nvmm_flush_blk_fn *flush_blk;
  
  	nvmm_submit_io_fn *submit_io;
  	nvmm_end_io_fn *end_io;
  	nvmm_erase_blk_fn *erase_blk;
  
  	/* Configuration management */
  	nvmm_get_lun_fn *get_lun;
  
  	/* Statistics */
2fde0e482   Javier Gonzalez   lightnvm: add fre...
403
  	nvmm_lun_info_print_fn *lun_info_print;
cd9e9808d   Matias Bjørling   lightnvm: Support...
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
  	struct list_head list;
  };
  
  extern int nvm_register_mgr(struct nvmm_type *);
  extern void nvm_unregister_mgr(struct nvmm_type *);
  
  extern struct nvm_block *nvm_get_blk(struct nvm_dev *, struct nvm_lun *,
  								unsigned long);
  extern void nvm_put_blk(struct nvm_dev *, struct nvm_block *);
  
  extern int nvm_register(struct request_queue *, char *,
  						struct nvm_dev_ops *);
  extern void nvm_unregister(char *);
  
  extern int nvm_submit_io(struct nvm_dev *, struct nvm_rq *);
  extern int nvm_erase_blk(struct nvm_dev *, struct nvm_block *);
  #else /* CONFIG_NVM */
  struct nvm_dev_ops;
  
  static inline int nvm_register(struct request_queue *q, char *disk_name,
  							struct nvm_dev_ops *ops)
  {
  	return -EINVAL;
  }
  static inline void nvm_unregister(char *disk_name) {}
  #endif /* CONFIG_NVM */
  #endif /* LIGHTNVM.H */