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);
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;
}
}
+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 = {
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",
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;
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");
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 ||
struct nvme_nvm_lp_mlc mlc;
};
-struct nvme_nvm_id_group {
+struct nvme_nvm_id12_group {
__u8 mtype;
__u8 fmtype;
__le16 res16;
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_MCCAP_ENCRYPT = 3,
};
-struct nvme_nvm_id {
+struct nvme_nvm_id12 {
__u8 ver_id;
__u8 vmnt;
__u8 cgrps;
__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 {