diff options
Diffstat (limited to '')
-rw-r--r-- | nvme-lightnvm.h | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/nvme-lightnvm.h b/nvme-lightnvm.h new file mode 100644 index 0000000..19660b7 --- /dev/null +++ b/nvme-lightnvm.h @@ -0,0 +1,329 @@ +/* + * Copyright (C) 2016 CNEX Labs. All rights reserved. + * + * Author: Matias Bjoerling <matias@cnexlabs.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, + * USA. + */ + +#ifndef NVME_LIGHTNVM_H_ +#define NVME_LIGHTNVM_H_ + +#include "linux/lightnvm.h" + +enum nvme_nvm_admin_opcode { + nvme_nvm_admin_identity = 0xe2, + nvme_nvm_admin_get_bb_tbl = 0xf2, + nvme_nvm_admin_set_bb_tbl = 0xf1, +}; + +struct nvme_nvm_identity { + __u8 opcode; + __u8 flags; + __le16 command_id; + __le32 nsid; + __le64 rsvd[2]; + __le64 prp1; + __le64 prp2; + __le32 chnl_off; + __le32 rsvd11[5]; +}; + +struct nvme_nvm_setbbtbl { + __u8 opcode; + __u8 flags; + __le16 rsvd1; + __le32 nsid; + __le32 cdw2; + __le32 cdw3; + __le64 metadata; + __u64 addr; + __le32 metadata_len; + __le32 data_len; + __le64 ppa; + __le16 nlb; + __u8 value; + __u8 rsvd2; + __le32 cdw14; + __le32 cdw15; + __le32 timeout_ms; + __le32 result; +}; + +struct nvme_nvm_getbbtbl { + __u8 opcode; + __u8 flags; + __le16 rsvd1; + __le32 nsid; + __le32 cdw2; + __le32 cdw3; + __u64 metadata; + __u64 addr; + __u32 metadata_len; + __u32 data_len; + __le64 ppa; + __le32 cdw12; + __le32 cdw13; + __le32 cdw14; + __le32 cdw15; + __le32 timeout_ms; + __le32 result; +}; + +struct nvme_nvm_command { + union { + struct nvme_nvm_identity identity; + struct nvme_nvm_getbbtbl get_bb; + }; +}; + +struct nvme_nvm_completion { + __le64 result; /* Used by LightNVM to return ppa completions */ + __le16 sq_head; /* how much of this queue may be reclaimed */ + __le16 sq_id; /* submission queue that generated this entry */ + __le16 command_id; /* of the command which completed */ + __le16 status; /* did the command fail, and if so, why? */ +}; + +#define NVME_NVM_LP_MLC_PAIRS 886 +struct nvme_nvm_lp_mlc { + __le16 num_pairs; + __u8 pairs[NVME_NVM_LP_MLC_PAIRS]; +}; + +struct nvme_nvm_lp_tbl { + __u8 id[8]; + struct nvme_nvm_lp_mlc mlc; +}; + +struct nvme_nvm_id12_group { + __u8 mtype; + __u8 fmtype; + __le16 res16; + __u8 num_ch; + __u8 num_lun; + __u8 num_pln; + __u8 rsvd1; + __le16 num_blk; + __le16 num_pg; + __le16 fpg_sz; + __le16 csecs; + __le16 sos; + __le16 rsvd2; + __le32 trdt; + __le32 trdm; + __le32 tprt; + __le32 tprm; + __le32 tbet; + __le32 tbem; + __le32 mpos; + __le32 mccap; + __le16 cpar; + __u8 reserved[10]; + struct nvme_nvm_lp_tbl lptbl; +} __attribute__((packed)); + +struct nvme_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; + __u8 res[4]; +} __attribute__((packed)); + +enum { + LNVM_IDFY_CAP_BAD_BLK_TBL_MGMT = 0, + LNVM_IDFY_CAP_HYBRID_CMD_SUPP = 1, + LNVM_IDFY_CAP_VCOPY = 0, + LNVM_IDFY_CAP_MRESETS = 1, + LNVM_IDFY_DOM_HYBRID_MODE = 0, + LNVM_IDFY_DOM_ECC_MODE = 1, + LNVM_IDFY_GRP_MTYPE_NAND = 0, + LNVM_IDFY_GRP_FMTYPE_SLC = 0, + LNVM_IDFY_GRP_FMTYPE_MLC = 1, + LNVM_IDFY_GRP_FMTYPE_TLC = 2, + LNVM_IDFY_GRP_MPOS_SNGL_PLN_RD = 0, + LNVM_IDFY_GRP_MPOS_DUAL_PLN_RD = 1, + LNVM_IDFY_GRP_MPOS_QUAD_PLN_RD = 2, + LNVM_IDFY_GRP_MPOS_SNGL_PLN_PRG = 8, + LNVM_IDFY_GRP_MPOS_DUAL_PLN_PRG = 9, + LNVM_IDFY_GRP_MPOS_QUAD_PLN_PRG = 10, + LNVM_IDFY_GRP_MPOS_SNGL_PLN_ERS = 16, + LNVM_IDFY_GRP_MPOS_DUAL_PLN_ERS = 17, + LNVM_IDFY_GRP_MPOS_QUAD_PLN_ERS = 18, + LNVM_IDFY_GRP_MCCAP_SLC = 0, + LNVM_IDFY_GRP_MCCAP_CMD_SUSP = 1, + LNVM_IDFY_GRP_MCCAP_SCRAMBLE = 2, + LNVM_IDFY_GRP_MCCAP_ENCRYPT = 3, +}; + +struct nvme_nvm_id12 { + __u8 ver_id; + __u8 vmnt; + __u8 cgrps; + __u8 res; + __le32 cap; + __le32 dom; + struct nvme_nvm_addr_format ppaf; + __u8 resv[228]; + struct nvme_nvm_id12_group groups[4]; +} __attribute__((packed)); + +struct nvme_nvm_id20_addrf { + __u8 grp_len; + __u8 pu_len; + __u8 chk_len; + __u8 lba_len; + __u8 resv[4]; +} __attribute__((packed)); + +struct nvme_nvm_id20 { + __u8 mjr; + __u8 mnr; + __u8 resv[6]; + + struct nvme_nvm_id20_addrf lbaf; + + __le32 mccap; + __u8 resv2[12]; + + __u8 wit; + __u8 resv3[31]; + + /* Geometry */ + __le16 num_grp; + __le16 num_pu; + __le32 num_chk; + __le32 clba; + __u8 resv4[52]; + + /* Write data requirements */ + __le32 ws_min; + __le32 ws_opt; + __le32 mw_cunits; + __le32 maxoc; + __le32 maxocpu; + __u8 resv5[44]; + + /* Performance related metrics */ + __le32 trdt; + __le32 trdm; + __le32 twrt; + __le32 twrm; + __le32 tcrst; + __le32 tcrsm; + __u8 resv6[40]; + + /* Reserved area */ + __u8 resv7[2816]; + + /* Vendor specific */ + __u8 vs[1024]; +} __attribute__((packed)); + +struct nvme_nvm_id { + __u8 ver_id; + __u8 resv[4095]; +} __attribute__((packed)); + +enum { + NVM_LID_CHUNK_INFO = 0xCA, +}; + +struct nvme_nvm_chunk_desc { + __u8 cs; + __u8 ct; + __u8 wli; + __u8 rsvd_7_3[5]; + __u64 slba; + __u64 cnlb; + __u64 wp; +}; + +struct nvme_nvm_bb_tbl { + __u8 tblid[4]; + __le16 verid; + __le16 revid; + __le32 rvsd1; + __le32 tblks; + __le32 tfact; + __le32 tgrown; + __le32 tdresv; + __le32 thresv; + __le32 rsvd2[8]; + __u8 blk[0]; +}; + +#define NVM_BLK_BITS (16) +#define NVM_PG_BITS (16) +#define NVM_SEC_BITS (8) +#define NVM_PL_BITS (8) +#define NVM_LUN_BITS (8) +#define NVM_CH_BITS (7) + +struct ppa_addr { + /* Generic structure for all addresses */ + union { + struct { + __u64 blk : NVM_BLK_BITS; + __u64 pg : NVM_PG_BITS; + __u64 sec : NVM_SEC_BITS; + __u64 pl : NVM_PL_BITS; + __u64 lun : NVM_LUN_BITS; + __u64 ch : NVM_CH_BITS; + __u64 reserved : 1; + } g; + + __u64 ppa; + }; +}; + +static inline struct ppa_addr generic_to_dev_addr( + struct nvme_nvm_addr_format *ppaf, struct ppa_addr r) +{ + struct ppa_addr l; + + l.ppa = ((__u64)r.g.blk) << ppaf->blk_offset; + l.ppa |= ((__u64)r.g.pg) << ppaf->pg_offset; + l.ppa |= ((__u64)r.g.sec) << ppaf->sect_offset; + l.ppa |= ((__u64)r.g.pl) << ppaf->pln_offset; + l.ppa |= ((__u64)r.g.lun) << ppaf->lun_offset; + l.ppa |= ((__u64)r.g.ch) << ppaf->ch_offset; + + return l; +} + +int lnvm_get_identity(int fd, int nsid, struct nvme_nvm_id *nvm_id); + +int lnvm_do_init(char *, char *); +int lnvm_do_list_devices(void); +int lnvm_do_info(void); +int lnvm_do_create_tgt(char *, char *, char *, int, int, int, int); +int lnvm_do_remove_tgt(char *); +int lnvm_do_factory_init(char *, int, int, int); +int lnvm_do_id_ns(int, int, unsigned int); +int lnvm_do_chunk_log(int, __u32, __u32, void *, unsigned int); +int lnvm_do_get_bbtbl(int, int, int, int, unsigned int); +int lnvm_do_set_bbtbl(int, int, int, int, int, int, __u8); + +#endif |