aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lightnvm/core.c
diff options
context:
space:
mode:
authorMatias Bjørling <matias@cnexlabs.com>2018-01-05 08:16:03 -0500
committerJens Axboe <axboe@kernel.dk>2018-01-05 10:50:12 -0500
commitfae7fae4077c24dc2be720b9f21f53adea98d7dd (patch)
treef77436958399d9caa2f4198f7aeeb706867ac24d /drivers/lightnvm/core.c
parentbb27aa9ecd1f72e68b0fa2dffeb45bee3b1cb5ca (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.c91
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}
741EXPORT_SYMBOL(nvm_bb_tbl_fold); 741EXPORT_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;
860err: 857err:
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