329 lines
6.8 KiB
C
329 lines
6.8 KiB
C
/*
|
|
* 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
|