From: Matias Bjørling Date: Fri, 25 May 2018 07:04:34 +0000 (+0200) Subject: Add open-channel 2.0 identify support X-Git-Tag: v1.6~41^2 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=000e7d63ea17d011dd7ff4ec5f893746a5268cd0;p=users%2Fsagi%2Fnvme-cli.git Add open-channel 2.0 identify support The 2.0 specification has been released. Update the lightnvm submodule to understand the 2.0 geometry structure. Signed-off-by: Matias Bjørling --- diff --git a/nvme-lightnvm.c b/nvme-lightnvm.c index 12a0b01d..465f4912 100644 --- a/nvme-lightnvm.c +++ b/nvme-lightnvm.c @@ -239,7 +239,7 @@ int lnvm_do_factory_init(char *devname, int erase_only_marked, return ret; } -static void show_lnvm_id_grp(struct nvme_nvm_id_group *grp, int human) +static void show_lnvm_id_grp(struct nvme_nvm_id12_group *grp, int human) { uint32_t mpos = (uint32_t)le32_to_cpu(grp->mpos); uint32_t mccap = (uint32_t)le32_to_cpu(grp->mccap); @@ -329,7 +329,7 @@ static void show_lnvm_ppaf(struct nvme_nvm_addr_format *ppaf) ppaf->sect_offset, ppaf->sect_len); } -static void show_lnvm_id_ns(struct nvme_nvm_id *id, unsigned int flags) +static void show_lnvm_id12_ns(struct nvme_nvm_id12 *id, unsigned int flags) { int i; int human = flags & HUMAN; @@ -374,6 +374,66 @@ static void show_lnvm_id_ns(struct nvme_nvm_id *id, unsigned int flags) } } +static void show_lnvm_id20_ns(struct nvme_nvm_id20 *id, unsigned int flags) +{ + int human = flags & HUMAN; + uint32_t mccap = (uint32_t) le32_to_cpu(id->mccap); + + printf("ver_major : %#x\n", id->mjr); + printf("ver_minor : %#x\n", id->mnr); + + printf("mccap : %#x\n", mccap); + if (human) { + if (mccap & (1 << LNVM_IDFY_CAP_VCOPY)) + printf(" [0]: Vector copy support\n"); + if (mccap & (1 << LNVM_IDFY_CAP_MRESETS)) + printf(" [1]: Multiple resets support\n"); + } + printf("wit : %d\n", id->wit); + + printf("lba format\n"); + printf(" grp len : %d\n", id->lbaf.grp_len); + printf(" pu len : %d\n", id->lbaf.pu_len); + printf(" chk len : %d\n", id->lbaf.chk_len); + printf(" clba len : %d\n", id->lbaf.lba_len); + + printf("geometry\n"); + printf(" num_grp : %d\n", le16_to_cpu(id->num_grp)); + printf(" num_pu : %d\n", le16_to_cpu(id->num_pu)); + printf(" num_chk : %d\n", le32_to_cpu(id->num_chk)); + printf(" clba : %d\n", le32_to_cpu(id->clba)); + printf("write req\n"); + printf(" ws_min : %d\n", le32_to_cpu(id->ws_min)); + printf(" ws_opt : %d\n", le32_to_cpu(id->ws_opt)); + printf(" mw_cunits : %d\n", le32_to_cpu(id->mw_cunits)); + printf(" maxoc : %d\n", le32_to_cpu(id->maxoc)); + printf(" maxocpu : %d\n", le32_to_cpu(id->maxocpu)); + printf("perf metrics\n"); + printf(" trdt (ns) : %d\n", le32_to_cpu(id->trdt)); + printf(" trdm (ns) : %d\n", le32_to_cpu(id->trdm)); + printf(" twrt (ns) : %d\n", le32_to_cpu(id->twrt)); + printf(" twrm (ns) : %d\n", le32_to_cpu(id->twrm)); + printf(" tcrst (ns) : %d\n", le32_to_cpu(id->tcrst)); + printf(" tcrsm (ns) : %d\n", le32_to_cpu(id->tcrsm)); +} + +static void show_lnvm_id_ns(struct nvme_nvm_id *id, unsigned int flags) +{ + switch (id->ver_id) { + case 1: + show_lnvm_id12_ns((struct nvme_nvm_id12 *)id, + flags); + break; + case 2: + show_lnvm_id20_ns((struct nvme_nvm_id20 *)id, + flags); + break; + default: + fprintf(stderr, "Version %d not supported.\n", + id->ver_id); + } +} + static int lnvm_get_identity(int fd, int nsid, struct nvme_nvm_id *nvm_id) { struct nvme_admin_cmd cmd = { @@ -395,10 +455,8 @@ int lnvm_do_id_ns(int fd, int nsid, unsigned int flags) if (!err) { if (flags & RAW) d_raw((unsigned char *)&nvm_id, sizeof(nvm_id)); - else { - printf("LightNVM Identify Geometry (%d):\n", nsid); + else show_lnvm_id_ns(&nvm_id, flags); - } } else if (err > 0) fprintf(stderr, "NVMe Status:%s(%x) NSID:%d\n", @@ -417,11 +475,11 @@ static void show_lnvm_bbtbl(struct nvme_nvm_bb_tbl *tbl) printf("Use raw output to retrieve table.\n"); } -static int __lnvm_do_get_bbtbl(int fd, struct nvme_nvm_id *id, +static int __lnvm_do_get_bbtbl(int fd, struct nvme_nvm_id12 *id, struct ppa_addr ppa, unsigned int flags) { - struct nvme_nvm_id_group *grp = &id->groups[0]; + struct nvme_nvm_id12_group *grp = &id->groups[0]; int bbtblsz = ((uint16_t)le16_to_cpu(grp->num_blk) * grp->num_pln); int bufsz = bbtblsz + sizeof(struct nvme_nvm_bb_tbl); struct nvme_nvm_bb_tbl *bbtbl; @@ -461,17 +519,23 @@ static int __lnvm_do_get_bbtbl(int fd, struct nvme_nvm_id *id, int lnvm_do_get_bbtbl(int fd, int nsid, int lunid, int chid, unsigned int flags) { - struct nvme_nvm_id nvm_id; + struct nvme_nvm_id12 nvm_id; struct ppa_addr ppa; int err; - err = lnvm_get_identity(fd, nsid, &nvm_id); + err = lnvm_get_identity(fd, nsid, (struct nvme_nvm_id *)&nvm_id); if (err) { fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); return err; } + if (nvm_id.ver_id != 1) { + fprintf(stderr, "Get bad block table not supported on version %d\n", + nvm_id.ver_id); + return -EINVAL; + } + if (chid >= nvm_id.groups[0].num_ch || lunid >= nvm_id.groups[0].num_lun) { fprintf(stderr, "Out of bound channel id or LUN id\n"); @@ -513,17 +577,23 @@ int lnvm_do_set_bbtbl(int fd, int nsid, int chid, int lunid, int plnid, int blkid, __u8 value) { - struct nvme_nvm_id nvm_id; + struct nvme_nvm_id12 nvm_id; struct ppa_addr ppa; int err; - err = lnvm_get_identity(fd, nsid, &nvm_id); + err = lnvm_get_identity(fd, nsid, (struct nvme_nvm_id *)&nvm_id); if (err) { fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); return err; } + if (nvm_id.ver_id != 1) { + fprintf(stderr, "Set bad block table not supported on version %d\n", + nvm_id.ver_id); + return -EINVAL; + } + if (chid >= nvm_id.groups[0].num_ch || lunid >= nvm_id.groups[0].num_lun || plnid >= nvm_id.groups[0].num_pln || diff --git a/nvme-lightnvm.h b/nvme-lightnvm.h index 8faca80e..a13c0cf2 100644 --- a/nvme-lightnvm.h +++ b/nvme-lightnvm.h @@ -109,7 +109,7 @@ struct nvme_nvm_lp_tbl { struct nvme_nvm_lp_mlc mlc; }; -struct nvme_nvm_id_group { +struct nvme_nvm_id12_group { __u8 mtype; __u8 fmtype; __le16 res16; @@ -155,6 +155,8 @@ struct nvme_nvm_addr_format { 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, @@ -176,7 +178,7 @@ enum { LNVM_IDFY_GRP_MCCAP_ENCRYPT = 3, }; -struct nvme_nvm_id { +struct nvme_nvm_id12 { __u8 ver_id; __u8 vmnt; __u8 cgrps; @@ -185,7 +187,64 @@ struct nvme_nvm_id { __le32 dom; struct nvme_nvm_addr_format ppaf; __u8 resv[228]; - struct nvme_nvm_id_group groups[4]; + 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)); struct nvme_nvm_bb_tbl {