diff options
Diffstat (limited to 'drivers/lightnvm/pblk-init.c')
-rw-r--r-- | drivers/lightnvm/pblk-init.c | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c index e8055b796381..f9a3e47b6a93 100644 --- a/drivers/lightnvm/pblk-init.c +++ b/drivers/lightnvm/pblk-init.c | |||
@@ -399,6 +399,7 @@ static int pblk_core_init(struct pblk *pblk) | |||
399 | pblk->nr_flush_rst = 0; | 399 | pblk->nr_flush_rst = 0; |
400 | 400 | ||
401 | pblk->min_write_pgs = geo->ws_opt; | 401 | pblk->min_write_pgs = geo->ws_opt; |
402 | pblk->min_write_pgs_data = pblk->min_write_pgs; | ||
402 | max_write_ppas = pblk->min_write_pgs * geo->all_luns; | 403 | max_write_ppas = pblk->min_write_pgs * geo->all_luns; |
403 | pblk->max_write_pgs = min_t(int, max_write_ppas, NVM_MAX_VLBA); | 404 | pblk->max_write_pgs = min_t(int, max_write_ppas, NVM_MAX_VLBA); |
404 | pblk->max_write_pgs = min_t(int, pblk->max_write_pgs, | 405 | pblk->max_write_pgs = min_t(int, pblk->max_write_pgs, |
@@ -406,9 +407,35 @@ static int pblk_core_init(struct pblk *pblk) | |||
406 | pblk_set_sec_per_write(pblk, pblk->min_write_pgs); | 407 | pblk_set_sec_per_write(pblk, pblk->min_write_pgs); |
407 | 408 | ||
408 | pblk->oob_meta_size = geo->sos; | 409 | pblk->oob_meta_size = geo->sos; |
409 | if (pblk->oob_meta_size < sizeof(struct pblk_sec_meta)) { | 410 | if (!pblk_is_oob_meta_supported(pblk)) { |
410 | pblk_err(pblk, "Unsupported metadata size\n"); | 411 | /* For drives which does not have OOB metadata feature |
411 | return -EINVAL; | 412 | * in order to support recovery feature we need to use |
413 | * so called packed metadata. Packed metada will store | ||
414 | * the same information as OOB metadata (l2p table mapping, | ||
415 | * but in the form of the single page at the end of | ||
416 | * every write request. | ||
417 | */ | ||
418 | if (pblk->min_write_pgs | ||
419 | * sizeof(struct pblk_sec_meta) > PAGE_SIZE) { | ||
420 | /* We want to keep all the packed metadata on single | ||
421 | * page per write requests. So we need to ensure that | ||
422 | * it will fit. | ||
423 | * | ||
424 | * This is more like sanity check, since there is | ||
425 | * no device with such a big minimal write size | ||
426 | * (above 1 metabytes). | ||
427 | */ | ||
428 | pblk_err(pblk, "Not supported min write size\n"); | ||
429 | return -EINVAL; | ||
430 | } | ||
431 | /* For packed meta approach we do some simplification. | ||
432 | * On read path we always issue requests which size | ||
433 | * equal to max_write_pgs, with all pages filled with | ||
434 | * user payload except of last one page which will be | ||
435 | * filled with packed metadata. | ||
436 | */ | ||
437 | pblk->max_write_pgs = pblk->min_write_pgs; | ||
438 | pblk->min_write_pgs_data = pblk->min_write_pgs - 1; | ||
412 | } | 439 | } |
413 | 440 | ||
414 | pblk->pad_dist = kcalloc(pblk->min_write_pgs - 1, sizeof(atomic64_t), | 441 | pblk->pad_dist = kcalloc(pblk->min_write_pgs - 1, sizeof(atomic64_t), |
@@ -641,7 +668,7 @@ static int pblk_set_provision(struct pblk *pblk, int nr_free_chks) | |||
641 | struct pblk_line_meta *lm = &pblk->lm; | 668 | struct pblk_line_meta *lm = &pblk->lm; |
642 | struct nvm_geo *geo = &dev->geo; | 669 | struct nvm_geo *geo = &dev->geo; |
643 | sector_t provisioned; | 670 | sector_t provisioned; |
644 | int sec_meta, blk_meta; | 671 | int sec_meta, blk_meta, clba; |
645 | int minimum; | 672 | int minimum; |
646 | 673 | ||
647 | if (geo->op == NVM_TARGET_DEFAULT_OP) | 674 | if (geo->op == NVM_TARGET_DEFAULT_OP) |
@@ -682,7 +709,8 @@ static int pblk_set_provision(struct pblk *pblk, int nr_free_chks) | |||
682 | sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines; | 709 | sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines; |
683 | blk_meta = DIV_ROUND_UP(sec_meta, geo->clba); | 710 | blk_meta = DIV_ROUND_UP(sec_meta, geo->clba); |
684 | 711 | ||
685 | pblk->capacity = (provisioned - blk_meta) * geo->clba; | 712 | clba = (geo->clba / pblk->min_write_pgs) * pblk->min_write_pgs_data; |
713 | pblk->capacity = (provisioned - blk_meta) * clba; | ||
686 | 714 | ||
687 | atomic_set(&pblk->rl.free_blocks, nr_free_chks); | 715 | atomic_set(&pblk->rl.free_blocks, nr_free_chks); |
688 | atomic_set(&pblk->rl.free_user_blocks, nr_free_chks); | 716 | atomic_set(&pblk->rl.free_user_blocks, nr_free_chks); |