aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lightnvm/pblk-init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/lightnvm/pblk-init.c')
-rw-r--r--drivers/lightnvm/pblk-init.c116
1 files changed, 3 insertions, 113 deletions
diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 039f62d05e84..53bd52114aee 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -540,67 +540,6 @@ static void pblk_lines_free(struct pblk *pblk)
540 kfree(pblk->lines); 540 kfree(pblk->lines);
541} 541}
542 542
543static int pblk_bb_get_tbl(struct nvm_tgt_dev *dev, struct pblk_lun *rlun,
544 u8 *blks, int nr_blks)
545{
546 struct ppa_addr ppa;
547 int ret;
548
549 ppa.ppa = 0;
550 ppa.g.ch = rlun->bppa.g.ch;
551 ppa.g.lun = rlun->bppa.g.lun;
552
553 ret = nvm_get_tgt_bb_tbl(dev, ppa, blks);
554 if (ret)
555 return ret;
556
557 nr_blks = nvm_bb_tbl_fold(dev->parent, blks, nr_blks);
558 if (nr_blks < 0)
559 return -EIO;
560
561 return 0;
562}
563
564static void *pblk_bb_get_meta(struct pblk *pblk)
565{
566 struct nvm_tgt_dev *dev = pblk->dev;
567 struct nvm_geo *geo = &dev->geo;
568 u8 *meta;
569 int i, nr_blks, blk_per_lun;
570 int ret;
571
572 blk_per_lun = geo->num_chk * geo->pln_mode;
573 nr_blks = blk_per_lun * geo->all_luns;
574
575 meta = kmalloc(nr_blks, GFP_KERNEL);
576 if (!meta)
577 return ERR_PTR(-ENOMEM);
578
579 for (i = 0; i < geo->all_luns; i++) {
580 struct pblk_lun *rlun = &pblk->luns[i];
581 u8 *meta_pos = meta + i * blk_per_lun;
582
583 ret = pblk_bb_get_tbl(dev, rlun, meta_pos, blk_per_lun);
584 if (ret) {
585 kfree(meta);
586 return ERR_PTR(-EIO);
587 }
588 }
589
590 return meta;
591}
592
593static void *pblk_chunk_get_meta(struct pblk *pblk)
594{
595 struct nvm_tgt_dev *dev = pblk->dev;
596 struct nvm_geo *geo = &dev->geo;
597
598 if (geo->version == NVM_OCSSD_SPEC_12)
599 return pblk_bb_get_meta(pblk);
600 else
601 return pblk_chunk_get_info(pblk);
602}
603
604static int pblk_luns_init(struct pblk *pblk) 543static int pblk_luns_init(struct pblk *pblk)
605{ 544{
606 struct nvm_tgt_dev *dev = pblk->dev; 545 struct nvm_tgt_dev *dev = pblk->dev;
@@ -699,51 +638,7 @@ static void pblk_set_provision(struct pblk *pblk, long nr_free_blks)
699 atomic_set(&pblk->rl.free_user_blocks, nr_free_blks); 638 atomic_set(&pblk->rl.free_user_blocks, nr_free_blks);
700} 639}
701 640
702static int pblk_setup_line_meta_12(struct pblk *pblk, struct pblk_line *line, 641static int pblk_setup_line_meta_chk(struct pblk *pblk, struct pblk_line *line,
703 void *chunk_meta)
704{
705 struct nvm_tgt_dev *dev = pblk->dev;
706 struct nvm_geo *geo = &dev->geo;
707 struct pblk_line_meta *lm = &pblk->lm;
708 int i, chk_per_lun, nr_bad_chks = 0;
709
710 chk_per_lun = geo->num_chk * geo->pln_mode;
711
712 for (i = 0; i < lm->blk_per_line; i++) {
713 struct pblk_lun *rlun = &pblk->luns[i];
714 struct nvm_chk_meta *chunk;
715 int pos = pblk_ppa_to_pos(geo, rlun->bppa);
716 u8 *lun_bb_meta = chunk_meta + pos * chk_per_lun;
717
718 chunk = &line->chks[pos];
719
720 /*
721 * In 1.2 spec. chunk state is not persisted by the device. Thus
722 * some of the values are reset each time pblk is instantiated,
723 * so we have to assume that the block is closed.
724 */
725 if (lun_bb_meta[line->id] == NVM_BLK_T_FREE)
726 chunk->state = NVM_CHK_ST_CLOSED;
727 else
728 chunk->state = NVM_CHK_ST_OFFLINE;
729
730 chunk->type = NVM_CHK_TP_W_SEQ;
731 chunk->wi = 0;
732 chunk->slba = -1;
733 chunk->cnlb = geo->clba;
734 chunk->wp = 0;
735
736 if (!(chunk->state & NVM_CHK_ST_OFFLINE))
737 continue;
738
739 set_bit(pos, line->blk_bitmap);
740 nr_bad_chks++;
741 }
742
743 return nr_bad_chks;
744}
745
746static int pblk_setup_line_meta_20(struct pblk *pblk, struct pblk_line *line,
747 struct nvm_chk_meta *meta) 642 struct nvm_chk_meta *meta)
748{ 643{
749 struct nvm_tgt_dev *dev = pblk->dev; 644 struct nvm_tgt_dev *dev = pblk->dev;
@@ -790,8 +685,6 @@ static int pblk_setup_line_meta_20(struct pblk *pblk, struct pblk_line *line,
790static long pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line, 685static long pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
791 void *chunk_meta, int line_id) 686 void *chunk_meta, int line_id)
792{ 687{
793 struct nvm_tgt_dev *dev = pblk->dev;
794 struct nvm_geo *geo = &dev->geo;
795 struct pblk_line_mgmt *l_mg = &pblk->l_mg; 688 struct pblk_line_mgmt *l_mg = &pblk->l_mg;
796 struct pblk_line_meta *lm = &pblk->lm; 689 struct pblk_line_meta *lm = &pblk->lm;
797 long nr_bad_chks, chk_in_line; 690 long nr_bad_chks, chk_in_line;
@@ -804,10 +697,7 @@ static long pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
804 line->vsc = &l_mg->vsc_list[line_id]; 697 line->vsc = &l_mg->vsc_list[line_id];
805 spin_lock_init(&line->lock); 698 spin_lock_init(&line->lock);
806 699
807 if (geo->version == NVM_OCSSD_SPEC_12) 700 nr_bad_chks = pblk_setup_line_meta_chk(pblk, line, chunk_meta);
808 nr_bad_chks = pblk_setup_line_meta_12(pblk, line, chunk_meta);
809 else
810 nr_bad_chks = pblk_setup_line_meta_20(pblk, line, chunk_meta);
811 701
812 chk_in_line = lm->blk_per_line - nr_bad_chks; 702 chk_in_line = lm->blk_per_line - nr_bad_chks;
813 if (nr_bad_chks < 0 || nr_bad_chks > lm->blk_per_line || 703 if (nr_bad_chks < 0 || nr_bad_chks > lm->blk_per_line ||
@@ -1058,7 +948,7 @@ static int pblk_lines_init(struct pblk *pblk)
1058 if (ret) 948 if (ret)
1059 goto fail_free_meta; 949 goto fail_free_meta;
1060 950
1061 chunk_meta = pblk_chunk_get_meta(pblk); 951 chunk_meta = pblk_get_chunk_meta(pblk);
1062 if (IS_ERR(chunk_meta)) { 952 if (IS_ERR(chunk_meta)) {
1063 ret = PTR_ERR(chunk_meta); 953 ret = PTR_ERR(chunk_meta);
1064 goto fail_free_luns; 954 goto fail_free_luns;