diff options
Diffstat (limited to 'drivers/lightnvm/pblk-init.c')
-rw-r--r-- | drivers/lightnvm/pblk-init.c | 116 |
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 | ||
543 | static 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 | |||
564 | static 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 | |||
593 | static 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 | |||
604 | static int pblk_luns_init(struct pblk *pblk) | 543 | static 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 | ||
702 | static int pblk_setup_line_meta_12(struct pblk *pblk, struct pblk_line *line, | 641 | static 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 | |||
746 | static 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, | |||
790 | static long pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line, | 685 | static 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; |