From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S967582AbeCAKtC (ORCPT ); Thu, 1 Mar 2018 05:49:02 -0500 Received: from mail-lf0-f66.google.com ([209.85.215.66]:45890 "EHLO mail-lf0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S967382AbeCAKs5 (ORCPT ); Thu, 1 Mar 2018 05:48:57 -0500 X-Google-Smtp-Source: AG47ELvP1Bgu7OcHFXwieT9aMJke3sA6KOTOpZvhwv09DOywVKewklMGrrW9MrcfTg5lbWhmZy4NSQ== Subject: Re: [PATCH 15/15] lightnvm: pblk: implement 2.0 support To: =?UTF-8?Q?Javier_Gonz=c3=a1lez?= Cc: linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nvme@lists.infradead.org, =?UTF-8?Q?Javier_Gonz=c3=a1lez?= References: <1519832975-25432-1-git-send-email-javier@cnexlabs.com> <1519832975-25432-16-git-send-email-javier@cnexlabs.com> From: =?UTF-8?Q?Matias_Bj=c3=b8rling?= Message-ID: Date: Thu, 1 Mar 2018 11:48:54 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.0 MIME-Version: 1.0 In-Reply-To: <1519832975-25432-16-git-send-email-javier@cnexlabs.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-GB Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 02/28/2018 04:49 PM, Javier González wrote: > Implement 2.0 support in pblk. This includes the address formatting and > mapping paths, as well as the sysfs entries for them. > > Signed-off-by: Javier González > --- > drivers/lightnvm/pblk-init.c | 57 ++++++++++-- > drivers/lightnvm/pblk-sysfs.c | 36 ++++++-- > drivers/lightnvm/pblk.h | 198 ++++++++++++++++++++++++++++++++---------- > 3 files changed, 233 insertions(+), 58 deletions(-) > > diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c > index b3e15ef63df3..474f3f047087 100644 > --- a/drivers/lightnvm/pblk-init.c > +++ b/drivers/lightnvm/pblk-init.c > @@ -231,20 +231,63 @@ static int pblk_set_addrf_12(struct nvm_geo *geo, > return dst->blk_offset + src->blk_len; > } > > +static int pblk_set_addrf_20(struct nvm_geo *geo, > + struct nvm_addr_format *adst, > + struct pblk_addr_format *udst) > +{ > + struct nvm_addr_format *src = &geo->addrf; > + > + adst->ch_len = get_count_order(geo->num_ch); > + adst->lun_len = get_count_order(geo->num_lun); > + adst->chk_len = src->chk_len; > + adst->sec_len = src->sec_len; > + > + adst->sec_offset = 0; > + adst->ch_offset = adst->sec_len; > + adst->lun_offset = adst->ch_offset + adst->ch_len; > + adst->chk_offset = adst->lun_offset + adst->lun_len; > + > + adst->sec_mask = ((1ULL << adst->sec_len) - 1) << adst->sec_offset; > + adst->chk_mask = ((1ULL << adst->chk_len) - 1) << adst->chk_offset; > + adst->lun_mask = ((1ULL << adst->lun_len) - 1) << adst->lun_offset; > + adst->ch_mask = ((1ULL << adst->ch_len) - 1) << adst->ch_offset; > + > + udst->sec_stripe = geo->ws_opt; > + udst->ch_stripe = geo->num_ch; > + udst->lun_stripe = geo->num_lun; > + > + udst->sec_lun_stripe = udst->sec_stripe * udst->ch_stripe; > + udst->sec_ws_stripe = udst->sec_lun_stripe * udst->lun_stripe; > + > + return adst->chk_offset + adst->chk_len; > +} > + > static int pblk_set_addrf(struct pblk *pblk) > { > struct nvm_tgt_dev *dev = pblk->dev; > struct nvm_geo *geo = &dev->geo; > int mod; > > - div_u64_rem(geo->clba, pblk->min_write_pgs, &mod); > - if (mod) { > - pr_err("pblk: bad configuration of sectors/pages\n"); > + switch (geo->version) { > + case NVM_OCSSD_SPEC_12: > + div_u64_rem(geo->clba, pblk->min_write_pgs, &mod); > + if (mod) { > + pr_err("pblk: bad configuration of sectors/pages\n"); > + return -EINVAL; > + } > + > + pblk->addrf_len = pblk_set_addrf_12(geo, (void *)&pblk->addrf); > + break; > + case NVM_OCSSD_SPEC_20: > + pblk->addrf_len = pblk_set_addrf_20(geo, (void *)&pblk->addrf, > + &pblk->uaddrf); > + break; > + default: > + pr_err("pblk: OCSSD revision not supported (%d)\n", > + geo->version); > return -EINVAL; > } > > - pblk->addrf_len = pblk_set_addrf_12(geo, (void *)&pblk->addrf); > - > return 0; > } > > @@ -1117,7 +1160,9 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk, > struct pblk *pblk; > int ret; > > - if (geo->version != NVM_OCSSD_SPEC_12) { > + /* pblk supports 1.2 and 2.0 versions */ > + if (!(geo->version == NVM_OCSSD_SPEC_12 || > + geo->version == NVM_OCSSD_SPEC_20)) { > pr_err("pblk: OCSSD version not supported (%u)\n", > geo->version); > return ERR_PTR(-EINVAL); > diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c > index a643dc623731..391f865b02d9 100644 > --- a/drivers/lightnvm/pblk-sysfs.c > +++ b/drivers/lightnvm/pblk-sysfs.c > @@ -113,15 +113,16 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page) > { > struct nvm_tgt_dev *dev = pblk->dev; > struct nvm_geo *geo = &dev->geo; > - struct nvm_addr_format_12 *ppaf; > - struct nvm_addr_format_12 *geo_ppaf; > ssize_t sz = 0; > > - ppaf = (struct nvm_addr_format_12 *)&pblk->addrf; > - geo_ppaf = (struct nvm_addr_format_12 *)&geo->addrf; > + if (geo->version == NVM_OCSSD_SPEC_12) { > + struct nvm_addr_format_12 *ppaf = > + (struct nvm_addr_format_12 *)&pblk->addrf; > + struct nvm_addr_format_12 *geo_ppaf = > + (struct nvm_addr_format_12 *)&geo->addrf; > > - sz = snprintf(page, PAGE_SIZE, > - "pblk:(s:%d)ch:%d/%d,lun:%d/%d,blk:%d/%d,pg:%d/%d,pl:%d/%d,sec:%d/%d\n", > + sz = snprintf(page, PAGE_SIZE, > + "pblk:(s:%d)ch:%d/%d,lun:%d/%d,blk:%d/%d,pg:%d/%d,pl:%d/%d,sec:%d/%d\n", > pblk->addrf_len, > ppaf->ch_offset, ppaf->ch_len, > ppaf->lun_offset, ppaf->lun_len, > @@ -130,14 +131,33 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page) > ppaf->pln_offset, ppaf->pln_len, > ppaf->sec_offset, ppaf->sec_len); > > - sz += snprintf(page + sz, PAGE_SIZE - sz, > - "device:ch:%d/%d,lun:%d/%d,blk:%d/%d,pg:%d/%d,pl:%d/%d,sec:%d/%d\n", > + sz += snprintf(page + sz, PAGE_SIZE - sz, > + "device:ch:%d/%d,lun:%d/%d,blk:%d/%d,pg:%d/%d,pl:%d/%d,sec:%d/%d\n", > geo_ppaf->ch_offset, geo_ppaf->ch_len, > geo_ppaf->lun_offset, geo_ppaf->lun_len, > geo_ppaf->blk_offset, geo_ppaf->blk_len, > geo_ppaf->pg_offset, geo_ppaf->pg_len, > geo_ppaf->pln_offset, geo_ppaf->pln_len, > geo_ppaf->sec_offset, geo_ppaf->sec_len); > + } else { > + struct nvm_addr_format *ppaf = &pblk->addrf; > + struct nvm_addr_format *geo_ppaf = &geo->addrf; > + > + sz = snprintf(page, PAGE_SIZE, > + "pblk:(s:%d)ch:%d/%d,lun:%d/%d,chk:%d/%d/sec:%d/%d\n", > + pblk->addrf_len, > + ppaf->ch_offset, ppaf->ch_len, > + ppaf->lun_offset, ppaf->lun_len, > + ppaf->chk_offset, ppaf->chk_len, > + ppaf->sec_offset, ppaf->sec_len); > + > + sz += snprintf(page + sz, PAGE_SIZE - sz, > + "device:ch:%d/%d,lun:%d/%d,chk:%d/%d,sec:%d/%d\n", > + geo_ppaf->ch_offset, geo_ppaf->ch_len, > + geo_ppaf->lun_offset, geo_ppaf->lun_len, > + geo_ppaf->chk_offset, geo_ppaf->chk_len, > + geo_ppaf->sec_offset, geo_ppaf->sec_len); > + } > > return sz; > } > diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h > index ee149766b7a0..1deddd38c0ac 100644 > --- a/drivers/lightnvm/pblk.h > +++ b/drivers/lightnvm/pblk.h > @@ -561,6 +561,18 @@ enum { > PBLK_STATE_STOPPED = 3, > }; > > +/* Internal format to support not power-of-2 device formats */ > +struct pblk_addr_format { > + /* gen to dev */ > + int sec_stripe; > + int ch_stripe; > + int lun_stripe; > + > + /* dev to gen */ > + int sec_lun_stripe; > + int sec_ws_stripe; > +}; > + > struct pblk { > struct nvm_tgt_dev *dev; > struct gendisk *disk; > @@ -573,7 +585,8 @@ struct pblk { > struct pblk_line_mgmt l_mg; /* Line management */ > struct pblk_line_meta lm; /* Line metadata */ > > - struct nvm_addr_format addrf; > + struct nvm_addr_format addrf; /* Aligned address format */ > + struct pblk_addr_format uaddrf; /* Unaligned address format */ > int addrf_len; > > struct pblk_rb rwb; > @@ -954,17 +967,43 @@ static inline int pblk_ppa_to_pos(struct nvm_geo *geo, struct ppa_addr p) > static inline struct ppa_addr addr_to_gen_ppa(struct pblk *pblk, u64 paddr, > u64 line_id) > { > - struct nvm_addr_format_12 *ppaf = > - (struct nvm_addr_format_12 *)&pblk->addrf; > + struct nvm_tgt_dev *dev = pblk->dev; > + struct nvm_geo *geo = &dev->geo; > struct ppa_addr ppa; > > - ppa.ppa = 0; > - ppa.g.blk = line_id; > - ppa.g.pg = (paddr & ppaf->pg_mask) >> ppaf->pg_offset; > - ppa.g.lun = (paddr & ppaf->lun_mask) >> ppaf->lun_offset; > - ppa.g.ch = (paddr & ppaf->ch_mask) >> ppaf->ch_offset; > - ppa.g.pl = (paddr & ppaf->pln_mask) >> ppaf->pln_offset; > - ppa.g.sec = (paddr & ppaf->sec_mask) >> ppaf->sec_offset; > + if (geo->version == NVM_OCSSD_SPEC_12) { > + struct nvm_addr_format_12 *ppaf = > + (struct nvm_addr_format_12 *)&pblk->addrf; > + > + ppa.ppa = 0; > + ppa.g.blk = line_id; > + ppa.g.pg = (paddr & ppaf->pg_mask) >> ppaf->pg_offset; > + ppa.g.lun = (paddr & ppaf->lun_mask) >> ppaf->lun_offset; > + ppa.g.ch = (paddr & ppaf->ch_mask) >> ppaf->ch_offset; > + ppa.g.pl = (paddr & ppaf->pln_mask) >> ppaf->pln_offset; > + ppa.g.sec = (paddr & ppaf->sec_mask) >> ppaf->sec_offset; > + } else { > + struct pblk_addr_format *uaddrf = &pblk->uaddrf; > + int secs, chnls, luns; > + > + ppa.ppa = 0; > + > + ppa.m.chk = line_id; > + > + div_u64_rem(paddr, uaddrf->sec_stripe, &secs); > + ppa.m.sec = secs; > + > + sector_div(paddr, uaddrf->sec_stripe); > + div_u64_rem(paddr, uaddrf->ch_stripe, &chnls); > + ppa.m.grp = chnls; > + > + sector_div(paddr, uaddrf->ch_stripe); > + div_u64_rem(paddr, uaddrf->lun_stripe, &luns); > + ppa.m.pu = luns; > + > + sector_div(paddr, uaddrf->lun_stripe); > + ppa.m.sec += uaddrf->sec_stripe * paddr; > + } > > return ppa; > } > @@ -972,15 +1011,32 @@ static inline struct ppa_addr addr_to_gen_ppa(struct pblk *pblk, u64 paddr, > static inline u64 pblk_dev_ppa_to_line_addr(struct pblk *pblk, > struct ppa_addr p) > { > - struct nvm_addr_format_12 *ppaf = > - (struct nvm_addr_format_12 *)&pblk->addrf; > + struct nvm_tgt_dev *dev = pblk->dev; > + struct nvm_geo *geo = &dev->geo; > u64 paddr; > > - paddr = (u64)p.g.ch << ppaf->ch_offset; > - paddr |= (u64)p.g.lun << ppaf->lun_offset; > - paddr |= (u64)p.g.pg << ppaf->pg_offset; > - paddr |= (u64)p.g.pl << ppaf->pln_offset; > - paddr |= (u64)p.g.sec << ppaf->sec_offset; > + if (geo->version == NVM_OCSSD_SPEC_12) { > + struct nvm_addr_format_12 *ppaf = > + (struct nvm_addr_format_12 *)&pblk->addrf; > + > + paddr = (u64)p.g.ch << ppaf->ch_offset; > + paddr |= (u64)p.g.lun << ppaf->lun_offset; > + paddr |= (u64)p.g.pg << ppaf->pg_offset; > + paddr |= (u64)p.g.pl << ppaf->pln_offset; > + paddr |= (u64)p.g.sec << ppaf->sec_offset; > + } else { > + struct pblk_addr_format *uaddrf = &pblk->uaddrf; > + u64 secs = (u64)p.m.sec; > + int sec_stripe; > + > + paddr = (u64)p.m.grp * uaddrf->sec_stripe; > + paddr += (u64)p.m.pu * uaddrf->sec_lun_stripe; > + > + div_u64_rem(secs, uaddrf->sec_stripe, &sec_stripe); > + sector_div(secs, uaddrf->sec_stripe); > + paddr += secs * uaddrf->sec_ws_stripe; > + paddr += sec_stripe; > + } > > return paddr; > } > @@ -997,15 +1053,37 @@ static inline struct ppa_addr pblk_ppa32_to_ppa64(struct pblk *pblk, u32 ppa32) > ppa64.c.line = ppa32 & ((~0U) >> 1); > ppa64.c.is_cached = 1; > } else { > - struct nvm_addr_format_12 *ppaf = > + struct nvm_tgt_dev *dev = pblk->dev; > + struct nvm_geo *geo = &dev->geo; > + > + if (geo->version == NVM_OCSSD_SPEC_12) { > + struct nvm_addr_format_12 *ppaf = > (struct nvm_addr_format_12 *)&pblk->addrf; > > - ppa64.g.ch = (ppa32 & ppaf->ch_mask) >> ppaf->ch_offset; > - ppa64.g.lun = (ppa32 & ppaf->lun_mask) >> ppaf->lun_offset; > - ppa64.g.blk = (ppa32 & ppaf->blk_mask) >> ppaf->blk_offset; > - ppa64.g.pg = (ppa32 & ppaf->pg_mask) >> ppaf->pg_offset; > - ppa64.g.pl = (ppa32 & ppaf->pln_mask) >> ppaf->pln_offset; > - ppa64.g.sec = (ppa32 & ppaf->sec_mask) >> ppaf->sec_offset; > + ppa64.g.ch = (ppa32 & ppaf->ch_mask) >> > + ppaf->ch_offset; > + ppa64.g.lun = (ppa32 & ppaf->lun_mask) >> > + ppaf->lun_offset; > + ppa64.g.blk = (ppa32 & ppaf->blk_mask) >> > + ppaf->blk_offset; > + ppa64.g.pg = (ppa32 & ppaf->pg_mask) >> > + ppaf->pg_offset; > + ppa64.g.pl = (ppa32 & ppaf->pln_mask) >> > + ppaf->pln_offset; > + ppa64.g.sec = (ppa32 & ppaf->sec_mask) >> > + ppaf->sec_offset; > + } else { > + struct nvm_addr_format *lbaf = &pblk->addrf; > + > + ppa64.m.grp = (ppa32 & lbaf->ch_mask) >> > + lbaf->ch_offset; > + ppa64.m.pu = (ppa32 & lbaf->lun_mask) >> > + lbaf->lun_offset; > + ppa64.m.chk = (ppa32 & lbaf->chk_mask) >> > + lbaf->chk_offset; > + ppa64.m.sec = (ppa32 & lbaf->sec_mask) >> > + lbaf->sec_offset; > + } > } > > return ppa64; > @@ -1021,15 +1099,27 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64) > ppa32 |= ppa64.c.line; > ppa32 |= 1U << 31; > } else { > - struct nvm_addr_format_12 *ppaf = > + struct nvm_tgt_dev *dev = pblk->dev; > + struct nvm_geo *geo = &dev->geo; > + > + if (geo->version == NVM_OCSSD_SPEC_12) { > + struct nvm_addr_format_12 *ppaf = > (struct nvm_addr_format_12 *)&pblk->addrf; > > - ppa32 |= ppa64.g.ch << ppaf->ch_offset; > - ppa32 |= ppa64.g.lun << ppaf->lun_offset; > - ppa32 |= ppa64.g.blk << ppaf->blk_offset; > - ppa32 |= ppa64.g.pg << ppaf->pg_offset; > - ppa32 |= ppa64.g.pl << ppaf->pln_offset; > - ppa32 |= ppa64.g.sec << ppaf->sec_offset; > + ppa32 |= ppa64.g.ch << ppaf->ch_offset; > + ppa32 |= ppa64.g.lun << ppaf->lun_offset; > + ppa32 |= ppa64.g.blk << ppaf->blk_offset; > + ppa32 |= ppa64.g.pg << ppaf->pg_offset; > + ppa32 |= ppa64.g.pl << ppaf->pln_offset; > + ppa32 |= ppa64.g.sec << ppaf->sec_offset; > + } else { > + struct nvm_addr_format *lbaf = &pblk->addrf; > + > + ppa32 |= ppa64.m.grp << lbaf->ch_offset; > + ppa32 |= ppa64.m.pu << lbaf->lun_offset; > + ppa32 |= ppa64.m.chk << lbaf->chk_offset; > + ppa32 |= ppa64.m.sec << lbaf->sec_offset; > + } > } > > return ppa32; > @@ -1147,6 +1237,9 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type) > struct nvm_geo *geo = &dev->geo; > int flags; > > + if (geo->version == NVM_OCSSD_SPEC_20) > + return 0; > + > flags = geo->pln_mode >> 1; > > if (type == PBLK_WRITE) > @@ -1166,6 +1259,9 @@ static inline int pblk_set_read_mode(struct pblk *pblk, int type) > struct nvm_geo *geo = &dev->geo; > int flags; > > + if (geo->version == NVM_OCSSD_SPEC_20) > + return 0; > + > flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE; > if (type == PBLK_READ_SEQUENTIAL) > flags |= geo->pln_mode >> 1; > @@ -1179,16 +1275,21 @@ static inline int pblk_io_aligned(struct pblk *pblk, int nr_secs) > } > > #ifdef CONFIG_NVM_DEBUG > -static inline void print_ppa(struct ppa_addr *p, char *msg, int error) > +static inline void print_ppa(struct nvm_geo *geo, struct ppa_addr *p, > + char *msg, int error) > { > if (p->c.is_cached) { > pr_err("ppa: (%s: %x) cache line: %llu\n", > msg, error, (u64)p->c.line); > - } else { > + } else if (geo->version == NVM_OCSSD_SPEC_12) { > pr_err("ppa: (%s: %x):ch:%d,lun:%d,blk:%d,pg:%d,pl:%d,sec:%d\n", > msg, error, > p->g.ch, p->g.lun, p->g.blk, > p->g.pg, p->g.pl, p->g.sec); > + } else { > + pr_err("ppa: (%s: %x):ch:%d,lun:%d,chk:%d,sec:%d\n", > + msg, error, > + p->m.grp, p->m.pu, p->m.chk, p->m.sec); > } > } > > @@ -1198,13 +1299,13 @@ static inline void pblk_print_failed_rqd(struct pblk *pblk, struct nvm_rq *rqd, > int bit = -1; > > if (rqd->nr_ppas == 1) { > - print_ppa(&rqd->ppa_addr, "rqd", error); > + print_ppa(&pblk->dev->geo, &rqd->ppa_addr, "rqd", error); > return; > } > > while ((bit = find_next_bit((void *)&rqd->ppa_status, rqd->nr_ppas, > bit + 1)) < rqd->nr_ppas) { > - print_ppa(&rqd->ppa_list[bit], "rqd", error); > + print_ppa(&pblk->dev->geo, &rqd->ppa_list[bit], "rqd", error); > } > > pr_err("error:%d, ppa_status:%llx\n", error, rqd->ppa_status); > @@ -1220,16 +1321,25 @@ static inline int pblk_boundary_ppa_checks(struct nvm_tgt_dev *tgt_dev, > for (i = 0; i < nr_ppas; i++) { > ppa = &ppas[i]; > > - if (!ppa->c.is_cached && > - ppa->g.ch < geo->num_ch && > - ppa->g.lun < geo->num_lun && > - ppa->g.pl < geo->num_pln && > - ppa->g.blk < geo->num_chk && > - ppa->g.pg < geo->num_pg && > - ppa->g.sec < geo->ws_min) > - continue; > + if (geo->version == NVM_OCSSD_SPEC_12) { > + if (!ppa->c.is_cached && > + ppa->g.ch < geo->num_ch && > + ppa->g.lun < geo->num_lun && > + ppa->g.pl < geo->num_pln && > + ppa->g.blk < geo->num_chk && > + ppa->g.pg < geo->num_pg && > + ppa->g.sec < geo->ws_min) > + continue; > + } else { > + if (!ppa->c.is_cached && > + ppa->m.grp < geo->num_ch && > + ppa->m.pu < geo->num_lun && > + ppa->m.chk < geo->num_chk && > + ppa->m.sec < geo->clba) > + continue; > + } > > - print_ppa(ppa, "boundary", i); > + print_ppa(geo, ppa, "boundary", i); > > return 1; > } > Ok, I think this is close to be good such that the patches can be picked up in v5.