]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
lightnvm: transform target get/set bad block
authorJavier González <javier@cnexlabs.com>
Mon, 28 Nov 2016 21:39:14 +0000 (22:39 +0100)
committerJens Axboe <axboe@fb.com>
Tue, 29 Nov 2016 19:12:51 +0000 (12:12 -0700)
Since targets are given a virtual target device, it is necessary to
translate all communication between targets and the backend device.
Implement the translation layer for get/set bad block table.

Signed-off-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <m@bjorling.me>
Signed-off-by: Jens Axboe <axboe@fb.com>
drivers/lightnvm/core.c
drivers/lightnvm/gennvm.c
drivers/lightnvm/rrpc.c
include/linux/lightnvm.h

index 07bf989d2f776abc90b82a0ca3a5aac24f6901bc..7622e3dc5d82e0b5ff3059b36ec1fd3b402a7cfe 100644 (file)
@@ -175,6 +175,26 @@ static struct nvm_dev *nvm_find_nvm_dev(const char *name)
        return NULL;
 }
 
+static void nvm_tgt_generic_to_addr_mode(struct nvm_tgt_dev *tgt_dev,
+                                        struct nvm_rq *rqd)
+{
+       struct nvm_dev *dev = tgt_dev->parent;
+       int i;
+
+       if (rqd->nr_ppas > 1) {
+               for (i = 0; i < rqd->nr_ppas; i++) {
+                       rqd->ppa_list[i] = dev->mt->trans_ppa(tgt_dev,
+                                       rqd->ppa_list[i], TRANS_TGT_TO_DEV);
+                       rqd->ppa_list[i] = generic_to_dev_addr(dev,
+                                                       rqd->ppa_list[i]);
+               }
+       } else {
+               rqd->ppa_addr = dev->mt->trans_ppa(tgt_dev, rqd->ppa_addr,
+                                               TRANS_TGT_TO_DEV);
+               rqd->ppa_addr = generic_to_dev_addr(dev, rqd->ppa_addr);
+       }
+}
+
 int nvm_set_bb_tbl(struct nvm_dev *dev, struct ppa_addr *ppas, int nr_ppas,
                                                                int type)
 {
@@ -202,6 +222,34 @@ int nvm_set_bb_tbl(struct nvm_dev *dev, struct ppa_addr *ppas, int nr_ppas,
 }
 EXPORT_SYMBOL(nvm_set_bb_tbl);
 
+int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *ppas,
+                      int nr_ppas, int type)
+{
+       struct nvm_dev *dev = tgt_dev->parent;
+       struct nvm_rq rqd;
+       int ret;
+
+       if (nr_ppas > dev->ops->max_phys_sect) {
+               pr_err("nvm: unable to update all blocks atomically\n");
+               return -EINVAL;
+       }
+
+       memset(&rqd, 0, sizeof(struct nvm_rq));
+
+       nvm_set_rqd_ppalist(dev, &rqd, ppas, nr_ppas, 1);
+       nvm_tgt_generic_to_addr_mode(tgt_dev, &rqd);
+
+       ret = dev->ops->set_bb_tbl(dev, &rqd.ppa_addr, rqd.nr_ppas, type);
+       nvm_free_rqd_ppalist(dev, &rqd);
+       if (ret) {
+               pr_err("nvm: sysblk failed bb mark\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(nvm_set_tgt_bb_tbl);
+
 int nvm_max_phys_sects(struct nvm_tgt_dev *tgt_dev)
 {
        struct nvm_dev *dev = tgt_dev->parent;
@@ -519,6 +567,16 @@ int nvm_get_bb_tbl(struct nvm_dev *dev, struct ppa_addr ppa, u8 *blks)
 }
 EXPORT_SYMBOL(nvm_get_bb_tbl);
 
+int nvm_get_tgt_bb_tbl(struct nvm_tgt_dev *tgt_dev, struct ppa_addr ppa,
+                      u8 *blks)
+{
+       struct nvm_dev *dev = tgt_dev->parent;
+
+       ppa = dev->mt->trans_ppa(tgt_dev, ppa, TRANS_TGT_TO_DEV);
+       return nvm_get_bb_tbl(dev, ppa, blks);
+}
+EXPORT_SYMBOL(nvm_get_tgt_bb_tbl);
+
 static int nvm_init_slc_tbl(struct nvm_dev *dev, struct nvm_id_group *grp)
 {
        struct nvm_geo *geo = &dev->geo;
index befa8281ab3f220e42696c521a20800aadbf3712..ca7880082d80648647e6d08258d25afedbbb1e90 100644 (file)
@@ -482,12 +482,6 @@ static void gen_unregister(struct nvm_dev *dev)
        module_put(THIS_MODULE);
 }
 
-enum {
-       TRANS_TGT_TO_DEV =      0x0,
-       TRANS_DEV_TO_TGT =      0x1,
-};
-
-
 static int gen_map_to_dev(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
 {
        struct gen_dev_map *dev_map = tgt_dev->map;
@@ -584,6 +578,18 @@ static int gen_erase_blk(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p,
        return nvm_erase_ppa(tgt_dev->parent, p, 1, flags);
 }
 
+static struct ppa_addr gen_trans_ppa(struct nvm_tgt_dev *tgt_dev,
+                                    struct ppa_addr p, int direction)
+{
+       gen_trans_fn *f;
+       struct ppa_addr ppa = p;
+
+       f = (direction == TRANS_TGT_TO_DEV) ? gen_map_to_dev : gen_map_to_tgt;
+       f(tgt_dev, &ppa);
+
+       return ppa;
+}
+
 static void gen_part_to_tgt(struct nvm_dev *dev, sector_t *entries,
                               int len)
 {
@@ -631,6 +637,7 @@ static struct nvmm_type gen = {
        .get_area               = gen_get_area,
        .put_area               = gen_put_area,
 
+       .trans_ppa              = gen_trans_ppa,
        .part_to_tgt            = gen_part_to_tgt,
 };
 
index 8a27bcc62f23e7f34a09e5fb4ae1ae74ebaec78b..9fb7de395915ca8e3893f16273a5e6c20d4a763d 100644 (file)
@@ -735,7 +735,7 @@ static void __rrpc_mark_bad_block(struct rrpc *rrpc, struct ppa_addr ppa)
        rblk = &rlun->blocks[ppa.g.blk];
        rblk->state = NVM_BLK_ST_BAD;
 
-       nvm_set_bb_tbl(dev->parent, &ppa, 1, NVM_BLK_T_GRWN_BAD);
+       nvm_set_tgt_bb_tbl(dev, &ppa, 1, NVM_BLK_T_GRWN_BAD);
 }
 
 static void rrpc_mark_bad_block(struct rrpc *rrpc, struct nvm_rq *rqd)
@@ -1267,7 +1267,7 @@ static int rrpc_bb_discovery(struct nvm_tgt_dev *dev, struct rrpc_lun *rlun)
        ppa.g.ch = rlun->bppa.g.ch;
        ppa.g.lun = rlun->bppa.g.lun;
 
-       ret = nvm_get_bb_tbl(dev->parent, ppa, blks);
+       ret = nvm_get_tgt_bb_tbl(dev, ppa, blks);
        if (ret) {
                pr_err("rrpc: could not get BB table\n");
                goto out;
index e76f9c4aa49b26a73117d423be16271c191a1359..7c273bbc5351d528357d223dfb1427eb269b14c7 100644 (file)
@@ -496,8 +496,15 @@ typedef int (nvmm_submit_io_fn)(struct nvm_tgt_dev *, struct nvm_rq *);
 typedef int (nvmm_erase_blk_fn)(struct nvm_tgt_dev *, struct ppa_addr *, int);
 typedef int (nvmm_get_area_fn)(struct nvm_dev *, sector_t *, sector_t);
 typedef void (nvmm_put_area_fn)(struct nvm_dev *, sector_t);
+typedef struct ppa_addr (nvmm_trans_ppa_fn)(struct nvm_tgt_dev *,
+                                           struct ppa_addr, int);
 typedef void (nvmm_part_to_tgt_fn)(struct nvm_dev *, sector_t*, int);
 
+enum {
+       TRANS_TGT_TO_DEV =      0x0,
+       TRANS_DEV_TO_TGT =      0x1,
+};
+
 struct nvmm_type {
        const char *name;
        unsigned int version[3];
@@ -514,6 +521,7 @@ struct nvmm_type {
        nvmm_get_area_fn *get_area;
        nvmm_put_area_fn *put_area;
 
+       nvmm_trans_ppa_fn *trans_ppa;
        nvmm_part_to_tgt_fn *part_to_tgt;
 
        struct list_head list;
@@ -526,9 +534,9 @@ extern struct nvm_dev *nvm_alloc_dev(int);
 extern int nvm_register(struct nvm_dev *);
 extern void nvm_unregister(struct nvm_dev *);
 
-extern int nvm_set_bb_tbl(struct nvm_dev *dev, struct ppa_addr *ppas,
-                                                       int nr_ppas, int type);
-
+extern int nvm_set_bb_tbl(struct nvm_dev *, struct ppa_addr *, int, int);
+extern int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *, struct ppa_addr *,
+                             int, int);
 extern int nvm_max_phys_sects(struct nvm_tgt_dev *);
 extern int nvm_submit_io(struct nvm_tgt_dev *, struct nvm_rq *);
 extern void nvm_generic_to_addr_mode(struct nvm_dev *, struct nvm_rq *);
@@ -549,6 +557,7 @@ extern int nvm_submit_ppa_list(struct nvm_dev *, struct ppa_addr *, int, int,
                                                        int, void *, int);
 extern int nvm_bb_tbl_fold(struct nvm_dev *, u8 *, int);
 extern int nvm_get_bb_tbl(struct nvm_dev *, struct ppa_addr, u8 *);
+extern int nvm_get_tgt_bb_tbl(struct nvm_tgt_dev *, struct ppa_addr, u8 *);
 
 /* sysblk.c */
 #define NVM_SYSBLK_MAGIC 0x4E564D53 /* "NVMS" */