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