lightnvm: add support for 2.0 address format
authorJavier González <javier@cnexlabs.com>
Thu, 29 Mar 2018 22:05:15 +0000 (00:05 +0200)
committerJens Axboe <axboe@kernel.dk>
Thu, 29 Mar 2018 23:29:09 +0000 (17:29 -0600)
Add support for 2.0 address format. Also, align address bits for 1.2 and
2.0 to be able to operate on channel and luns without requiring a format
conversion. Use a generic address format for this purpose.

Also, convert the generic operations to the generic format in pblk.

Signed-off-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/lightnvm/core.c
drivers/lightnvm/pblk-core.c
drivers/lightnvm/pblk-map.c
drivers/lightnvm/pblk-sysfs.c
drivers/lightnvm/pblk.h
include/linux/lightnvm.h

index 94b3b423840b948a4e7ca15269338bb7f6cad083..63d948cc6dec3b36213dd674d91b363fde9378f8 100644 (file)
@@ -194,8 +194,8 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
 
                for (j = 0; j < luns_in_chnl; j++) {
                        luns[lunid].ppa = 0;
-                       luns[lunid].g.ch = i;
-                       luns[lunid++].g.lun = j;
+                       luns[lunid].a.ch = i;
+                       luns[lunid++].a.lun = j;
 
                        lun_offs[j] = blun;
                        lun_roffs[j + blun] = blun;
@@ -556,22 +556,22 @@ static void nvm_unregister_map(struct nvm_dev *dev)
 static void nvm_map_to_dev(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
 {
        struct nvm_dev_map *dev_map = tgt_dev->map;
-       struct nvm_ch_map *ch_map = &dev_map->chnls[p->g.ch];
-       int lun_off = ch_map->lun_offs[p->g.lun];
+       struct nvm_ch_map *ch_map = &dev_map->chnls[p->a.ch];
+       int lun_off = ch_map->lun_offs[p->a.lun];
 
-       p->g.ch += ch_map->ch_off;
-       p->g.lun += lun_off;
+       p->a.ch += ch_map->ch_off;
+       p->a.lun += lun_off;
 }
 
 static void nvm_map_to_tgt(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
 {
        struct nvm_dev *dev = tgt_dev->parent;
        struct nvm_dev_map *dev_rmap = dev->rmap;
-       struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[p->g.ch];
-       int lun_roff = ch_rmap->lun_offs[p->g.lun];
+       struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[p->a.ch];
+       int lun_roff = ch_rmap->lun_offs[p->a.lun];
 
-       p->g.ch -= ch_rmap->ch_off;
-       p->g.lun -= lun_roff;
+       p->a.ch -= ch_rmap->ch_off;
+       p->a.lun -= lun_roff;
 }
 
 static void nvm_ppa_tgt_to_dev(struct nvm_tgt_dev *tgt_dev,
index 64c87dd4f1cd8fedf2053aef0fd280265c45065b..c3eb135fce076b3f314b4ce11e26e74eb5e969d9 100644 (file)
@@ -885,7 +885,7 @@ int pblk_line_erase(struct pblk *pblk, struct pblk_line *line)
                }
 
                ppa = pblk->luns[bit].bppa; /* set ch and lun */
-               ppa.g.blk = line->id;
+               ppa.a.blk = line->id;
 
                atomic_dec(&line->left_eblks);
                WARN_ON(test_and_set_bit(bit, line->erase_bitmap));
@@ -1683,8 +1683,8 @@ static void __pblk_down_page(struct pblk *pblk, struct ppa_addr *ppa_list,
        int i;
 
        for (i = 1; i < nr_ppas; i++)
-               WARN_ON(ppa_list[0].g.lun != ppa_list[i].g.lun ||
-                               ppa_list[0].g.ch != ppa_list[i].g.ch);
+               WARN_ON(ppa_list[0].a.lun != ppa_list[i].a.lun ||
+                               ppa_list[0].a.ch != ppa_list[i].a.ch);
 #endif
 
        ret = down_timeout(&rlun->wr_sem, msecs_to_jiffies(30000));
@@ -1728,8 +1728,8 @@ void pblk_up_page(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas)
        int i;
 
        for (i = 1; i < nr_ppas; i++)
-               WARN_ON(ppa_list[0].g.lun != ppa_list[i].g.lun ||
-                               ppa_list[0].g.ch != ppa_list[i].g.ch);
+               WARN_ON(ppa_list[0].a.lun != ppa_list[i].a.lun ||
+                               ppa_list[0].a.ch != ppa_list[i].a.ch);
 #endif
 
        rlun = &pblk->luns[pos];
index 04e08d76ea5f9a581520e3313720fe8f8c1673f9..20dbaa89c9dfe3e4837e7d64acecaea4a0ba616e 100644 (file)
@@ -127,7 +127,7 @@ void pblk_map_erase_rq(struct pblk *pblk, struct nvm_rq *rqd,
                        atomic_dec(&e_line->left_eblks);
 
                        *erase_ppa = rqd->ppa_list[i];
-                       erase_ppa->g.blk = e_line->id;
+                       erase_ppa->a.blk = e_line->id;
 
                        spin_unlock(&e_line->lock);
 
@@ -168,6 +168,6 @@ retry:
                set_bit(bit, e_line->erase_bitmap);
                atomic_dec(&e_line->left_eblks);
                *erase_ppa = pblk->luns[bit].bppa; /* set ch and lun */
-               erase_ppa->g.blk = e_line->id;
+               erase_ppa->a.blk = e_line->id;
        }
 }
index 3e9364f60b44452995649e8478c580421e9825d3..2489ea0edfa01c7377843a73f43f719370eef950 100644 (file)
@@ -39,8 +39,8 @@ static ssize_t pblk_sysfs_luns_show(struct pblk *pblk, char *page)
                sz += snprintf(page + sz, PAGE_SIZE - sz,
                                "pblk: pos:%d, ch:%d, lun:%d - %d\n",
                                        i,
-                                       rlun->bppa.g.ch,
-                                       rlun->bppa.g.lun,
+                                       rlun->bppa.a.ch,
+                                       rlun->bppa.a.lun,
                                        active);
        }
 
index dcdad255ccb5d4c18af734827c000a2019768afc..6607c41b23c0e695223a73e5b98013066396ab18 100644 (file)
@@ -936,12 +936,12 @@ static inline int pblk_pad_distance(struct pblk *pblk)
 
 static inline int pblk_ppa_to_line(struct ppa_addr p)
 {
-       return p.g.blk;
+       return p.a.blk;
 }
 
 static inline int pblk_ppa_to_pos(struct nvm_geo *geo, struct ppa_addr p)
 {
-       return p.g.lun * geo->num_ch + p.g.ch;
+       return p.a.lun * geo->num_ch + p.a.ch;
 }
 
 static inline struct ppa_addr addr_to_gen_ppa(struct pblk *pblk, u64 paddr,
index 00295d9f95224ce82be45c42e5b0e568fe907469..f2549b4b862662032c284891d35da27637e69309 100644 (file)
@@ -16,12 +16,21 @@ enum {
        NVM_IOTYPE_GC = 1,
 };
 
-#define NVM_BLK_BITS (16)
-#define NVM_PG_BITS  (16)
-#define NVM_SEC_BITS (8)
-#define NVM_PL_BITS  (8)
-#define NVM_LUN_BITS (8)
-#define NVM_CH_BITS  (7)
+/* common format */
+#define NVM_GEN_CH_BITS  (8)
+#define NVM_GEN_LUN_BITS (8)
+#define NVM_GEN_BLK_BITS (16)
+#define NVM_GEN_RESERVED (32)
+
+/* 1.2 format */
+#define NVM_12_PG_BITS  (16)
+#define NVM_12_PL_BITS  (4)
+#define NVM_12_SEC_BITS (4)
+#define NVM_12_RESERVED (8)
+
+/* 2.0 format */
+#define NVM_20_SEC_BITS (24)
+#define NVM_20_RESERVED (8)
 
 enum {
        NVM_OCSSD_SPEC_12 = 12,
@@ -31,16 +40,34 @@ enum {
 struct ppa_addr {
        /* Generic structure for all addresses */
        union {
+               /* generic device format */
                struct {
-                       u64 blk         : NVM_BLK_BITS;
-                       u64 pg          : NVM_PG_BITS;
-                       u64 sec         : NVM_SEC_BITS;
-                       u64 pl          : NVM_PL_BITS;
-                       u64 lun         : NVM_LUN_BITS;
-                       u64 ch          : NVM_CH_BITS;
-                       u64 reserved    : 1;
+                       u64 ch          : NVM_GEN_CH_BITS;
+                       u64 lun         : NVM_GEN_LUN_BITS;
+                       u64 blk         : NVM_GEN_BLK_BITS;
+                       u64 reserved    : NVM_GEN_RESERVED;
+               } a;
+
+               /* 1.2 device format */
+               struct {
+                       u64 ch          : NVM_GEN_CH_BITS;
+                       u64 lun         : NVM_GEN_LUN_BITS;
+                       u64 blk         : NVM_GEN_BLK_BITS;
+                       u64 pg          : NVM_12_PG_BITS;
+                       u64 pl          : NVM_12_PL_BITS;
+                       u64 sec         : NVM_12_SEC_BITS;
+                       u64 reserved    : NVM_12_RESERVED;
                } g;
 
+               /* 2.0 device format */
+               struct {
+                       u64 grp         : NVM_GEN_CH_BITS;
+                       u64 pu          : NVM_GEN_LUN_BITS;
+                       u64 chk         : NVM_GEN_BLK_BITS;
+                       u64 sec         : NVM_20_SEC_BITS;
+                       u64 reserved    : NVM_20_RESERVED;
+               } m;
+
                struct {
                        u64 line        : 63;
                        u64 is_cached   : 1;
@@ -374,15 +401,25 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
                                                  struct ppa_addr r)
 {
        struct nvm_geo *geo = &tgt_dev->geo;
-       struct nvm_addrf_12 *ppaf = (struct nvm_addrf_12 *)&geo->addrf;
        struct ppa_addr l;
 
-       l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
-       l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
-       l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
-       l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
-       l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
-       l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
+       if (geo->version == NVM_OCSSD_SPEC_12) {
+               struct nvm_addrf_12 *ppaf = (struct nvm_addrf_12 *)&geo->addrf;
+
+               l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
+               l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
+               l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
+               l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
+               l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
+               l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
+       } else {
+               struct nvm_addrf *lbaf = &geo->addrf;
+
+               l.ppa = ((u64)r.m.grp) << lbaf->ch_offset;
+               l.ppa |= ((u64)r.m.pu) << lbaf->lun_offset;
+               l.ppa |= ((u64)r.m.chk) << lbaf->chk_offset;
+               l.ppa |= ((u64)r.m.sec) << lbaf->sec_offset;
+       }
 
        return l;
 }
@@ -391,17 +428,27 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
                                                  struct ppa_addr r)
 {
        struct nvm_geo *geo = &tgt_dev->geo;
-       struct nvm_addrf_12 *ppaf = (struct nvm_addrf_12 *)&geo->addrf;
        struct ppa_addr l;
 
        l.ppa = 0;
 
-       l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
-       l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
-       l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
-       l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
-       l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
-       l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
+       if (geo->version == NVM_OCSSD_SPEC_12) {
+               struct nvm_addrf_12 *ppaf = (struct nvm_addrf_12 *)&geo->addrf;
+
+               l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
+               l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
+               l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
+               l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
+               l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
+               l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
+       } else {
+               struct nvm_addrf *lbaf = &geo->addrf;
+
+               l.m.grp = (r.ppa & lbaf->ch_mask) >> lbaf->ch_offset;
+               l.m.pu = (r.ppa & lbaf->lun_mask) >> lbaf->lun_offset;
+               l.m.chk = (r.ppa & lbaf->chk_mask) >> lbaf->chk_offset;
+               l.m.sec = (r.ppa & lbaf->sec_mask) >> lbaf->sec_offset;
+       }
 
        return l;
 }