summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJavier González <javier@cnexlabs.com>2018-03-29 18:05:17 -0400
committerJens Axboe <axboe@kernel.dk>2018-03-29 19:29:09 -0400
commita294c199455187d124b0760fa8f86c13cdaa4b25 (patch)
tree15df9cbb23f8fd0286db1f2671498f73914233ab /drivers
parent7100d50a7e58a6884368001e2b1a32b7169c072c (diff)
lightnvm: implement get log report chunk helpers
The 2.0 spec provides a report chunk log page that can be retrieved using the stangard nvme get log page. This replaces the dedicated get/put bad block table in 1.2. This patch implements the helper functions to allow targets retrieve the chunk metadata using get log page. It makes nvme_get_log_ext available outside of nvme core so that we can use it form lightnvm. 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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/lightnvm/core.c11
-rw-r--r--drivers/nvme/host/core.c4
-rw-r--r--drivers/nvme/host/lightnvm.c74
3 files changed, 87 insertions, 2 deletions
diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 77901bf17416..63171cdce270 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -712,6 +712,17 @@ static void nvm_free_rqd_ppalist(struct nvm_tgt_dev *tgt_dev,
712 nvm_dev_dma_free(tgt_dev->parent, rqd->ppa_list, rqd->dma_ppa_list); 712 nvm_dev_dma_free(tgt_dev->parent, rqd->ppa_list, rqd->dma_ppa_list);
713} 713}
714 714
715int nvm_get_chunk_meta(struct nvm_tgt_dev *tgt_dev, struct nvm_chk_meta *meta,
716 struct ppa_addr ppa, int nchks)
717{
718 struct nvm_dev *dev = tgt_dev->parent;
719
720 nvm_ppa_tgt_to_dev(tgt_dev, &ppa, 1);
721
722 return dev->ops->get_chk_meta(tgt_dev->parent, meta,
723 (sector_t)ppa.ppa, nchks);
724}
725EXPORT_SYMBOL(nvm_get_chunk_meta);
715 726
716int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *ppas, 727int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *ppas,
717 int nr_ppas, int type) 728 int nr_ppas, int type)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index e7ec2fb5c59a..f81e3b323366 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -2219,8 +2219,8 @@ out_unlock:
2219} 2219}
2220 2220
2221int nvme_get_log_ext(struct nvme_ctrl *ctrl, struct nvme_ns *ns, 2221int nvme_get_log_ext(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
2222 u8 log_page, void *log, 2222 u8 log_page, void *log,
2223 size_t size, size_t offset) 2223 size_t size, size_t offset)
2224{ 2224{
2225 struct nvme_command c = { }; 2225 struct nvme_command c = { };
2226 unsigned long dwlen = size / 4 - 1; 2226 unsigned long dwlen = size / 4 - 1;
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 08f0f6b5bc06..ffd64a83c8c3 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -35,6 +35,10 @@ enum nvme_nvm_admin_opcode {
35 nvme_nvm_admin_set_bb_tbl = 0xf1, 35 nvme_nvm_admin_set_bb_tbl = 0xf1,
36}; 36};
37 37
38enum nvme_nvm_log_page {
39 NVME_NVM_LOG_REPORT_CHUNK = 0xca,
40};
41
38struct nvme_nvm_ph_rw { 42struct nvme_nvm_ph_rw {
39 __u8 opcode; 43 __u8 opcode;
40 __u8 flags; 44 __u8 flags;
@@ -236,6 +240,16 @@ struct nvme_nvm_id20 {
236 __u8 vs[1024]; 240 __u8 vs[1024];
237}; 241};
238 242
243struct nvme_nvm_chk_meta {
244 __u8 state;
245 __u8 type;
246 __u8 wi;
247 __u8 rsvd[5];
248 __le64 slba;
249 __le64 cnlb;
250 __le64 wp;
251};
252
239/* 253/*
240 * Check we didn't inadvertently grow the command struct 254 * Check we didn't inadvertently grow the command struct
241 */ 255 */
@@ -252,6 +266,9 @@ static inline void _nvme_nvm_check_size(void)
252 BUILD_BUG_ON(sizeof(struct nvme_nvm_bb_tbl) != 64); 266 BUILD_BUG_ON(sizeof(struct nvme_nvm_bb_tbl) != 64);
253 BUILD_BUG_ON(sizeof(struct nvme_nvm_id20_addrf) != 8); 267 BUILD_BUG_ON(sizeof(struct nvme_nvm_id20_addrf) != 8);
254 BUILD_BUG_ON(sizeof(struct nvme_nvm_id20) != NVME_IDENTIFY_DATA_SIZE); 268 BUILD_BUG_ON(sizeof(struct nvme_nvm_id20) != NVME_IDENTIFY_DATA_SIZE);
269 BUILD_BUG_ON(sizeof(struct nvme_nvm_chk_meta) != 32);
270 BUILD_BUG_ON(sizeof(struct nvme_nvm_chk_meta) !=
271 sizeof(struct nvm_chk_meta));
255} 272}
256 273
257static void nvme_nvm_set_addr_12(struct nvm_addrf_12 *dst, 274static void nvme_nvm_set_addr_12(struct nvm_addrf_12 *dst,
@@ -552,6 +569,61 @@ static int nvme_nvm_set_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr *ppas,
552 return ret; 569 return ret;
553} 570}
554 571
572/*
573 * Expect the lba in device format
574 */
575static int nvme_nvm_get_chk_meta(struct nvm_dev *ndev,
576 struct nvm_chk_meta *meta,
577 sector_t slba, int nchks)
578{
579 struct nvm_geo *geo = &ndev->geo;
580 struct nvme_ns *ns = ndev->q->queuedata;
581 struct nvme_ctrl *ctrl = ns->ctrl;
582 struct nvme_nvm_chk_meta *dev_meta = (struct nvme_nvm_chk_meta *)meta;
583 struct ppa_addr ppa;
584 size_t left = nchks * sizeof(struct nvme_nvm_chk_meta);
585 size_t log_pos, offset, len;
586 int ret, i;
587
588 /* Normalize lba address space to obtain log offset */
589 ppa.ppa = slba;
590 ppa = dev_to_generic_addr(ndev, ppa);
591
592 log_pos = ppa.m.chk;
593 log_pos += ppa.m.pu * geo->num_chk;
594 log_pos += ppa.m.grp * geo->num_lun * geo->num_chk;
595
596 offset = log_pos * sizeof(struct nvme_nvm_chk_meta);
597
598 while (left) {
599 len = min_t(unsigned int, left, ctrl->max_hw_sectors << 9);
600
601 ret = nvme_get_log_ext(ctrl, ns, NVME_NVM_LOG_REPORT_CHUNK,
602 dev_meta, len, offset);
603 if (ret) {
604 dev_err(ctrl->device, "Get REPORT CHUNK log error\n");
605 break;
606 }
607
608 for (i = 0; i < len; i += sizeof(struct nvme_nvm_chk_meta)) {
609 meta->state = dev_meta->state;
610 meta->type = dev_meta->type;
611 meta->wi = dev_meta->wi;
612 meta->slba = le64_to_cpu(dev_meta->slba);
613 meta->cnlb = le64_to_cpu(dev_meta->cnlb);
614 meta->wp = le64_to_cpu(dev_meta->wp);
615
616 meta++;
617 dev_meta++;
618 }
619
620 offset += len;
621 left -= len;
622 }
623
624 return ret;
625}
626
555static inline void nvme_nvm_rqtocmd(struct nvm_rq *rqd, struct nvme_ns *ns, 627static inline void nvme_nvm_rqtocmd(struct nvm_rq *rqd, struct nvme_ns *ns,
556 struct nvme_nvm_command *c) 628 struct nvme_nvm_command *c)
557{ 629{
@@ -683,6 +755,8 @@ static struct nvm_dev_ops nvme_nvm_dev_ops = {
683 .get_bb_tbl = nvme_nvm_get_bb_tbl, 755 .get_bb_tbl = nvme_nvm_get_bb_tbl,
684 .set_bb_tbl = nvme_nvm_set_bb_tbl, 756 .set_bb_tbl = nvme_nvm_set_bb_tbl,
685 757
758 .get_chk_meta = nvme_nvm_get_chk_meta,
759
686 .submit_io = nvme_nvm_submit_io, 760 .submit_io = nvme_nvm_submit_io,
687 .submit_io_sync = nvme_nvm_submit_io_sync, 761 .submit_io_sync = nvme_nvm_submit_io_sync,
688 762