diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index 0296223392f7dce8c7cdc4d26f937c3848759bdf..e6d7a98baeb274400c1e2c987a462f172e789def 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -467,6 +467,14 @@ int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks) } EXPORT_SYMBOL(nvm_bb_tbl_fold); +int nvm_get_bb_tbl(struct nvm_dev *dev, struct ppa_addr ppa, u8 *blks) +{ + ppa = generic_to_dev_addr(dev, ppa); + + return dev->ops->get_bb_tbl(dev, ppa, blks); +} +EXPORT_SYMBOL(nvm_get_bb_tbl); + static int nvm_init_slc_tbl(struct nvm_dev *dev, struct nvm_id_group *grp) { int i; diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c index 6096077c5dde112ba1eb518d268f0ec7c2557edc..9c6b141606e95a16357db14de53d663fef531a8c 100644 --- a/drivers/lightnvm/gennvm.c +++ b/drivers/lightnvm/gennvm.c @@ -129,10 +129,10 @@ static int gennvm_luns_init(struct nvm_dev *dev, struct gen_nvm *gn) return 0; } -static int gennvm_block_bb(struct nvm_dev *dev, struct ppa_addr ppa, - u8 *blks, int nr_blks, void *private) +static int gennvm_block_bb(struct gen_nvm *gn, struct ppa_addr ppa, + u8 *blks, int nr_blks) { - struct gen_nvm *gn = private; + struct nvm_dev *dev = gn->dev; struct gen_lun *lun; struct nvm_block *blk; int i; @@ -219,13 +219,21 @@ static int gennvm_blocks_init(struct nvm_dev *dev, struct gen_nvm *gn) struct gen_lun *lun; struct nvm_block *block; sector_t lun_iter, blk_iter, cur_block_id = 0; - int ret; + int ret, nr_blks; + u8 *blks; + + nr_blks = dev->blks_per_lun * dev->plane_mode; + blks = kmalloc(nr_blks, GFP_KERNEL); + if (!blks) + return -ENOMEM; gennvm_for_each_lun(gn, lun, lun_iter) { lun->vlun.blocks = vzalloc(sizeof(struct nvm_block) * dev->blks_per_lun); - if (!lun->vlun.blocks) + if (!lun->vlun.blocks) { + kfree(blks); return -ENOMEM; + } for (blk_iter = 0; blk_iter < dev->blks_per_lun; blk_iter++) { block = &lun->vlun.blocks[blk_iter]; @@ -250,12 +258,14 @@ static int gennvm_blocks_init(struct nvm_dev *dev, struct gen_nvm *gn) ppa.ppa = 0; ppa.g.ch = lun->vlun.chnl_id; ppa.g.lun = lun->vlun.id; - ppa = generic_to_dev_addr(dev, ppa); - ret = dev->ops->get_bb_tbl(dev, ppa, - gennvm_block_bb, gn); + ret = nvm_get_bb_tbl(dev, ppa, blks); + if (ret) + pr_err("gennvm: could not get BB table\n"); + + ret = gennvm_block_bb(gn, ppa, blks, nr_blks); if (ret) - pr_err("gennvm: could not read BB table\n"); + pr_err("gennvm: BB table map failed\n"); } } @@ -268,6 +278,7 @@ static int gennvm_blocks_init(struct nvm_dev *dev, struct gen_nvm *gn) } } + kfree(blks); return 0; } diff --git a/drivers/lightnvm/sysblk.c b/drivers/lightnvm/sysblk.c index a48093d17fea0ce88f9d9fc119dde1bf19bf3390..dc99c0ac87014a922107d2cdc97f3c4f97a29c81 100644 --- a/drivers/lightnvm/sysblk.c +++ b/drivers/lightnvm/sysblk.c @@ -93,10 +93,45 @@ void nvm_setup_sysblk_scan(struct nvm_dev *dev, struct sysblk_scan *s, s->nr_rows = nvm_setup_sysblks(dev, sysblk_ppas); } +static int sysblk_get_free_blks(struct nvm_dev *dev, struct ppa_addr ppa, + u8 *blks, int nr_blks, + struct sysblk_scan *s) +{ + struct ppa_addr *sppa; + int i, blkid = 0; + + nr_blks = nvm_bb_tbl_fold(dev, blks, nr_blks); + if (nr_blks < 0) + return nr_blks; + + for (i = 0; i < nr_blks; i++) { + if (blks[i] == NVM_BLK_T_HOST) + return -EEXIST; + + if (blks[i] != NVM_BLK_T_FREE) + continue; + + sppa = &s->ppas[scan_ppa_idx(s->row, blkid)]; + sppa->g.ch = ppa.g.ch; + sppa->g.lun = ppa.g.lun; + sppa->g.blk = i; + s->nr_ppas++; + blkid++; + + pr_debug("nvm: use (%u %u %u) as sysblk\n", + sppa->g.ch, sppa->g.lun, sppa->g.blk); + if (blkid > MAX_BLKS_PR_SYSBLK - 1) + return 0; + } + + pr_err("nvm: sysblk failed get sysblk\n"); + return -EINVAL; +} + static int sysblk_get_host_blks(struct nvm_dev *dev, struct ppa_addr ppa, - u8 *blks, int nr_blks, void *private) + u8 *blks, int nr_blks, + struct sysblk_scan *s) { - struct sysblk_scan *s = private; int i, nr_sysblk = 0; nr_blks = nvm_bb_tbl_fold(dev, blks, nr_blks); @@ -123,26 +158,42 @@ static int sysblk_get_host_blks(struct nvm_dev *dev, struct ppa_addr ppa, } static int nvm_get_all_sysblks(struct nvm_dev *dev, struct sysblk_scan *s, - struct ppa_addr *ppas, nvm_bb_update_fn *fn) + struct ppa_addr *ppas, int get_free) { - struct ppa_addr dppa; - int i, ret = 0; + int i, nr_blks, ret = 0; + u8 *blks; s->nr_ppas = 0; + nr_blks = dev->blks_per_lun * dev->plane_mode; + + blks = kmalloc(nr_blks, GFP_KERNEL); + if (!blks) + return -ENOMEM; for (i = 0; i < s->nr_rows; i++) { - dppa = generic_to_dev_addr(dev, ppas[i]); s->row = i; - ret = dev->ops->get_bb_tbl(dev, dppa, fn, s); + ret = nvm_get_bb_tbl(dev, ppas[i], blks); if (ret) { pr_err("nvm: failed bb tbl for ppa (%u %u)\n", ppas[i].g.ch, ppas[i].g.blk); - return ret; + goto err_get; } + + if (get_free) + ret = sysblk_get_free_blks(dev, ppas[i], blks, nr_blks, + s); + else + ret = sysblk_get_host_blks(dev, ppas[i], blks, nr_blks, + s); + + if (ret) + goto err_get; } +err_get: + kfree(blks); return ret; } @@ -239,41 +290,6 @@ static int nvm_set_bb_tbl(struct nvm_dev *dev, struct sysblk_scan *s, int type) return 0; } -static int sysblk_get_free_blks(struct nvm_dev *dev, struct ppa_addr ppa, - u8 *blks, int nr_blks, void *private) -{ - struct sysblk_scan *s = private; - struct ppa_addr *sppa; - int i, blkid = 0; - - nr_blks = nvm_bb_tbl_fold(dev, blks, nr_blks); - if (nr_blks < 0) - return nr_blks; - - for (i = 0; i < nr_blks; i++) { - if (blks[i] == NVM_BLK_T_HOST) - return -EEXIST; - - if (blks[i] != NVM_BLK_T_FREE) - continue; - - sppa = &s->ppas[scan_ppa_idx(s->row, blkid)]; - sppa->g.ch = ppa.g.ch; - sppa->g.lun = ppa.g.lun; - sppa->g.blk = i; - s->nr_ppas++; - blkid++; - - pr_debug("nvm: use (%u %u %u) as sysblk\n", - sppa->g.ch, sppa->g.lun, sppa->g.blk); - if (blkid > MAX_BLKS_PR_SYSBLK - 1) - return 0; - } - - pr_err("nvm: sysblk failed get sysblk\n"); - return -EINVAL; -} - static int nvm_write_and_verify(struct nvm_dev *dev, struct nvm_sb_info *info, struct sysblk_scan *s) { @@ -393,7 +409,7 @@ int nvm_get_sysblock(struct nvm_dev *dev, struct nvm_sb_info *info) nvm_setup_sysblk_scan(dev, &s, sysblk_ppas); mutex_lock(&dev->mlock); - ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, sysblk_get_host_blks); + ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, 0); if (ret) goto err_sysblk; @@ -453,7 +469,7 @@ int nvm_update_sysblock(struct nvm_dev *dev, struct nvm_sb_info *new) nvm_setup_sysblk_scan(dev, &s, sysblk_ppas); mutex_lock(&dev->mlock); - ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, sysblk_get_host_blks); + ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, 0); if (ret) goto err_sysblk; @@ -551,7 +567,7 @@ int nvm_init_sysblock(struct nvm_dev *dev, struct nvm_sb_info *info) nvm_setup_sysblk_scan(dev, &s, sysblk_ppas); mutex_lock(&dev->mlock); - ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, sysblk_get_free_blks); + ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, 1); if (ret) goto err_mark; @@ -587,9 +603,9 @@ static unsigned int factory_blk_offset(struct nvm_dev *dev, int ch, int lun) } static int nvm_factory_blks(struct nvm_dev *dev, struct ppa_addr ppa, - u8 *blks, int nr_blks, void *private) + u8 *blks, int nr_blks, + struct factory_blks *f) { - struct factory_blks *f = private; int i, lunoff; nr_blks = nvm_bb_tbl_fold(dev, blks, nr_blks); @@ -659,32 +675,29 @@ static int nvm_fact_get_blks(struct nvm_dev *dev, struct ppa_addr *erase_list, return ppa_cnt; } -static int nvm_fact_get_bb_tbl(struct nvm_dev *dev, struct ppa_addr ppa, - nvm_bb_update_fn *fn, void *priv) -{ - struct ppa_addr dev_ppa; - int ret; - - dev_ppa = generic_to_dev_addr(dev, ppa); - - ret = dev->ops->get_bb_tbl(dev, dev_ppa, fn, priv); - if (ret) - pr_err("nvm: failed bb tbl for ch%u lun%u\n", - ppa.g.ch, ppa.g.blk); - return ret; -} - static int nvm_fact_select_blks(struct nvm_dev *dev, struct factory_blks *f) { - int ch, lun, ret; struct ppa_addr ppa; + int ch, lun, nr_blks, ret; + u8 *blks; + + nr_blks = dev->blks_per_lun * dev->plane_mode; + blks = kmalloc(nr_blks, GFP_KERNEL); + if (!blks) + return -ENOMEM; nvm_for_each_lun_ppa(dev, ppa, ch, lun) { - ret = nvm_fact_get_bb_tbl(dev, ppa, nvm_factory_blks, f); + ret = nvm_get_bb_tbl(dev, ppa, blks); + if (ret) + pr_err("nvm: failed bb tbl for ch%u lun%u\n", + ppa.g.ch, ppa.g.blk); + + ret = nvm_factory_blks(dev, ppa, blks, nr_blks, f); if (ret) return ret; } + kfree(blks); return 0; } @@ -722,8 +735,7 @@ int nvm_dev_factory(struct nvm_dev *dev, int flags) if (flags & NVM_FACTORY_RESET_HOST_BLKS) { nvm_setup_sysblk_scan(dev, &s, sysblk_ppas); mutex_lock(&dev->mlock); - ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, - sysblk_get_host_blks); + ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, 0); if (!ret) ret = nvm_set_bb_tbl(dev, &s, NVM_BLK_T_FREE); mutex_unlock(&dev->mlock); diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c index d289980d2bc8d4529ba112995cc4b37046c699ce..45e3511d5d3dada6b82a02343dd3e3dd2f4c5883 100644 --- a/drivers/nvme/host/lightnvm.c +++ b/drivers/nvme/host/lightnvm.c @@ -388,7 +388,7 @@ static int nvme_nvm_get_l2p_tbl(struct nvm_dev *nvmdev, u64 slba, u32 nlb, } static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa, - nvm_bb_update_fn *update_bbtbl, void *priv) + u8 *blks) { struct request_queue *q = nvmdev->q; struct nvme_ns *ns = q->queuedata; @@ -435,9 +435,7 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa, goto out; } - ppa = dev_to_generic_addr(nvmdev, ppa); - ret = update_bbtbl(nvmdev, ppa, bb_tbl->blk, nr_blks, priv); - + memcpy(blks, bb_tbl->blk, nvmdev->blks_per_lun * nvmdev->plane_mode); out: kfree(bb_tbl); return ret; diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index 3f256355b9faf224da4dd6d4ca419f9e4853a6b5..16d4f2edf5b4da3164858143d415ab266023795e 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -41,13 +41,10 @@ struct nvm_id; struct nvm_dev; typedef int (nvm_l2p_update_fn)(u64, u32, __le64 *, void *); -typedef int (nvm_bb_update_fn)(struct nvm_dev *, struct ppa_addr, u8 *, int, - void *); typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *); typedef int (nvm_get_l2p_tbl_fn)(struct nvm_dev *, u64, u32, nvm_l2p_update_fn *, void *); -typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, - nvm_bb_update_fn *, void *); +typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, u8 *); typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct nvm_rq *, int); typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *); typedef int (nvm_erase_blk_fn)(struct nvm_dev *, struct nvm_rq *); @@ -539,6 +536,7 @@ extern int nvm_submit_ppa(struct nvm_dev *, struct ppa_addr *, int, int, int, extern int nvm_submit_ppa_list(struct nvm_dev *, struct ppa_addr *, int, int, int, void *, int); extern int nvm_bb_tbl_fold(struct nvm_dev *, u8 *, int); +extern int nvm_get_bb_tbl(struct nvm_dev *, struct ppa_addr, u8 *); /* sysblk.c */ #define NVM_SYSBLK_MAGIC 0x4E564D53 /* "NVMS" */