diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2022-07-14 18:27:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2022-07-16 15:11:56 +0000 |
commit | 6197903bd42478987516bc4cc3f0769488a37065 (patch) | |
tree | 508d399340039960289dd1d96696db7c56c22321 /nvme-lightnvm.c | |
parent | Adding upstream version 1.16. (diff) | |
download | nvme-cli-6197903bd42478987516bc4cc3f0769488a37065.tar.xz nvme-cli-6197903bd42478987516bc4cc3f0769488a37065.zip |
Adding upstream version 2.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'nvme-lightnvm.c')
-rw-r--r-- | nvme-lightnvm.c | 700 |
1 files changed, 0 insertions, 700 deletions
diff --git a/nvme-lightnvm.c b/nvme-lightnvm.c deleted file mode 100644 index d81fac6..0000000 --- a/nvme-lightnvm.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * lightnvm.c -- LightNVM NVMe integration. - * - * Copyright (c) 2016, CNEX Labs. - * - * Written by 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 - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * 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; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <string.h> -#include <errno.h> -#include <inttypes.h> - -#include "nvme-lightnvm.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" - -static int lnvm_open(void) -{ - char dev[FILENAME_MAX] = NVM_CTRL_FILE; - int fd; - - fd = open(dev, O_WRONLY); - if (fd < 0) { - printf("Failed to open LightNVM mgmt interface\n"); - perror(dev); - return fd; - } - - return fd; -} - -static void lnvm_close(int fd) -{ - close(fd); -} - -int lnvm_do_init(char *dev, char *mmtype) -{ - struct nvm_ioctl_dev_init init; - int fd, ret; - - fd = lnvm_open(); - if (fd < 0) - return fd; - - memset(&init, 0, sizeof(struct nvm_ioctl_dev_init)); - strncpy(init.dev, dev, DISK_NAME_LEN - 1); - strncpy(init.mmtype, mmtype, NVM_MMTYPE_LEN - 1); - - ret = ioctl(fd, NVM_DEV_INIT, &init); - switch (errno) { - case EINVAL: - printf("Initialization failed.\n"); - break; - case EEXIST: - printf("Device has already been initialized.\n"); - break; - case 0: - break; - default: - printf("Unknown error occurred (%d)\n", errno); - break; - } - - lnvm_close(fd); - - return ret; -} - -int lnvm_do_list_devices(void) -{ - struct nvm_ioctl_get_devices devs; - int fd, ret, i; - - fd = lnvm_open(); - if (fd < 0) - return fd; - - ret = ioctl(fd, NVM_GET_DEVICES, &devs); - if (ret) { - lnvm_close(fd); - return ret; - } - - printf("Number of devices: %u\n", devs.nr_devices); - printf("%-12s\t%-12s\tVersion\n", "Device", "Block manager"); - - for (i = 0; i < devs.nr_devices && i < 31; i++) { - struct nvm_ioctl_device_info *info = &devs.info[i]; - - printf("%-12s\t%-12s\t(%u,%u,%u)\n", info->devname, info->bmname, - info->bmversion[0], info->bmversion[1], - info->bmversion[2]); - } - - lnvm_close(fd); - - return 0; -} - -int lnvm_do_info(void) -{ - struct nvm_ioctl_info c; - int fd, ret, i; - - fd = lnvm_open(); - if (fd < 0) - return fd; - - memset(&c, 0, sizeof(struct nvm_ioctl_info)); - ret = ioctl(fd, NVM_INFO, &c); - if (ret) { - lnvm_close(fd); - return ret; - } - - printf("LightNVM (%u,%u,%u). %u target type(s) registered.\n", - c.version[0], c.version[1], c.version[2], c.tgtsize); - printf("Type\tVersion\n"); - - for (i = 0; i < c.tgtsize; i++) { - struct nvm_ioctl_info_tgt *tgt = &c.tgts[i]; - - printf("%s\t(%u,%u,%u)\n", - tgt->tgtname, tgt->version[0], tgt->version[1], - tgt->version[2]); - } - - lnvm_close(fd); - return 0; -} - -int lnvm_do_create_tgt(char *devname, char *tgtname, char *tgttype, - int lun_begin, int lun_end, - int over_prov, int flags) -{ - struct nvm_ioctl_create c; - int fd, ret; - - fd = lnvm_open(); - if (fd < 0) - return fd; - - strncpy(c.dev, devname, DISK_NAME_LEN - 1); - strncpy(c.tgtname, tgtname, DISK_NAME_LEN - 1); - strncpy(c.tgttype, tgttype, NVM_TTYPE_NAME_MAX - 1); - c.flags = flags; - - /* Fall back into simple IOCTL version if no extended attributes used */ - if (over_prov != -1) { - c.conf.type = NVM_CONFIG_TYPE_EXTENDED; - c.conf.e.lun_begin = lun_begin; - c.conf.e.lun_end = lun_end; - c.conf.e.over_prov = over_prov; - } else { - c.conf.type = NVM_CONFIG_TYPE_SIMPLE; - c.conf.s.lun_begin = lun_begin; - c.conf.s.lun_end = lun_end; - } - - ret = ioctl(fd, NVM_DEV_CREATE, &c); - if (ret) - fprintf(stderr, "Creation of target failed. Please see dmesg.\n"); - - lnvm_close(fd); - return ret; -} - -int lnvm_do_remove_tgt(char *tgtname) -{ - struct nvm_ioctl_remove c; - int fd, ret; - - fd = lnvm_open(); - if (fd < 0) - return fd; - - strncpy(c.tgtname, tgtname, DISK_NAME_LEN - 1); - c.flags = 0; - - ret = ioctl(fd, NVM_DEV_REMOVE, &c); - if (ret) - fprintf(stderr, "Remove of target failed. Please see dmesg.\n"); - - lnvm_close(fd); - return ret; -} - -int lnvm_do_factory_init(char *devname, int erase_only_marked, - int clear_host_marks, - int clear_bb_marks) -{ - struct nvm_ioctl_dev_factory fact; - int fd, ret; - - fd = lnvm_open(); - if (fd < 0) - return fd; - - memset(&fact, 0, sizeof(struct nvm_ioctl_dev_factory)); - - strncpy(fact.dev, devname, DISK_NAME_LEN - 1); - if (erase_only_marked) - fact.flags |= NVM_FACTORY_ERASE_ONLY_USER; - if (clear_host_marks) - fact.flags |= NVM_FACTORY_RESET_HOST_BLKS; - if (clear_bb_marks) - fact.flags |= NVM_FACTORY_RESET_GRWN_BBLKS; - - ret = ioctl(fd, NVM_DEV_FACTORY, &fact); - switch (errno) { - case EINVAL: - fprintf(stderr, "Factory reset failed.\n"); - break; - case 0: - break; - default: - fprintf(stderr, "Unknown error occurred (%d)\n", errno); - break; - } - - lnvm_close(fd); - return ret; -} - -static void show_lnvm_id_grp(void *t, int human) -{ - struct nvme_nvm_id12_group *grp = t; - uint32_t mpos = (uint32_t)le32_to_cpu(grp->mpos); - uint32_t mccap = (uint32_t)le32_to_cpu(grp->mccap); - - printf(" mtype : %d\n", grp->mtype); - if (human) { - if (grp->mtype == LNVM_IDFY_GRP_MTYPE_NAND) - printf(" NAND Flash Memory\n"); - else - printf(" Reserved\n"); - } - printf(" fmtype : %d\n", grp->fmtype); - if (human) { - if (grp->fmtype == LNVM_IDFY_GRP_FMTYPE_SLC) - printf(" Single bit Level Cell flash (SLC)\n"); - else if (grp->fmtype == LNVM_IDFY_GRP_FMTYPE_MLC) - printf(" Two bit Level Cell flash (MLC)\n"); - else if (grp->fmtype == LNVM_IDFY_GRP_FMTYPE_TLC) - printf(" Three bit Level Cell flash (TLC)\n"); - else - printf(" Reserved\n"); - } - printf(" chnls : %d\n", grp->num_ch); - printf(" luns : %d\n", grp->num_lun); - printf(" plns : %d\n", grp->num_pln); - printf(" blks : %d\n", (uint16_t)le16_to_cpu(grp->num_blk)); - printf(" pgs : %d\n", (uint16_t)le16_to_cpu(grp->num_pg)); - printf(" fpg_sz : %d\n", (uint16_t)le16_to_cpu(grp->fpg_sz)); - printf(" csecs : %d\n", (uint16_t)le16_to_cpu(grp->csecs)); - printf(" sos : %d\n", (uint16_t)le16_to_cpu(grp->sos)); - printf(" trdt : %d\n", (uint32_t)le32_to_cpu(grp->trdt)); - printf(" trdm : %d\n", (uint32_t)le32_to_cpu(grp->trdm)); - printf(" tprt : %d\n", (uint32_t)le32_to_cpu(grp->tprt)); - printf(" tprm : %d\n", (uint32_t)le32_to_cpu(grp->tprm)); - printf(" tbet : %d\n", (uint32_t)le32_to_cpu(grp->tbet)); - printf(" tbem : %d\n", (uint32_t)le32_to_cpu(grp->tbem)); - printf(" mpos : %#x\n", mpos); - if (human) { - if (mpos & (1 << LNVM_IDFY_GRP_MPOS_SNGL_PLN_RD)) - printf(" [0]: Single plane read\n"); - if (mpos & (1 << LNVM_IDFY_GRP_MPOS_DUAL_PLN_RD)) - printf(" [1]: Dual plane read\n"); - if (mpos & (1 << LNVM_IDFY_GRP_MPOS_QUAD_PLN_RD)) - printf(" [2]: Quad plane read\n"); - if (mpos & (1 << LNVM_IDFY_GRP_MPOS_SNGL_PLN_PRG)) - printf(" [8]: Single plane program\n"); - if (mpos & (1 << LNVM_IDFY_GRP_MPOS_DUAL_PLN_PRG)) - printf(" [9]: Dual plane program\n"); - if (mpos & (1 << LNVM_IDFY_GRP_MPOS_QUAD_PLN_PRG)) - printf(" [10]: Quad plane program\n"); - if (mpos & (1 << LNVM_IDFY_GRP_MPOS_SNGL_PLN_ERS)) - printf(" [16]: Single plane erase\n"); - if (mpos & (1 << LNVM_IDFY_GRP_MPOS_DUAL_PLN_ERS)) - printf(" [17]: Dual plane erase\n"); - if (mpos & (1 << LNVM_IDFY_GRP_MPOS_QUAD_PLN_ERS)) - printf(" [18]: Quad plane erase\n"); - } - printf(" mccap : %#x\n", mccap); - if (human) { - if (mccap & (1 << LNVM_IDFY_GRP_MCCAP_SLC)) - printf(" [0]: SLC mode\n"); - if (mccap & (1 << LNVM_IDFY_GRP_MCCAP_CMD_SUSP)) - printf(" [1]: Command suspension\n"); - if (mccap & (1 << LNVM_IDFY_GRP_MCCAP_SCRAMBLE)) - printf(" [2]: Scramble\n"); - if (mccap & (1 << LNVM_IDFY_GRP_MCCAP_ENCRYPT)) - printf(" [3]: Encryption\n"); - } - printf(" cpar : %#x\n", (uint16_t)le16_to_cpu(grp->cpar)); - -} - -static void show_lnvm_ppaf(struct nvme_nvm_addr_format *ppaf) -{ - printf("ppaf :\n"); - printf(" ch offs : %d ch bits : %d\n", - ppaf->ch_offset, ppaf->ch_len); - printf(" lun offs: %d lun bits : %d\n", - ppaf->lun_offset, ppaf->lun_len); - printf(" pl offs : %d pl bits : %d\n", - ppaf->pln_offset, ppaf->pln_len); - printf(" blk offs: %d blk bits : %d\n", - ppaf->blk_offset, ppaf->blk_len); - printf(" pg offs : %d pg bits : %d\n", - ppaf->pg_offset, ppaf->pg_len); - printf(" sec offs: %d sec bits : %d\n", - ppaf->sect_offset, ppaf->sect_len); -} - -static void show_lnvm_id12_ns(void *t, unsigned int flags) -{ - int i; - int human = flags & VERBOSE; - struct nvme_nvm_id12 *id = t; - - uint32_t cap = (uint32_t) le32_to_cpu(id->cap); - uint32_t dom = (uint32_t) le32_to_cpu(id->dom); - uint32_t cgrps = id->cgrps; - - if (id->cgrps > 4) { - fprintf(stderr, "invalid identify geometry returned\n"); - return; - } - - printf("verid : %#x\n", id->ver_id); - printf("vmnt : %#x\n", id->vmnt); - if (human) { - if (!id->vmnt) - printf(" Generic/Enable opcodes as found in this spec."); - else - printf(" Reserved/Reserved for future opcode configurations"); - } - printf("\n"); - printf("cgrps : %d\n", id->cgrps); - printf("cap : %#x\n", cap); - if (human) { - if (cap & (1 << LNVM_IDFY_CAP_BAD_BLK_TBL_MGMT)) - printf(" [0]: Bad block table management\n"); - if (cap & (1 << LNVM_IDFY_CAP_HYBRID_CMD_SUPP)) - printf(" [1]: Hybrid command support\n"); - } - printf("dom : %#x\n", dom); - if (human) { - if (dom & (1 << LNVM_IDFY_DOM_HYBRID_MODE)) - printf(" [0]: Hybrid mode (L2P MAP is in device)\n"); - if (dom & (1 << LNVM_IDFY_DOM_ECC_MODE)) - printf(" [1]: Error Code Correction(ECC) mode\n"); - } - show_lnvm_ppaf(&id->ppaf); - - for (i = 0; i < cgrps; i++) { - printf("grp : %d\n", i); - show_lnvm_id_grp((void *)&id->groups[i], human); - } -} - -static void show_lnvm_id20_ns(struct nvme_nvm_id20 *id, unsigned int flags) -{ - int human = flags & VERBOSE; - 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((void *) id, flags); - break; - case 2: - show_lnvm_id20_ns((void *) id, flags); - break; - default: - fprintf(stderr, "Version %d not supported.\n", - id->ver_id); - } -} - -int lnvm_get_identity(int fd, int nsid, struct nvme_nvm_id *nvm_id) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_nvm_admin_identity, - .nsid = nsid, - .addr = (__u64)(uintptr_t)nvm_id, - .data_len = sizeof(struct nvme_nvm_id), - }; - - return nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &cmd); -} - -int lnvm_do_id_ns(int fd, int nsid, unsigned int flags) -{ - struct nvme_nvm_id nvm_id; - int err; - - err = lnvm_get_identity(fd, nsid, &nvm_id); - if (!err) { - if (flags & BINARY) - d_raw((unsigned char *)&nvm_id, sizeof(nvm_id)); - else - show_lnvm_id_ns(&nvm_id, flags); - } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x) NSID:%d\n", - nvme_status_to_string(err), err, nsid); - return err; -} - -static inline const char *print_chunk_state(__u8 cs) -{ - switch (cs) { - case 1 << 0: return "FREE"; - case 1 << 1: return "CLOSED"; - case 1 << 2: return "OPEN"; - case 1 << 3: return "OFFLINE"; - default: return "UNKNOWN"; - } -} - -static inline const char *print_chunk_type(__u8 ct) -{ - switch (ct & 0xF) { - case 1 << 0: return "SEQWRITE_REQ"; - case 1 << 1: return "RANDWRITE_ALLOWED"; - default: return "UNKNOWN"; - } -} - -static inline const char *print_chunk_attr(__u8 ct) -{ - switch (ct & 0xF0) { - case 1 << 4: return "DEVIATED"; - default: return "NONE"; - } -} - -static void show_lnvm_chunk_log(struct nvme_nvm_chunk_desc *chunk_log, - __u32 data_len) -{ - int nr_entry = data_len / sizeof(struct nvme_nvm_chunk_desc); - int idx; - - printf("Total chunks in namespace: %d\n", nr_entry); - for (idx = 0; idx < nr_entry; idx++) { - struct nvme_nvm_chunk_desc *desc = &chunk_log[idx]; - - printf(" [%5d] { ", idx); - printf("SLBA: 0x%016"PRIx64, le64_to_cpu(desc->slba)); - printf(", WP: 0x%016"PRIx64, le64_to_cpu(desc->wp)); - printf(", CNLB: 0x%016"PRIx64, le64_to_cpu(desc->cnlb)); - printf(", State: %-8s", print_chunk_state(desc->cs)); - printf(", Type: %-20s", print_chunk_type(desc->ct)); - printf(", Attr: %-8s", print_chunk_attr(desc->ct)); - printf(", WLI: %4d }\n", desc->wli); - } -} - -int lnvm_do_chunk_log(int fd, __u32 nsid, __u32 data_len, void *data, - unsigned int flags) -{ - int err; - - err = nvme_get_log13(fd, nsid, NVM_LID_CHUNK_INFO, 0, 0, 0, - false, data_len, data); - if (err > 0) { - fprintf(stderr, "NVMe Status:%s(%x) NSID:%d\n", - nvme_status_to_string(err), err, nsid); - - goto out; - } else if (err < 0) { - err = -errno; - perror("nvme_get_log13"); - - goto out; - } - - if (flags & BINARY) - d_raw(data, data_len); - else - show_lnvm_chunk_log(data, data_len); - -out: - return err; -} - -static void show_lnvm_bbtbl(struct nvme_nvm_bb_tbl *tbl) -{ - printf("verid : %#x\n", (uint16_t)le16_to_cpu(tbl->verid)); - printf("tblks : %d\n", (uint32_t)le32_to_cpu(tbl->tblks)); - printf("tfact : %d\n", (uint32_t)le32_to_cpu(tbl->tfact)); - printf("tgrown : %d\n", (uint32_t)le32_to_cpu(tbl->tgrown)); - printf("tdresv : %d\n", (uint32_t)le32_to_cpu(tbl->tdresv)); - printf("thresv : %d\n", (uint32_t)le32_to_cpu(tbl->thresv)); - printf("Use raw output to retrieve table.\n"); -} - -static int __lnvm_do_get_bbtbl(int fd, struct nvme_nvm_id12 *id, - struct ppa_addr ppa, - unsigned int flags) -{ - 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 err; - - bbtbl = calloc(1, bufsz); - if (!bbtbl) - return -ENOMEM; - - struct nvme_nvm_getbbtbl cmd = { - .opcode = nvme_nvm_admin_get_bb_tbl, - .nsid = cpu_to_le32(1), - .addr = (__u64)(uintptr_t)bbtbl, - .data_len = bufsz, - .ppa = cpu_to_le64(ppa.ppa), - }; - void *tmp = &cmd; - struct nvme_passthru_cmd *nvme_cmd = tmp; - - err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, nvme_cmd); - if (err > 0) { - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); - free(bbtbl); - return err; - } - - if (flags & BINARY) - d_raw((unsigned char *)&bbtbl->blk, bbtblsz); - else { - printf("LightNVM Bad Block Stats:\n"); - show_lnvm_bbtbl(bbtbl); - } - - free(bbtbl); - return 0; -} - -int lnvm_do_get_bbtbl(int fd, int nsid, int lunid, int chid, unsigned int flags) -{ - struct nvme_nvm_id12 nvm_id; - struct ppa_addr ppa; - int err; - void *tmp = &nvm_id; - - err = lnvm_get_identity(fd, nsid, (struct nvme_nvm_id *)tmp); - 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"); - return -EINVAL; - } - - ppa.ppa = 0; - ppa.g.lun = lunid; - ppa.g.ch = chid; - - ppa = generic_to_dev_addr(&nvm_id.ppaf, ppa); - - return __lnvm_do_get_bbtbl(fd, &nvm_id, ppa, flags); -} - -static int __lnvm_do_set_bbtbl(int fd, struct ppa_addr ppa, __u8 value) -{ - int err; - - struct nvme_nvm_setbbtbl cmd = { - .opcode = nvme_nvm_admin_set_bb_tbl, - .nsid = cpu_to_le32(1), - .ppa = cpu_to_le64(ppa.ppa), - .nlb = cpu_to_le16(0), - .value = value, - }; - void *tmp = &cmd; - struct nvme_passthru_cmd *nvme_cmd = tmp; - - err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, nvme_cmd); - if (err > 0) { - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); - return err; - } - return 0; -} - -int lnvm_do_set_bbtbl(int fd, int nsid, - int chid, int lunid, int plnid, int blkid, - __u8 value) -{ - struct nvme_nvm_id12 nvm_id; - struct ppa_addr ppa; - int err; - void *tmp = &nvm_id; - - err = lnvm_get_identity(fd, nsid, (struct nvme_nvm_id *)tmp); - 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 || - blkid >= le16_to_cpu(nvm_id.groups[0].num_blk)) { - fprintf(stderr, "Out of bound channel id, LUN id, plane id, or"\ - "block id\n"); - return -EINVAL; - } - - ppa.ppa = 0; - ppa.g.lun = lunid; - ppa.g.ch = chid; - ppa.g.pl = plnid; - ppa.g.blk = blkid; - - ppa = generic_to_dev_addr(&nvm_id.ppaf, ppa); - - return __lnvm_do_set_bbtbl(fd, ppa, value); -} |