Skip to content

Commit a294c19

Browse files
Javier Gonzálezaxboe
authored andcommitted
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>
1 parent 7100d50 commit a294c19

File tree

4 files changed

+111
-2
lines changed

4 files changed

+111
-2
lines changed

drivers/lightnvm/core.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,17 @@ static void nvm_free_rqd_ppalist(struct nvm_tgt_dev *tgt_dev,
712712
nvm_dev_dma_free(tgt_dev->parent, rqd->ppa_list, rqd->dma_ppa_list);
713713
}
714714

715+
int 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+
}
725+
EXPORT_SYMBOL(nvm_get_chunk_meta);
715726

716727
int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *ppas,
717728
int nr_ppas, int type)

drivers/nvme/host/core.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2219,8 +2219,8 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
22192219
}
22202220

22212221
int nvme_get_log_ext(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
2222-
u8 log_page, void *log,
2223-
size_t size, size_t offset)
2222+
u8 log_page, void *log,
2223+
size_t size, size_t offset)
22242224
{
22252225
struct nvme_command c = { };
22262226
unsigned long dwlen = size / 4 - 1;

drivers/nvme/host/lightnvm.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ enum nvme_nvm_admin_opcode {
3535
nvme_nvm_admin_set_bb_tbl = 0xf1,
3636
};
3737

38+
enum nvme_nvm_log_page {
39+
NVME_NVM_LOG_REPORT_CHUNK = 0xca,
40+
};
41+
3842
struct nvme_nvm_ph_rw {
3943
__u8 opcode;
4044
__u8 flags;
@@ -236,6 +240,16 @@ struct nvme_nvm_id20 {
236240
__u8 vs[1024];
237241
};
238242

243+
struct 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+
239253
/*
240254
* Check we didn't inadvertently grow the command struct
241255
*/
@@ -252,6 +266,9 @@ static inline void _nvme_nvm_check_size(void)
252266
BUILD_BUG_ON(sizeof(struct nvme_nvm_bb_tbl) != 64);
253267
BUILD_BUG_ON(sizeof(struct nvme_nvm_id20_addrf) != 8);
254268
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));
255272
}
256273

257274
static 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,
552569
return ret;
553570
}
554571

572+
/*
573+
* Expect the lba in device format
574+
*/
575+
static 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+
555627
static inline void nvme_nvm_rqtocmd(struct nvm_rq *rqd, struct nvme_ns *ns,
556628
struct nvme_nvm_command *c)
557629
{
@@ -683,6 +755,8 @@ static struct nvm_dev_ops nvme_nvm_dev_ops = {
683755
.get_bb_tbl = nvme_nvm_get_bb_tbl,
684756
.set_bb_tbl = nvme_nvm_set_bb_tbl,
685757

758+
.get_chk_meta = nvme_nvm_get_chk_meta,
759+
686760
.submit_io = nvme_nvm_submit_io,
687761
.submit_io_sync = nvme_nvm_submit_io_sync,
688762

include/linux/lightnvm.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,13 @@ struct nvm_rq;
8181
struct nvm_id;
8282
struct nvm_dev;
8383
struct nvm_tgt_dev;
84+
struct nvm_chk_meta;
8485

8586
typedef int (nvm_id_fn)(struct nvm_dev *);
8687
typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, u8 *);
8788
typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct ppa_addr *, int, int);
89+
typedef int (nvm_get_chk_meta_fn)(struct nvm_dev *, struct nvm_chk_meta *,
90+
sector_t, int);
8891
typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
8992
typedef int (nvm_submit_io_sync_fn)(struct nvm_dev *, struct nvm_rq *);
9093
typedef void *(nvm_create_dma_pool_fn)(struct nvm_dev *, char *);
@@ -98,6 +101,8 @@ struct nvm_dev_ops {
98101
nvm_op_bb_tbl_fn *get_bb_tbl;
99102
nvm_op_set_bb_fn *set_bb_tbl;
100103

104+
nvm_get_chk_meta_fn *get_chk_meta;
105+
101106
nvm_submit_io_fn *submit_io;
102107
nvm_submit_io_sync_fn *submit_io_sync;
103108

@@ -227,6 +232,20 @@ struct nvm_addrf {
227232
u64 rsv_mask[2];
228233
};
229234

235+
/*
236+
* Note: The structure size is linked to nvme_nvm_chk_meta such that the same
237+
* buffer can be used when converting from little endian to cpu addressing.
238+
*/
239+
struct nvm_chk_meta {
240+
u8 state;
241+
u8 type;
242+
u8 wi;
243+
u8 rsvd[5];
244+
u64 slba;
245+
u64 cnlb;
246+
u64 wp;
247+
};
248+
230249
struct nvm_target {
231250
struct list_head list;
232251
struct nvm_tgt_dev *dev;
@@ -492,6 +511,11 @@ extern struct nvm_dev *nvm_alloc_dev(int);
492511
extern int nvm_register(struct nvm_dev *);
493512
extern void nvm_unregister(struct nvm_dev *);
494513

514+
515+
extern int nvm_get_chunk_meta(struct nvm_tgt_dev *tgt_dev,
516+
struct nvm_chk_meta *meta, struct ppa_addr ppa,
517+
int nchks);
518+
495519
extern int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *, struct ppa_addr *,
496520
int, int);
497521
extern int nvm_submit_io(struct nvm_tgt_dev *, struct nvm_rq *);

0 commit comments

Comments
 (0)