aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatias Bjørling <m@bjorling.me>2016-05-06 14:03:07 -0400
committerJens Axboe <axboe@fb.com>2016-05-06 14:51:10 -0400
commit5ebc7d9fe13ff9bd3622d0be3cd39c8751459be6 (patch)
treedfca4e0b1029af8fcf8fe52ce6de69a4eb7bcdb0
parent6659d4d80c6fc6b4b5bc2e99988f32b1b3865f1d (diff)
lightnvm: make nvm_set_rqd_ppalist() aware of vblks
A virtual block enables a block to identify multiple physical blocks. This is useful for metadata where a device media supports multiple planes. In that case, a block, with multiple planes can be managed as a single vblk. Reducing the metadata required by one forth. nvm_set_rqd_ppalist() takes care of expanding a ppa_list with vblks automatically. However, for some use-cases, where only a single physical block is required, the ppa_list should not be expanded. Therefore, add a vblk parameter to nvm_set_rqd_ppalist(), and only expand the ppa_list if vblk is set. Signed-off-by: Matias Bjørling <m@bjorling.me> Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r--drivers/lightnvm/core.c31
-rw-r--r--drivers/lightnvm/sysblk.c2
-rw-r--r--include/linux/lightnvm.h2
3 files changed, 19 insertions, 16 deletions
diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index e6d7a98baeb2..de5db7b2c456 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -251,33 +251,36 @@ void nvm_generic_to_addr_mode(struct nvm_dev *dev, struct nvm_rq *rqd)
251EXPORT_SYMBOL(nvm_generic_to_addr_mode); 251EXPORT_SYMBOL(nvm_generic_to_addr_mode);
252 252
253int nvm_set_rqd_ppalist(struct nvm_dev *dev, struct nvm_rq *rqd, 253int nvm_set_rqd_ppalist(struct nvm_dev *dev, struct nvm_rq *rqd,
254 struct ppa_addr *ppas, int nr_ppas) 254 struct ppa_addr *ppas, int nr_ppas, int vblk)
255{ 255{
256 int i, plane_cnt, pl_idx; 256 int i, plane_cnt, pl_idx;
257 257
258 if (dev->plane_mode == NVM_PLANE_SINGLE && nr_ppas == 1) { 258 if ((!vblk || dev->plane_mode == NVM_PLANE_SINGLE) && nr_ppas == 1) {
259 rqd->nr_pages = 1; 259 rqd->nr_pages = nr_ppas;
260 rqd->ppa_addr = ppas[0]; 260 rqd->ppa_addr = ppas[0];
261 261
262 return 0; 262 return 0;
263 } 263 }
264 264
265 plane_cnt = dev->plane_mode; 265 rqd->nr_pages = nr_ppas;
266 rqd->nr_pages = plane_cnt * nr_ppas;
267
268 if (dev->ops->max_phys_sect < rqd->nr_pages)
269 return -EINVAL;
270
271 rqd->ppa_list = nvm_dev_dma_alloc(dev, GFP_KERNEL, &rqd->dma_ppa_list); 266 rqd->ppa_list = nvm_dev_dma_alloc(dev, GFP_KERNEL, &rqd->dma_ppa_list);
272 if (!rqd->ppa_list) { 267 if (!rqd->ppa_list) {
273 pr_err("nvm: failed to allocate dma memory\n"); 268 pr_err("nvm: failed to allocate dma memory\n");
274 return -ENOMEM; 269 return -ENOMEM;
275 } 270 }
276 271
277 for (pl_idx = 0; pl_idx < plane_cnt; pl_idx++) { 272 if (!vblk) {
273 for (i = 0; i < nr_ppas; i++)
274 rqd->ppa_list[i] = ppas[i];
275 } else {
276 plane_cnt = dev->plane_mode;
277 rqd->nr_pages *= plane_cnt;
278
278 for (i = 0; i < nr_ppas; i++) { 279 for (i = 0; i < nr_ppas; i++) {
279 ppas[i].g.pl = pl_idx; 280 for (pl_idx = 0; pl_idx < plane_cnt; pl_idx++) {
280 rqd->ppa_list[(pl_idx * nr_ppas) + i] = ppas[i]; 281 ppas[i].g.pl = pl_idx;
282 rqd->ppa_list[(pl_idx * nr_ppas) + i] = ppas[i];
283 }
281 } 284 }
282 } 285 }
283 286
@@ -304,7 +307,7 @@ int nvm_erase_ppa(struct nvm_dev *dev, struct ppa_addr *ppas, int nr_ppas)
304 307
305 memset(&rqd, 0, sizeof(struct nvm_rq)); 308 memset(&rqd, 0, sizeof(struct nvm_rq));
306 309
307 ret = nvm_set_rqd_ppalist(dev, &rqd, ppas, nr_ppas); 310 ret = nvm_set_rqd_ppalist(dev, &rqd, ppas, nr_ppas, 1);
308 if (ret) 311 if (ret)
309 return ret; 312 return ret;
310 313
@@ -420,7 +423,7 @@ int nvm_submit_ppa(struct nvm_dev *dev, struct ppa_addr *ppa, int nr_ppas,
420 int ret; 423 int ret;
421 424
422 memset(&rqd, 0, sizeof(struct nvm_rq)); 425 memset(&rqd, 0, sizeof(struct nvm_rq));
423 ret = nvm_set_rqd_ppalist(dev, &rqd, ppa, nr_ppas); 426 ret = nvm_set_rqd_ppalist(dev, &rqd, ppa, nr_ppas, 1);
424 if (ret) 427 if (ret)
425 return ret; 428 return ret;
426 429
diff --git a/drivers/lightnvm/sysblk.c b/drivers/lightnvm/sysblk.c
index bca690248bd7..737fbc3c5cf1 100644
--- a/drivers/lightnvm/sysblk.c
+++ b/drivers/lightnvm/sysblk.c
@@ -277,7 +277,7 @@ static int nvm_set_bb_tbl(struct nvm_dev *dev, struct sysblk_scan *s, int type)
277 277
278 memset(&rqd, 0, sizeof(struct nvm_rq)); 278 memset(&rqd, 0, sizeof(struct nvm_rq));
279 279
280 nvm_set_rqd_ppalist(dev, &rqd, s->ppas, s->nr_ppas); 280 nvm_set_rqd_ppalist(dev, &rqd, s->ppas, s->nr_ppas, 1);
281 nvm_generic_to_addr_mode(dev, &rqd); 281 nvm_generic_to_addr_mode(dev, &rqd);
282 282
283 ret = dev->ops->set_bb_tbl(dev, &rqd, type); 283 ret = dev->ops->set_bb_tbl(dev, &rqd, type);
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 16d4f2edf5b4..9ae0b7c6deb2 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -526,7 +526,7 @@ extern int nvm_submit_io(struct nvm_dev *, struct nvm_rq *);
526extern void nvm_generic_to_addr_mode(struct nvm_dev *, struct nvm_rq *); 526extern void nvm_generic_to_addr_mode(struct nvm_dev *, struct nvm_rq *);
527extern void nvm_addr_to_generic_mode(struct nvm_dev *, struct nvm_rq *); 527extern void nvm_addr_to_generic_mode(struct nvm_dev *, struct nvm_rq *);
528extern int nvm_set_rqd_ppalist(struct nvm_dev *, struct nvm_rq *, 528extern int nvm_set_rqd_ppalist(struct nvm_dev *, struct nvm_rq *,
529 struct ppa_addr *, int); 529 struct ppa_addr *, int, int);
530extern void nvm_free_rqd_ppalist(struct nvm_dev *, struct nvm_rq *); 530extern void nvm_free_rqd_ppalist(struct nvm_dev *, struct nvm_rq *);
531extern int nvm_erase_ppa(struct nvm_dev *, struct ppa_addr *, int); 531extern int nvm_erase_ppa(struct nvm_dev *, struct ppa_addr *, int);
532extern int nvm_erase_blk(struct nvm_dev *, struct nvm_block *); 532extern int nvm_erase_blk(struct nvm_dev *, struct nvm_block *);