diff options
author | Matias Bjørling <matias@cnexlabs.com> | 2018-01-05 08:16:03 -0500 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2018-01-05 10:50:12 -0500 |
commit | fae7fae4077c24dc2be720b9f21f53adea98d7dd (patch) | |
tree | f77436958399d9caa2f4198f7aeeb706867ac24d /drivers/lightnvm/core.c | |
parent | bb27aa9ecd1f72e68b0fa2dffeb45bee3b1cb5ca (diff) |
lightnvm: make geometry structures 2.0 ready
Prepare for the 2.0 revision by adapting the geometry
structures to coexist with the 1.2 revision.
Signed-off-by: Matias Bjørling <m@bjorling.me>
Reviewed-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <m@bjorling.me>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/lightnvm/core.c')
-rw-r--r-- | drivers/lightnvm/core.c | 91 |
1 files changed, 44 insertions, 47 deletions
diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index 52059dd0ed18..6d6d2c12ff5b 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c | |||
@@ -98,7 +98,7 @@ static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear) | |||
98 | if (clear) { | 98 | if (clear) { |
99 | for (j = 0; j < ch_map->nr_luns; j++) { | 99 | for (j = 0; j < ch_map->nr_luns; j++) { |
100 | int lun = j + lun_offs[j]; | 100 | int lun = j + lun_offs[j]; |
101 | int lunid = (ch * dev->geo.luns_per_chnl) + lun; | 101 | int lunid = (ch * dev->geo.nr_luns) + lun; |
102 | 102 | ||
103 | WARN_ON(!test_and_clear_bit(lunid, | 103 | WARN_ON(!test_and_clear_bit(lunid, |
104 | dev->lun_map)); | 104 | dev->lun_map)); |
@@ -124,10 +124,10 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev, | |||
124 | struct ppa_addr *luns; | 124 | struct ppa_addr *luns; |
125 | int nr_luns = lun_end - lun_begin + 1; | 125 | int nr_luns = lun_end - lun_begin + 1; |
126 | int luns_left = nr_luns; | 126 | int luns_left = nr_luns; |
127 | int nr_chnls = nr_luns / dev->geo.luns_per_chnl; | 127 | int nr_chnls = nr_luns / dev->geo.nr_luns; |
128 | int nr_chnls_mod = nr_luns % dev->geo.luns_per_chnl; | 128 | int nr_chnls_mod = nr_luns % dev->geo.nr_luns; |
129 | int bch = lun_begin / dev->geo.luns_per_chnl; | 129 | int bch = lun_begin / dev->geo.nr_luns; |
130 | int blun = lun_begin % dev->geo.luns_per_chnl; | 130 | int blun = lun_begin % dev->geo.nr_luns; |
131 | int lunid = 0; | 131 | int lunid = 0; |
132 | int lun_balanced = 1; | 132 | int lun_balanced = 1; |
133 | int prev_nr_luns; | 133 | int prev_nr_luns; |
@@ -148,15 +148,15 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev, | |||
148 | if (!luns) | 148 | if (!luns) |
149 | goto err_luns; | 149 | goto err_luns; |
150 | 150 | ||
151 | prev_nr_luns = (luns_left > dev->geo.luns_per_chnl) ? | 151 | prev_nr_luns = (luns_left > dev->geo.nr_luns) ? |
152 | dev->geo.luns_per_chnl : luns_left; | 152 | dev->geo.nr_luns : luns_left; |
153 | for (i = 0; i < nr_chnls; i++) { | 153 | for (i = 0; i < nr_chnls; i++) { |
154 | struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[i + bch]; | 154 | struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[i + bch]; |
155 | int *lun_roffs = ch_rmap->lun_offs; | 155 | int *lun_roffs = ch_rmap->lun_offs; |
156 | struct nvm_ch_map *ch_map = &dev_map->chnls[i]; | 156 | struct nvm_ch_map *ch_map = &dev_map->chnls[i]; |
157 | int *lun_offs; | 157 | int *lun_offs; |
158 | int luns_in_chnl = (luns_left > dev->geo.luns_per_chnl) ? | 158 | int luns_in_chnl = (luns_left > dev->geo.nr_luns) ? |
159 | dev->geo.luns_per_chnl : luns_left; | 159 | dev->geo.nr_luns : luns_left; |
160 | 160 | ||
161 | if (lun_balanced && prev_nr_luns != luns_in_chnl) | 161 | if (lun_balanced && prev_nr_luns != luns_in_chnl) |
162 | lun_balanced = 0; | 162 | lun_balanced = 0; |
@@ -193,8 +193,8 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev, | |||
193 | memcpy(&tgt_dev->geo, &dev->geo, sizeof(struct nvm_geo)); | 193 | memcpy(&tgt_dev->geo, &dev->geo, sizeof(struct nvm_geo)); |
194 | /* Target device only owns a portion of the physical device */ | 194 | /* Target device only owns a portion of the physical device */ |
195 | tgt_dev->geo.nr_chnls = nr_chnls; | 195 | tgt_dev->geo.nr_chnls = nr_chnls; |
196 | tgt_dev->geo.nr_luns = nr_luns; | 196 | tgt_dev->geo.all_luns = nr_luns; |
197 | tgt_dev->geo.luns_per_chnl = (lun_balanced) ? prev_nr_luns : -1; | 197 | tgt_dev->geo.nr_luns = (lun_balanced) ? prev_nr_luns : -1; |
198 | tgt_dev->total_secs = nr_luns * tgt_dev->geo.sec_per_lun; | 198 | tgt_dev->total_secs = nr_luns * tgt_dev->geo.sec_per_lun; |
199 | tgt_dev->q = dev->q; | 199 | tgt_dev->q = dev->q; |
200 | tgt_dev->map = dev_map; | 200 | tgt_dev->map = dev_map; |
@@ -414,7 +414,7 @@ static int nvm_register_map(struct nvm_dev *dev) | |||
414 | for (i = 0; i < dev->geo.nr_chnls; i++) { | 414 | for (i = 0; i < dev->geo.nr_chnls; i++) { |
415 | struct nvm_ch_map *ch_rmap; | 415 | struct nvm_ch_map *ch_rmap; |
416 | int *lun_roffs; | 416 | int *lun_roffs; |
417 | int luns_in_chnl = dev->geo.luns_per_chnl; | 417 | int luns_in_chnl = dev->geo.nr_luns; |
418 | 418 | ||
419 | ch_rmap = &rmap->chnls[i]; | 419 | ch_rmap = &rmap->chnls[i]; |
420 | 420 | ||
@@ -717,10 +717,10 @@ int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks) | |||
717 | struct nvm_geo *geo = &dev->geo; | 717 | struct nvm_geo *geo = &dev->geo; |
718 | int blk, offset, pl, blktype; | 718 | int blk, offset, pl, blktype; |
719 | 719 | ||
720 | if (nr_blks != geo->blks_per_lun * geo->plane_mode) | 720 | if (nr_blks != geo->nr_chks * geo->plane_mode) |
721 | return -EINVAL; | 721 | return -EINVAL; |
722 | 722 | ||
723 | for (blk = 0; blk < geo->blks_per_lun; blk++) { | 723 | for (blk = 0; blk < geo->nr_chks; blk++) { |
724 | offset = blk * geo->plane_mode; | 724 | offset = blk * geo->plane_mode; |
725 | blktype = blks[offset]; | 725 | blktype = blks[offset]; |
726 | 726 | ||
@@ -736,7 +736,7 @@ int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks) | |||
736 | blks[blk] = blktype; | 736 | blks[blk] = blktype; |
737 | } | 737 | } |
738 | 738 | ||
739 | return geo->blks_per_lun; | 739 | return geo->nr_chks; |
740 | } | 740 | } |
741 | EXPORT_SYMBOL(nvm_bb_tbl_fold); | 741 | EXPORT_SYMBOL(nvm_bb_tbl_fold); |
742 | 742 | ||
@@ -758,43 +758,40 @@ static int nvm_core_init(struct nvm_dev *dev) | |||
758 | struct nvm_geo *geo = &dev->geo; | 758 | struct nvm_geo *geo = &dev->geo; |
759 | int ret; | 759 | int ret; |
760 | 760 | ||
761 | memcpy(&geo->ppaf, &id->ppaf, sizeof(struct nvm_addr_format)); | ||
762 | |||
763 | if (grp->mtype != 0) { | ||
764 | pr_err("nvm: memory type not supported\n"); | ||
765 | return -EINVAL; | ||
766 | } | ||
767 | |||
761 | /* Whole device values */ | 768 | /* Whole device values */ |
762 | geo->nr_chnls = grp->num_ch; | 769 | geo->nr_chnls = grp->num_ch; |
763 | geo->luns_per_chnl = grp->num_lun; | 770 | geo->nr_luns = grp->num_lun; |
764 | 771 | ||
765 | /* Generic device values */ | 772 | /* Generic device geometry values */ |
766 | geo->pgs_per_blk = grp->num_pg; | 773 | geo->ws_min = grp->ws_min; |
767 | geo->blks_per_lun = grp->num_blk; | 774 | geo->ws_opt = grp->ws_opt; |
768 | geo->nr_planes = grp->num_pln; | 775 | geo->ws_seq = grp->ws_seq; |
769 | geo->fpg_size = grp->fpg_sz; | 776 | geo->ws_per_chk = grp->ws_per_chk; |
770 | geo->pfpg_size = grp->fpg_sz * grp->num_pln; | 777 | geo->nr_chks = grp->num_chk; |
771 | geo->sec_size = grp->csecs; | 778 | geo->sec_size = grp->csecs; |
772 | geo->oob_size = grp->sos; | 779 | geo->oob_size = grp->sos; |
773 | geo->sec_per_pg = grp->fpg_sz / grp->csecs; | ||
774 | geo->mccap = grp->mccap; | 780 | geo->mccap = grp->mccap; |
775 | memcpy(&geo->ppaf, &id->ppaf, sizeof(struct nvm_addr_format)); | ||
776 | |||
777 | geo->plane_mode = NVM_PLANE_SINGLE; | ||
778 | geo->max_rq_size = dev->ops->max_phys_sect * geo->sec_size; | 781 | geo->max_rq_size = dev->ops->max_phys_sect * geo->sec_size; |
779 | 782 | ||
780 | if (grp->mpos & 0x020202) | 783 | geo->sec_per_chk = grp->clba; |
781 | geo->plane_mode = NVM_PLANE_DOUBLE; | 784 | geo->sec_per_lun = geo->sec_per_chk * geo->nr_chks; |
782 | if (grp->mpos & 0x040404) | 785 | geo->all_luns = geo->nr_luns * geo->nr_chnls; |
783 | geo->plane_mode = NVM_PLANE_QUAD; | ||
784 | |||
785 | if (grp->mtype != 0) { | ||
786 | pr_err("nvm: memory type not supported\n"); | ||
787 | return -EINVAL; | ||
788 | } | ||
789 | 786 | ||
790 | /* calculated values */ | 787 | /* 1.2 spec device geometry values */ |
788 | geo->plane_mode = 1 << geo->ws_seq; | ||
789 | geo->nr_planes = geo->ws_opt / geo->ws_min; | ||
790 | geo->sec_per_pg = geo->ws_min; | ||
791 | geo->sec_per_pl = geo->sec_per_pg * geo->nr_planes; | 791 | geo->sec_per_pl = geo->sec_per_pg * geo->nr_planes; |
792 | geo->sec_per_blk = geo->sec_per_pl * geo->pgs_per_blk; | ||
793 | geo->sec_per_lun = geo->sec_per_blk * geo->blks_per_lun; | ||
794 | geo->nr_luns = geo->luns_per_chnl * geo->nr_chnls; | ||
795 | 792 | ||
796 | dev->total_secs = geo->nr_luns * geo->sec_per_lun; | 793 | dev->total_secs = geo->all_luns * geo->sec_per_lun; |
797 | dev->lun_map = kcalloc(BITS_TO_LONGS(geo->nr_luns), | 794 | dev->lun_map = kcalloc(BITS_TO_LONGS(geo->all_luns), |
798 | sizeof(unsigned long), GFP_KERNEL); | 795 | sizeof(unsigned long), GFP_KERNEL); |
799 | if (!dev->lun_map) | 796 | if (!dev->lun_map) |
800 | return -ENOMEM; | 797 | return -ENOMEM; |
@@ -854,8 +851,8 @@ static int nvm_init(struct nvm_dev *dev) | |||
854 | 851 | ||
855 | pr_info("nvm: registered %s [%u/%u/%u/%u/%u/%u]\n", | 852 | pr_info("nvm: registered %s [%u/%u/%u/%u/%u/%u]\n", |
856 | dev->name, geo->sec_per_pg, geo->nr_planes, | 853 | dev->name, geo->sec_per_pg, geo->nr_planes, |
857 | geo->pgs_per_blk, geo->blks_per_lun, | 854 | geo->ws_per_chk, geo->nr_chks, |
858 | geo->nr_luns, geo->nr_chnls); | 855 | geo->all_luns, geo->nr_chnls); |
859 | return 0; | 856 | return 0; |
860 | err: | 857 | err: |
861 | pr_err("nvm: failed to initialize nvm\n"); | 858 | pr_err("nvm: failed to initialize nvm\n"); |
@@ -946,12 +943,12 @@ static int __nvm_configure_create(struct nvm_ioctl_create *create) | |||
946 | 943 | ||
947 | if (s->lun_begin == -1 && s->lun_end == -1) { | 944 | if (s->lun_begin == -1 && s->lun_end == -1) { |
948 | s->lun_begin = 0; | 945 | s->lun_begin = 0; |
949 | s->lun_end = dev->geo.nr_luns - 1; | 946 | s->lun_end = dev->geo.all_luns - 1; |
950 | } | 947 | } |
951 | 948 | ||
952 | if (s->lun_begin > s->lun_end || s->lun_end >= dev->geo.nr_luns) { | 949 | if (s->lun_begin > s->lun_end || s->lun_end >= dev->geo.all_luns) { |
953 | pr_err("nvm: lun out of bound (%u:%u > %u)\n", | 950 | pr_err("nvm: lun out of bound (%u:%u > %u)\n", |
954 | s->lun_begin, s->lun_end, dev->geo.nr_luns - 1); | 951 | s->lun_begin, s->lun_end, dev->geo.all_luns - 1); |
955 | return -EINVAL; | 952 | return -EINVAL; |
956 | } | 953 | } |
957 | 954 | ||