diff options
author | Matias Bjørling <m@bjorling.me> | 2016-05-06 14:03:07 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2016-05-06 14:51:10 -0400 |
commit | 5ebc7d9fe13ff9bd3622d0be3cd39c8751459be6 (patch) | |
tree | dfca4e0b1029af8fcf8fe52ce6de69a4eb7bcdb0 | |
parent | 6659d4d80c6fc6b4b5bc2e99988f32b1b3865f1d (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.c | 31 | ||||
-rw-r--r-- | drivers/lightnvm/sysblk.c | 2 | ||||
-rw-r--r-- | include/linux/lightnvm.h | 2 |
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) | |||
251 | EXPORT_SYMBOL(nvm_generic_to_addr_mode); | 251 | EXPORT_SYMBOL(nvm_generic_to_addr_mode); |
252 | 252 | ||
253 | int nvm_set_rqd_ppalist(struct nvm_dev *dev, struct nvm_rq *rqd, | 253 | int 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 *); | |||
526 | extern void nvm_generic_to_addr_mode(struct nvm_dev *, struct nvm_rq *); | 526 | extern void nvm_generic_to_addr_mode(struct nvm_dev *, struct nvm_rq *); |
527 | extern void nvm_addr_to_generic_mode(struct nvm_dev *, struct nvm_rq *); | 527 | extern void nvm_addr_to_generic_mode(struct nvm_dev *, struct nvm_rq *); |
528 | extern int nvm_set_rqd_ppalist(struct nvm_dev *, struct nvm_rq *, | 528 | extern int nvm_set_rqd_ppalist(struct nvm_dev *, struct nvm_rq *, |
529 | struct ppa_addr *, int); | 529 | struct ppa_addr *, int, int); |
530 | extern void nvm_free_rqd_ppalist(struct nvm_dev *, struct nvm_rq *); | 530 | extern void nvm_free_rqd_ppalist(struct nvm_dev *, struct nvm_rq *); |
531 | extern int nvm_erase_ppa(struct nvm_dev *, struct ppa_addr *, int); | 531 | extern int nvm_erase_ppa(struct nvm_dev *, struct ppa_addr *, int); |
532 | extern int nvm_erase_blk(struct nvm_dev *, struct nvm_block *); | 532 | extern int nvm_erase_blk(struct nvm_dev *, struct nvm_block *); |