All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 00/20] lightnvm: pblk: implement 2.0 support
@ 2018-02-21  9:26 ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

Changes since V1:

Apply Matias' feedback:
  - Rebase on top of Matias' latest patches.
  - Use nvme_get_log_ext to submit report chunk and export it.
  - Re-write report chunk based on Matias' suggestions. Here, I
    maintained the lba interface, but it was necessary to redo the
    address formatting to match the chunk log page format. For pblk,
    this means a double address transformation, but it enables the
    standard path to use lbas, plus, this is not in the fast path.
  - Fold address format together with address transformations.
  - Split the generic geometry patch in different patches.
  - Remove refactoring of ligthnvm's core sysfs.

Feedback not applied:
  - Not letting pblk know about 1.2 and 2.0 bad block paths. Since the
    interfaces for get/set bad block and report chunk are so different,
    moving this logic to core adds assumptions on how the targets would
    want to get the data back. A way of doing this is creating a logical
    report chunk on the 1.2 path, but this would mean that values like
    the wear-index are invalid, which requires the target knowledge. I'm
    open to suggestions here.

Also:
  - Do some further renamings
  - Create a generic address format to make it explicit where we share
    1.2 and 2.0 fields to avoid address formatting in the fast path.
  - Add new fields to sysfs to complete spec and show major/minor
    versions (version and subversion to respect current interface).

Implement 2.0 support in pblk. This includes the address formatting and
mapping paths, as well as the sysfs entries for them.

Javier

Javier González (20):
  lightnvm: simplify geometry structure.
  lightnvm: add controller capabilities to 2.0
  lightnvm: fix capabilities for 2.0 sysfs
  lightnvm: add minor version to generic geometry
  lightnvm: rename number of channels and luns
  lightnvm: add shorten OCSSD version in geo
  lightnvm: rename sect_* to sec_*
  lightnvm: complete geo structure with maxoc*
  lightnvm: use generic identify structure
  lightnvm: pblk: rename ppaf* to addrf*
  lightnvm: pblk: check for supported version
  lightnvm: complete 2.0 values in sysfs
  lightnvm: add support for 2.0 address format
  lightnvm: make address conversions depend on generic device
  nvme: make nvme_get_log_ext available
  lightnvm: implement get log report chunk helpers
  lightnvm: define chunk states
  lightnvm: pblk: implement get log report chunk
  lightnvm: pblk: refactor init/exit sequences
  lightnvm: pblk: implement 2.0 support

 drivers/lightnvm/core.c          | 205 +++++-----
 drivers/lightnvm/pblk-core.c     | 141 +++++--
 drivers/lightnvm/pblk-gc.c       |   2 +-
 drivers/lightnvm/pblk-init.c     | 787 +++++++++++++++++++++++----------------
 drivers/lightnvm/pblk-read.c     |   2 +-
 drivers/lightnvm/pblk-recovery.c |  14 +-
 drivers/lightnvm/pblk-rl.c       |   2 +-
 drivers/lightnvm/pblk-sysfs.c    | 130 ++++++-
 drivers/lightnvm/pblk-write.c    |   2 +-
 drivers/lightnvm/pblk.h          | 253 +++++++++----
 drivers/nvme/host/lightnvm.c     | 480 ++++++++++++++++--------
 drivers/nvme/host/nvme.h         |   3 +
 include/linux/lightnvm.h         | 338 +++++++++++------
 13 files changed, 1546 insertions(+), 813 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH V2 00/20] lightnvm: pblk: implement 2.0 support
@ 2018-02-21  9:26 ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


Changes since V1:

Apply Matias' feedback:
  - Rebase on top of Matias' latest patches.
  - Use nvme_get_log_ext to submit report chunk and export it.
  - Re-write report chunk based on Matias' suggestions. Here, I
    maintained the lba interface, but it was necessary to redo the
    address formatting to match the chunk log page format. For pblk,
    this means a double address transformation, but it enables the
    standard path to use lbas, plus, this is not in the fast path.
  - Fold address format together with address transformations.
  - Split the generic geometry patch in different patches.
  - Remove refactoring of ligthnvm's core sysfs.

Feedback not applied:
  - Not letting pblk know about 1.2 and 2.0 bad block paths. Since the
    interfaces for get/set bad block and report chunk are so different,
    moving this logic to core adds assumptions on how the targets would
    want to get the data back. A way of doing this is creating a logical
    report chunk on the 1.2 path, but this would mean that values like
    the wear-index are invalid, which requires the target knowledge. I'm
    open to suggestions here.

Also:
  - Do some further renamings
  - Create a generic address format to make it explicit where we share
    1.2 and 2.0 fields to avoid address formatting in the fast path.
  - Add new fields to sysfs to complete spec and show major/minor
    versions (version and subversion to respect current interface).

Implement 2.0 support in pblk. This includes the address formatting and
mapping paths, as well as the sysfs entries for them.

Javier

Javier Gonz?lez (20):
  lightnvm: simplify geometry structure.
  lightnvm: add controller capabilities to 2.0
  lightnvm: fix capabilities for 2.0 sysfs
  lightnvm: add minor version to generic geometry
  lightnvm: rename number of channels and luns
  lightnvm: add shorten OCSSD version in geo
  lightnvm: rename sect_* to sec_*
  lightnvm: complete geo structure with maxoc*
  lightnvm: use generic identify structure
  lightnvm: pblk: rename ppaf* to addrf*
  lightnvm: pblk: check for supported version
  lightnvm: complete 2.0 values in sysfs
  lightnvm: add support for 2.0 address format
  lightnvm: make address conversions depend on generic device
  nvme: make nvme_get_log_ext available
  lightnvm: implement get log report chunk helpers
  lightnvm: define chunk states
  lightnvm: pblk: implement get log report chunk
  lightnvm: pblk: refactor init/exit sequences
  lightnvm: pblk: implement 2.0 support

 drivers/lightnvm/core.c          | 205 +++++-----
 drivers/lightnvm/pblk-core.c     | 141 +++++--
 drivers/lightnvm/pblk-gc.c       |   2 +-
 drivers/lightnvm/pblk-init.c     | 787 +++++++++++++++++++++++----------------
 drivers/lightnvm/pblk-read.c     |   2 +-
 drivers/lightnvm/pblk-recovery.c |  14 +-
 drivers/lightnvm/pblk-rl.c       |   2 +-
 drivers/lightnvm/pblk-sysfs.c    | 130 ++++++-
 drivers/lightnvm/pblk-write.c    |   2 +-
 drivers/lightnvm/pblk.h          | 253 +++++++++----
 drivers/nvme/host/lightnvm.c     | 480 ++++++++++++++++--------
 drivers/nvme/host/nvme.h         |   3 +
 include/linux/lightnvm.h         | 338 +++++++++++------
 13 files changed, 1546 insertions(+), 813 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 01/20] lightnvm: simplify geometry structure.
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

Currently, the device geometry is stored redundantly in the nvm_id and
nvm_geo structures at a device level. Moreover, when instantiating
targets on a specific number of LUNs, these structures are replicated
and manually modified to fit the instance channel and LUN partitioning.

Instead, create a generic geometry around two base structures:
nvm_dev_geo, which describes the geometry of the whole device and
nvm_geo, which describes the geometry of the instance. Since these share
a big part of the geometry, create a nvm_common_geo structure that keeps
the static geoometry values that are shared across instances.

As we introduce support for 2.0, these structures allow to abstract
spec. specific values and present a common geometry to targets.

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/lightnvm/core.c          | 137 +++++++---------
 drivers/lightnvm/pblk-core.c     |  16 +-
 drivers/lightnvm/pblk-gc.c       |   2 +-
 drivers/lightnvm/pblk-init.c     | 123 +++++++-------
 drivers/lightnvm/pblk-read.c     |   2 +-
 drivers/lightnvm/pblk-recovery.c |  14 +-
 drivers/lightnvm/pblk-rl.c       |   2 +-
 drivers/lightnvm/pblk-sysfs.c    |  39 +++--
 drivers/lightnvm/pblk-write.c    |   2 +-
 drivers/lightnvm/pblk.h          |  93 +++++------
 drivers/nvme/host/lightnvm.c     | 339 +++++++++++++++++++++++----------------
 include/linux/lightnvm.h         | 204 ++++++++++++-----------
 12 files changed, 514 insertions(+), 459 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 689c97b97775..42596afdf64c 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -111,6 +111,7 @@ static void nvm_release_luns_err(struct nvm_dev *dev, int lun_begin,
 static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
 {
 	struct nvm_dev *dev = tgt_dev->parent;
+	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
 	struct nvm_dev_map *dev_map = tgt_dev->map;
 	int i, j;
 
@@ -122,7 +123,7 @@ static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
 		if (clear) {
 			for (j = 0; j < ch_map->nr_luns; j++) {
 				int lun = j + lun_offs[j];
-				int lunid = (ch * dev->geo.nr_luns) + lun;
+				int lunid = (ch * dev_geo->nr_luns) + lun;
 
 				WARN_ON(!test_and_clear_bit(lunid,
 							dev->lun_map));
@@ -143,19 +144,20 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
 					      u16 lun_begin, u16 lun_end,
 					      u16 op)
 {
+	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
 	struct nvm_tgt_dev *tgt_dev = NULL;
 	struct nvm_dev_map *dev_rmap = dev->rmap;
 	struct nvm_dev_map *dev_map;
 	struct ppa_addr *luns;
 	int nr_luns = lun_end - lun_begin + 1;
 	int luns_left = nr_luns;
-	int nr_chnls = nr_luns / dev->geo.nr_luns;
-	int nr_chnls_mod = nr_luns % dev->geo.nr_luns;
-	int bch = lun_begin / dev->geo.nr_luns;
-	int blun = lun_begin % dev->geo.nr_luns;
+	int nr_chnls = nr_luns / dev_geo->nr_luns;
+	int nr_chnls_mod = nr_luns % dev_geo->nr_luns;
+	int bch = lun_begin / dev_geo->nr_luns;
+	int blun = lun_begin % dev_geo->nr_luns;
 	int lunid = 0;
 	int lun_balanced = 1;
-	int prev_nr_luns;
+	int sec_per_lun, prev_nr_luns;
 	int i, j;
 
 	nr_chnls = (nr_chnls_mod == 0) ? nr_chnls : nr_chnls + 1;
@@ -173,15 +175,15 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
 	if (!luns)
 		goto err_luns;
 
-	prev_nr_luns = (luns_left > dev->geo.nr_luns) ?
-					dev->geo.nr_luns : luns_left;
+	prev_nr_luns = (luns_left > dev_geo->nr_luns) ?
+					dev_geo->nr_luns : luns_left;
 	for (i = 0; i < nr_chnls; i++) {
 		struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[i + bch];
 		int *lun_roffs = ch_rmap->lun_offs;
 		struct nvm_ch_map *ch_map = &dev_map->chnls[i];
 		int *lun_offs;
-		int luns_in_chnl = (luns_left > dev->geo.nr_luns) ?
-					dev->geo.nr_luns : luns_left;
+		int luns_in_chnl = (luns_left > dev_geo->nr_luns) ?
+					dev_geo->nr_luns : luns_left;
 
 		if (lun_balanced && prev_nr_luns != luns_in_chnl)
 			lun_balanced = 0;
@@ -215,18 +217,22 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
 	if (!tgt_dev)
 		goto err_ch;
 
-	memcpy(&tgt_dev->geo, &dev->geo, sizeof(struct nvm_geo));
 	/* Target device only owns a portion of the physical device */
 	tgt_dev->geo.nr_chnls = nr_chnls;
-	tgt_dev->geo.all_luns = nr_luns;
 	tgt_dev->geo.nr_luns = (lun_balanced) ? prev_nr_luns : -1;
+	tgt_dev->geo.all_luns = nr_luns;
+	tgt_dev->geo.all_chunks = nr_luns * dev_geo->c.num_chk;
+
 	tgt_dev->geo.op = op;
-	tgt_dev->total_secs = nr_luns * tgt_dev->geo.sec_per_lun;
+
+	sec_per_lun = dev_geo->c.clba * dev_geo->c.num_chk;
+	tgt_dev->geo.total_secs = nr_luns * sec_per_lun;
+
+	tgt_dev->geo.c = dev_geo->c;
+
 	tgt_dev->q = dev->q;
 	tgt_dev->map = dev_map;
 	tgt_dev->luns = luns;
-	memcpy(&tgt_dev->identity, &dev->identity, sizeof(struct nvm_id));
-
 	tgt_dev->parent = dev;
 
 	return tgt_dev;
@@ -268,12 +274,12 @@ static struct nvm_tgt_type *nvm_find_target_type(const char *name)
 	return tt;
 }
 
-static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
+static int nvm_config_check_luns(struct nvm_dev_geo *dev_geo, int lun_begin,
 				 int lun_end)
 {
-	if (lun_begin > lun_end || lun_end >= geo->all_luns) {
+	if (lun_begin > lun_end || lun_end >= dev_geo->all_luns) {
 		pr_err("nvm: lun out of bound (%u:%u > %u)\n",
-			lun_begin, lun_end, geo->all_luns - 1);
+			lun_begin, lun_end, dev_geo->all_luns - 1);
 		return -EINVAL;
 	}
 
@@ -283,24 +289,24 @@ static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
 static int __nvm_config_simple(struct nvm_dev *dev,
 			       struct nvm_ioctl_create_simple *s)
 {
-	struct nvm_geo *geo = &dev->geo;
+	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
 
 	if (s->lun_begin == -1 && s->lun_end == -1) {
 		s->lun_begin = 0;
-		s->lun_end = geo->all_luns - 1;
+		s->lun_end = dev_geo->all_luns - 1;
 	}
 
-	return nvm_config_check_luns(geo, s->lun_begin, s->lun_end);
+	return nvm_config_check_luns(dev_geo, s->lun_begin, s->lun_end);
 }
 
 static int __nvm_config_extended(struct nvm_dev *dev,
 				 struct nvm_ioctl_create_extended *e)
 {
-	struct nvm_geo *geo = &dev->geo;
+	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
 
 	if (e->lun_begin == 0xFFFF && e->lun_end == 0xFFFF) {
 		e->lun_begin = 0;
-		e->lun_end = dev->geo.all_luns - 1;
+		e->lun_end = dev_geo->all_luns - 1;
 	}
 
 	/* op not set falls into target's default */
@@ -313,7 +319,7 @@ static int __nvm_config_extended(struct nvm_dev *dev,
 		return -EINVAL;
 	}
 
-	return nvm_config_check_luns(geo, e->lun_begin, e->lun_end);
+	return nvm_config_check_luns(dev_geo, e->lun_begin, e->lun_end);
 }
 
 static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
@@ -408,7 +414,7 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
 	tqueue->queuedata = targetdata;
 
 	blk_queue_max_hw_sectors(tqueue,
-			(dev->geo.sec_size >> 9) * NVM_MAX_VLBA);
+			(dev->dev_geo.c.csecs >> 9) * NVM_MAX_VLBA);
 
 	set_capacity(tdisk, tt->capacity(targetdata));
 	add_disk(tdisk);
@@ -497,6 +503,7 @@ static int nvm_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove)
 
 static int nvm_register_map(struct nvm_dev *dev)
 {
+	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
 	struct nvm_dev_map *rmap;
 	int i, j;
 
@@ -504,15 +511,15 @@ static int nvm_register_map(struct nvm_dev *dev)
 	if (!rmap)
 		goto err_rmap;
 
-	rmap->chnls = kcalloc(dev->geo.nr_chnls, sizeof(struct nvm_ch_map),
+	rmap->chnls = kcalloc(dev_geo->nr_chnls, sizeof(struct nvm_ch_map),
 								GFP_KERNEL);
 	if (!rmap->chnls)
 		goto err_chnls;
 
-	for (i = 0; i < dev->geo.nr_chnls; i++) {
+	for (i = 0; i < dev_geo->nr_chnls; i++) {
 		struct nvm_ch_map *ch_rmap;
 		int *lun_roffs;
-		int luns_in_chnl = dev->geo.nr_luns;
+		int luns_in_chnl = dev_geo->nr_luns;
 
 		ch_rmap = &rmap->chnls[i];
 
@@ -543,10 +550,11 @@ static int nvm_register_map(struct nvm_dev *dev)
 
 static void nvm_unregister_map(struct nvm_dev *dev)
 {
+	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
 	struct nvm_dev_map *rmap = dev->rmap;
 	int i;
 
-	for (i = 0; i < dev->geo.nr_chnls; i++)
+	for (i = 0; i < dev_geo->nr_chnls; i++)
 		kfree(rmap->chnls[i].lun_offs);
 
 	kfree(rmap->chnls);
@@ -675,7 +683,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
 	int i, plane_cnt, pl_idx;
 	struct ppa_addr ppa;
 
-	if (geo->plane_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
+	if (geo->c.pln_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
 		rqd->nr_ppas = nr_ppas;
 		rqd->ppa_addr = ppas[0];
 
@@ -689,7 +697,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
 		return -ENOMEM;
 	}
 
-	plane_cnt = geo->plane_mode;
+	plane_cnt = geo->c.pln_mode;
 	rqd->nr_ppas *= plane_cnt;
 
 	for (i = 0; i < nr_ppas; i++) {
@@ -804,18 +812,18 @@ EXPORT_SYMBOL(nvm_end_io);
  */
 int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
 {
-	struct nvm_geo *geo = &dev->geo;
+	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
 	int blk, offset, pl, blktype;
 
-	if (nr_blks != geo->nr_chks * geo->plane_mode)
+	if (nr_blks != dev_geo->c.num_chk * dev_geo->c.pln_mode)
 		return -EINVAL;
 
-	for (blk = 0; blk < geo->nr_chks; blk++) {
-		offset = blk * geo->plane_mode;
+	for (blk = 0; blk < dev_geo->c.num_chk; blk++) {
+		offset = blk * dev_geo->c.pln_mode;
 		blktype = blks[offset];
 
 		/* Bad blocks on any planes take precedence over other types */
-		for (pl = 0; pl < geo->plane_mode; pl++) {
+		for (pl = 0; pl < dev_geo->c.pln_mode; pl++) {
 			if (blks[offset + pl] &
 					(NVM_BLK_T_BAD|NVM_BLK_T_GRWN_BAD)) {
 				blktype = blks[offset + pl];
@@ -826,7 +834,7 @@ int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
 		blks[blk] = blktype;
 	}
 
-	return geo->nr_chks;
+	return dev_geo->c.num_chk;
 }
 EXPORT_SYMBOL(nvm_bb_tbl_fold);
 
@@ -843,41 +851,10 @@ EXPORT_SYMBOL(nvm_get_tgt_bb_tbl);
 
 static int nvm_core_init(struct nvm_dev *dev)
 {
-	struct nvm_id *id = &dev->identity;
-	struct nvm_geo *geo = &dev->geo;
+	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
 	int ret;
 
-	memcpy(&geo->ppaf, &id->ppaf, sizeof(struct nvm_addr_format));
-
-	if (id->mtype != 0) {
-		pr_err("nvm: memory type not supported\n");
-		return -EINVAL;
-	}
-
-	/* Whole device values */
-	geo->nr_chnls = id->num_ch;
-	geo->nr_luns = id->num_lun;
-
-	/* Generic device geometry values */
-	geo->ws_min = id->ws_min;
-	geo->ws_opt = id->ws_opt;
-	geo->ws_seq = id->ws_seq;
-	geo->ws_per_chk = id->ws_per_chk;
-	geo->nr_chks = id->num_chk;
-	geo->mccap = id->mccap;
-
-	geo->sec_per_chk = id->clba;
-	geo->sec_per_lun = geo->sec_per_chk * geo->nr_chks;
-	geo->all_luns = geo->nr_luns * geo->nr_chnls;
-
-	/* 1.2 spec device geometry values */
-	geo->plane_mode = 1 << geo->ws_seq;
-	geo->nr_planes = geo->ws_opt / geo->ws_min;
-	geo->sec_per_pg = geo->ws_min;
-	geo->sec_per_pl = geo->sec_per_pg * geo->nr_planes;
-
-	dev->total_secs = geo->all_luns * geo->sec_per_lun;
-	dev->lun_map = kcalloc(BITS_TO_LONGS(geo->all_luns),
+	dev->lun_map = kcalloc(BITS_TO_LONGS(dev_geo->all_luns),
 					sizeof(unsigned long), GFP_KERNEL);
 	if (!dev->lun_map)
 		return -ENOMEM;
@@ -912,19 +889,17 @@ static void nvm_free(struct nvm_dev *dev)
 
 static int nvm_init(struct nvm_dev *dev)
 {
-	struct nvm_geo *geo = &dev->geo;
+	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
 	int ret = -EINVAL;
 
-	if (dev->ops->identity(dev, &dev->identity)) {
+	if (dev->ops->identity(dev)) {
 		pr_err("nvm: device could not be identified\n");
 		goto err;
 	}
 
-	if (dev->identity.ver_id != 1 && dev->identity.ver_id != 2) {
-		pr_err("nvm: device ver_id %d not supported by kernel.\n",
-				dev->identity.ver_id);
-		goto err;
-	}
+	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
+				dev_geo->ver_id,
+				dev_geo->c.vmnt);
 
 	ret = nvm_core_init(dev);
 	if (ret) {
@@ -932,10 +907,10 @@ static int nvm_init(struct nvm_dev *dev)
 		goto err;
 	}
 
-	pr_info("nvm: registered %s [%u/%u/%u/%u/%u/%u]\n",
-			dev->name, geo->sec_per_pg, geo->nr_planes,
-			geo->ws_per_chk, geo->nr_chks,
-			geo->all_luns, geo->nr_chnls);
+	pr_info("nvm: registered %s [%u/%u/%u/%u/%u]\n",
+			dev->name, dev_geo->c.ws_min, dev_geo->c.ws_opt,
+			dev_geo->c.num_chk, dev_geo->all_luns,
+			dev_geo->nr_chnls);
 	return 0;
 err:
 	pr_err("nvm: failed to initialize nvm\n");
diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index 22e61cd4f801..519af8b9eab7 100644
--- a/drivers/lightnvm/pblk-core.c
+++ b/drivers/lightnvm/pblk-core.c
@@ -613,7 +613,7 @@ static int pblk_line_submit_emeta_io(struct pblk *pblk, struct pblk_line *line,
 	memset(&rqd, 0, sizeof(struct nvm_rq));
 
 	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
-	rq_len = rq_ppas * geo->sec_size;
+	rq_len = rq_ppas * geo->c.csecs;
 
 	bio = pblk_bio_map_addr(pblk, emeta_buf, rq_ppas, rq_len,
 					l_mg->emeta_alloc_type, GFP_KERNEL);
@@ -722,7 +722,7 @@ u64 pblk_line_smeta_start(struct pblk *pblk, struct pblk_line *line)
 	if (bit >= lm->blk_per_line)
 		return -1;
 
-	return bit * geo->sec_per_pl;
+	return bit * geo->c.ws_opt;
 }
 
 static int pblk_line_submit_smeta_io(struct pblk *pblk, struct pblk_line *line,
@@ -1035,19 +1035,19 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
 	/* Capture bad block information on line mapping bitmaps */
 	while ((bit = find_next_bit(line->blk_bitmap, lm->blk_per_line,
 					bit + 1)) < lm->blk_per_line) {
-		off = bit * geo->sec_per_pl;
+		off = bit * geo->c.ws_opt;
 		bitmap_shift_left(l_mg->bb_aux, l_mg->bb_template, off,
 							lm->sec_per_line);
 		bitmap_or(line->map_bitmap, line->map_bitmap, l_mg->bb_aux,
 							lm->sec_per_line);
-		line->sec_in_line -= geo->sec_per_chk;
+		line->sec_in_line -= geo->c.clba;
 		if (bit >= lm->emeta_bb)
 			nr_bb++;
 	}
 
 	/* Mark smeta metadata sectors as bad sectors */
 	bit = find_first_zero_bit(line->blk_bitmap, lm->blk_per_line);
-	off = bit * geo->sec_per_pl;
+	off = bit * geo->c.ws_opt;
 	bitmap_set(line->map_bitmap, off, lm->smeta_sec);
 	line->sec_in_line -= lm->smeta_sec;
 	line->smeta_ssec = off;
@@ -1066,10 +1066,10 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
 	emeta_secs = lm->emeta_sec[0];
 	off = lm->sec_per_line;
 	while (emeta_secs) {
-		off -= geo->sec_per_pl;
+		off -= geo->c.ws_opt;
 		if (!test_bit(off, line->invalid_bitmap)) {
-			bitmap_set(line->invalid_bitmap, off, geo->sec_per_pl);
-			emeta_secs -= geo->sec_per_pl;
+			bitmap_set(line->invalid_bitmap, off, geo->c.ws_opt);
+			emeta_secs -= geo->c.ws_opt;
 		}
 	}
 
diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c
index 320f99af99e9..16afea3f5541 100644
--- a/drivers/lightnvm/pblk-gc.c
+++ b/drivers/lightnvm/pblk-gc.c
@@ -88,7 +88,7 @@ static void pblk_gc_line_ws(struct work_struct *work)
 
 	up(&gc->gc_sem);
 
-	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->sec_size);
+	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->c.csecs);
 	if (!gc_rq->data) {
 		pr_err("pblk: could not GC line:%d (%d/%d)\n",
 					line->id, *line->vsc, gc_rq->nr_secs);
diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 5261702e9ff7..95ecb0ec736b 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -146,7 +146,7 @@ static int pblk_rwb_init(struct pblk *pblk)
 		return -ENOMEM;
 
 	power_size = get_count_order(nr_entries);
-	power_seg_sz = get_count_order(geo->sec_size);
+	power_seg_sz = get_count_order(geo->c.csecs);
 
 	return pblk_rb_init(&pblk->rwb, entries, power_size, power_seg_sz);
 }
@@ -154,11 +154,11 @@ static int pblk_rwb_init(struct pblk *pblk)
 /* Minimum pages needed within a lun */
 #define ADDR_POOL_SIZE 64
 
-static int pblk_set_ppaf(struct pblk *pblk)
+static int pblk_set_addrf_12(struct nvm_geo *geo,
+			     struct nvm_addr_format_12 *dst)
 {
-	struct nvm_tgt_dev *dev = pblk->dev;
-	struct nvm_geo *geo = &dev->geo;
-	struct nvm_addr_format ppaf = geo->ppaf;
+	struct nvm_addr_format_12 *src =
+				(struct nvm_addr_format_12 *)&geo->c.addrf;
 	int power_len;
 
 	/* Re-calculate channel and lun format to adapt to configuration */
@@ -167,34 +167,50 @@ static int pblk_set_ppaf(struct pblk *pblk)
 		pr_err("pblk: supports only power-of-two channel config.\n");
 		return -EINVAL;
 	}
-	ppaf.ch_len = power_len;
+	dst->ch_len = power_len;
 
 	power_len = get_count_order(geo->nr_luns);
 	if (1 << power_len != geo->nr_luns) {
 		pr_err("pblk: supports only power-of-two LUN config.\n");
 		return -EINVAL;
 	}
-	ppaf.lun_len = power_len;
+	dst->lun_len = power_len;
 
-	pblk->ppaf.sec_offset = 0;
-	pblk->ppaf.pln_offset = ppaf.sect_len;
-	pblk->ppaf.ch_offset = pblk->ppaf.pln_offset + ppaf.pln_len;
-	pblk->ppaf.lun_offset = pblk->ppaf.ch_offset + ppaf.ch_len;
-	pblk->ppaf.pg_offset = pblk->ppaf.lun_offset + ppaf.lun_len;
-	pblk->ppaf.blk_offset = pblk->ppaf.pg_offset + ppaf.pg_len;
-	pblk->ppaf.sec_mask = (1ULL << ppaf.sect_len) - 1;
-	pblk->ppaf.pln_mask = ((1ULL << ppaf.pln_len) - 1) <<
-							pblk->ppaf.pln_offset;
-	pblk->ppaf.ch_mask = ((1ULL << ppaf.ch_len) - 1) <<
-							pblk->ppaf.ch_offset;
-	pblk->ppaf.lun_mask = ((1ULL << ppaf.lun_len) - 1) <<
-							pblk->ppaf.lun_offset;
-	pblk->ppaf.pg_mask = ((1ULL << ppaf.pg_len) - 1) <<
-							pblk->ppaf.pg_offset;
-	pblk->ppaf.blk_mask = ((1ULL << ppaf.blk_len) - 1) <<
-							pblk->ppaf.blk_offset;
+	dst->blk_len = src->blk_len;
+	dst->pg_len = src->pg_len;
+	dst->pln_len = src->pln_len;
+	dst->sect_len = src->sect_len;
 
-	pblk->ppaf_bitsize = pblk->ppaf.blk_offset + ppaf.blk_len;
+	dst->sect_offset = 0;
+	dst->pln_offset = dst->sect_len;
+	dst->ch_offset = dst->pln_offset + dst->pln_len;
+	dst->lun_offset = dst->ch_offset + dst->ch_len;
+	dst->pg_offset = dst->lun_offset + dst->lun_len;
+	dst->blk_offset = dst->pg_offset + dst->pg_len;
+
+	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
+	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
+	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
+	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
+	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
+	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
+
+	return dst->blk_offset + src->blk_len;
+}
+
+static int pblk_set_ppaf(struct pblk *pblk)
+{
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	int mod;
+
+	div_u64_rem(geo->c.clba, pblk->min_write_pgs, &mod);
+	if (mod) {
+		pr_err("pblk: bad configuration of sectors/pages\n");
+		return -EINVAL;
+	}
+
+	pblk->ppaf_bitsize = pblk_set_addrf_12(geo, (void *)&pblk->ppaf);
 
 	return 0;
 }
@@ -253,8 +269,7 @@ static int pblk_core_init(struct pblk *pblk)
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
 
-	pblk->pgs_in_buffer = NVM_MEM_PAGE_WRITE * geo->sec_per_pg *
-						geo->nr_planes * geo->all_luns;
+	pblk->pgs_in_buffer = geo->c.mw_cunits * geo->c.ws_opt * geo->all_luns;
 
 	if (pblk_init_global_caches(pblk))
 		return -ENOMEM;
@@ -433,7 +448,7 @@ static void *pblk_bb_get_log(struct pblk *pblk)
 	int i, nr_blks, blk_per_lun;
 	int ret;
 
-	blk_per_lun = geo->nr_chks * geo->plane_mode;
+	blk_per_lun = geo->c.num_chk * geo->c.pln_mode;
 	nr_blks = blk_per_lun * geo->all_luns;
 
 	log = kmalloc(nr_blks, GFP_KERNEL);
@@ -551,18 +566,18 @@ static unsigned int calc_emeta_len(struct pblk *pblk)
 	/* Round to sector size so that lba_list starts on its own sector */
 	lm->emeta_sec[1] = DIV_ROUND_UP(
 			sizeof(struct line_emeta) + lm->blk_bitmap_len +
-			sizeof(struct wa_counters), geo->sec_size);
-	lm->emeta_len[1] = lm->emeta_sec[1] * geo->sec_size;
+			sizeof(struct wa_counters), geo->c.csecs);
+	lm->emeta_len[1] = lm->emeta_sec[1] * geo->c.csecs;
 
 	/* Round to sector size so that vsc_list starts on its own sector */
 	lm->dsec_per_line = lm->sec_per_line - lm->emeta_sec[0];
 	lm->emeta_sec[2] = DIV_ROUND_UP(lm->dsec_per_line * sizeof(u64),
-			geo->sec_size);
-	lm->emeta_len[2] = lm->emeta_sec[2] * geo->sec_size;
+			geo->c.csecs);
+	lm->emeta_len[2] = lm->emeta_sec[2] * geo->c.csecs;
 
 	lm->emeta_sec[3] = DIV_ROUND_UP(l_mg->nr_lines * sizeof(u32),
-			geo->sec_size);
-	lm->emeta_len[3] = lm->emeta_sec[3] * geo->sec_size;
+			geo->c.csecs);
+	lm->emeta_len[3] = lm->emeta_sec[3] * geo->c.csecs;
 
 	lm->vsc_list_len = l_mg->nr_lines * sizeof(u32);
 
@@ -593,13 +608,13 @@ static void pblk_set_provision(struct pblk *pblk, long nr_free_blks)
 	 * on user capacity consider only provisioned blocks
 	 */
 	pblk->rl.total_blocks = nr_free_blks;
-	pblk->rl.nr_secs = nr_free_blks * geo->sec_per_chk;
+	pblk->rl.nr_secs = nr_free_blks * geo->c.clba;
 
 	/* Consider sectors used for metadata */
 	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
-	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
+	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
 
-	pblk->capacity = (provisioned - blk_meta) * geo->sec_per_chk;
+	pblk->capacity = (provisioned - blk_meta) * geo->c.clba;
 
 	atomic_set(&pblk->rl.free_blocks, nr_free_blks);
 	atomic_set(&pblk->rl.free_user_blocks, nr_free_blks);
@@ -710,10 +725,10 @@ static int pblk_lines_init(struct pblk *pblk)
 	void *chunk_log;
 	unsigned int smeta_len, emeta_len;
 	long nr_bad_blks = 0, nr_free_blks = 0;
-	int bb_distance, max_write_ppas, mod;
+	int bb_distance, max_write_ppas;
 	int i, ret;
 
-	pblk->min_write_pgs = geo->sec_per_pl * (geo->sec_size / PAGE_SIZE);
+	pblk->min_write_pgs = geo->c.ws_opt * (geo->c.csecs / PAGE_SIZE);
 	max_write_ppas = pblk->min_write_pgs * geo->all_luns;
 	pblk->max_write_pgs = min_t(int, max_write_ppas, NVM_MAX_VLBA);
 	pblk_set_sec_per_write(pblk, pblk->min_write_pgs);
@@ -724,19 +739,13 @@ static int pblk_lines_init(struct pblk *pblk)
 		return -EINVAL;
 	}
 
-	div_u64_rem(geo->sec_per_chk, pblk->min_write_pgs, &mod);
-	if (mod) {
-		pr_err("pblk: bad configuration of sectors/pages\n");
-		return -EINVAL;
-	}
-
-	l_mg->nr_lines = geo->nr_chks;
+	l_mg->nr_lines = geo->c.num_chk;
 	l_mg->log_line = l_mg->data_line = NULL;
 	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
 	l_mg->nr_free_lines = 0;
 	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
 
-	lm->sec_per_line = geo->sec_per_chk * geo->all_luns;
+	lm->sec_per_line = geo->c.clba * geo->all_luns;
 	lm->blk_per_line = geo->all_luns;
 	lm->blk_bitmap_len = BITS_TO_LONGS(geo->all_luns) * sizeof(long);
 	lm->sec_bitmap_len = BITS_TO_LONGS(lm->sec_per_line) * sizeof(long);
@@ -750,8 +759,8 @@ static int pblk_lines_init(struct pblk *pblk)
 	 */
 	i = 1;
 add_smeta_page:
-	lm->smeta_sec = i * geo->sec_per_pl;
-	lm->smeta_len = lm->smeta_sec * geo->sec_size;
+	lm->smeta_sec = i * geo->c.ws_opt;
+	lm->smeta_len = lm->smeta_sec * geo->c.csecs;
 
 	smeta_len = sizeof(struct line_smeta) + lm->lun_bitmap_len;
 	if (smeta_len > lm->smeta_len) {
@@ -764,8 +773,8 @@ static int pblk_lines_init(struct pblk *pblk)
 	 */
 	i = 1;
 add_emeta_page:
-	lm->emeta_sec[0] = i * geo->sec_per_pl;
-	lm->emeta_len[0] = lm->emeta_sec[0] * geo->sec_size;
+	lm->emeta_sec[0] = i * geo->c.ws_opt;
+	lm->emeta_len[0] = lm->emeta_sec[0] * geo->c.csecs;
 
 	emeta_len = calc_emeta_len(pblk);
 	if (emeta_len > lm->emeta_len[0]) {
@@ -778,7 +787,7 @@ static int pblk_lines_init(struct pblk *pblk)
 	lm->min_blk_line = 1;
 	if (geo->all_luns > 1)
 		lm->min_blk_line += DIV_ROUND_UP(lm->smeta_sec +
-					lm->emeta_sec[0], geo->sec_per_chk);
+					lm->emeta_sec[0], geo->c.clba);
 
 	if (lm->min_blk_line > lm->blk_per_line) {
 		pr_err("pblk: config. not supported. Min. LUN in line:%d\n",
@@ -802,9 +811,9 @@ static int pblk_lines_init(struct pblk *pblk)
 		goto fail_free_bb_template;
 	}
 
-	bb_distance = (geo->all_luns) * geo->sec_per_pl;
+	bb_distance = (geo->all_luns) * geo->c.ws_opt;
 	for (i = 0; i < lm->sec_per_line; i += bb_distance)
-		bitmap_set(l_mg->bb_template, i, geo->sec_per_pl);
+		bitmap_set(l_mg->bb_template, i, geo->c.ws_opt);
 
 	INIT_LIST_HEAD(&l_mg->free_list);
 	INIT_LIST_HEAD(&l_mg->corrupt_list);
@@ -981,9 +990,9 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 	struct pblk *pblk;
 	int ret;
 
-	if (dev->identity.dom & NVM_RSP_L2P) {
+	if (dev->geo.c.dom & NVM_RSP_L2P) {
 		pr_err("pblk: host-side L2P table not supported. (%x)\n",
-							dev->identity.dom);
+							dev->geo.c.dom);
 		return ERR_PTR(-EINVAL);
 	}
 
@@ -1091,7 +1100,7 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 
 	blk_queue_write_cache(tqueue, true, false);
 
-	tqueue->limits.discard_granularity = geo->sec_per_chk * geo->sec_size;
+	tqueue->limits.discard_granularity = geo->c.clba * geo->c.csecs;
 	tqueue->limits.discard_alignment = 0;
 	blk_queue_max_discard_sectors(tqueue, UINT_MAX >> 9);
 	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, tqueue);
diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c
index 2f761283f43e..ebb6bae3a3b8 100644
--- a/drivers/lightnvm/pblk-read.c
+++ b/drivers/lightnvm/pblk-read.c
@@ -563,7 +563,7 @@ int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq)
 	if (!(gc_rq->secs_to_gc))
 		goto out;
 
-	data_len = (gc_rq->secs_to_gc) * geo->sec_size;
+	data_len = (gc_rq->secs_to_gc) * geo->c.csecs;
 	bio = pblk_bio_map_addr(pblk, gc_rq->data, gc_rq->secs_to_gc, data_len,
 						PBLK_VMALLOC_META, GFP_KERNEL);
 	if (IS_ERR(bio)) {
diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
index aaab9a5c17cc..1574dbbfbb1c 100644
--- a/drivers/lightnvm/pblk-recovery.c
+++ b/drivers/lightnvm/pblk-recovery.c
@@ -184,7 +184,7 @@ static int pblk_calc_sec_in_line(struct pblk *pblk, struct pblk_line *line)
 	int nr_bb = bitmap_weight(line->blk_bitmap, lm->blk_per_line);
 
 	return lm->sec_per_line - lm->smeta_sec - lm->emeta_sec[0] -
-				nr_bb * geo->sec_per_chk;
+				nr_bb * geo->c.clba;
 }
 
 struct pblk_recov_alloc {
@@ -232,7 +232,7 @@ static int pblk_recov_read_oob(struct pblk *pblk, struct pblk_line *line,
 	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
 	if (!rq_ppas)
 		rq_ppas = pblk->min_write_pgs;
-	rq_len = rq_ppas * geo->sec_size;
+	rq_len = rq_ppas * geo->c.csecs;
 
 	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
 	if (IS_ERR(bio))
@@ -351,7 +351,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
 	if (!pad_rq)
 		return -ENOMEM;
 
-	data = vzalloc(pblk->max_write_pgs * geo->sec_size);
+	data = vzalloc(pblk->max_write_pgs * geo->c.csecs);
 	if (!data) {
 		ret = -ENOMEM;
 		goto free_rq;
@@ -368,7 +368,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
 		goto fail_free_pad;
 	}
 
-	rq_len = rq_ppas * geo->sec_size;
+	rq_len = rq_ppas * geo->c.csecs;
 
 	meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, &dma_meta_list);
 	if (!meta_list) {
@@ -509,7 +509,7 @@ static int pblk_recov_scan_all_oob(struct pblk *pblk, struct pblk_line *line,
 	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
 	if (!rq_ppas)
 		rq_ppas = pblk->min_write_pgs;
-	rq_len = rq_ppas * geo->sec_size;
+	rq_len = rq_ppas * geo->c.csecs;
 
 	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
 	if (IS_ERR(bio))
@@ -640,7 +640,7 @@ static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line,
 	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
 	if (!rq_ppas)
 		rq_ppas = pblk->min_write_pgs;
-	rq_len = rq_ppas * geo->sec_size;
+	rq_len = rq_ppas * geo->c.csecs;
 
 	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
 	if (IS_ERR(bio))
@@ -745,7 +745,7 @@ static int pblk_recov_l2p_from_oob(struct pblk *pblk, struct pblk_line *line)
 	ppa_list = (void *)(meta_list) + pblk_dma_meta_size;
 	dma_ppa_list = dma_meta_list + pblk_dma_meta_size;
 
-	data = kcalloc(pblk->max_write_pgs, geo->sec_size, GFP_KERNEL);
+	data = kcalloc(pblk->max_write_pgs, geo->c.csecs, GFP_KERNEL);
 	if (!data) {
 		ret = -ENOMEM;
 		goto free_meta_list;
diff --git a/drivers/lightnvm/pblk-rl.c b/drivers/lightnvm/pblk-rl.c
index 0d457b162f23..bcab203477ec 100644
--- a/drivers/lightnvm/pblk-rl.c
+++ b/drivers/lightnvm/pblk-rl.c
@@ -200,7 +200,7 @@ void pblk_rl_init(struct pblk_rl *rl, int budget)
 
 	/* Consider sectors used for metadata */
 	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
-	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
+	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
 
 	rl->high = pblk->op_blks - blk_meta - lm->blk_per_line;
 	rl->high_pw = get_count_order(rl->high);
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index d93e9b1f083a..5eb21a279361 100644
--- a/drivers/lightnvm/pblk-sysfs.c
+++ b/drivers/lightnvm/pblk-sysfs.c
@@ -113,26 +113,31 @@ 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;
 
-	sz = snprintf(page, PAGE_SIZE - sz,
-		"g:(b:%d)blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
-		pblk->ppaf_bitsize,
-		pblk->ppaf.blk_offset, geo->ppaf.blk_len,
-		pblk->ppaf.pg_offset, geo->ppaf.pg_len,
-		pblk->ppaf.lun_offset, geo->ppaf.lun_len,
-		pblk->ppaf.ch_offset, geo->ppaf.ch_len,
-		pblk->ppaf.pln_offset, geo->ppaf.pln_len,
-		pblk->ppaf.sec_offset, geo->ppaf.sect_len);
+	ppaf = (struct nvm_addr_format_12 *)&pblk->ppaf;
+	geo_ppaf = (struct nvm_addr_format_12 *)&geo->c.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",
+			pblk->ppaf_bitsize,
+			ppaf->ch_offset, ppaf->ch_len,
+			ppaf->lun_offset, ppaf->lun_len,
+			ppaf->blk_offset, ppaf->blk_len,
+			ppaf->pg_offset, ppaf->pg_len,
+			ppaf->pln_offset, ppaf->pln_len,
+			ppaf->sect_offset, ppaf->sect_len);
 
 	sz += snprintf(page + sz, PAGE_SIZE - sz,
-		"d:blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
-		geo->ppaf.blk_offset, geo->ppaf.blk_len,
-		geo->ppaf.pg_offset, geo->ppaf.pg_len,
-		geo->ppaf.lun_offset, geo->ppaf.lun_len,
-		geo->ppaf.ch_offset, geo->ppaf.ch_len,
-		geo->ppaf.pln_offset, geo->ppaf.pln_len,
-		geo->ppaf.sect_offset, geo->ppaf.sect_len);
+		"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->sect_offset, geo_ppaf->sect_len);
 
 	return sz;
 }
@@ -288,7 +293,7 @@ static ssize_t pblk_sysfs_lines_info(struct pblk *pblk, char *page)
 				"blk_line:%d, sec_line:%d, sec_blk:%d\n",
 					lm->blk_per_line,
 					lm->sec_per_line,
-					geo->sec_per_chk);
+					geo->c.clba);
 
 	return sz;
 }
diff --git a/drivers/lightnvm/pblk-write.c b/drivers/lightnvm/pblk-write.c
index aae86ed60b98..c49b27539d5a 100644
--- a/drivers/lightnvm/pblk-write.c
+++ b/drivers/lightnvm/pblk-write.c
@@ -333,7 +333,7 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line)
 	m_ctx = nvm_rq_to_pdu(rqd);
 	m_ctx->private = meta_line;
 
-	rq_len = rq_ppas * geo->sec_size;
+	rq_len = rq_ppas * geo->c.csecs;
 	data = ((void *)emeta->buf) + emeta->mem;
 
 	bio = pblk_bio_map_addr(pblk, data, rq_ppas, rq_len,
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 282dfc8780e8..67ffb53608f7 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -551,21 +551,6 @@ struct pblk_line_meta {
 	unsigned int meta_distance;	/* Distance between data and metadata */
 };
 
-struct pblk_addr_format {
-	u64	ch_mask;
-	u64	lun_mask;
-	u64	pln_mask;
-	u64	blk_mask;
-	u64	pg_mask;
-	u64	sec_mask;
-	u8	ch_offset;
-	u8	lun_offset;
-	u8	pln_offset;
-	u8	blk_offset;
-	u8	pg_offset;
-	u8	sec_offset;
-};
-
 enum {
 	PBLK_STATE_RUNNING = 0,
 	PBLK_STATE_STOPPING = 1,
@@ -585,8 +570,8 @@ struct pblk {
 	struct pblk_line_mgmt l_mg;		/* Line management */
 	struct pblk_line_meta lm;		/* Line metadata */
 
+	struct nvm_addr_format ppaf;
 	int ppaf_bitsize;
-	struct pblk_addr_format ppaf;
 
 	struct pblk_rb rwb;
 
@@ -941,14 +926,12 @@ static inline int pblk_line_vsc(struct pblk_line *line)
 	return le32_to_cpu(*line->vsc);
 }
 
-#define NVM_MEM_PAGE_WRITE (8)
-
 static inline int pblk_pad_distance(struct pblk *pblk)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
 
-	return NVM_MEM_PAGE_WRITE * geo->all_luns * geo->sec_per_pl;
+	return geo->c.mw_cunits * geo->all_luns * geo->c.ws_opt;
 }
 
 static inline int pblk_ppa_to_line(struct ppa_addr p)
@@ -964,15 +947,17 @@ 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->ppaf;
 	struct ppa_addr ppa;
 
 	ppa.ppa = 0;
 	ppa.g.blk = line_id;
-	ppa.g.pg = (paddr & pblk->ppaf.pg_mask) >> pblk->ppaf.pg_offset;
-	ppa.g.lun = (paddr & pblk->ppaf.lun_mask) >> pblk->ppaf.lun_offset;
-	ppa.g.ch = (paddr & pblk->ppaf.ch_mask) >> pblk->ppaf.ch_offset;
-	ppa.g.pl = (paddr & pblk->ppaf.pln_mask) >> pblk->ppaf.pln_offset;
-	ppa.g.sec = (paddr & pblk->ppaf.sec_mask) >> pblk->ppaf.sec_offset;
+	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->sect_offset;
 
 	return ppa;
 }
@@ -980,13 +965,15 @@ 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->ppaf;
 	u64 paddr;
 
-	paddr = (u64)p.g.pg << pblk->ppaf.pg_offset;
-	paddr |= (u64)p.g.lun << pblk->ppaf.lun_offset;
-	paddr |= (u64)p.g.ch << pblk->ppaf.ch_offset;
-	paddr |= (u64)p.g.pl << pblk->ppaf.pln_offset;
-	paddr |= (u64)p.g.sec << pblk->ppaf.sec_offset;
+	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->sect_offset;
 
 	return paddr;
 }
@@ -1003,18 +990,15 @@ 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 {
-		ppa64.g.blk = (ppa32 & pblk->ppaf.blk_mask) >>
-							pblk->ppaf.blk_offset;
-		ppa64.g.pg = (ppa32 & pblk->ppaf.pg_mask) >>
-							pblk->ppaf.pg_offset;
-		ppa64.g.lun = (ppa32 & pblk->ppaf.lun_mask) >>
-							pblk->ppaf.lun_offset;
-		ppa64.g.ch = (ppa32 & pblk->ppaf.ch_mask) >>
-							pblk->ppaf.ch_offset;
-		ppa64.g.pl = (ppa32 & pblk->ppaf.pln_mask) >>
-							pblk->ppaf.pln_offset;
-		ppa64.g.sec = (ppa32 & pblk->ppaf.sec_mask) >>
-							pblk->ppaf.sec_offset;
+		struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&pblk->ppaf;
+
+		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->sect_offset;
 	}
 
 	return ppa64;
@@ -1030,12 +1014,15 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
 		ppa32 |= ppa64.c.line;
 		ppa32 |= 1U << 31;
 	} else {
-		ppa32 |= ppa64.g.blk << pblk->ppaf.blk_offset;
-		ppa32 |= ppa64.g.pg << pblk->ppaf.pg_offset;
-		ppa32 |= ppa64.g.lun << pblk->ppaf.lun_offset;
-		ppa32 |= ppa64.g.ch << pblk->ppaf.ch_offset;
-		ppa32 |= ppa64.g.pl << pblk->ppaf.pln_offset;
-		ppa32 |= ppa64.g.sec << pblk->ppaf.sec_offset;
+		struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&pblk->ppaf;
+
+		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->sect_offset;
 	}
 
 	return ppa32;
@@ -1153,7 +1140,7 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type)
 	struct nvm_geo *geo = &dev->geo;
 	int flags;
 
-	flags = geo->plane_mode >> 1;
+	flags = geo->c.pln_mode >> 1;
 
 	if (type == PBLK_WRITE)
 		flags |= NVM_IO_SCRAMBLE_ENABLE;
@@ -1174,7 +1161,7 @@ static inline int pblk_set_read_mode(struct pblk *pblk, int type)
 
 	flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
 	if (type == PBLK_READ_SEQUENTIAL)
-		flags |= geo->plane_mode >> 1;
+		flags |= geo->c.pln_mode >> 1;
 
 	return flags;
 }
@@ -1229,10 +1216,10 @@ static inline int pblk_boundary_ppa_checks(struct nvm_tgt_dev *tgt_dev,
 		if (!ppa->c.is_cached &&
 				ppa->g.ch < geo->nr_chnls &&
 				ppa->g.lun < geo->nr_luns &&
-				ppa->g.pl < geo->nr_planes &&
-				ppa->g.blk < geo->nr_chks &&
-				ppa->g.pg < geo->ws_per_chk &&
-				ppa->g.sec < geo->sec_per_pg)
+				ppa->g.pl < geo->c.num_pln &&
+				ppa->g.blk < geo->c.num_chk &&
+				ppa->g.pg < geo->c.num_pg &&
+				ppa->g.sec < geo->c.ws_min)
 			continue;
 
 		print_ppa(ppa, "boundary", i);
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 839c0b96466a..c81e64cc20d7 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -152,8 +152,8 @@ struct nvme_nvm_id12_addrf {
 	__u8			blk_len;
 	__u8			pg_offset;
 	__u8			pg_len;
-	__u8			sect_offset;
-	__u8			sect_len;
+	__u8			sec_offset;
+	__u8			sec_len;
 	__u8			res[4];
 } __packed;
 
@@ -254,106 +254,157 @@ static inline void _nvme_nvm_check_size(void)
 	BUILD_BUG_ON(sizeof(struct nvme_nvm_id20) != NVME_IDENTIFY_DATA_SIZE);
 }
 
-static int init_grp(struct nvm_id *nvm_id, struct nvme_nvm_id12 *id12)
+static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
+				 struct nvme_nvm_id12_addrf *src)
+{
+	dst->ch_len = src->ch_len;
+	dst->lun_len = src->lun_len;
+	dst->blk_len = src->blk_len;
+	dst->pg_len = src->pg_len;
+	dst->pln_len = src->pln_len;
+	dst->sect_len = src->sec_len;
+
+	dst->ch_offset = src->ch_offset;
+	dst->lun_offset = src->lun_offset;
+	dst->blk_offset = src->blk_offset;
+	dst->pg_offset = src->pg_offset;
+	dst->pln_offset = src->pln_offset;
+	dst->sect_offset = src->sec_offset;
+
+	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
+	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
+	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
+	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
+	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
+	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
+}
+
+static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
+			     struct nvm_dev_geo *dev_geo)
 {
 	struct nvme_nvm_id12_grp *src;
 	int sec_per_pg, sec_per_pl, pg_per_blk;
 
-	if (id12->cgrps != 1)
+	if (id->cgrps != 1)
 		return -EINVAL;
 
-	src = &id12->grp;
+	src = &id->grp;
 
-	nvm_id->mtype = src->mtype;
-	nvm_id->fmtype = src->fmtype;
+	if (src->mtype != 0) {
+		pr_err("nvm: memory type not supported\n");
+		return -EINVAL;
+	}
+
+	/* 1.2 spec. only reports a single version id - unfold */
+	dev_geo->ver_id = id->ver_id;
 
-	nvm_id->num_ch = src->num_ch;
-	nvm_id->num_lun = src->num_lun;
+	dev_geo->nr_chnls = src->num_ch;
+	dev_geo->nr_luns = src->num_lun;
+	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
 
-	nvm_id->num_chk = le16_to_cpu(src->num_chk);
-	nvm_id->csecs = le16_to_cpu(src->csecs);
-	nvm_id->sos = le16_to_cpu(src->sos);
+	dev_geo->c.num_chk = le16_to_cpu(src->num_chk);
+	dev_geo->c.csecs = le16_to_cpu(src->csecs);
+	dev_geo->c.sos = le16_to_cpu(src->sos);
 
 	pg_per_blk = le16_to_cpu(src->num_pg);
-	sec_per_pg = le16_to_cpu(src->fpg_sz) / nvm_id->csecs;
+	sec_per_pg = le16_to_cpu(src->fpg_sz) / dev_geo->c.csecs;
 	sec_per_pl = sec_per_pg * src->num_pln;
-	nvm_id->clba = sec_per_pl * pg_per_blk;
-	nvm_id->ws_per_chk = pg_per_blk;
-
-	nvm_id->mpos = le32_to_cpu(src->mpos);
-	nvm_id->cpar = le16_to_cpu(src->cpar);
-	nvm_id->mccap = le32_to_cpu(src->mccap);
-
-	nvm_id->ws_opt = nvm_id->ws_min = sec_per_pg;
-	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
-
-	if (nvm_id->mpos & 0x020202) {
-		nvm_id->ws_seq = NVM_IO_DUAL_ACCESS;
-		nvm_id->ws_opt <<= 1;
-	} else if (nvm_id->mpos & 0x040404) {
-		nvm_id->ws_seq = NVM_IO_QUAD_ACCESS;
-		nvm_id->ws_opt <<= 2;
+	dev_geo->c.clba = sec_per_pl * pg_per_blk;
+
+	dev_geo->c.ws_min = sec_per_pg;
+	dev_geo->c.ws_opt = sec_per_pg;
+	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
+
+	dev_geo->c.mccap = le32_to_cpu(src->mccap);
+
+	dev_geo->c.trdt = le32_to_cpu(src->trdt);
+	dev_geo->c.trdm = le32_to_cpu(src->trdm);
+	dev_geo->c.tprt = le32_to_cpu(src->tprt);
+	dev_geo->c.tprm = le32_to_cpu(src->tprm);
+	dev_geo->c.tbet = le32_to_cpu(src->tbet);
+	dev_geo->c.tbem = le32_to_cpu(src->tbem);
+
+	/* 1.2 compatibility */
+	dev_geo->c.vmnt = id->vmnt;
+	dev_geo->c.cap = le32_to_cpu(id->cap);
+	dev_geo->c.dom = le32_to_cpu(id->dom);
+
+	dev_geo->c.mtype = src->mtype;
+	dev_geo->c.fmtype = src->fmtype;
+
+	dev_geo->c.cpar = le16_to_cpu(src->cpar);
+	dev_geo->c.mpos = le32_to_cpu(src->mpos);
+
+	dev_geo->c.pln_mode = NVM_PLANE_SINGLE;
+
+	if (dev_geo->c.mpos & 0x020202) {
+		dev_geo->c.pln_mode = NVM_PLANE_DOUBLE;
+		dev_geo->c.ws_opt <<= 1;
+	} else if (dev_geo->c.mpos & 0x040404) {
+		dev_geo->c.pln_mode = NVM_PLANE_QUAD;
+		dev_geo->c.ws_opt <<= 2;
 	}
 
-	nvm_id->trdt = le32_to_cpu(src->trdt);
-	nvm_id->trdm = le32_to_cpu(src->trdm);
-	nvm_id->tprt = le32_to_cpu(src->tprt);
-	nvm_id->tprm = le32_to_cpu(src->tprm);
-	nvm_id->tbet = le32_to_cpu(src->tbet);
-	nvm_id->tbem = le32_to_cpu(src->tbem);
-
-	/* 1.2 compatibility */
-	nvm_id->num_pln = src->num_pln;
-	nvm_id->num_pg = le16_to_cpu(src->num_pg);
-	nvm_id->fpg_sz = le16_to_cpu(src->fpg_sz);
+	dev_geo->c.num_pln = src->num_pln;
+	dev_geo->c.num_pg = le16_to_cpu(src->num_pg);
+	dev_geo->c.fpg_sz = le16_to_cpu(src->fpg_sz);
+
+	nvme_nvm_set_addr_12((struct nvm_addr_format_12 *)&dev_geo->c.addrf,
+								&id->ppaf);
 
 	return 0;
 }
 
-static int nvme_nvm_setup_12(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
-		struct nvme_nvm_id12 *id)
+static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
+				 struct nvme_nvm_id20_addrf *src)
 {
-	nvm_id->ver_id = id->ver_id;
-	nvm_id->vmnt = id->vmnt;
-	nvm_id->cap = le32_to_cpu(id->cap);
-	nvm_id->dom = le32_to_cpu(id->dom);
-	memcpy(&nvm_id->ppaf, &id->ppaf,
-					sizeof(struct nvm_addr_format));
-
-	return init_grp(nvm_id, id);
+	dst->ch_len = src->grp_len;
+	dst->lun_len = src->pu_len;
+	dst->chk_len = src->chk_len;
+	dst->sec_len = src->lba_len;
+
+	dst->sec_offset = 0;
+	dst->chk_offset = dst->sec_len;
+	dst->lun_offset = dst->chk_offset + dst->chk_len;
+	dst->ch_offset = dst->lun_offset + dst->lun_len;
+
+	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
+	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
+	dst->chk_mask = ((1ULL << dst->chk_len) - 1) << dst->chk_offset;
+	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
 }
 
-static int nvme_nvm_setup_20(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
-		struct nvme_nvm_id20 *id)
+static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
+			     struct nvm_dev_geo *dev_geo)
 {
-	nvm_id->ver_id = id->mjr;
+	dev_geo->ver_id = id->mjr;
 
-	nvm_id->num_ch = le16_to_cpu(id->num_grp);
-	nvm_id->num_lun = le16_to_cpu(id->num_pu);
-	nvm_id->num_chk = le32_to_cpu(id->num_chk);
-	nvm_id->clba = le32_to_cpu(id->clba);
+	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
+	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
+	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
 
-	nvm_id->ws_min = le32_to_cpu(id->ws_min);
-	nvm_id->ws_opt = le32_to_cpu(id->ws_opt);
-	nvm_id->mw_cunits = le32_to_cpu(id->mw_cunits);
+	dev_geo->c.num_chk = le32_to_cpu(id->num_chk);
+	dev_geo->c.clba = le32_to_cpu(id->clba);
+	dev_geo->c.csecs = -1;		/* Set by nvme identify */
+	dev_geo->c.sos = -1;		/* Set bu nvme identify */
 
-	nvm_id->trdt = le32_to_cpu(id->trdt);
-	nvm_id->trdm = le32_to_cpu(id->trdm);
-	nvm_id->tprt = le32_to_cpu(id->twrt);
-	nvm_id->tprm = le32_to_cpu(id->twrm);
-	nvm_id->tbet = le32_to_cpu(id->tcrst);
-	nvm_id->tbem = le32_to_cpu(id->tcrsm);
+	dev_geo->c.ws_min = le32_to_cpu(id->ws_min);
+	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
+	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
 
-	/* calculated values */
-	nvm_id->ws_per_chk = nvm_id->clba / nvm_id->ws_min;
+	dev_geo->c.trdt = le32_to_cpu(id->trdt);
+	dev_geo->c.trdm = le32_to_cpu(id->trdm);
+	dev_geo->c.tprt = le32_to_cpu(id->twrt);
+	dev_geo->c.tprm = le32_to_cpu(id->twrm);
+	dev_geo->c.tbet = le32_to_cpu(id->tcrst);
+	dev_geo->c.tbem = le32_to_cpu(id->tcrsm);
 
-	/* 1.2 compatibility */
-	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
+	nvme_nvm_set_addr_20(&dev_geo->c.addrf, &id->lbaf);
 
 	return 0;
 }
 
-static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
+static int nvme_nvm_identity(struct nvm_dev *nvmdev)
 {
 	struct nvme_ns *ns = nvmdev->q->queuedata;
 	struct nvme_nvm_id12 *id;
@@ -380,18 +431,18 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
 	 */
 	switch (id->ver_id) {
 	case 1:
-		ret = nvme_nvm_setup_12(nvmdev, nvm_id, id);
+		ret = nvme_nvm_setup_12(id, &nvmdev->dev_geo);
 		break;
 	case 2:
-		ret = nvme_nvm_setup_20(nvmdev, nvm_id,
-				(struct nvme_nvm_id20 *)id);
+		ret = nvme_nvm_setup_20((struct nvme_nvm_id20 *)id,
+							&nvmdev->dev_geo);
 		break;
 	default:
-		dev_err(ns->ctrl->device,
-			"OCSSD revision not supported (%d)\n",
-			nvm_id->ver_id);
+		dev_err(ns->ctrl->device, "OCSSD revision not supported (%d)\n",
+							id->ver_id);
 		ret = -EINVAL;
 	}
+
 out:
 	kfree(id);
 	return ret;
@@ -401,12 +452,12 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
 								u8 *blks)
 {
 	struct request_queue *q = nvmdev->q;
-	struct nvm_geo *geo = &nvmdev->geo;
+	struct nvm_dev_geo *dev_geo = &nvmdev->dev_geo;
 	struct nvme_ns *ns = q->queuedata;
 	struct nvme_ctrl *ctrl = ns->ctrl;
 	struct nvme_nvm_command c = {};
 	struct nvme_nvm_bb_tbl *bb_tbl;
-	int nr_blks = geo->nr_chks * geo->plane_mode;
+	int nr_blks = dev_geo->c.num_chk * dev_geo->c.num_pln;
 	int tblsz = sizeof(struct nvme_nvm_bb_tbl) + nr_blks;
 	int ret = 0;
 
@@ -447,7 +498,7 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
 		goto out;
 	}
 
-	memcpy(blks, bb_tbl->blk, geo->nr_chks * geo->plane_mode);
+	memcpy(blks, bb_tbl->blk, dev_geo->c.num_chk * dev_geo->c.num_pln);
 out:
 	kfree(bb_tbl);
 	return ret;
@@ -815,9 +866,10 @@ int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd, unsigned long arg)
 void nvme_nvm_update_nvm_info(struct nvme_ns *ns)
 {
 	struct nvm_dev *ndev = ns->ndev;
+	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
 
-	ndev->identity.csecs = ndev->geo.sec_size = 1 << ns->lba_shift;
-	ndev->identity.sos = ndev->geo.oob_size = ns->ms;
+	dev_geo->c.csecs = 1 << ns->lba_shift;
+	dev_geo->c.sos = ns->ms;
 }
 
 int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node)
@@ -850,23 +902,22 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
 {
 	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
 	struct nvm_dev *ndev = ns->ndev;
-	struct nvm_id *id;
+	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
 	struct attribute *attr;
 
 	if (!ndev)
 		return 0;
 
-	id = &ndev->identity;
 	attr = &dattr->attr;
 
 	if (strcmp(attr->name, "version") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->ver_id);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
 	} else if (strcmp(attr->name, "capabilities") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->cap);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
 	} else if (strcmp(attr->name, "read_typ") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdt);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
 	} else if (strcmp(attr->name, "read_max") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdm);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdm);
 	} else {
 		return scnprintf(page,
 				 PAGE_SIZE,
@@ -875,75 +926,79 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
 	}
 }
 
+static ssize_t nvm_dev_attr_show_ppaf(struct nvm_addr_format_12 *ppaf,
+					 char *page)
+{
+	return scnprintf(page, PAGE_SIZE,
+		"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+				ppaf->ch_offset, ppaf->ch_len,
+				ppaf->lun_offset, ppaf->lun_len,
+				ppaf->pln_offset, ppaf->pln_len,
+				ppaf->blk_offset, ppaf->blk_len,
+				ppaf->pg_offset, ppaf->pg_len,
+				ppaf->sect_offset, ppaf->sect_len);
+}
+
 static ssize_t nvm_dev_attr_show_12(struct device *dev,
 		struct device_attribute *dattr, char *page)
 {
 	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
 	struct nvm_dev *ndev = ns->ndev;
-	struct nvm_id *id;
+	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
 	struct attribute *attr;
 
 	if (!ndev)
 		return 0;
 
-	id = &ndev->identity;
 	attr = &dattr->attr;
 
 	if (strcmp(attr->name, "vendor_opcode") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->vmnt);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.vmnt);
 	} else if (strcmp(attr->name, "device_mode") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->dom);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.dom);
 	/* kept for compatibility */
 	} else if (strcmp(attr->name, "media_manager") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%s\n", "gennvm");
 	} else if (strcmp(attr->name, "ppa_format") == 0) {
-		return scnprintf(page, PAGE_SIZE,
-			"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
-			id->ppaf.ch_offset, id->ppaf.ch_len,
-			id->ppaf.lun_offset, id->ppaf.lun_len,
-			id->ppaf.pln_offset, id->ppaf.pln_len,
-			id->ppaf.blk_offset, id->ppaf.blk_len,
-			id->ppaf.pg_offset, id->ppaf.pg_len,
-			id->ppaf.sect_offset, id->ppaf.sect_len);
+		return nvm_dev_attr_show_ppaf((void *)&dev_geo->c.addrf, page);
 	} else if (strcmp(attr->name, "media_type") == 0) {	/* u8 */
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->mtype);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mtype);
 	} else if (strcmp(attr->name, "flash_media_type") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->fmtype);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fmtype);
 	} else if (strcmp(attr->name, "num_channels") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
 	} else if (strcmp(attr->name, "num_luns") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
 	} else if (strcmp(attr->name, "num_planes") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pln);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pln);
 	} else if (strcmp(attr->name, "num_blocks") == 0) {	/* u16 */
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
 	} else if (strcmp(attr->name, "num_pages") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pg);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pg);
 	} else if (strcmp(attr->name, "page_size") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->fpg_sz);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fpg_sz);
 	} else if (strcmp(attr->name, "hw_sector_size") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->csecs);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.csecs);
 	} else if (strcmp(attr->name, "oob_sector_size") == 0) {/* u32 */
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->sos);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.sos);
 	} else if (strcmp(attr->name, "prog_typ") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
 	} else if (strcmp(attr->name, "prog_max") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
 	} else if (strcmp(attr->name, "erase_typ") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
 	} else if (strcmp(attr->name, "erase_max") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
 	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
-		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mpos);
+		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
 	} else if (strcmp(attr->name, "media_capabilities") == 0) {
-		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mccap);
+		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
 	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
 	} else {
-		return scnprintf(page,
-				 PAGE_SIZE,
-				 "Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
-				 attr->name);
+		return scnprintf(page, PAGE_SIZE,
+			"Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
+			attr->name);
 	}
 }
 
@@ -952,42 +1007,40 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
 {
 	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
 	struct nvm_dev *ndev = ns->ndev;
-	struct nvm_id *id;
+	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
 	struct attribute *attr;
 
 	if (!ndev)
 		return 0;
 
-	id = &ndev->identity;
 	attr = &dattr->attr;
 
 	if (strcmp(attr->name, "groups") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
 	} else if (strcmp(attr->name, "punits") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
 	} else if (strcmp(attr->name, "chunks") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
 	} else if (strcmp(attr->name, "clba") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->clba);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.clba);
 	} else if (strcmp(attr->name, "ws_min") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_min);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_min);
 	} else if (strcmp(attr->name, "ws_opt") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_opt);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_opt);
 	} else if (strcmp(attr->name, "mw_cunits") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->mw_cunits);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mw_cunits);
 	} else if (strcmp(attr->name, "write_typ") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
 	} else if (strcmp(attr->name, "write_max") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
 	} else if (strcmp(attr->name, "reset_typ") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
 	} else if (strcmp(attr->name, "reset_max") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
 	} else {
-		return scnprintf(page,
-				 PAGE_SIZE,
-				 "Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
-				 attr->name);
+		return scnprintf(page, PAGE_SIZE,
+			"Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
+			attr->name);
 	}
 }
 
@@ -1106,10 +1159,13 @@ static const struct attribute_group nvm_dev_attr_group_20 = {
 
 int nvme_nvm_register_sysfs(struct nvme_ns *ns)
 {
-	if (!ns->ndev)
+	struct nvm_dev *ndev = ns->ndev;
+	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
+
+	if (!ndev)
 		return -EINVAL;
 
-	switch (ns->ndev->identity.ver_id) {
+	switch (dev_geo->ver_id) {
 	case 1:
 		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
 					&nvm_dev_attr_group_12);
@@ -1123,7 +1179,10 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
 
 void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
 {
-	switch (ns->ndev->identity.ver_id) {
+	struct nvm_dev *ndev = ns->ndev;
+	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
+
+	switch (dev_geo->ver_id) {
 	case 1:
 		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
 					&nvm_dev_attr_group_12);
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index e55b10573c99..18e3751b1632 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -50,7 +50,7 @@ struct nvm_id;
 struct nvm_dev;
 struct nvm_tgt_dev;
 
-typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *);
+typedef int (nvm_id_fn)(struct nvm_dev *);
 typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, u8 *);
 typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct ppa_addr *, int, int);
 typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
@@ -152,62 +152,107 @@ struct nvm_id_lp_tbl {
 	struct nvm_id_lp_mlc mlc;
 };
 
-struct nvm_addr_format {
-	u8	ch_offset;
+struct nvm_addr_format_12 {
 	u8	ch_len;
-	u8	lun_offset;
 	u8	lun_len;
-	u8	pln_offset;
+	u8	blk_len;
+	u8	pg_len;
 	u8	pln_len;
+	u8	sect_len;
+
+	u8	ch_offset;
+	u8	lun_offset;
 	u8	blk_offset;
-	u8	blk_len;
 	u8	pg_offset;
-	u8	pg_len;
+	u8	pln_offset;
 	u8	sect_offset;
-	u8	sect_len;
+
+	u64	ch_mask;
+	u64	lun_mask;
+	u64	blk_mask;
+	u64	pg_mask;
+	u64	pln_mask;
+	u64	sec_mask;
+};
+
+struct nvm_addr_format {
+	u8	ch_len;
+	u8	lun_len;
+	u8	chk_len;
+	u8	sec_len;
+	u8	rsv_len[2];
+
+	u8	ch_offset;
+	u8	lun_offset;
+	u8	chk_offset;
+	u8	sec_offset;
+	u8	rsv_off[2];
+
+	u64	ch_mask;
+	u64	lun_mask;
+	u64	chk_mask;
+	u64	sec_mask;
+	u64	rsv_mask[2];
 };
 
-struct nvm_id {
-	u8	ver_id;
+/* Device common geometry */
+struct nvm_common_geo {
+	/* chunk geometry */
+	u32	num_chk;	/* chunks per lun */
+	u32	clba;		/* sectors per chunk */
+	u16	csecs;		/* sector size */
+	u16	sos;		/* out-of-band area size */
+
+	/* device write constrains */
+	u32	ws_min;		/* minimum write size */
+	u32	ws_opt;		/* optimal write size */
+	u32	mw_cunits;	/* distance required for successful read */
+
+	/* device capabilities */
+	u32	mccap;
+
+	/* device timings */
+	u32	trdt;		/* Avg. Tread (ns) */
+	u32	trdm;		/* Max Tread (ns) */
+	u32	tprt;		/* Avg. Tprog (ns) */
+	u32	tprm;		/* Max Tprog (ns) */
+	u32	tbet;		/* Avg. Terase (ns) */
+	u32	tbem;		/* Max Terase (ns) */
+
+	/* generic address format */
+	struct nvm_addr_format addrf;
+
+	/* 1.2 compatibility */
 	u8	vmnt;
 	u32	cap;
 	u32	dom;
 
-	struct	nvm_addr_format ppaf;
-
-	u8	num_ch;
-	u8	num_lun;
-	u16	num_chk;
-	u16	clba;
-	u16	csecs;
-	u16	sos;
-
-	u32	ws_min;
-	u32	ws_opt;
-	u32	mw_cunits;
-
-	u32	trdt;
-	u32	trdm;
-	u32	tprt;
-	u32	tprm;
-	u32	tbet;
-	u32	tbem;
-	u32	mpos;
-	u32	mccap;
-	u16	cpar;
-
-	/* calculated values */
-	u16	ws_seq;
-	u16	ws_per_chk;
-
-	/* 1.2 compatibility */
 	u8	mtype;
 	u8	fmtype;
 
+	u16	cpar;
+	u32	mpos;
+
 	u8	num_pln;
+	u8	pln_mode;
 	u16	num_pg;
 	u16	fpg_sz;
-} __packed;
+};
+
+/* Device identified geometry */
+struct nvm_dev_geo {
+	/* device reported version */
+	u8	ver_id;
+
+	/* full device geometry */
+	u16	nr_chnls;
+	u16	nr_luns;
+
+	/* calculated values */
+	u16	all_luns;
+
+	struct nvm_common_geo c;
+};
 
 struct nvm_target {
 	struct list_head list;
@@ -274,36 +319,22 @@ enum {
 	NVM_BLK_ST_BAD =	0x8,	/* Bad block */
 };
 
-
-/* Device generic information */
+/* Instance geometry */
 struct nvm_geo {
-	/* generic geometry */
+	/* instance specific geometry */
 	int nr_chnls;
-	int all_luns; /* across channels */
-	int nr_luns; /* per channel */
-	int nr_chks; /* per lun */
-
-	int sec_size;
-	int oob_size;
-	int mccap;
-
-	int sec_per_chk;
-	int sec_per_lun;
-
-	int ws_min;
-	int ws_opt;
-	int ws_seq;
-	int ws_per_chk;
+	int nr_luns;		/* per channel */
 
 	int op;
 
-	struct nvm_addr_format ppaf;
+	/* common geometry */
+	struct nvm_common_geo c;
 
-	/* Legacy 1.2 specific geometry */
-	int plane_mode; /* drive device in single, double or quad mode */
-	int nr_planes;
-	int sec_per_pg; /* only sectors for a single page */
-	int sec_per_pl; /* all sectors across planes */
+	/* calculated values */
+	int all_luns;		/* across channels */
+	int all_chunks;		/* across channels */
+
+	sector_t total_secs;	/* across channels */
 };
 
 /* sub-device structure */
@@ -314,9 +345,6 @@ struct nvm_tgt_dev {
 	/* Base ppas for target LUNs */
 	struct ppa_addr *luns;
 
-	sector_t total_secs;
-
-	struct nvm_id identity;
 	struct request_queue *q;
 
 	struct nvm_dev *parent;
@@ -329,15 +357,11 @@ struct nvm_dev {
 	struct list_head devices;
 
 	/* Device information */
-	struct nvm_geo geo;
-
-	unsigned long total_secs;
+	struct nvm_dev_geo dev_geo;
 
 	unsigned long *lun_map;
 	void *dma_pool;
 
-	struct nvm_id identity;
-
 	/* Backend device */
 	struct request_queue *q;
 	char name[DISK_NAME_LEN];
@@ -357,14 +381,16 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
 						  struct ppa_addr r)
 {
 	struct nvm_geo *geo = &tgt_dev->geo;
+	struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&geo->c.addrf;
 	struct ppa_addr l;
 
-	l.ppa = ((u64)r.g.blk) << geo->ppaf.blk_offset;
-	l.ppa |= ((u64)r.g.pg) << geo->ppaf.pg_offset;
-	l.ppa |= ((u64)r.g.sec) << geo->ppaf.sect_offset;
-	l.ppa |= ((u64)r.g.pl) << geo->ppaf.pln_offset;
-	l.ppa |= ((u64)r.g.lun) << geo->ppaf.lun_offset;
-	l.ppa |= ((u64)r.g.ch) << geo->ppaf.ch_offset;
+	l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
+	l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
+	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
+	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
+	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
+	l.ppa |= ((u64)r.g.sec) << ppaf->sect_offset;
 
 	return l;
 }
@@ -373,24 +399,18 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
 						  struct ppa_addr r)
 {
 	struct nvm_geo *geo = &tgt_dev->geo;
+	struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&geo->c.addrf;
 	struct ppa_addr l;
 
 	l.ppa = 0;
-	/*
-	 * (r.ppa << X offset) & X len bitmask. X eq. blk, pg, etc.
-	 */
-	l.g.blk = (r.ppa >> geo->ppaf.blk_offset) &
-					(((1 << geo->ppaf.blk_len) - 1));
-	l.g.pg |= (r.ppa >> geo->ppaf.pg_offset) &
-					(((1 << geo->ppaf.pg_len) - 1));
-	l.g.sec |= (r.ppa >> geo->ppaf.sect_offset) &
-					(((1 << geo->ppaf.sect_len) - 1));
-	l.g.pl |= (r.ppa >> geo->ppaf.pln_offset) &
-					(((1 << geo->ppaf.pln_len) - 1));
-	l.g.lun |= (r.ppa >> geo->ppaf.lun_offset) &
-					(((1 << geo->ppaf.lun_len) - 1));
-	l.g.ch |= (r.ppa >> geo->ppaf.ch_offset) &
-					(((1 << geo->ppaf.ch_len) - 1));
+
+	l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
+	l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
+	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
+	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
+	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
+	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sect_offset;
 
 	return l;
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 01/20] lightnvm: simplify geometry structure.
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


Currently, the device geometry is stored redundantly in the nvm_id and
nvm_geo structures at a device level. Moreover, when instantiating
targets on a specific number of LUNs, these structures are replicated
and manually modified to fit the instance channel and LUN partitioning.

Instead, create a generic geometry around two base structures:
nvm_dev_geo, which describes the geometry of the whole device and
nvm_geo, which describes the geometry of the instance. Since these share
a big part of the geometry, create a nvm_common_geo structure that keeps
the static geoometry values that are shared across instances.

As we introduce support for 2.0, these structures allow to abstract
spec. specific values and present a common geometry to targets.

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/lightnvm/core.c          | 137 +++++++---------
 drivers/lightnvm/pblk-core.c     |  16 +-
 drivers/lightnvm/pblk-gc.c       |   2 +-
 drivers/lightnvm/pblk-init.c     | 123 +++++++-------
 drivers/lightnvm/pblk-read.c     |   2 +-
 drivers/lightnvm/pblk-recovery.c |  14 +-
 drivers/lightnvm/pblk-rl.c       |   2 +-
 drivers/lightnvm/pblk-sysfs.c    |  39 +++--
 drivers/lightnvm/pblk-write.c    |   2 +-
 drivers/lightnvm/pblk.h          |  93 +++++------
 drivers/nvme/host/lightnvm.c     | 339 +++++++++++++++++++++++----------------
 include/linux/lightnvm.h         | 204 ++++++++++++-----------
 12 files changed, 514 insertions(+), 459 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 689c97b97775..42596afdf64c 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -111,6 +111,7 @@ static void nvm_release_luns_err(struct nvm_dev *dev, int lun_begin,
 static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
 {
 	struct nvm_dev *dev = tgt_dev->parent;
+	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
 	struct nvm_dev_map *dev_map = tgt_dev->map;
 	int i, j;
 
@@ -122,7 +123,7 @@ static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
 		if (clear) {
 			for (j = 0; j < ch_map->nr_luns; j++) {
 				int lun = j + lun_offs[j];
-				int lunid = (ch * dev->geo.nr_luns) + lun;
+				int lunid = (ch * dev_geo->nr_luns) + lun;
 
 				WARN_ON(!test_and_clear_bit(lunid,
 							dev->lun_map));
@@ -143,19 +144,20 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
 					      u16 lun_begin, u16 lun_end,
 					      u16 op)
 {
+	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
 	struct nvm_tgt_dev *tgt_dev = NULL;
 	struct nvm_dev_map *dev_rmap = dev->rmap;
 	struct nvm_dev_map *dev_map;
 	struct ppa_addr *luns;
 	int nr_luns = lun_end - lun_begin + 1;
 	int luns_left = nr_luns;
-	int nr_chnls = nr_luns / dev->geo.nr_luns;
-	int nr_chnls_mod = nr_luns % dev->geo.nr_luns;
-	int bch = lun_begin / dev->geo.nr_luns;
-	int blun = lun_begin % dev->geo.nr_luns;
+	int nr_chnls = nr_luns / dev_geo->nr_luns;
+	int nr_chnls_mod = nr_luns % dev_geo->nr_luns;
+	int bch = lun_begin / dev_geo->nr_luns;
+	int blun = lun_begin % dev_geo->nr_luns;
 	int lunid = 0;
 	int lun_balanced = 1;
-	int prev_nr_luns;
+	int sec_per_lun, prev_nr_luns;
 	int i, j;
 
 	nr_chnls = (nr_chnls_mod == 0) ? nr_chnls : nr_chnls + 1;
@@ -173,15 +175,15 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
 	if (!luns)
 		goto err_luns;
 
-	prev_nr_luns = (luns_left > dev->geo.nr_luns) ?
-					dev->geo.nr_luns : luns_left;
+	prev_nr_luns = (luns_left > dev_geo->nr_luns) ?
+					dev_geo->nr_luns : luns_left;
 	for (i = 0; i < nr_chnls; i++) {
 		struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[i + bch];
 		int *lun_roffs = ch_rmap->lun_offs;
 		struct nvm_ch_map *ch_map = &dev_map->chnls[i];
 		int *lun_offs;
-		int luns_in_chnl = (luns_left > dev->geo.nr_luns) ?
-					dev->geo.nr_luns : luns_left;
+		int luns_in_chnl = (luns_left > dev_geo->nr_luns) ?
+					dev_geo->nr_luns : luns_left;
 
 		if (lun_balanced && prev_nr_luns != luns_in_chnl)
 			lun_balanced = 0;
@@ -215,18 +217,22 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
 	if (!tgt_dev)
 		goto err_ch;
 
-	memcpy(&tgt_dev->geo, &dev->geo, sizeof(struct nvm_geo));
 	/* Target device only owns a portion of the physical device */
 	tgt_dev->geo.nr_chnls = nr_chnls;
-	tgt_dev->geo.all_luns = nr_luns;
 	tgt_dev->geo.nr_luns = (lun_balanced) ? prev_nr_luns : -1;
+	tgt_dev->geo.all_luns = nr_luns;
+	tgt_dev->geo.all_chunks = nr_luns * dev_geo->c.num_chk;
+
 	tgt_dev->geo.op = op;
-	tgt_dev->total_secs = nr_luns * tgt_dev->geo.sec_per_lun;
+
+	sec_per_lun = dev_geo->c.clba * dev_geo->c.num_chk;
+	tgt_dev->geo.total_secs = nr_luns * sec_per_lun;
+
+	tgt_dev->geo.c = dev_geo->c;
+
 	tgt_dev->q = dev->q;
 	tgt_dev->map = dev_map;
 	tgt_dev->luns = luns;
-	memcpy(&tgt_dev->identity, &dev->identity, sizeof(struct nvm_id));
-
 	tgt_dev->parent = dev;
 
 	return tgt_dev;
@@ -268,12 +274,12 @@ static struct nvm_tgt_type *nvm_find_target_type(const char *name)
 	return tt;
 }
 
-static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
+static int nvm_config_check_luns(struct nvm_dev_geo *dev_geo, int lun_begin,
 				 int lun_end)
 {
-	if (lun_begin > lun_end || lun_end >= geo->all_luns) {
+	if (lun_begin > lun_end || lun_end >= dev_geo->all_luns) {
 		pr_err("nvm: lun out of bound (%u:%u > %u)\n",
-			lun_begin, lun_end, geo->all_luns - 1);
+			lun_begin, lun_end, dev_geo->all_luns - 1);
 		return -EINVAL;
 	}
 
@@ -283,24 +289,24 @@ static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
 static int __nvm_config_simple(struct nvm_dev *dev,
 			       struct nvm_ioctl_create_simple *s)
 {
-	struct nvm_geo *geo = &dev->geo;
+	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
 
 	if (s->lun_begin == -1 && s->lun_end == -1) {
 		s->lun_begin = 0;
-		s->lun_end = geo->all_luns - 1;
+		s->lun_end = dev_geo->all_luns - 1;
 	}
 
-	return nvm_config_check_luns(geo, s->lun_begin, s->lun_end);
+	return nvm_config_check_luns(dev_geo, s->lun_begin, s->lun_end);
 }
 
 static int __nvm_config_extended(struct nvm_dev *dev,
 				 struct nvm_ioctl_create_extended *e)
 {
-	struct nvm_geo *geo = &dev->geo;
+	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
 
 	if (e->lun_begin == 0xFFFF && e->lun_end == 0xFFFF) {
 		e->lun_begin = 0;
-		e->lun_end = dev->geo.all_luns - 1;
+		e->lun_end = dev_geo->all_luns - 1;
 	}
 
 	/* op not set falls into target's default */
@@ -313,7 +319,7 @@ static int __nvm_config_extended(struct nvm_dev *dev,
 		return -EINVAL;
 	}
 
-	return nvm_config_check_luns(geo, e->lun_begin, e->lun_end);
+	return nvm_config_check_luns(dev_geo, e->lun_begin, e->lun_end);
 }
 
 static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
@@ -408,7 +414,7 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
 	tqueue->queuedata = targetdata;
 
 	blk_queue_max_hw_sectors(tqueue,
-			(dev->geo.sec_size >> 9) * NVM_MAX_VLBA);
+			(dev->dev_geo.c.csecs >> 9) * NVM_MAX_VLBA);
 
 	set_capacity(tdisk, tt->capacity(targetdata));
 	add_disk(tdisk);
@@ -497,6 +503,7 @@ static int nvm_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove)
 
 static int nvm_register_map(struct nvm_dev *dev)
 {
+	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
 	struct nvm_dev_map *rmap;
 	int i, j;
 
@@ -504,15 +511,15 @@ static int nvm_register_map(struct nvm_dev *dev)
 	if (!rmap)
 		goto err_rmap;
 
-	rmap->chnls = kcalloc(dev->geo.nr_chnls, sizeof(struct nvm_ch_map),
+	rmap->chnls = kcalloc(dev_geo->nr_chnls, sizeof(struct nvm_ch_map),
 								GFP_KERNEL);
 	if (!rmap->chnls)
 		goto err_chnls;
 
-	for (i = 0; i < dev->geo.nr_chnls; i++) {
+	for (i = 0; i < dev_geo->nr_chnls; i++) {
 		struct nvm_ch_map *ch_rmap;
 		int *lun_roffs;
-		int luns_in_chnl = dev->geo.nr_luns;
+		int luns_in_chnl = dev_geo->nr_luns;
 
 		ch_rmap = &rmap->chnls[i];
 
@@ -543,10 +550,11 @@ static int nvm_register_map(struct nvm_dev *dev)
 
 static void nvm_unregister_map(struct nvm_dev *dev)
 {
+	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
 	struct nvm_dev_map *rmap = dev->rmap;
 	int i;
 
-	for (i = 0; i < dev->geo.nr_chnls; i++)
+	for (i = 0; i < dev_geo->nr_chnls; i++)
 		kfree(rmap->chnls[i].lun_offs);
 
 	kfree(rmap->chnls);
@@ -675,7 +683,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
 	int i, plane_cnt, pl_idx;
 	struct ppa_addr ppa;
 
-	if (geo->plane_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
+	if (geo->c.pln_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
 		rqd->nr_ppas = nr_ppas;
 		rqd->ppa_addr = ppas[0];
 
@@ -689,7 +697,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
 		return -ENOMEM;
 	}
 
-	plane_cnt = geo->plane_mode;
+	plane_cnt = geo->c.pln_mode;
 	rqd->nr_ppas *= plane_cnt;
 
 	for (i = 0; i < nr_ppas; i++) {
@@ -804,18 +812,18 @@ EXPORT_SYMBOL(nvm_end_io);
  */
 int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
 {
-	struct nvm_geo *geo = &dev->geo;
+	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
 	int blk, offset, pl, blktype;
 
-	if (nr_blks != geo->nr_chks * geo->plane_mode)
+	if (nr_blks != dev_geo->c.num_chk * dev_geo->c.pln_mode)
 		return -EINVAL;
 
-	for (blk = 0; blk < geo->nr_chks; blk++) {
-		offset = blk * geo->plane_mode;
+	for (blk = 0; blk < dev_geo->c.num_chk; blk++) {
+		offset = blk * dev_geo->c.pln_mode;
 		blktype = blks[offset];
 
 		/* Bad blocks on any planes take precedence over other types */
-		for (pl = 0; pl < geo->plane_mode; pl++) {
+		for (pl = 0; pl < dev_geo->c.pln_mode; pl++) {
 			if (blks[offset + pl] &
 					(NVM_BLK_T_BAD|NVM_BLK_T_GRWN_BAD)) {
 				blktype = blks[offset + pl];
@@ -826,7 +834,7 @@ int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
 		blks[blk] = blktype;
 	}
 
-	return geo->nr_chks;
+	return dev_geo->c.num_chk;
 }
 EXPORT_SYMBOL(nvm_bb_tbl_fold);
 
@@ -843,41 +851,10 @@ EXPORT_SYMBOL(nvm_get_tgt_bb_tbl);
 
 static int nvm_core_init(struct nvm_dev *dev)
 {
-	struct nvm_id *id = &dev->identity;
-	struct nvm_geo *geo = &dev->geo;
+	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
 	int ret;
 
-	memcpy(&geo->ppaf, &id->ppaf, sizeof(struct nvm_addr_format));
-
-	if (id->mtype != 0) {
-		pr_err("nvm: memory type not supported\n");
-		return -EINVAL;
-	}
-
-	/* Whole device values */
-	geo->nr_chnls = id->num_ch;
-	geo->nr_luns = id->num_lun;
-
-	/* Generic device geometry values */
-	geo->ws_min = id->ws_min;
-	geo->ws_opt = id->ws_opt;
-	geo->ws_seq = id->ws_seq;
-	geo->ws_per_chk = id->ws_per_chk;
-	geo->nr_chks = id->num_chk;
-	geo->mccap = id->mccap;
-
-	geo->sec_per_chk = id->clba;
-	geo->sec_per_lun = geo->sec_per_chk * geo->nr_chks;
-	geo->all_luns = geo->nr_luns * geo->nr_chnls;
-
-	/* 1.2 spec device geometry values */
-	geo->plane_mode = 1 << geo->ws_seq;
-	geo->nr_planes = geo->ws_opt / geo->ws_min;
-	geo->sec_per_pg = geo->ws_min;
-	geo->sec_per_pl = geo->sec_per_pg * geo->nr_planes;
-
-	dev->total_secs = geo->all_luns * geo->sec_per_lun;
-	dev->lun_map = kcalloc(BITS_TO_LONGS(geo->all_luns),
+	dev->lun_map = kcalloc(BITS_TO_LONGS(dev_geo->all_luns),
 					sizeof(unsigned long), GFP_KERNEL);
 	if (!dev->lun_map)
 		return -ENOMEM;
@@ -912,19 +889,17 @@ static void nvm_free(struct nvm_dev *dev)
 
 static int nvm_init(struct nvm_dev *dev)
 {
-	struct nvm_geo *geo = &dev->geo;
+	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
 	int ret = -EINVAL;
 
-	if (dev->ops->identity(dev, &dev->identity)) {
+	if (dev->ops->identity(dev)) {
 		pr_err("nvm: device could not be identified\n");
 		goto err;
 	}
 
-	if (dev->identity.ver_id != 1 && dev->identity.ver_id != 2) {
-		pr_err("nvm: device ver_id %d not supported by kernel.\n",
-				dev->identity.ver_id);
-		goto err;
-	}
+	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
+				dev_geo->ver_id,
+				dev_geo->c.vmnt);
 
 	ret = nvm_core_init(dev);
 	if (ret) {
@@ -932,10 +907,10 @@ static int nvm_init(struct nvm_dev *dev)
 		goto err;
 	}
 
-	pr_info("nvm: registered %s [%u/%u/%u/%u/%u/%u]\n",
-			dev->name, geo->sec_per_pg, geo->nr_planes,
-			geo->ws_per_chk, geo->nr_chks,
-			geo->all_luns, geo->nr_chnls);
+	pr_info("nvm: registered %s [%u/%u/%u/%u/%u]\n",
+			dev->name, dev_geo->c.ws_min, dev_geo->c.ws_opt,
+			dev_geo->c.num_chk, dev_geo->all_luns,
+			dev_geo->nr_chnls);
 	return 0;
 err:
 	pr_err("nvm: failed to initialize nvm\n");
diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index 22e61cd4f801..519af8b9eab7 100644
--- a/drivers/lightnvm/pblk-core.c
+++ b/drivers/lightnvm/pblk-core.c
@@ -613,7 +613,7 @@ static int pblk_line_submit_emeta_io(struct pblk *pblk, struct pblk_line *line,
 	memset(&rqd, 0, sizeof(struct nvm_rq));
 
 	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
-	rq_len = rq_ppas * geo->sec_size;
+	rq_len = rq_ppas * geo->c.csecs;
 
 	bio = pblk_bio_map_addr(pblk, emeta_buf, rq_ppas, rq_len,
 					l_mg->emeta_alloc_type, GFP_KERNEL);
@@ -722,7 +722,7 @@ u64 pblk_line_smeta_start(struct pblk *pblk, struct pblk_line *line)
 	if (bit >= lm->blk_per_line)
 		return -1;
 
-	return bit * geo->sec_per_pl;
+	return bit * geo->c.ws_opt;
 }
 
 static int pblk_line_submit_smeta_io(struct pblk *pblk, struct pblk_line *line,
@@ -1035,19 +1035,19 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
 	/* Capture bad block information on line mapping bitmaps */
 	while ((bit = find_next_bit(line->blk_bitmap, lm->blk_per_line,
 					bit + 1)) < lm->blk_per_line) {
-		off = bit * geo->sec_per_pl;
+		off = bit * geo->c.ws_opt;
 		bitmap_shift_left(l_mg->bb_aux, l_mg->bb_template, off,
 							lm->sec_per_line);
 		bitmap_or(line->map_bitmap, line->map_bitmap, l_mg->bb_aux,
 							lm->sec_per_line);
-		line->sec_in_line -= geo->sec_per_chk;
+		line->sec_in_line -= geo->c.clba;
 		if (bit >= lm->emeta_bb)
 			nr_bb++;
 	}
 
 	/* Mark smeta metadata sectors as bad sectors */
 	bit = find_first_zero_bit(line->blk_bitmap, lm->blk_per_line);
-	off = bit * geo->sec_per_pl;
+	off = bit * geo->c.ws_opt;
 	bitmap_set(line->map_bitmap, off, lm->smeta_sec);
 	line->sec_in_line -= lm->smeta_sec;
 	line->smeta_ssec = off;
@@ -1066,10 +1066,10 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
 	emeta_secs = lm->emeta_sec[0];
 	off = lm->sec_per_line;
 	while (emeta_secs) {
-		off -= geo->sec_per_pl;
+		off -= geo->c.ws_opt;
 		if (!test_bit(off, line->invalid_bitmap)) {
-			bitmap_set(line->invalid_bitmap, off, geo->sec_per_pl);
-			emeta_secs -= geo->sec_per_pl;
+			bitmap_set(line->invalid_bitmap, off, geo->c.ws_opt);
+			emeta_secs -= geo->c.ws_opt;
 		}
 	}
 
diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c
index 320f99af99e9..16afea3f5541 100644
--- a/drivers/lightnvm/pblk-gc.c
+++ b/drivers/lightnvm/pblk-gc.c
@@ -88,7 +88,7 @@ static void pblk_gc_line_ws(struct work_struct *work)
 
 	up(&gc->gc_sem);
 
-	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->sec_size);
+	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->c.csecs);
 	if (!gc_rq->data) {
 		pr_err("pblk: could not GC line:%d (%d/%d)\n",
 					line->id, *line->vsc, gc_rq->nr_secs);
diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 5261702e9ff7..95ecb0ec736b 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -146,7 +146,7 @@ static int pblk_rwb_init(struct pblk *pblk)
 		return -ENOMEM;
 
 	power_size = get_count_order(nr_entries);
-	power_seg_sz = get_count_order(geo->sec_size);
+	power_seg_sz = get_count_order(geo->c.csecs);
 
 	return pblk_rb_init(&pblk->rwb, entries, power_size, power_seg_sz);
 }
@@ -154,11 +154,11 @@ static int pblk_rwb_init(struct pblk *pblk)
 /* Minimum pages needed within a lun */
 #define ADDR_POOL_SIZE 64
 
-static int pblk_set_ppaf(struct pblk *pblk)
+static int pblk_set_addrf_12(struct nvm_geo *geo,
+			     struct nvm_addr_format_12 *dst)
 {
-	struct nvm_tgt_dev *dev = pblk->dev;
-	struct nvm_geo *geo = &dev->geo;
-	struct nvm_addr_format ppaf = geo->ppaf;
+	struct nvm_addr_format_12 *src =
+				(struct nvm_addr_format_12 *)&geo->c.addrf;
 	int power_len;
 
 	/* Re-calculate channel and lun format to adapt to configuration */
@@ -167,34 +167,50 @@ static int pblk_set_ppaf(struct pblk *pblk)
 		pr_err("pblk: supports only power-of-two channel config.\n");
 		return -EINVAL;
 	}
-	ppaf.ch_len = power_len;
+	dst->ch_len = power_len;
 
 	power_len = get_count_order(geo->nr_luns);
 	if (1 << power_len != geo->nr_luns) {
 		pr_err("pblk: supports only power-of-two LUN config.\n");
 		return -EINVAL;
 	}
-	ppaf.lun_len = power_len;
+	dst->lun_len = power_len;
 
-	pblk->ppaf.sec_offset = 0;
-	pblk->ppaf.pln_offset = ppaf.sect_len;
-	pblk->ppaf.ch_offset = pblk->ppaf.pln_offset + ppaf.pln_len;
-	pblk->ppaf.lun_offset = pblk->ppaf.ch_offset + ppaf.ch_len;
-	pblk->ppaf.pg_offset = pblk->ppaf.lun_offset + ppaf.lun_len;
-	pblk->ppaf.blk_offset = pblk->ppaf.pg_offset + ppaf.pg_len;
-	pblk->ppaf.sec_mask = (1ULL << ppaf.sect_len) - 1;
-	pblk->ppaf.pln_mask = ((1ULL << ppaf.pln_len) - 1) <<
-							pblk->ppaf.pln_offset;
-	pblk->ppaf.ch_mask = ((1ULL << ppaf.ch_len) - 1) <<
-							pblk->ppaf.ch_offset;
-	pblk->ppaf.lun_mask = ((1ULL << ppaf.lun_len) - 1) <<
-							pblk->ppaf.lun_offset;
-	pblk->ppaf.pg_mask = ((1ULL << ppaf.pg_len) - 1) <<
-							pblk->ppaf.pg_offset;
-	pblk->ppaf.blk_mask = ((1ULL << ppaf.blk_len) - 1) <<
-							pblk->ppaf.blk_offset;
+	dst->blk_len = src->blk_len;
+	dst->pg_len = src->pg_len;
+	dst->pln_len = src->pln_len;
+	dst->sect_len = src->sect_len;
 
-	pblk->ppaf_bitsize = pblk->ppaf.blk_offset + ppaf.blk_len;
+	dst->sect_offset = 0;
+	dst->pln_offset = dst->sect_len;
+	dst->ch_offset = dst->pln_offset + dst->pln_len;
+	dst->lun_offset = dst->ch_offset + dst->ch_len;
+	dst->pg_offset = dst->lun_offset + dst->lun_len;
+	dst->blk_offset = dst->pg_offset + dst->pg_len;
+
+	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
+	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
+	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
+	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
+	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
+	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
+
+	return dst->blk_offset + src->blk_len;
+}
+
+static int pblk_set_ppaf(struct pblk *pblk)
+{
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	int mod;
+
+	div_u64_rem(geo->c.clba, pblk->min_write_pgs, &mod);
+	if (mod) {
+		pr_err("pblk: bad configuration of sectors/pages\n");
+		return -EINVAL;
+	}
+
+	pblk->ppaf_bitsize = pblk_set_addrf_12(geo, (void *)&pblk->ppaf);
 
 	return 0;
 }
@@ -253,8 +269,7 @@ static int pblk_core_init(struct pblk *pblk)
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
 
-	pblk->pgs_in_buffer = NVM_MEM_PAGE_WRITE * geo->sec_per_pg *
-						geo->nr_planes * geo->all_luns;
+	pblk->pgs_in_buffer = geo->c.mw_cunits * geo->c.ws_opt * geo->all_luns;
 
 	if (pblk_init_global_caches(pblk))
 		return -ENOMEM;
@@ -433,7 +448,7 @@ static void *pblk_bb_get_log(struct pblk *pblk)
 	int i, nr_blks, blk_per_lun;
 	int ret;
 
-	blk_per_lun = geo->nr_chks * geo->plane_mode;
+	blk_per_lun = geo->c.num_chk * geo->c.pln_mode;
 	nr_blks = blk_per_lun * geo->all_luns;
 
 	log = kmalloc(nr_blks, GFP_KERNEL);
@@ -551,18 +566,18 @@ static unsigned int calc_emeta_len(struct pblk *pblk)
 	/* Round to sector size so that lba_list starts on its own sector */
 	lm->emeta_sec[1] = DIV_ROUND_UP(
 			sizeof(struct line_emeta) + lm->blk_bitmap_len +
-			sizeof(struct wa_counters), geo->sec_size);
-	lm->emeta_len[1] = lm->emeta_sec[1] * geo->sec_size;
+			sizeof(struct wa_counters), geo->c.csecs);
+	lm->emeta_len[1] = lm->emeta_sec[1] * geo->c.csecs;
 
 	/* Round to sector size so that vsc_list starts on its own sector */
 	lm->dsec_per_line = lm->sec_per_line - lm->emeta_sec[0];
 	lm->emeta_sec[2] = DIV_ROUND_UP(lm->dsec_per_line * sizeof(u64),
-			geo->sec_size);
-	lm->emeta_len[2] = lm->emeta_sec[2] * geo->sec_size;
+			geo->c.csecs);
+	lm->emeta_len[2] = lm->emeta_sec[2] * geo->c.csecs;
 
 	lm->emeta_sec[3] = DIV_ROUND_UP(l_mg->nr_lines * sizeof(u32),
-			geo->sec_size);
-	lm->emeta_len[3] = lm->emeta_sec[3] * geo->sec_size;
+			geo->c.csecs);
+	lm->emeta_len[3] = lm->emeta_sec[3] * geo->c.csecs;
 
 	lm->vsc_list_len = l_mg->nr_lines * sizeof(u32);
 
@@ -593,13 +608,13 @@ static void pblk_set_provision(struct pblk *pblk, long nr_free_blks)
 	 * on user capacity consider only provisioned blocks
 	 */
 	pblk->rl.total_blocks = nr_free_blks;
-	pblk->rl.nr_secs = nr_free_blks * geo->sec_per_chk;
+	pblk->rl.nr_secs = nr_free_blks * geo->c.clba;
 
 	/* Consider sectors used for metadata */
 	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
-	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
+	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
 
-	pblk->capacity = (provisioned - blk_meta) * geo->sec_per_chk;
+	pblk->capacity = (provisioned - blk_meta) * geo->c.clba;
 
 	atomic_set(&pblk->rl.free_blocks, nr_free_blks);
 	atomic_set(&pblk->rl.free_user_blocks, nr_free_blks);
@@ -710,10 +725,10 @@ static int pblk_lines_init(struct pblk *pblk)
 	void *chunk_log;
 	unsigned int smeta_len, emeta_len;
 	long nr_bad_blks = 0, nr_free_blks = 0;
-	int bb_distance, max_write_ppas, mod;
+	int bb_distance, max_write_ppas;
 	int i, ret;
 
-	pblk->min_write_pgs = geo->sec_per_pl * (geo->sec_size / PAGE_SIZE);
+	pblk->min_write_pgs = geo->c.ws_opt * (geo->c.csecs / PAGE_SIZE);
 	max_write_ppas = pblk->min_write_pgs * geo->all_luns;
 	pblk->max_write_pgs = min_t(int, max_write_ppas, NVM_MAX_VLBA);
 	pblk_set_sec_per_write(pblk, pblk->min_write_pgs);
@@ -724,19 +739,13 @@ static int pblk_lines_init(struct pblk *pblk)
 		return -EINVAL;
 	}
 
-	div_u64_rem(geo->sec_per_chk, pblk->min_write_pgs, &mod);
-	if (mod) {
-		pr_err("pblk: bad configuration of sectors/pages\n");
-		return -EINVAL;
-	}
-
-	l_mg->nr_lines = geo->nr_chks;
+	l_mg->nr_lines = geo->c.num_chk;
 	l_mg->log_line = l_mg->data_line = NULL;
 	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
 	l_mg->nr_free_lines = 0;
 	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
 
-	lm->sec_per_line = geo->sec_per_chk * geo->all_luns;
+	lm->sec_per_line = geo->c.clba * geo->all_luns;
 	lm->blk_per_line = geo->all_luns;
 	lm->blk_bitmap_len = BITS_TO_LONGS(geo->all_luns) * sizeof(long);
 	lm->sec_bitmap_len = BITS_TO_LONGS(lm->sec_per_line) * sizeof(long);
@@ -750,8 +759,8 @@ static int pblk_lines_init(struct pblk *pblk)
 	 */
 	i = 1;
 add_smeta_page:
-	lm->smeta_sec = i * geo->sec_per_pl;
-	lm->smeta_len = lm->smeta_sec * geo->sec_size;
+	lm->smeta_sec = i * geo->c.ws_opt;
+	lm->smeta_len = lm->smeta_sec * geo->c.csecs;
 
 	smeta_len = sizeof(struct line_smeta) + lm->lun_bitmap_len;
 	if (smeta_len > lm->smeta_len) {
@@ -764,8 +773,8 @@ static int pblk_lines_init(struct pblk *pblk)
 	 */
 	i = 1;
 add_emeta_page:
-	lm->emeta_sec[0] = i * geo->sec_per_pl;
-	lm->emeta_len[0] = lm->emeta_sec[0] * geo->sec_size;
+	lm->emeta_sec[0] = i * geo->c.ws_opt;
+	lm->emeta_len[0] = lm->emeta_sec[0] * geo->c.csecs;
 
 	emeta_len = calc_emeta_len(pblk);
 	if (emeta_len > lm->emeta_len[0]) {
@@ -778,7 +787,7 @@ static int pblk_lines_init(struct pblk *pblk)
 	lm->min_blk_line = 1;
 	if (geo->all_luns > 1)
 		lm->min_blk_line += DIV_ROUND_UP(lm->smeta_sec +
-					lm->emeta_sec[0], geo->sec_per_chk);
+					lm->emeta_sec[0], geo->c.clba);
 
 	if (lm->min_blk_line > lm->blk_per_line) {
 		pr_err("pblk: config. not supported. Min. LUN in line:%d\n",
@@ -802,9 +811,9 @@ static int pblk_lines_init(struct pblk *pblk)
 		goto fail_free_bb_template;
 	}
 
-	bb_distance = (geo->all_luns) * geo->sec_per_pl;
+	bb_distance = (geo->all_luns) * geo->c.ws_opt;
 	for (i = 0; i < lm->sec_per_line; i += bb_distance)
-		bitmap_set(l_mg->bb_template, i, geo->sec_per_pl);
+		bitmap_set(l_mg->bb_template, i, geo->c.ws_opt);
 
 	INIT_LIST_HEAD(&l_mg->free_list);
 	INIT_LIST_HEAD(&l_mg->corrupt_list);
@@ -981,9 +990,9 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 	struct pblk *pblk;
 	int ret;
 
-	if (dev->identity.dom & NVM_RSP_L2P) {
+	if (dev->geo.c.dom & NVM_RSP_L2P) {
 		pr_err("pblk: host-side L2P table not supported. (%x)\n",
-							dev->identity.dom);
+							dev->geo.c.dom);
 		return ERR_PTR(-EINVAL);
 	}
 
@@ -1091,7 +1100,7 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 
 	blk_queue_write_cache(tqueue, true, false);
 
-	tqueue->limits.discard_granularity = geo->sec_per_chk * geo->sec_size;
+	tqueue->limits.discard_granularity = geo->c.clba * geo->c.csecs;
 	tqueue->limits.discard_alignment = 0;
 	blk_queue_max_discard_sectors(tqueue, UINT_MAX >> 9);
 	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, tqueue);
diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c
index 2f761283f43e..ebb6bae3a3b8 100644
--- a/drivers/lightnvm/pblk-read.c
+++ b/drivers/lightnvm/pblk-read.c
@@ -563,7 +563,7 @@ int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq)
 	if (!(gc_rq->secs_to_gc))
 		goto out;
 
-	data_len = (gc_rq->secs_to_gc) * geo->sec_size;
+	data_len = (gc_rq->secs_to_gc) * geo->c.csecs;
 	bio = pblk_bio_map_addr(pblk, gc_rq->data, gc_rq->secs_to_gc, data_len,
 						PBLK_VMALLOC_META, GFP_KERNEL);
 	if (IS_ERR(bio)) {
diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
index aaab9a5c17cc..1574dbbfbb1c 100644
--- a/drivers/lightnvm/pblk-recovery.c
+++ b/drivers/lightnvm/pblk-recovery.c
@@ -184,7 +184,7 @@ static int pblk_calc_sec_in_line(struct pblk *pblk, struct pblk_line *line)
 	int nr_bb = bitmap_weight(line->blk_bitmap, lm->blk_per_line);
 
 	return lm->sec_per_line - lm->smeta_sec - lm->emeta_sec[0] -
-				nr_bb * geo->sec_per_chk;
+				nr_bb * geo->c.clba;
 }
 
 struct pblk_recov_alloc {
@@ -232,7 +232,7 @@ static int pblk_recov_read_oob(struct pblk *pblk, struct pblk_line *line,
 	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
 	if (!rq_ppas)
 		rq_ppas = pblk->min_write_pgs;
-	rq_len = rq_ppas * geo->sec_size;
+	rq_len = rq_ppas * geo->c.csecs;
 
 	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
 	if (IS_ERR(bio))
@@ -351,7 +351,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
 	if (!pad_rq)
 		return -ENOMEM;
 
-	data = vzalloc(pblk->max_write_pgs * geo->sec_size);
+	data = vzalloc(pblk->max_write_pgs * geo->c.csecs);
 	if (!data) {
 		ret = -ENOMEM;
 		goto free_rq;
@@ -368,7 +368,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
 		goto fail_free_pad;
 	}
 
-	rq_len = rq_ppas * geo->sec_size;
+	rq_len = rq_ppas * geo->c.csecs;
 
 	meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, &dma_meta_list);
 	if (!meta_list) {
@@ -509,7 +509,7 @@ static int pblk_recov_scan_all_oob(struct pblk *pblk, struct pblk_line *line,
 	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
 	if (!rq_ppas)
 		rq_ppas = pblk->min_write_pgs;
-	rq_len = rq_ppas * geo->sec_size;
+	rq_len = rq_ppas * geo->c.csecs;
 
 	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
 	if (IS_ERR(bio))
@@ -640,7 +640,7 @@ static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line,
 	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
 	if (!rq_ppas)
 		rq_ppas = pblk->min_write_pgs;
-	rq_len = rq_ppas * geo->sec_size;
+	rq_len = rq_ppas * geo->c.csecs;
 
 	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
 	if (IS_ERR(bio))
@@ -745,7 +745,7 @@ static int pblk_recov_l2p_from_oob(struct pblk *pblk, struct pblk_line *line)
 	ppa_list = (void *)(meta_list) + pblk_dma_meta_size;
 	dma_ppa_list = dma_meta_list + pblk_dma_meta_size;
 
-	data = kcalloc(pblk->max_write_pgs, geo->sec_size, GFP_KERNEL);
+	data = kcalloc(pblk->max_write_pgs, geo->c.csecs, GFP_KERNEL);
 	if (!data) {
 		ret = -ENOMEM;
 		goto free_meta_list;
diff --git a/drivers/lightnvm/pblk-rl.c b/drivers/lightnvm/pblk-rl.c
index 0d457b162f23..bcab203477ec 100644
--- a/drivers/lightnvm/pblk-rl.c
+++ b/drivers/lightnvm/pblk-rl.c
@@ -200,7 +200,7 @@ void pblk_rl_init(struct pblk_rl *rl, int budget)
 
 	/* Consider sectors used for metadata */
 	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
-	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
+	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
 
 	rl->high = pblk->op_blks - blk_meta - lm->blk_per_line;
 	rl->high_pw = get_count_order(rl->high);
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index d93e9b1f083a..5eb21a279361 100644
--- a/drivers/lightnvm/pblk-sysfs.c
+++ b/drivers/lightnvm/pblk-sysfs.c
@@ -113,26 +113,31 @@ 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;
 
-	sz = snprintf(page, PAGE_SIZE - sz,
-		"g:(b:%d)blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
-		pblk->ppaf_bitsize,
-		pblk->ppaf.blk_offset, geo->ppaf.blk_len,
-		pblk->ppaf.pg_offset, geo->ppaf.pg_len,
-		pblk->ppaf.lun_offset, geo->ppaf.lun_len,
-		pblk->ppaf.ch_offset, geo->ppaf.ch_len,
-		pblk->ppaf.pln_offset, geo->ppaf.pln_len,
-		pblk->ppaf.sec_offset, geo->ppaf.sect_len);
+	ppaf = (struct nvm_addr_format_12 *)&pblk->ppaf;
+	geo_ppaf = (struct nvm_addr_format_12 *)&geo->c.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",
+			pblk->ppaf_bitsize,
+			ppaf->ch_offset, ppaf->ch_len,
+			ppaf->lun_offset, ppaf->lun_len,
+			ppaf->blk_offset, ppaf->blk_len,
+			ppaf->pg_offset, ppaf->pg_len,
+			ppaf->pln_offset, ppaf->pln_len,
+			ppaf->sect_offset, ppaf->sect_len);
 
 	sz += snprintf(page + sz, PAGE_SIZE - sz,
-		"d:blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
-		geo->ppaf.blk_offset, geo->ppaf.blk_len,
-		geo->ppaf.pg_offset, geo->ppaf.pg_len,
-		geo->ppaf.lun_offset, geo->ppaf.lun_len,
-		geo->ppaf.ch_offset, geo->ppaf.ch_len,
-		geo->ppaf.pln_offset, geo->ppaf.pln_len,
-		geo->ppaf.sect_offset, geo->ppaf.sect_len);
+		"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->sect_offset, geo_ppaf->sect_len);
 
 	return sz;
 }
@@ -288,7 +293,7 @@ static ssize_t pblk_sysfs_lines_info(struct pblk *pblk, char *page)
 				"blk_line:%d, sec_line:%d, sec_blk:%d\n",
 					lm->blk_per_line,
 					lm->sec_per_line,
-					geo->sec_per_chk);
+					geo->c.clba);
 
 	return sz;
 }
diff --git a/drivers/lightnvm/pblk-write.c b/drivers/lightnvm/pblk-write.c
index aae86ed60b98..c49b27539d5a 100644
--- a/drivers/lightnvm/pblk-write.c
+++ b/drivers/lightnvm/pblk-write.c
@@ -333,7 +333,7 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line)
 	m_ctx = nvm_rq_to_pdu(rqd);
 	m_ctx->private = meta_line;
 
-	rq_len = rq_ppas * geo->sec_size;
+	rq_len = rq_ppas * geo->c.csecs;
 	data = ((void *)emeta->buf) + emeta->mem;
 
 	bio = pblk_bio_map_addr(pblk, data, rq_ppas, rq_len,
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 282dfc8780e8..67ffb53608f7 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -551,21 +551,6 @@ struct pblk_line_meta {
 	unsigned int meta_distance;	/* Distance between data and metadata */
 };
 
-struct pblk_addr_format {
-	u64	ch_mask;
-	u64	lun_mask;
-	u64	pln_mask;
-	u64	blk_mask;
-	u64	pg_mask;
-	u64	sec_mask;
-	u8	ch_offset;
-	u8	lun_offset;
-	u8	pln_offset;
-	u8	blk_offset;
-	u8	pg_offset;
-	u8	sec_offset;
-};
-
 enum {
 	PBLK_STATE_RUNNING = 0,
 	PBLK_STATE_STOPPING = 1,
@@ -585,8 +570,8 @@ struct pblk {
 	struct pblk_line_mgmt l_mg;		/* Line management */
 	struct pblk_line_meta lm;		/* Line metadata */
 
+	struct nvm_addr_format ppaf;
 	int ppaf_bitsize;
-	struct pblk_addr_format ppaf;
 
 	struct pblk_rb rwb;
 
@@ -941,14 +926,12 @@ static inline int pblk_line_vsc(struct pblk_line *line)
 	return le32_to_cpu(*line->vsc);
 }
 
-#define NVM_MEM_PAGE_WRITE (8)
-
 static inline int pblk_pad_distance(struct pblk *pblk)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
 
-	return NVM_MEM_PAGE_WRITE * geo->all_luns * geo->sec_per_pl;
+	return geo->c.mw_cunits * geo->all_luns * geo->c.ws_opt;
 }
 
 static inline int pblk_ppa_to_line(struct ppa_addr p)
@@ -964,15 +947,17 @@ 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->ppaf;
 	struct ppa_addr ppa;
 
 	ppa.ppa = 0;
 	ppa.g.blk = line_id;
-	ppa.g.pg = (paddr & pblk->ppaf.pg_mask) >> pblk->ppaf.pg_offset;
-	ppa.g.lun = (paddr & pblk->ppaf.lun_mask) >> pblk->ppaf.lun_offset;
-	ppa.g.ch = (paddr & pblk->ppaf.ch_mask) >> pblk->ppaf.ch_offset;
-	ppa.g.pl = (paddr & pblk->ppaf.pln_mask) >> pblk->ppaf.pln_offset;
-	ppa.g.sec = (paddr & pblk->ppaf.sec_mask) >> pblk->ppaf.sec_offset;
+	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->sect_offset;
 
 	return ppa;
 }
@@ -980,13 +965,15 @@ 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->ppaf;
 	u64 paddr;
 
-	paddr = (u64)p.g.pg << pblk->ppaf.pg_offset;
-	paddr |= (u64)p.g.lun << pblk->ppaf.lun_offset;
-	paddr |= (u64)p.g.ch << pblk->ppaf.ch_offset;
-	paddr |= (u64)p.g.pl << pblk->ppaf.pln_offset;
-	paddr |= (u64)p.g.sec << pblk->ppaf.sec_offset;
+	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->sect_offset;
 
 	return paddr;
 }
@@ -1003,18 +990,15 @@ 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 {
-		ppa64.g.blk = (ppa32 & pblk->ppaf.blk_mask) >>
-							pblk->ppaf.blk_offset;
-		ppa64.g.pg = (ppa32 & pblk->ppaf.pg_mask) >>
-							pblk->ppaf.pg_offset;
-		ppa64.g.lun = (ppa32 & pblk->ppaf.lun_mask) >>
-							pblk->ppaf.lun_offset;
-		ppa64.g.ch = (ppa32 & pblk->ppaf.ch_mask) >>
-							pblk->ppaf.ch_offset;
-		ppa64.g.pl = (ppa32 & pblk->ppaf.pln_mask) >>
-							pblk->ppaf.pln_offset;
-		ppa64.g.sec = (ppa32 & pblk->ppaf.sec_mask) >>
-							pblk->ppaf.sec_offset;
+		struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&pblk->ppaf;
+
+		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->sect_offset;
 	}
 
 	return ppa64;
@@ -1030,12 +1014,15 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
 		ppa32 |= ppa64.c.line;
 		ppa32 |= 1U << 31;
 	} else {
-		ppa32 |= ppa64.g.blk << pblk->ppaf.blk_offset;
-		ppa32 |= ppa64.g.pg << pblk->ppaf.pg_offset;
-		ppa32 |= ppa64.g.lun << pblk->ppaf.lun_offset;
-		ppa32 |= ppa64.g.ch << pblk->ppaf.ch_offset;
-		ppa32 |= ppa64.g.pl << pblk->ppaf.pln_offset;
-		ppa32 |= ppa64.g.sec << pblk->ppaf.sec_offset;
+		struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&pblk->ppaf;
+
+		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->sect_offset;
 	}
 
 	return ppa32;
@@ -1153,7 +1140,7 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type)
 	struct nvm_geo *geo = &dev->geo;
 	int flags;
 
-	flags = geo->plane_mode >> 1;
+	flags = geo->c.pln_mode >> 1;
 
 	if (type == PBLK_WRITE)
 		flags |= NVM_IO_SCRAMBLE_ENABLE;
@@ -1174,7 +1161,7 @@ static inline int pblk_set_read_mode(struct pblk *pblk, int type)
 
 	flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
 	if (type == PBLK_READ_SEQUENTIAL)
-		flags |= geo->plane_mode >> 1;
+		flags |= geo->c.pln_mode >> 1;
 
 	return flags;
 }
@@ -1229,10 +1216,10 @@ static inline int pblk_boundary_ppa_checks(struct nvm_tgt_dev *tgt_dev,
 		if (!ppa->c.is_cached &&
 				ppa->g.ch < geo->nr_chnls &&
 				ppa->g.lun < geo->nr_luns &&
-				ppa->g.pl < geo->nr_planes &&
-				ppa->g.blk < geo->nr_chks &&
-				ppa->g.pg < geo->ws_per_chk &&
-				ppa->g.sec < geo->sec_per_pg)
+				ppa->g.pl < geo->c.num_pln &&
+				ppa->g.blk < geo->c.num_chk &&
+				ppa->g.pg < geo->c.num_pg &&
+				ppa->g.sec < geo->c.ws_min)
 			continue;
 
 		print_ppa(ppa, "boundary", i);
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 839c0b96466a..c81e64cc20d7 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -152,8 +152,8 @@ struct nvme_nvm_id12_addrf {
 	__u8			blk_len;
 	__u8			pg_offset;
 	__u8			pg_len;
-	__u8			sect_offset;
-	__u8			sect_len;
+	__u8			sec_offset;
+	__u8			sec_len;
 	__u8			res[4];
 } __packed;
 
@@ -254,106 +254,157 @@ static inline void _nvme_nvm_check_size(void)
 	BUILD_BUG_ON(sizeof(struct nvme_nvm_id20) != NVME_IDENTIFY_DATA_SIZE);
 }
 
-static int init_grp(struct nvm_id *nvm_id, struct nvme_nvm_id12 *id12)
+static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
+				 struct nvme_nvm_id12_addrf *src)
+{
+	dst->ch_len = src->ch_len;
+	dst->lun_len = src->lun_len;
+	dst->blk_len = src->blk_len;
+	dst->pg_len = src->pg_len;
+	dst->pln_len = src->pln_len;
+	dst->sect_len = src->sec_len;
+
+	dst->ch_offset = src->ch_offset;
+	dst->lun_offset = src->lun_offset;
+	dst->blk_offset = src->blk_offset;
+	dst->pg_offset = src->pg_offset;
+	dst->pln_offset = src->pln_offset;
+	dst->sect_offset = src->sec_offset;
+
+	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
+	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
+	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
+	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
+	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
+	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
+}
+
+static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
+			     struct nvm_dev_geo *dev_geo)
 {
 	struct nvme_nvm_id12_grp *src;
 	int sec_per_pg, sec_per_pl, pg_per_blk;
 
-	if (id12->cgrps != 1)
+	if (id->cgrps != 1)
 		return -EINVAL;
 
-	src = &id12->grp;
+	src = &id->grp;
 
-	nvm_id->mtype = src->mtype;
-	nvm_id->fmtype = src->fmtype;
+	if (src->mtype != 0) {
+		pr_err("nvm: memory type not supported\n");
+		return -EINVAL;
+	}
+
+	/* 1.2 spec. only reports a single version id - unfold */
+	dev_geo->ver_id = id->ver_id;
 
-	nvm_id->num_ch = src->num_ch;
-	nvm_id->num_lun = src->num_lun;
+	dev_geo->nr_chnls = src->num_ch;
+	dev_geo->nr_luns = src->num_lun;
+	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
 
-	nvm_id->num_chk = le16_to_cpu(src->num_chk);
-	nvm_id->csecs = le16_to_cpu(src->csecs);
-	nvm_id->sos = le16_to_cpu(src->sos);
+	dev_geo->c.num_chk = le16_to_cpu(src->num_chk);
+	dev_geo->c.csecs = le16_to_cpu(src->csecs);
+	dev_geo->c.sos = le16_to_cpu(src->sos);
 
 	pg_per_blk = le16_to_cpu(src->num_pg);
-	sec_per_pg = le16_to_cpu(src->fpg_sz) / nvm_id->csecs;
+	sec_per_pg = le16_to_cpu(src->fpg_sz) / dev_geo->c.csecs;
 	sec_per_pl = sec_per_pg * src->num_pln;
-	nvm_id->clba = sec_per_pl * pg_per_blk;
-	nvm_id->ws_per_chk = pg_per_blk;
-
-	nvm_id->mpos = le32_to_cpu(src->mpos);
-	nvm_id->cpar = le16_to_cpu(src->cpar);
-	nvm_id->mccap = le32_to_cpu(src->mccap);
-
-	nvm_id->ws_opt = nvm_id->ws_min = sec_per_pg;
-	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
-
-	if (nvm_id->mpos & 0x020202) {
-		nvm_id->ws_seq = NVM_IO_DUAL_ACCESS;
-		nvm_id->ws_opt <<= 1;
-	} else if (nvm_id->mpos & 0x040404) {
-		nvm_id->ws_seq = NVM_IO_QUAD_ACCESS;
-		nvm_id->ws_opt <<= 2;
+	dev_geo->c.clba = sec_per_pl * pg_per_blk;
+
+	dev_geo->c.ws_min = sec_per_pg;
+	dev_geo->c.ws_opt = sec_per_pg;
+	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
+
+	dev_geo->c.mccap = le32_to_cpu(src->mccap);
+
+	dev_geo->c.trdt = le32_to_cpu(src->trdt);
+	dev_geo->c.trdm = le32_to_cpu(src->trdm);
+	dev_geo->c.tprt = le32_to_cpu(src->tprt);
+	dev_geo->c.tprm = le32_to_cpu(src->tprm);
+	dev_geo->c.tbet = le32_to_cpu(src->tbet);
+	dev_geo->c.tbem = le32_to_cpu(src->tbem);
+
+	/* 1.2 compatibility */
+	dev_geo->c.vmnt = id->vmnt;
+	dev_geo->c.cap = le32_to_cpu(id->cap);
+	dev_geo->c.dom = le32_to_cpu(id->dom);
+
+	dev_geo->c.mtype = src->mtype;
+	dev_geo->c.fmtype = src->fmtype;
+
+	dev_geo->c.cpar = le16_to_cpu(src->cpar);
+	dev_geo->c.mpos = le32_to_cpu(src->mpos);
+
+	dev_geo->c.pln_mode = NVM_PLANE_SINGLE;
+
+	if (dev_geo->c.mpos & 0x020202) {
+		dev_geo->c.pln_mode = NVM_PLANE_DOUBLE;
+		dev_geo->c.ws_opt <<= 1;
+	} else if (dev_geo->c.mpos & 0x040404) {
+		dev_geo->c.pln_mode = NVM_PLANE_QUAD;
+		dev_geo->c.ws_opt <<= 2;
 	}
 
-	nvm_id->trdt = le32_to_cpu(src->trdt);
-	nvm_id->trdm = le32_to_cpu(src->trdm);
-	nvm_id->tprt = le32_to_cpu(src->tprt);
-	nvm_id->tprm = le32_to_cpu(src->tprm);
-	nvm_id->tbet = le32_to_cpu(src->tbet);
-	nvm_id->tbem = le32_to_cpu(src->tbem);
-
-	/* 1.2 compatibility */
-	nvm_id->num_pln = src->num_pln;
-	nvm_id->num_pg = le16_to_cpu(src->num_pg);
-	nvm_id->fpg_sz = le16_to_cpu(src->fpg_sz);
+	dev_geo->c.num_pln = src->num_pln;
+	dev_geo->c.num_pg = le16_to_cpu(src->num_pg);
+	dev_geo->c.fpg_sz = le16_to_cpu(src->fpg_sz);
+
+	nvme_nvm_set_addr_12((struct nvm_addr_format_12 *)&dev_geo->c.addrf,
+								&id->ppaf);
 
 	return 0;
 }
 
-static int nvme_nvm_setup_12(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
-		struct nvme_nvm_id12 *id)
+static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
+				 struct nvme_nvm_id20_addrf *src)
 {
-	nvm_id->ver_id = id->ver_id;
-	nvm_id->vmnt = id->vmnt;
-	nvm_id->cap = le32_to_cpu(id->cap);
-	nvm_id->dom = le32_to_cpu(id->dom);
-	memcpy(&nvm_id->ppaf, &id->ppaf,
-					sizeof(struct nvm_addr_format));
-
-	return init_grp(nvm_id, id);
+	dst->ch_len = src->grp_len;
+	dst->lun_len = src->pu_len;
+	dst->chk_len = src->chk_len;
+	dst->sec_len = src->lba_len;
+
+	dst->sec_offset = 0;
+	dst->chk_offset = dst->sec_len;
+	dst->lun_offset = dst->chk_offset + dst->chk_len;
+	dst->ch_offset = dst->lun_offset + dst->lun_len;
+
+	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
+	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
+	dst->chk_mask = ((1ULL << dst->chk_len) - 1) << dst->chk_offset;
+	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
 }
 
-static int nvme_nvm_setup_20(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
-		struct nvme_nvm_id20 *id)
+static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
+			     struct nvm_dev_geo *dev_geo)
 {
-	nvm_id->ver_id = id->mjr;
+	dev_geo->ver_id = id->mjr;
 
-	nvm_id->num_ch = le16_to_cpu(id->num_grp);
-	nvm_id->num_lun = le16_to_cpu(id->num_pu);
-	nvm_id->num_chk = le32_to_cpu(id->num_chk);
-	nvm_id->clba = le32_to_cpu(id->clba);
+	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
+	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
+	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
 
-	nvm_id->ws_min = le32_to_cpu(id->ws_min);
-	nvm_id->ws_opt = le32_to_cpu(id->ws_opt);
-	nvm_id->mw_cunits = le32_to_cpu(id->mw_cunits);
+	dev_geo->c.num_chk = le32_to_cpu(id->num_chk);
+	dev_geo->c.clba = le32_to_cpu(id->clba);
+	dev_geo->c.csecs = -1;		/* Set by nvme identify */
+	dev_geo->c.sos = -1;		/* Set bu nvme identify */
 
-	nvm_id->trdt = le32_to_cpu(id->trdt);
-	nvm_id->trdm = le32_to_cpu(id->trdm);
-	nvm_id->tprt = le32_to_cpu(id->twrt);
-	nvm_id->tprm = le32_to_cpu(id->twrm);
-	nvm_id->tbet = le32_to_cpu(id->tcrst);
-	nvm_id->tbem = le32_to_cpu(id->tcrsm);
+	dev_geo->c.ws_min = le32_to_cpu(id->ws_min);
+	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
+	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
 
-	/* calculated values */
-	nvm_id->ws_per_chk = nvm_id->clba / nvm_id->ws_min;
+	dev_geo->c.trdt = le32_to_cpu(id->trdt);
+	dev_geo->c.trdm = le32_to_cpu(id->trdm);
+	dev_geo->c.tprt = le32_to_cpu(id->twrt);
+	dev_geo->c.tprm = le32_to_cpu(id->twrm);
+	dev_geo->c.tbet = le32_to_cpu(id->tcrst);
+	dev_geo->c.tbem = le32_to_cpu(id->tcrsm);
 
-	/* 1.2 compatibility */
-	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
+	nvme_nvm_set_addr_20(&dev_geo->c.addrf, &id->lbaf);
 
 	return 0;
 }
 
-static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
+static int nvme_nvm_identity(struct nvm_dev *nvmdev)
 {
 	struct nvme_ns *ns = nvmdev->q->queuedata;
 	struct nvme_nvm_id12 *id;
@@ -380,18 +431,18 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
 	 */
 	switch (id->ver_id) {
 	case 1:
-		ret = nvme_nvm_setup_12(nvmdev, nvm_id, id);
+		ret = nvme_nvm_setup_12(id, &nvmdev->dev_geo);
 		break;
 	case 2:
-		ret = nvme_nvm_setup_20(nvmdev, nvm_id,
-				(struct nvme_nvm_id20 *)id);
+		ret = nvme_nvm_setup_20((struct nvme_nvm_id20 *)id,
+							&nvmdev->dev_geo);
 		break;
 	default:
-		dev_err(ns->ctrl->device,
-			"OCSSD revision not supported (%d)\n",
-			nvm_id->ver_id);
+		dev_err(ns->ctrl->device, "OCSSD revision not supported (%d)\n",
+							id->ver_id);
 		ret = -EINVAL;
 	}
+
 out:
 	kfree(id);
 	return ret;
@@ -401,12 +452,12 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
 								u8 *blks)
 {
 	struct request_queue *q = nvmdev->q;
-	struct nvm_geo *geo = &nvmdev->geo;
+	struct nvm_dev_geo *dev_geo = &nvmdev->dev_geo;
 	struct nvme_ns *ns = q->queuedata;
 	struct nvme_ctrl *ctrl = ns->ctrl;
 	struct nvme_nvm_command c = {};
 	struct nvme_nvm_bb_tbl *bb_tbl;
-	int nr_blks = geo->nr_chks * geo->plane_mode;
+	int nr_blks = dev_geo->c.num_chk * dev_geo->c.num_pln;
 	int tblsz = sizeof(struct nvme_nvm_bb_tbl) + nr_blks;
 	int ret = 0;
 
@@ -447,7 +498,7 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
 		goto out;
 	}
 
-	memcpy(blks, bb_tbl->blk, geo->nr_chks * geo->plane_mode);
+	memcpy(blks, bb_tbl->blk, dev_geo->c.num_chk * dev_geo->c.num_pln);
 out:
 	kfree(bb_tbl);
 	return ret;
@@ -815,9 +866,10 @@ int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd, unsigned long arg)
 void nvme_nvm_update_nvm_info(struct nvme_ns *ns)
 {
 	struct nvm_dev *ndev = ns->ndev;
+	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
 
-	ndev->identity.csecs = ndev->geo.sec_size = 1 << ns->lba_shift;
-	ndev->identity.sos = ndev->geo.oob_size = ns->ms;
+	dev_geo->c.csecs = 1 << ns->lba_shift;
+	dev_geo->c.sos = ns->ms;
 }
 
 int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node)
@@ -850,23 +902,22 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
 {
 	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
 	struct nvm_dev *ndev = ns->ndev;
-	struct nvm_id *id;
+	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
 	struct attribute *attr;
 
 	if (!ndev)
 		return 0;
 
-	id = &ndev->identity;
 	attr = &dattr->attr;
 
 	if (strcmp(attr->name, "version") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->ver_id);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
 	} else if (strcmp(attr->name, "capabilities") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->cap);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
 	} else if (strcmp(attr->name, "read_typ") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdt);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
 	} else if (strcmp(attr->name, "read_max") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdm);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdm);
 	} else {
 		return scnprintf(page,
 				 PAGE_SIZE,
@@ -875,75 +926,79 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
 	}
 }
 
+static ssize_t nvm_dev_attr_show_ppaf(struct nvm_addr_format_12 *ppaf,
+					 char *page)
+{
+	return scnprintf(page, PAGE_SIZE,
+		"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+				ppaf->ch_offset, ppaf->ch_len,
+				ppaf->lun_offset, ppaf->lun_len,
+				ppaf->pln_offset, ppaf->pln_len,
+				ppaf->blk_offset, ppaf->blk_len,
+				ppaf->pg_offset, ppaf->pg_len,
+				ppaf->sect_offset, ppaf->sect_len);
+}
+
 static ssize_t nvm_dev_attr_show_12(struct device *dev,
 		struct device_attribute *dattr, char *page)
 {
 	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
 	struct nvm_dev *ndev = ns->ndev;
-	struct nvm_id *id;
+	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
 	struct attribute *attr;
 
 	if (!ndev)
 		return 0;
 
-	id = &ndev->identity;
 	attr = &dattr->attr;
 
 	if (strcmp(attr->name, "vendor_opcode") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->vmnt);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.vmnt);
 	} else if (strcmp(attr->name, "device_mode") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->dom);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.dom);
 	/* kept for compatibility */
 	} else if (strcmp(attr->name, "media_manager") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%s\n", "gennvm");
 	} else if (strcmp(attr->name, "ppa_format") == 0) {
-		return scnprintf(page, PAGE_SIZE,
-			"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
-			id->ppaf.ch_offset, id->ppaf.ch_len,
-			id->ppaf.lun_offset, id->ppaf.lun_len,
-			id->ppaf.pln_offset, id->ppaf.pln_len,
-			id->ppaf.blk_offset, id->ppaf.blk_len,
-			id->ppaf.pg_offset, id->ppaf.pg_len,
-			id->ppaf.sect_offset, id->ppaf.sect_len);
+		return nvm_dev_attr_show_ppaf((void *)&dev_geo->c.addrf, page);
 	} else if (strcmp(attr->name, "media_type") == 0) {	/* u8 */
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->mtype);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mtype);
 	} else if (strcmp(attr->name, "flash_media_type") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->fmtype);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fmtype);
 	} else if (strcmp(attr->name, "num_channels") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
 	} else if (strcmp(attr->name, "num_luns") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
 	} else if (strcmp(attr->name, "num_planes") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pln);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pln);
 	} else if (strcmp(attr->name, "num_blocks") == 0) {	/* u16 */
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
 	} else if (strcmp(attr->name, "num_pages") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pg);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pg);
 	} else if (strcmp(attr->name, "page_size") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->fpg_sz);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fpg_sz);
 	} else if (strcmp(attr->name, "hw_sector_size") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->csecs);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.csecs);
 	} else if (strcmp(attr->name, "oob_sector_size") == 0) {/* u32 */
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->sos);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.sos);
 	} else if (strcmp(attr->name, "prog_typ") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
 	} else if (strcmp(attr->name, "prog_max") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
 	} else if (strcmp(attr->name, "erase_typ") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
 	} else if (strcmp(attr->name, "erase_max") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
 	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
-		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mpos);
+		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
 	} else if (strcmp(attr->name, "media_capabilities") == 0) {
-		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mccap);
+		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
 	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
 	} else {
-		return scnprintf(page,
-				 PAGE_SIZE,
-				 "Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
-				 attr->name);
+		return scnprintf(page, PAGE_SIZE,
+			"Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
+			attr->name);
 	}
 }
 
@@ -952,42 +1007,40 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
 {
 	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
 	struct nvm_dev *ndev = ns->ndev;
-	struct nvm_id *id;
+	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
 	struct attribute *attr;
 
 	if (!ndev)
 		return 0;
 
-	id = &ndev->identity;
 	attr = &dattr->attr;
 
 	if (strcmp(attr->name, "groups") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
 	} else if (strcmp(attr->name, "punits") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
 	} else if (strcmp(attr->name, "chunks") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
 	} else if (strcmp(attr->name, "clba") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->clba);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.clba);
 	} else if (strcmp(attr->name, "ws_min") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_min);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_min);
 	} else if (strcmp(attr->name, "ws_opt") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_opt);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_opt);
 	} else if (strcmp(attr->name, "mw_cunits") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->mw_cunits);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mw_cunits);
 	} else if (strcmp(attr->name, "write_typ") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
 	} else if (strcmp(attr->name, "write_max") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
 	} else if (strcmp(attr->name, "reset_typ") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
 	} else if (strcmp(attr->name, "reset_max") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
 	} else {
-		return scnprintf(page,
-				 PAGE_SIZE,
-				 "Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
-				 attr->name);
+		return scnprintf(page, PAGE_SIZE,
+			"Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
+			attr->name);
 	}
 }
 
@@ -1106,10 +1159,13 @@ static const struct attribute_group nvm_dev_attr_group_20 = {
 
 int nvme_nvm_register_sysfs(struct nvme_ns *ns)
 {
-	if (!ns->ndev)
+	struct nvm_dev *ndev = ns->ndev;
+	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
+
+	if (!ndev)
 		return -EINVAL;
 
-	switch (ns->ndev->identity.ver_id) {
+	switch (dev_geo->ver_id) {
 	case 1:
 		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
 					&nvm_dev_attr_group_12);
@@ -1123,7 +1179,10 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
 
 void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
 {
-	switch (ns->ndev->identity.ver_id) {
+	struct nvm_dev *ndev = ns->ndev;
+	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
+
+	switch (dev_geo->ver_id) {
 	case 1:
 		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
 					&nvm_dev_attr_group_12);
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index e55b10573c99..18e3751b1632 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -50,7 +50,7 @@ struct nvm_id;
 struct nvm_dev;
 struct nvm_tgt_dev;
 
-typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *);
+typedef int (nvm_id_fn)(struct nvm_dev *);
 typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, u8 *);
 typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct ppa_addr *, int, int);
 typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
@@ -152,62 +152,107 @@ struct nvm_id_lp_tbl {
 	struct nvm_id_lp_mlc mlc;
 };
 
-struct nvm_addr_format {
-	u8	ch_offset;
+struct nvm_addr_format_12 {
 	u8	ch_len;
-	u8	lun_offset;
 	u8	lun_len;
-	u8	pln_offset;
+	u8	blk_len;
+	u8	pg_len;
 	u8	pln_len;
+	u8	sect_len;
+
+	u8	ch_offset;
+	u8	lun_offset;
 	u8	blk_offset;
-	u8	blk_len;
 	u8	pg_offset;
-	u8	pg_len;
+	u8	pln_offset;
 	u8	sect_offset;
-	u8	sect_len;
+
+	u64	ch_mask;
+	u64	lun_mask;
+	u64	blk_mask;
+	u64	pg_mask;
+	u64	pln_mask;
+	u64	sec_mask;
+};
+
+struct nvm_addr_format {
+	u8	ch_len;
+	u8	lun_len;
+	u8	chk_len;
+	u8	sec_len;
+	u8	rsv_len[2];
+
+	u8	ch_offset;
+	u8	lun_offset;
+	u8	chk_offset;
+	u8	sec_offset;
+	u8	rsv_off[2];
+
+	u64	ch_mask;
+	u64	lun_mask;
+	u64	chk_mask;
+	u64	sec_mask;
+	u64	rsv_mask[2];
 };
 
-struct nvm_id {
-	u8	ver_id;
+/* Device common geometry */
+struct nvm_common_geo {
+	/* chunk geometry */
+	u32	num_chk;	/* chunks per lun */
+	u32	clba;		/* sectors per chunk */
+	u16	csecs;		/* sector size */
+	u16	sos;		/* out-of-band area size */
+
+	/* device write constrains */
+	u32	ws_min;		/* minimum write size */
+	u32	ws_opt;		/* optimal write size */
+	u32	mw_cunits;	/* distance required for successful read */
+
+	/* device capabilities */
+	u32	mccap;
+
+	/* device timings */
+	u32	trdt;		/* Avg. Tread (ns) */
+	u32	trdm;		/* Max Tread (ns) */
+	u32	tprt;		/* Avg. Tprog (ns) */
+	u32	tprm;		/* Max Tprog (ns) */
+	u32	tbet;		/* Avg. Terase (ns) */
+	u32	tbem;		/* Max Terase (ns) */
+
+	/* generic address format */
+	struct nvm_addr_format addrf;
+
+	/* 1.2 compatibility */
 	u8	vmnt;
 	u32	cap;
 	u32	dom;
 
-	struct	nvm_addr_format ppaf;
-
-	u8	num_ch;
-	u8	num_lun;
-	u16	num_chk;
-	u16	clba;
-	u16	csecs;
-	u16	sos;
-
-	u32	ws_min;
-	u32	ws_opt;
-	u32	mw_cunits;
-
-	u32	trdt;
-	u32	trdm;
-	u32	tprt;
-	u32	tprm;
-	u32	tbet;
-	u32	tbem;
-	u32	mpos;
-	u32	mccap;
-	u16	cpar;
-
-	/* calculated values */
-	u16	ws_seq;
-	u16	ws_per_chk;
-
-	/* 1.2 compatibility */
 	u8	mtype;
 	u8	fmtype;
 
+	u16	cpar;
+	u32	mpos;
+
 	u8	num_pln;
+	u8	pln_mode;
 	u16	num_pg;
 	u16	fpg_sz;
-} __packed;
+};
+
+/* Device identified geometry */
+struct nvm_dev_geo {
+	/* device reported version */
+	u8	ver_id;
+
+	/* full device geometry */
+	u16	nr_chnls;
+	u16	nr_luns;
+
+	/* calculated values */
+	u16	all_luns;
+
+	struct nvm_common_geo c;
+};
 
 struct nvm_target {
 	struct list_head list;
@@ -274,36 +319,22 @@ enum {
 	NVM_BLK_ST_BAD =	0x8,	/* Bad block */
 };
 
-
-/* Device generic information */
+/* Instance geometry */
 struct nvm_geo {
-	/* generic geometry */
+	/* instance specific geometry */
 	int nr_chnls;
-	int all_luns; /* across channels */
-	int nr_luns; /* per channel */
-	int nr_chks; /* per lun */
-
-	int sec_size;
-	int oob_size;
-	int mccap;
-
-	int sec_per_chk;
-	int sec_per_lun;
-
-	int ws_min;
-	int ws_opt;
-	int ws_seq;
-	int ws_per_chk;
+	int nr_luns;		/* per channel */
 
 	int op;
 
-	struct nvm_addr_format ppaf;
+	/* common geometry */
+	struct nvm_common_geo c;
 
-	/* Legacy 1.2 specific geometry */
-	int plane_mode; /* drive device in single, double or quad mode */
-	int nr_planes;
-	int sec_per_pg; /* only sectors for a single page */
-	int sec_per_pl; /* all sectors across planes */
+	/* calculated values */
+	int all_luns;		/* across channels */
+	int all_chunks;		/* across channels */
+
+	sector_t total_secs;	/* across channels */
 };
 
 /* sub-device structure */
@@ -314,9 +345,6 @@ struct nvm_tgt_dev {
 	/* Base ppas for target LUNs */
 	struct ppa_addr *luns;
 
-	sector_t total_secs;
-
-	struct nvm_id identity;
 	struct request_queue *q;
 
 	struct nvm_dev *parent;
@@ -329,15 +357,11 @@ struct nvm_dev {
 	struct list_head devices;
 
 	/* Device information */
-	struct nvm_geo geo;
-
-	unsigned long total_secs;
+	struct nvm_dev_geo dev_geo;
 
 	unsigned long *lun_map;
 	void *dma_pool;
 
-	struct nvm_id identity;
-
 	/* Backend device */
 	struct request_queue *q;
 	char name[DISK_NAME_LEN];
@@ -357,14 +381,16 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
 						  struct ppa_addr r)
 {
 	struct nvm_geo *geo = &tgt_dev->geo;
+	struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&geo->c.addrf;
 	struct ppa_addr l;
 
-	l.ppa = ((u64)r.g.blk) << geo->ppaf.blk_offset;
-	l.ppa |= ((u64)r.g.pg) << geo->ppaf.pg_offset;
-	l.ppa |= ((u64)r.g.sec) << geo->ppaf.sect_offset;
-	l.ppa |= ((u64)r.g.pl) << geo->ppaf.pln_offset;
-	l.ppa |= ((u64)r.g.lun) << geo->ppaf.lun_offset;
-	l.ppa |= ((u64)r.g.ch) << geo->ppaf.ch_offset;
+	l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
+	l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
+	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
+	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
+	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
+	l.ppa |= ((u64)r.g.sec) << ppaf->sect_offset;
 
 	return l;
 }
@@ -373,24 +399,18 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
 						  struct ppa_addr r)
 {
 	struct nvm_geo *geo = &tgt_dev->geo;
+	struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&geo->c.addrf;
 	struct ppa_addr l;
 
 	l.ppa = 0;
-	/*
-	 * (r.ppa << X offset) & X len bitmask. X eq. blk, pg, etc.
-	 */
-	l.g.blk = (r.ppa >> geo->ppaf.blk_offset) &
-					(((1 << geo->ppaf.blk_len) - 1));
-	l.g.pg |= (r.ppa >> geo->ppaf.pg_offset) &
-					(((1 << geo->ppaf.pg_len) - 1));
-	l.g.sec |= (r.ppa >> geo->ppaf.sect_offset) &
-					(((1 << geo->ppaf.sect_len) - 1));
-	l.g.pl |= (r.ppa >> geo->ppaf.pln_offset) &
-					(((1 << geo->ppaf.pln_len) - 1));
-	l.g.lun |= (r.ppa >> geo->ppaf.lun_offset) &
-					(((1 << geo->ppaf.lun_len) - 1));
-	l.g.ch |= (r.ppa >> geo->ppaf.ch_offset) &
-					(((1 << geo->ppaf.ch_len) - 1));
+
+	l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
+	l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
+	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
+	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
+	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
+	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sect_offset;
 
 	return l;
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 02/20] lightnvm: add controller capabilities to 2.0
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

Assign missing mccap value on 2.0 path

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/nvme/host/lightnvm.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index c81e64cc20d7..969bb874850c 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -392,6 +392,8 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
 	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
 
+	dev_geo->c.mccap = le32_to_cpu(id->mccap);
+
 	dev_geo->c.trdt = le32_to_cpu(id->trdt);
 	dev_geo->c.trdm = le32_to_cpu(id->trdm);
 	dev_geo->c.tprt = le32_to_cpu(id->twrt);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 02/20] lightnvm: add controller capabilities to 2.0
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


Assign missing mccap value on 2.0 path

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/nvme/host/lightnvm.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index c81e64cc20d7..969bb874850c 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -392,6 +392,8 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
 	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
 
+	dev_geo->c.mccap = le32_to_cpu(id->mccap);
+
 	dev_geo->c.trdt = le32_to_cpu(id->trdt);
 	dev_geo->c.trdm = le32_to_cpu(id->trdm);
 	dev_geo->c.tprt = le32_to_cpu(id->twrt);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 03/20] lightnvm: fix capabilities for 2.0 sysfs
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

Both 1.2 and 2.0 specs define a field for media and controller
capabilities. Also, 1.2 defines a separate field dedicated to device
capabilities.

In 2.0 sysfs, this values have been mixed. Revert them to the right
value.

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/nvme/host/lightnvm.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 969bb874850c..598abba66f52 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -914,8 +914,8 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
 
 	if (strcmp(attr->name, "version") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
-	} else if (strcmp(attr->name, "capabilities") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
+	} else if (strcmp(attr->name, "media_capabilities") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
 	} else if (strcmp(attr->name, "read_typ") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
 	} else if (strcmp(attr->name, "read_max") == 0) {
@@ -993,8 +993,8 @@ static ssize_t nvm_dev_attr_show_12(struct device *dev,
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
 	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
 		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
-	} else if (strcmp(attr->name, "media_capabilities") == 0) {
-		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
+	} else if (strcmp(attr->name, "capabilities") == 0) {
+		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.cap);
 	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
 	} else {
@@ -1055,7 +1055,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
 
 /* general attributes */
 static NVM_DEV_ATTR_RO(version);
-static NVM_DEV_ATTR_RO(capabilities);
+static NVM_DEV_ATTR_RO(media_capabilities);
 
 static NVM_DEV_ATTR_RO(read_typ);
 static NVM_DEV_ATTR_RO(read_max);
@@ -1080,12 +1080,12 @@ static NVM_DEV_ATTR_12_RO(prog_max);
 static NVM_DEV_ATTR_12_RO(erase_typ);
 static NVM_DEV_ATTR_12_RO(erase_max);
 static NVM_DEV_ATTR_12_RO(multiplane_modes);
-static NVM_DEV_ATTR_12_RO(media_capabilities);
+static NVM_DEV_ATTR_12_RO(capabilities);
 static NVM_DEV_ATTR_12_RO(max_phys_secs);
 
 static struct attribute *nvm_dev_attrs_12[] = {
 	&dev_attr_version.attr,
-	&dev_attr_capabilities.attr,
+	&dev_attr_media_capabilities.attr,
 
 	&dev_attr_vendor_opcode.attr,
 	&dev_attr_device_mode.attr,
@@ -1108,7 +1108,7 @@ static struct attribute *nvm_dev_attrs_12[] = {
 	&dev_attr_erase_typ.attr,
 	&dev_attr_erase_max.attr,
 	&dev_attr_multiplane_modes.attr,
-	&dev_attr_media_capabilities.attr,
+	&dev_attr_capabilities.attr,
 	&dev_attr_max_phys_secs.attr,
 
 	NULL,
@@ -1134,7 +1134,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
 
 static struct attribute *nvm_dev_attrs_20[] = {
 	&dev_attr_version.attr,
-	&dev_attr_capabilities.attr,
+	&dev_attr_media_capabilities.attr,
 
 	&dev_attr_groups.attr,
 	&dev_attr_punits.attr,
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 03/20] lightnvm: fix capabilities for 2.0 sysfs
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


Both 1.2 and 2.0 specs define a field for media and controller
capabilities. Also, 1.2 defines a separate field dedicated to device
capabilities.

In 2.0 sysfs, this values have been mixed. Revert them to the right
value.

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/nvme/host/lightnvm.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 969bb874850c..598abba66f52 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -914,8 +914,8 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
 
 	if (strcmp(attr->name, "version") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
-	} else if (strcmp(attr->name, "capabilities") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
+	} else if (strcmp(attr->name, "media_capabilities") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
 	} else if (strcmp(attr->name, "read_typ") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
 	} else if (strcmp(attr->name, "read_max") == 0) {
@@ -993,8 +993,8 @@ static ssize_t nvm_dev_attr_show_12(struct device *dev,
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
 	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
 		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
-	} else if (strcmp(attr->name, "media_capabilities") == 0) {
-		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
+	} else if (strcmp(attr->name, "capabilities") == 0) {
+		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.cap);
 	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
 	} else {
@@ -1055,7 +1055,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
 
 /* general attributes */
 static NVM_DEV_ATTR_RO(version);
-static NVM_DEV_ATTR_RO(capabilities);
+static NVM_DEV_ATTR_RO(media_capabilities);
 
 static NVM_DEV_ATTR_RO(read_typ);
 static NVM_DEV_ATTR_RO(read_max);
@@ -1080,12 +1080,12 @@ static NVM_DEV_ATTR_12_RO(prog_max);
 static NVM_DEV_ATTR_12_RO(erase_typ);
 static NVM_DEV_ATTR_12_RO(erase_max);
 static NVM_DEV_ATTR_12_RO(multiplane_modes);
-static NVM_DEV_ATTR_12_RO(media_capabilities);
+static NVM_DEV_ATTR_12_RO(capabilities);
 static NVM_DEV_ATTR_12_RO(max_phys_secs);
 
 static struct attribute *nvm_dev_attrs_12[] = {
 	&dev_attr_version.attr,
-	&dev_attr_capabilities.attr,
+	&dev_attr_media_capabilities.attr,
 
 	&dev_attr_vendor_opcode.attr,
 	&dev_attr_device_mode.attr,
@@ -1108,7 +1108,7 @@ static struct attribute *nvm_dev_attrs_12[] = {
 	&dev_attr_erase_typ.attr,
 	&dev_attr_erase_max.attr,
 	&dev_attr_multiplane_modes.attr,
-	&dev_attr_media_capabilities.attr,
+	&dev_attr_capabilities.attr,
 	&dev_attr_max_phys_secs.attr,
 
 	NULL,
@@ -1134,7 +1134,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
 
 static struct attribute *nvm_dev_attrs_20[] = {
 	&dev_attr_version.attr,
-	&dev_attr_capabilities.attr,
+	&dev_attr_media_capabilities.attr,
 
 	&dev_attr_groups.attr,
 	&dev_attr_punits.attr,
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 04/20] lightnvm: add minor version to generic geometry
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

Separate the version between major and minor on the generic geometry.
Also, add a "subversion" entry to sysfs to expose the minor version
without breaking user space.

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/lightnvm/core.c      |  4 ++--
 drivers/nvme/host/lightnvm.c | 25 ++++++++++++++++++++-----
 include/linux/lightnvm.h     |  3 ++-
 3 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 42596afdf64c..dc9ec6baff45 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -897,8 +897,8 @@ static int nvm_init(struct nvm_dev *dev)
 		goto err;
 	}
 
-	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
-				dev_geo->ver_id,
+	pr_debug("nvm: ver:%u.%u nvm_vendor:%x\n",
+				dev_geo->major_ver_id, dev_geo->minor_ver_id,
 				dev_geo->c.vmnt);
 
 	ret = nvm_core_init(dev);
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 598abba66f52..71b4ac57a668 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -296,7 +296,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
 	}
 
 	/* 1.2 spec. only reports a single version id - unfold */
-	dev_geo->ver_id = id->ver_id;
+	dev_geo->major_ver_id = id->ver_id;
+	dev_geo->minor_ver_id = 2;
 
 	dev_geo->nr_chnls = src->num_ch;
 	dev_geo->nr_luns = src->num_lun;
@@ -377,7 +378,14 @@ static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
 static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 			     struct nvm_dev_geo *dev_geo)
 {
-	dev_geo->ver_id = id->mjr;
+	dev_geo->major_ver_id = id->mjr;
+	dev_geo->minor_ver_id = id->mnr;
+
+	if (!(dev_geo->major_ver_id == 2 && dev_geo->minor_ver_id == 0)) {
+		pr_err("nvm: OCSSD version not supported (v%d.%d)\n",
+				dev_geo->major_ver_id, dev_geo->minor_ver_id);
+		return -EINVAL;
+	}
 
 	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
 	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
@@ -913,7 +921,11 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
 	attr = &dattr->attr;
 
 	if (strcmp(attr->name, "version") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
+		return scnprintf(page, PAGE_SIZE, "%u\n",
+						dev_geo->major_ver_id);
+	} else if (strcmp(attr->name, "subversion") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n",
+						dev_geo->minor_ver_id);
 	} else if (strcmp(attr->name, "media_capabilities") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
 	} else if (strcmp(attr->name, "read_typ") == 0) {
@@ -1055,6 +1067,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
 
 /* general attributes */
 static NVM_DEV_ATTR_RO(version);
+static NVM_DEV_ATTR_RO(subversion);
 static NVM_DEV_ATTR_RO(media_capabilities);
 
 static NVM_DEV_ATTR_RO(read_typ);
@@ -1085,6 +1098,7 @@ static NVM_DEV_ATTR_12_RO(max_phys_secs);
 
 static struct attribute *nvm_dev_attrs_12[] = {
 	&dev_attr_version.attr,
+	&dev_attr_subversion.attr,
 	&dev_attr_media_capabilities.attr,
 
 	&dev_attr_vendor_opcode.attr,
@@ -1134,6 +1148,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
 
 static struct attribute *nvm_dev_attrs_20[] = {
 	&dev_attr_version.attr,
+	&dev_attr_subversion.attr,
 	&dev_attr_media_capabilities.attr,
 
 	&dev_attr_groups.attr,
@@ -1167,7 +1182,7 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
 	if (!ndev)
 		return -EINVAL;
 
-	switch (dev_geo->ver_id) {
+	switch (dev_geo->major_ver_id) {
 	case 1:
 		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
 					&nvm_dev_attr_group_12);
@@ -1184,7 +1199,7 @@ void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
 	struct nvm_dev *ndev = ns->ndev;
 	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
 
-	switch (dev_geo->ver_id) {
+	switch (dev_geo->major_ver_id) {
 	case 1:
 		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
 					&nvm_dev_attr_group_12);
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 18e3751b1632..5af0b8837095 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -242,7 +242,8 @@ struct nvm_common_geo {
 /* Device identified geometry */
 struct nvm_dev_geo {
 	/* device reported version */
-	u8	ver_id;
+	u8	major_ver_id;
+	u8	minor_ver_id;
 
 	/* full device geometry */
 	u16	nr_chnls;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 04/20] lightnvm: add minor version to generic geometry
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


Separate the version between major and minor on the generic geometry.
Also, add a "subversion" entry to sysfs to expose the minor version
without breaking user space.

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/lightnvm/core.c      |  4 ++--
 drivers/nvme/host/lightnvm.c | 25 ++++++++++++++++++++-----
 include/linux/lightnvm.h     |  3 ++-
 3 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 42596afdf64c..dc9ec6baff45 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -897,8 +897,8 @@ static int nvm_init(struct nvm_dev *dev)
 		goto err;
 	}
 
-	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
-				dev_geo->ver_id,
+	pr_debug("nvm: ver:%u.%u nvm_vendor:%x\n",
+				dev_geo->major_ver_id, dev_geo->minor_ver_id,
 				dev_geo->c.vmnt);
 
 	ret = nvm_core_init(dev);
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 598abba66f52..71b4ac57a668 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -296,7 +296,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
 	}
 
 	/* 1.2 spec. only reports a single version id - unfold */
-	dev_geo->ver_id = id->ver_id;
+	dev_geo->major_ver_id = id->ver_id;
+	dev_geo->minor_ver_id = 2;
 
 	dev_geo->nr_chnls = src->num_ch;
 	dev_geo->nr_luns = src->num_lun;
@@ -377,7 +378,14 @@ static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
 static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 			     struct nvm_dev_geo *dev_geo)
 {
-	dev_geo->ver_id = id->mjr;
+	dev_geo->major_ver_id = id->mjr;
+	dev_geo->minor_ver_id = id->mnr;
+
+	if (!(dev_geo->major_ver_id == 2 && dev_geo->minor_ver_id == 0)) {
+		pr_err("nvm: OCSSD version not supported (v%d.%d)\n",
+				dev_geo->major_ver_id, dev_geo->minor_ver_id);
+		return -EINVAL;
+	}
 
 	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
 	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
@@ -913,7 +921,11 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
 	attr = &dattr->attr;
 
 	if (strcmp(attr->name, "version") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
+		return scnprintf(page, PAGE_SIZE, "%u\n",
+						dev_geo->major_ver_id);
+	} else if (strcmp(attr->name, "subversion") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n",
+						dev_geo->minor_ver_id);
 	} else if (strcmp(attr->name, "media_capabilities") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
 	} else if (strcmp(attr->name, "read_typ") == 0) {
@@ -1055,6 +1067,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
 
 /* general attributes */
 static NVM_DEV_ATTR_RO(version);
+static NVM_DEV_ATTR_RO(subversion);
 static NVM_DEV_ATTR_RO(media_capabilities);
 
 static NVM_DEV_ATTR_RO(read_typ);
@@ -1085,6 +1098,7 @@ static NVM_DEV_ATTR_12_RO(max_phys_secs);
 
 static struct attribute *nvm_dev_attrs_12[] = {
 	&dev_attr_version.attr,
+	&dev_attr_subversion.attr,
 	&dev_attr_media_capabilities.attr,
 
 	&dev_attr_vendor_opcode.attr,
@@ -1134,6 +1148,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
 
 static struct attribute *nvm_dev_attrs_20[] = {
 	&dev_attr_version.attr,
+	&dev_attr_subversion.attr,
 	&dev_attr_media_capabilities.attr,
 
 	&dev_attr_groups.attr,
@@ -1167,7 +1182,7 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
 	if (!ndev)
 		return -EINVAL;
 
-	switch (dev_geo->ver_id) {
+	switch (dev_geo->major_ver_id) {
 	case 1:
 		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
 					&nvm_dev_attr_group_12);
@@ -1184,7 +1199,7 @@ void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
 	struct nvm_dev *ndev = ns->ndev;
 	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
 
-	switch (dev_geo->ver_id) {
+	switch (dev_geo->major_ver_id) {
 	case 1:
 		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
 					&nvm_dev_attr_group_12);
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 18e3751b1632..5af0b8837095 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -242,7 +242,8 @@ struct nvm_common_geo {
 /* Device identified geometry */
 struct nvm_dev_geo {
 	/* device reported version */
-	u8	ver_id;
+	u8	major_ver_id;
+	u8	minor_ver_id;
 
 	/* full device geometry */
 	u16	nr_chnls;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 05/20] lightnvm: rename number of channels and luns
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

Normalize nomenclature for naming number of channels and number of luns
in order to improve readability. Use num_ch and num_lun.

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/lightnvm/core.c      | 69 ++++++++++++++++++++++----------------------
 drivers/lightnvm/pblk-core.c |  4 +--
 drivers/lightnvm/pblk-init.c | 16 +++++-----
 drivers/lightnvm/pblk.h      |  6 ++--
 drivers/nvme/host/lightnvm.c | 20 ++++++-------
 include/linux/lightnvm.h     |  8 ++---
 6 files changed, 61 insertions(+), 62 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index dc9ec6baff45..f70a907223e2 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -36,13 +36,13 @@ static DECLARE_RWSEM(nvm_lock);
 /* Map between virtual and physical channel and lun */
 struct nvm_ch_map {
 	int ch_off;
-	int nr_luns;
+	int num_lun;
 	int *lun_offs;
 };
 
 struct nvm_dev_map {
 	struct nvm_ch_map *chnls;
-	int nr_chnls;
+	int num_ch;
 };
 
 static struct nvm_target *nvm_find_target(struct nvm_dev *dev, const char *name)
@@ -115,15 +115,15 @@ static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
 	struct nvm_dev_map *dev_map = tgt_dev->map;
 	int i, j;
 
-	for (i = 0; i < dev_map->nr_chnls; i++) {
+	for (i = 0; i < dev_map->num_ch; i++) {
 		struct nvm_ch_map *ch_map = &dev_map->chnls[i];
 		int *lun_offs = ch_map->lun_offs;
 		int ch = i + ch_map->ch_off;
 
 		if (clear) {
-			for (j = 0; j < ch_map->nr_luns; j++) {
+			for (j = 0; j < ch_map->num_lun; j++) {
 				int lun = j + lun_offs[j];
-				int lunid = (ch * dev_geo->nr_luns) + lun;
+				int lunid = (ch * dev_geo->num_lun) + lun;
 
 				WARN_ON(!test_and_clear_bit(lunid,
 							dev->lun_map));
@@ -149,47 +149,46 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
 	struct nvm_dev_map *dev_rmap = dev->rmap;
 	struct nvm_dev_map *dev_map;
 	struct ppa_addr *luns;
-	int nr_luns = lun_end - lun_begin + 1;
-	int luns_left = nr_luns;
-	int nr_chnls = nr_luns / dev_geo->nr_luns;
-	int nr_chnls_mod = nr_luns % dev_geo->nr_luns;
-	int bch = lun_begin / dev_geo->nr_luns;
-	int blun = lun_begin % dev_geo->nr_luns;
+	int num_lun = lun_end - lun_begin + 1;
+	int luns_left = num_lun;
+	int num_ch = num_lun / dev_geo->num_lun;
+	int num_ch_mod = num_lun % dev_geo->num_lun;
+	int bch = lun_begin / dev_geo->num_lun;
+	int blun = lun_begin % dev_geo->num_lun;
 	int lunid = 0;
 	int lun_balanced = 1;
-	int sec_per_lun, prev_nr_luns;
+	int sec_per_lun, prev_num_lun;
 	int i, j;
 
-	nr_chnls = (nr_chnls_mod == 0) ? nr_chnls : nr_chnls + 1;
+	num_ch = (num_ch_mod == 0) ? num_ch : num_ch + 1;
 
 	dev_map = kmalloc(sizeof(struct nvm_dev_map), GFP_KERNEL);
 	if (!dev_map)
 		goto err_dev;
 
-	dev_map->chnls = kcalloc(nr_chnls, sizeof(struct nvm_ch_map),
-								GFP_KERNEL);
+	dev_map->chnls = kcalloc(num_ch, sizeof(struct nvm_ch_map), GFP_KERNEL);
 	if (!dev_map->chnls)
 		goto err_chnls;
 
-	luns = kcalloc(nr_luns, sizeof(struct ppa_addr), GFP_KERNEL);
+	luns = kcalloc(num_lun, sizeof(struct ppa_addr), GFP_KERNEL);
 	if (!luns)
 		goto err_luns;
 
-	prev_nr_luns = (luns_left > dev_geo->nr_luns) ?
-					dev_geo->nr_luns : luns_left;
-	for (i = 0; i < nr_chnls; i++) {
+	prev_num_lun = (luns_left > dev_geo->num_lun) ?
+					dev_geo->num_lun : luns_left;
+	for (i = 0; i < num_ch; i++) {
 		struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[i + bch];
 		int *lun_roffs = ch_rmap->lun_offs;
 		struct nvm_ch_map *ch_map = &dev_map->chnls[i];
 		int *lun_offs;
-		int luns_in_chnl = (luns_left > dev_geo->nr_luns) ?
-					dev_geo->nr_luns : luns_left;
+		int luns_in_chnl = (luns_left > dev_geo->num_lun) ?
+					dev_geo->num_lun : luns_left;
 
-		if (lun_balanced && prev_nr_luns != luns_in_chnl)
+		if (lun_balanced && prev_num_lun != luns_in_chnl)
 			lun_balanced = 0;
 
 		ch_map->ch_off = ch_rmap->ch_off = bch;
-		ch_map->nr_luns = luns_in_chnl;
+		ch_map->num_lun = luns_in_chnl;
 
 		lun_offs = kcalloc(luns_in_chnl, sizeof(int), GFP_KERNEL);
 		if (!lun_offs)
@@ -211,22 +210,22 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
 		luns_left -= luns_in_chnl;
 	}
 
-	dev_map->nr_chnls = nr_chnls;
+	dev_map->num_ch = num_ch;
 
 	tgt_dev = kmalloc(sizeof(struct nvm_tgt_dev), GFP_KERNEL);
 	if (!tgt_dev)
 		goto err_ch;
 
 	/* Target device only owns a portion of the physical device */
-	tgt_dev->geo.nr_chnls = nr_chnls;
-	tgt_dev->geo.nr_luns = (lun_balanced) ? prev_nr_luns : -1;
-	tgt_dev->geo.all_luns = nr_luns;
-	tgt_dev->geo.all_chunks = nr_luns * dev_geo->c.num_chk;
+	tgt_dev->geo.num_ch = num_ch;
+	tgt_dev->geo.num_lun = (lun_balanced) ? prev_num_lun : -1;
+	tgt_dev->geo.all_luns = num_lun;
+	tgt_dev->geo.all_chunks = num_lun * dev_geo->c.num_chk;
 
 	tgt_dev->geo.op = op;
 
 	sec_per_lun = dev_geo->c.clba * dev_geo->c.num_chk;
-	tgt_dev->geo.total_secs = nr_luns * sec_per_lun;
+	tgt_dev->geo.total_secs = num_lun * sec_per_lun;
 
 	tgt_dev->geo.c = dev_geo->c;
 
@@ -511,20 +510,20 @@ static int nvm_register_map(struct nvm_dev *dev)
 	if (!rmap)
 		goto err_rmap;
 
-	rmap->chnls = kcalloc(dev_geo->nr_chnls, sizeof(struct nvm_ch_map),
+	rmap->chnls = kcalloc(dev_geo->num_ch, sizeof(struct nvm_ch_map),
 								GFP_KERNEL);
 	if (!rmap->chnls)
 		goto err_chnls;
 
-	for (i = 0; i < dev_geo->nr_chnls; i++) {
+	for (i = 0; i < dev_geo->num_ch; i++) {
 		struct nvm_ch_map *ch_rmap;
 		int *lun_roffs;
-		int luns_in_chnl = dev_geo->nr_luns;
+		int luns_in_chnl = dev_geo->num_lun;
 
 		ch_rmap = &rmap->chnls[i];
 
 		ch_rmap->ch_off = -1;
-		ch_rmap->nr_luns = luns_in_chnl;
+		ch_rmap->num_lun = luns_in_chnl;
 
 		lun_roffs = kcalloc(luns_in_chnl, sizeof(int), GFP_KERNEL);
 		if (!lun_roffs)
@@ -554,7 +553,7 @@ static void nvm_unregister_map(struct nvm_dev *dev)
 	struct nvm_dev_map *rmap = dev->rmap;
 	int i;
 
-	for (i = 0; i < dev_geo->nr_chnls; i++)
+	for (i = 0; i < dev_geo->num_ch; i++)
 		kfree(rmap->chnls[i].lun_offs);
 
 	kfree(rmap->chnls);
@@ -910,7 +909,7 @@ static int nvm_init(struct nvm_dev *dev)
 	pr_info("nvm: registered %s [%u/%u/%u/%u/%u]\n",
 			dev->name, dev_geo->c.ws_min, dev_geo->c.ws_opt,
 			dev_geo->c.num_chk, dev_geo->all_luns,
-			dev_geo->nr_chnls);
+			dev_geo->num_ch);
 	return 0;
 err:
 	pr_err("nvm: failed to initialize nvm\n");
diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index 519af8b9eab7..7c726003a8d2 100644
--- a/drivers/lightnvm/pblk-core.c
+++ b/drivers/lightnvm/pblk-core.c
@@ -1752,10 +1752,10 @@ void pblk_up_rq(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas,
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
 	struct pblk_lun *rlun;
-	int nr_luns = geo->all_luns;
+	int num_lun = geo->all_luns;
 	int bit = -1;
 
-	while ((bit = find_next_bit(lun_bitmap, nr_luns, bit + 1)) < nr_luns) {
+	while ((bit = find_next_bit(lun_bitmap, num_lun, bit + 1)) < num_lun) {
 		rlun = &pblk->luns[bit];
 		up(&rlun->wr_sem);
 	}
diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 95ecb0ec736b..455fc63a9409 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -162,15 +162,15 @@ static int pblk_set_addrf_12(struct nvm_geo *geo,
 	int power_len;
 
 	/* Re-calculate channel and lun format to adapt to configuration */
-	power_len = get_count_order(geo->nr_chnls);
-	if (1 << power_len != geo->nr_chnls) {
+	power_len = get_count_order(geo->num_ch);
+	if (1 << power_len != geo->num_ch) {
 		pr_err("pblk: supports only power-of-two channel config.\n");
 		return -EINVAL;
 	}
 	dst->ch_len = power_len;
 
-	power_len = get_count_order(geo->nr_luns);
-	if (1 << power_len != geo->nr_luns) {
+	power_len = get_count_order(geo->num_lun);
+	if (1 << power_len != geo->num_lun) {
 		pr_err("pblk: supports only power-of-two LUN config.\n");
 		return -EINVAL;
 	}
@@ -498,7 +498,7 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
 	int i;
 
 	/* TODO: Implement unbalanced LUN support */
-	if (geo->nr_luns < 0) {
+	if (geo->num_lun < 0) {
 		pr_err("pblk: unbalanced LUN config.\n");
 		return -EINVAL;
 	}
@@ -510,9 +510,9 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
 
 	for (i = 0; i < geo->all_luns; i++) {
 		/* Stripe across channels */
-		int ch = i % geo->nr_chnls;
-		int lun_raw = i / geo->nr_chnls;
-		int lunid = lun_raw + ch * geo->nr_luns;
+		int ch = i % geo->num_ch;
+		int lun_raw = i / geo->num_ch;
+		int lunid = lun_raw + ch * geo->num_lun;
 
 		rlun = &pblk->luns[i];
 		rlun->bppa = luns[lunid];
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 67ffb53608f7..1f32284b0aec 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -941,7 +941,7 @@ static inline int pblk_ppa_to_line(struct ppa_addr p)
 
 static inline int pblk_ppa_to_pos(struct nvm_geo *geo, struct ppa_addr p)
 {
-	return p.g.lun * geo->nr_chnls + p.g.ch;
+	return p.g.lun * geo->num_ch + p.g.ch;
 }
 
 static inline struct ppa_addr addr_to_gen_ppa(struct pblk *pblk, u64 paddr,
@@ -1214,8 +1214,8 @@ static inline int pblk_boundary_ppa_checks(struct nvm_tgt_dev *tgt_dev,
 		ppa = &ppas[i];
 
 		if (!ppa->c.is_cached &&
-				ppa->g.ch < geo->nr_chnls &&
-				ppa->g.lun < geo->nr_luns &&
+				ppa->g.ch < geo->num_ch &&
+				ppa->g.lun < geo->num_lun &&
 				ppa->g.pl < geo->c.num_pln &&
 				ppa->g.blk < geo->c.num_chk &&
 				ppa->g.pg < geo->c.num_pg &&
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 71b4ac57a668..f22331e61cef 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -299,9 +299,9 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
 	dev_geo->major_ver_id = id->ver_id;
 	dev_geo->minor_ver_id = 2;
 
-	dev_geo->nr_chnls = src->num_ch;
-	dev_geo->nr_luns = src->num_lun;
-	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
+	dev_geo->num_ch = src->num_ch;
+	dev_geo->num_lun = src->num_lun;
+	dev_geo->all_luns = dev_geo->num_ch * dev_geo->num_lun;
 
 	dev_geo->c.num_chk = le16_to_cpu(src->num_chk);
 	dev_geo->c.csecs = le16_to_cpu(src->csecs);
@@ -387,9 +387,9 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 		return -EINVAL;
 	}
 
-	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
-	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
-	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
+	dev_geo->num_ch = le16_to_cpu(id->num_grp);
+	dev_geo->num_lun = le16_to_cpu(id->num_pu);
+	dev_geo->all_luns = dev_geo->num_ch * dev_geo->num_lun;
 
 	dev_geo->c.num_chk = le32_to_cpu(id->num_chk);
 	dev_geo->c.clba = le32_to_cpu(id->clba);
@@ -980,9 +980,9 @@ static ssize_t nvm_dev_attr_show_12(struct device *dev,
 	} else if (strcmp(attr->name, "flash_media_type") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fmtype);
 	} else if (strcmp(attr->name, "num_channels") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->num_ch);
 	} else if (strcmp(attr->name, "num_luns") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->num_lun);
 	} else if (strcmp(attr->name, "num_planes") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pln);
 	} else if (strcmp(attr->name, "num_blocks") == 0) {	/* u16 */
@@ -1030,9 +1030,9 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
 	attr = &dattr->attr;
 
 	if (strcmp(attr->name, "groups") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->num_ch);
 	} else if (strcmp(attr->name, "punits") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->num_lun);
 	} else if (strcmp(attr->name, "chunks") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
 	} else if (strcmp(attr->name, "clba") == 0) {
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 5af0b8837095..28d429e0a1c9 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -246,8 +246,8 @@ struct nvm_dev_geo {
 	u8	minor_ver_id;
 
 	/* full device geometry */
-	u16	nr_chnls;
-	u16	nr_luns;
+	u16	num_ch;
+	u16	num_lun;
 
 	/* calculated values */
 	u16	all_luns;
@@ -323,8 +323,8 @@ enum {
 /* Instance geometry */
 struct nvm_geo {
 	/* instance specific geometry */
-	int nr_chnls;
-	int nr_luns;		/* per channel */
+	int num_ch;
+	int num_lun;		/* per channel */
 
 	int op;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 05/20] lightnvm: rename number of channels and luns
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


Normalize nomenclature for naming number of channels and number of luns
in order to improve readability. Use num_ch and num_lun.

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/lightnvm/core.c      | 69 ++++++++++++++++++++++----------------------
 drivers/lightnvm/pblk-core.c |  4 +--
 drivers/lightnvm/pblk-init.c | 16 +++++-----
 drivers/lightnvm/pblk.h      |  6 ++--
 drivers/nvme/host/lightnvm.c | 20 ++++++-------
 include/linux/lightnvm.h     |  8 ++---
 6 files changed, 61 insertions(+), 62 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index dc9ec6baff45..f70a907223e2 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -36,13 +36,13 @@ static DECLARE_RWSEM(nvm_lock);
 /* Map between virtual and physical channel and lun */
 struct nvm_ch_map {
 	int ch_off;
-	int nr_luns;
+	int num_lun;
 	int *lun_offs;
 };
 
 struct nvm_dev_map {
 	struct nvm_ch_map *chnls;
-	int nr_chnls;
+	int num_ch;
 };
 
 static struct nvm_target *nvm_find_target(struct nvm_dev *dev, const char *name)
@@ -115,15 +115,15 @@ static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
 	struct nvm_dev_map *dev_map = tgt_dev->map;
 	int i, j;
 
-	for (i = 0; i < dev_map->nr_chnls; i++) {
+	for (i = 0; i < dev_map->num_ch; i++) {
 		struct nvm_ch_map *ch_map = &dev_map->chnls[i];
 		int *lun_offs = ch_map->lun_offs;
 		int ch = i + ch_map->ch_off;
 
 		if (clear) {
-			for (j = 0; j < ch_map->nr_luns; j++) {
+			for (j = 0; j < ch_map->num_lun; j++) {
 				int lun = j + lun_offs[j];
-				int lunid = (ch * dev_geo->nr_luns) + lun;
+				int lunid = (ch * dev_geo->num_lun) + lun;
 
 				WARN_ON(!test_and_clear_bit(lunid,
 							dev->lun_map));
@@ -149,47 +149,46 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
 	struct nvm_dev_map *dev_rmap = dev->rmap;
 	struct nvm_dev_map *dev_map;
 	struct ppa_addr *luns;
-	int nr_luns = lun_end - lun_begin + 1;
-	int luns_left = nr_luns;
-	int nr_chnls = nr_luns / dev_geo->nr_luns;
-	int nr_chnls_mod = nr_luns % dev_geo->nr_luns;
-	int bch = lun_begin / dev_geo->nr_luns;
-	int blun = lun_begin % dev_geo->nr_luns;
+	int num_lun = lun_end - lun_begin + 1;
+	int luns_left = num_lun;
+	int num_ch = num_lun / dev_geo->num_lun;
+	int num_ch_mod = num_lun % dev_geo->num_lun;
+	int bch = lun_begin / dev_geo->num_lun;
+	int blun = lun_begin % dev_geo->num_lun;
 	int lunid = 0;
 	int lun_balanced = 1;
-	int sec_per_lun, prev_nr_luns;
+	int sec_per_lun, prev_num_lun;
 	int i, j;
 
-	nr_chnls = (nr_chnls_mod == 0) ? nr_chnls : nr_chnls + 1;
+	num_ch = (num_ch_mod == 0) ? num_ch : num_ch + 1;
 
 	dev_map = kmalloc(sizeof(struct nvm_dev_map), GFP_KERNEL);
 	if (!dev_map)
 		goto err_dev;
 
-	dev_map->chnls = kcalloc(nr_chnls, sizeof(struct nvm_ch_map),
-								GFP_KERNEL);
+	dev_map->chnls = kcalloc(num_ch, sizeof(struct nvm_ch_map), GFP_KERNEL);
 	if (!dev_map->chnls)
 		goto err_chnls;
 
-	luns = kcalloc(nr_luns, sizeof(struct ppa_addr), GFP_KERNEL);
+	luns = kcalloc(num_lun, sizeof(struct ppa_addr), GFP_KERNEL);
 	if (!luns)
 		goto err_luns;
 
-	prev_nr_luns = (luns_left > dev_geo->nr_luns) ?
-					dev_geo->nr_luns : luns_left;
-	for (i = 0; i < nr_chnls; i++) {
+	prev_num_lun = (luns_left > dev_geo->num_lun) ?
+					dev_geo->num_lun : luns_left;
+	for (i = 0; i < num_ch; i++) {
 		struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[i + bch];
 		int *lun_roffs = ch_rmap->lun_offs;
 		struct nvm_ch_map *ch_map = &dev_map->chnls[i];
 		int *lun_offs;
-		int luns_in_chnl = (luns_left > dev_geo->nr_luns) ?
-					dev_geo->nr_luns : luns_left;
+		int luns_in_chnl = (luns_left > dev_geo->num_lun) ?
+					dev_geo->num_lun : luns_left;
 
-		if (lun_balanced && prev_nr_luns != luns_in_chnl)
+		if (lun_balanced && prev_num_lun != luns_in_chnl)
 			lun_balanced = 0;
 
 		ch_map->ch_off = ch_rmap->ch_off = bch;
-		ch_map->nr_luns = luns_in_chnl;
+		ch_map->num_lun = luns_in_chnl;
 
 		lun_offs = kcalloc(luns_in_chnl, sizeof(int), GFP_KERNEL);
 		if (!lun_offs)
@@ -211,22 +210,22 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
 		luns_left -= luns_in_chnl;
 	}
 
-	dev_map->nr_chnls = nr_chnls;
+	dev_map->num_ch = num_ch;
 
 	tgt_dev = kmalloc(sizeof(struct nvm_tgt_dev), GFP_KERNEL);
 	if (!tgt_dev)
 		goto err_ch;
 
 	/* Target device only owns a portion of the physical device */
-	tgt_dev->geo.nr_chnls = nr_chnls;
-	tgt_dev->geo.nr_luns = (lun_balanced) ? prev_nr_luns : -1;
-	tgt_dev->geo.all_luns = nr_luns;
-	tgt_dev->geo.all_chunks = nr_luns * dev_geo->c.num_chk;
+	tgt_dev->geo.num_ch = num_ch;
+	tgt_dev->geo.num_lun = (lun_balanced) ? prev_num_lun : -1;
+	tgt_dev->geo.all_luns = num_lun;
+	tgt_dev->geo.all_chunks = num_lun * dev_geo->c.num_chk;
 
 	tgt_dev->geo.op = op;
 
 	sec_per_lun = dev_geo->c.clba * dev_geo->c.num_chk;
-	tgt_dev->geo.total_secs = nr_luns * sec_per_lun;
+	tgt_dev->geo.total_secs = num_lun * sec_per_lun;
 
 	tgt_dev->geo.c = dev_geo->c;
 
@@ -511,20 +510,20 @@ static int nvm_register_map(struct nvm_dev *dev)
 	if (!rmap)
 		goto err_rmap;
 
-	rmap->chnls = kcalloc(dev_geo->nr_chnls, sizeof(struct nvm_ch_map),
+	rmap->chnls = kcalloc(dev_geo->num_ch, sizeof(struct nvm_ch_map),
 								GFP_KERNEL);
 	if (!rmap->chnls)
 		goto err_chnls;
 
-	for (i = 0; i < dev_geo->nr_chnls; i++) {
+	for (i = 0; i < dev_geo->num_ch; i++) {
 		struct nvm_ch_map *ch_rmap;
 		int *lun_roffs;
-		int luns_in_chnl = dev_geo->nr_luns;
+		int luns_in_chnl = dev_geo->num_lun;
 
 		ch_rmap = &rmap->chnls[i];
 
 		ch_rmap->ch_off = -1;
-		ch_rmap->nr_luns = luns_in_chnl;
+		ch_rmap->num_lun = luns_in_chnl;
 
 		lun_roffs = kcalloc(luns_in_chnl, sizeof(int), GFP_KERNEL);
 		if (!lun_roffs)
@@ -554,7 +553,7 @@ static void nvm_unregister_map(struct nvm_dev *dev)
 	struct nvm_dev_map *rmap = dev->rmap;
 	int i;
 
-	for (i = 0; i < dev_geo->nr_chnls; i++)
+	for (i = 0; i < dev_geo->num_ch; i++)
 		kfree(rmap->chnls[i].lun_offs);
 
 	kfree(rmap->chnls);
@@ -910,7 +909,7 @@ static int nvm_init(struct nvm_dev *dev)
 	pr_info("nvm: registered %s [%u/%u/%u/%u/%u]\n",
 			dev->name, dev_geo->c.ws_min, dev_geo->c.ws_opt,
 			dev_geo->c.num_chk, dev_geo->all_luns,
-			dev_geo->nr_chnls);
+			dev_geo->num_ch);
 	return 0;
 err:
 	pr_err("nvm: failed to initialize nvm\n");
diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index 519af8b9eab7..7c726003a8d2 100644
--- a/drivers/lightnvm/pblk-core.c
+++ b/drivers/lightnvm/pblk-core.c
@@ -1752,10 +1752,10 @@ void pblk_up_rq(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas,
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
 	struct pblk_lun *rlun;
-	int nr_luns = geo->all_luns;
+	int num_lun = geo->all_luns;
 	int bit = -1;
 
-	while ((bit = find_next_bit(lun_bitmap, nr_luns, bit + 1)) < nr_luns) {
+	while ((bit = find_next_bit(lun_bitmap, num_lun, bit + 1)) < num_lun) {
 		rlun = &pblk->luns[bit];
 		up(&rlun->wr_sem);
 	}
diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 95ecb0ec736b..455fc63a9409 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -162,15 +162,15 @@ static int pblk_set_addrf_12(struct nvm_geo *geo,
 	int power_len;
 
 	/* Re-calculate channel and lun format to adapt to configuration */
-	power_len = get_count_order(geo->nr_chnls);
-	if (1 << power_len != geo->nr_chnls) {
+	power_len = get_count_order(geo->num_ch);
+	if (1 << power_len != geo->num_ch) {
 		pr_err("pblk: supports only power-of-two channel config.\n");
 		return -EINVAL;
 	}
 	dst->ch_len = power_len;
 
-	power_len = get_count_order(geo->nr_luns);
-	if (1 << power_len != geo->nr_luns) {
+	power_len = get_count_order(geo->num_lun);
+	if (1 << power_len != geo->num_lun) {
 		pr_err("pblk: supports only power-of-two LUN config.\n");
 		return -EINVAL;
 	}
@@ -498,7 +498,7 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
 	int i;
 
 	/* TODO: Implement unbalanced LUN support */
-	if (geo->nr_luns < 0) {
+	if (geo->num_lun < 0) {
 		pr_err("pblk: unbalanced LUN config.\n");
 		return -EINVAL;
 	}
@@ -510,9 +510,9 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
 
 	for (i = 0; i < geo->all_luns; i++) {
 		/* Stripe across channels */
-		int ch = i % geo->nr_chnls;
-		int lun_raw = i / geo->nr_chnls;
-		int lunid = lun_raw + ch * geo->nr_luns;
+		int ch = i % geo->num_ch;
+		int lun_raw = i / geo->num_ch;
+		int lunid = lun_raw + ch * geo->num_lun;
 
 		rlun = &pblk->luns[i];
 		rlun->bppa = luns[lunid];
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 67ffb53608f7..1f32284b0aec 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -941,7 +941,7 @@ static inline int pblk_ppa_to_line(struct ppa_addr p)
 
 static inline int pblk_ppa_to_pos(struct nvm_geo *geo, struct ppa_addr p)
 {
-	return p.g.lun * geo->nr_chnls + p.g.ch;
+	return p.g.lun * geo->num_ch + p.g.ch;
 }
 
 static inline struct ppa_addr addr_to_gen_ppa(struct pblk *pblk, u64 paddr,
@@ -1214,8 +1214,8 @@ static inline int pblk_boundary_ppa_checks(struct nvm_tgt_dev *tgt_dev,
 		ppa = &ppas[i];
 
 		if (!ppa->c.is_cached &&
-				ppa->g.ch < geo->nr_chnls &&
-				ppa->g.lun < geo->nr_luns &&
+				ppa->g.ch < geo->num_ch &&
+				ppa->g.lun < geo->num_lun &&
 				ppa->g.pl < geo->c.num_pln &&
 				ppa->g.blk < geo->c.num_chk &&
 				ppa->g.pg < geo->c.num_pg &&
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 71b4ac57a668..f22331e61cef 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -299,9 +299,9 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
 	dev_geo->major_ver_id = id->ver_id;
 	dev_geo->minor_ver_id = 2;
 
-	dev_geo->nr_chnls = src->num_ch;
-	dev_geo->nr_luns = src->num_lun;
-	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
+	dev_geo->num_ch = src->num_ch;
+	dev_geo->num_lun = src->num_lun;
+	dev_geo->all_luns = dev_geo->num_ch * dev_geo->num_lun;
 
 	dev_geo->c.num_chk = le16_to_cpu(src->num_chk);
 	dev_geo->c.csecs = le16_to_cpu(src->csecs);
@@ -387,9 +387,9 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 		return -EINVAL;
 	}
 
-	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
-	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
-	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
+	dev_geo->num_ch = le16_to_cpu(id->num_grp);
+	dev_geo->num_lun = le16_to_cpu(id->num_pu);
+	dev_geo->all_luns = dev_geo->num_ch * dev_geo->num_lun;
 
 	dev_geo->c.num_chk = le32_to_cpu(id->num_chk);
 	dev_geo->c.clba = le32_to_cpu(id->clba);
@@ -980,9 +980,9 @@ static ssize_t nvm_dev_attr_show_12(struct device *dev,
 	} else if (strcmp(attr->name, "flash_media_type") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fmtype);
 	} else if (strcmp(attr->name, "num_channels") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->num_ch);
 	} else if (strcmp(attr->name, "num_luns") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->num_lun);
 	} else if (strcmp(attr->name, "num_planes") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pln);
 	} else if (strcmp(attr->name, "num_blocks") == 0) {	/* u16 */
@@ -1030,9 +1030,9 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
 	attr = &dattr->attr;
 
 	if (strcmp(attr->name, "groups") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->num_ch);
 	} else if (strcmp(attr->name, "punits") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->num_lun);
 	} else if (strcmp(attr->name, "chunks") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
 	} else if (strcmp(attr->name, "clba") == 0) {
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 5af0b8837095..28d429e0a1c9 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -246,8 +246,8 @@ struct nvm_dev_geo {
 	u8	minor_ver_id;
 
 	/* full device geometry */
-	u16	nr_chnls;
-	u16	nr_luns;
+	u16	num_ch;
+	u16	num_lun;
 
 	/* calculated values */
 	u16	all_luns;
@@ -323,8 +323,8 @@ enum {
 /* Instance geometry */
 struct nvm_geo {
 	/* instance specific geometry */
-	int nr_chnls;
-	int nr_luns;		/* per channel */
+	int num_ch;
+	int num_lun;		/* per channel */
 
 	int op;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 06/20] lightnvm: add shorten OCSSD version in geo
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

Create a shorten version to use in the generic geometry.

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/nvme/host/lightnvm.c | 6 ++++++
 include/linux/lightnvm.h     | 8 ++++++++
 2 files changed, 14 insertions(+)

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index f22331e61cef..bd97672e0b4f 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -299,6 +299,9 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
 	dev_geo->major_ver_id = id->ver_id;
 	dev_geo->minor_ver_id = 2;
 
+	/* Set compacted version for upper layers */
+	dev_geo->c.version = NVM_OCSSD_SPEC_12;
+
 	dev_geo->num_ch = src->num_ch;
 	dev_geo->num_lun = src->num_lun;
 	dev_geo->all_luns = dev_geo->num_ch * dev_geo->num_lun;
@@ -381,6 +384,9 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 	dev_geo->major_ver_id = id->mjr;
 	dev_geo->minor_ver_id = id->mnr;
 
+	/* Set compacted version for upper layers */
+	dev_geo->c.version = NVM_OCSSD_SPEC_20;
+
 	if (!(dev_geo->major_ver_id == 2 && dev_geo->minor_ver_id == 0)) {
 		pr_err("nvm: OCSSD version not supported (v%d.%d)\n",
 				dev_geo->major_ver_id, dev_geo->minor_ver_id);
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 28d429e0a1c9..02f1fd617781 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -23,6 +23,11 @@ enum {
 #define NVM_LUN_BITS (8)
 #define NVM_CH_BITS  (7)
 
+enum {
+	NVM_OCSSD_SPEC_12 = 12,
+	NVM_OCSSD_SPEC_20 = 20,
+};
+
 struct ppa_addr {
 	/* Generic structure for all addresses */
 	union {
@@ -197,6 +202,9 @@ struct nvm_addr_format {
 
 /* Device common geometry */
 struct nvm_common_geo {
+	/* kernel short version */
+	u8	version;
+
 	/* chunk geometry */
 	u32	num_chk;	/* chunks per lun */
 	u32	clba;		/* sectors per chunk */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 06/20] lightnvm: add shorten OCSSD version in geo
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


Create a shorten version to use in the generic geometry.

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/nvme/host/lightnvm.c | 6 ++++++
 include/linux/lightnvm.h     | 8 ++++++++
 2 files changed, 14 insertions(+)

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index f22331e61cef..bd97672e0b4f 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -299,6 +299,9 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
 	dev_geo->major_ver_id = id->ver_id;
 	dev_geo->minor_ver_id = 2;
 
+	/* Set compacted version for upper layers */
+	dev_geo->c.version = NVM_OCSSD_SPEC_12;
+
 	dev_geo->num_ch = src->num_ch;
 	dev_geo->num_lun = src->num_lun;
 	dev_geo->all_luns = dev_geo->num_ch * dev_geo->num_lun;
@@ -381,6 +384,9 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 	dev_geo->major_ver_id = id->mjr;
 	dev_geo->minor_ver_id = id->mnr;
 
+	/* Set compacted version for upper layers */
+	dev_geo->c.version = NVM_OCSSD_SPEC_20;
+
 	if (!(dev_geo->major_ver_id == 2 && dev_geo->minor_ver_id == 0)) {
 		pr_err("nvm: OCSSD version not supported (v%d.%d)\n",
 				dev_geo->major_ver_id, dev_geo->minor_ver_id);
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 28d429e0a1c9..02f1fd617781 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -23,6 +23,11 @@ enum {
 #define NVM_LUN_BITS (8)
 #define NVM_CH_BITS  (7)
 
+enum {
+	NVM_OCSSD_SPEC_12 = 12,
+	NVM_OCSSD_SPEC_20 = 20,
+};
+
 struct ppa_addr {
 	/* Generic structure for all addresses */
 	union {
@@ -197,6 +202,9 @@ struct nvm_addr_format {
 
 /* Device common geometry */
 struct nvm_common_geo {
+	/* kernel short version */
+	u8	version;
+
 	/* chunk geometry */
 	u32	num_chk;	/* chunks per lun */
 	u32	clba;		/* sectors per chunk */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 07/20] lightnvm: rename sect_* to sec_*
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

Rename abbreviations for sector from sect_* to sec_* as most of the code
uses this format and it is confusing when using the different
structures.

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/lightnvm/pblk-init.c  | 8 ++++----
 drivers/lightnvm/pblk-sysfs.c | 4 ++--
 drivers/lightnvm/pblk.h       | 8 ++++----
 drivers/nvme/host/lightnvm.c  | 8 ++++----
 include/linux/lightnvm.h      | 8 ++++----
 5 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 455fc63a9409..6bf51ef8f516 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -179,16 +179,16 @@ static int pblk_set_addrf_12(struct nvm_geo *geo,
 	dst->blk_len = src->blk_len;
 	dst->pg_len = src->pg_len;
 	dst->pln_len = src->pln_len;
-	dst->sect_len = src->sect_len;
+	dst->sec_len = src->sec_len;
 
-	dst->sect_offset = 0;
-	dst->pln_offset = dst->sect_len;
+	dst->sec_offset = 0;
+	dst->pln_offset = dst->sec_len;
 	dst->ch_offset = dst->pln_offset + dst->pln_len;
 	dst->lun_offset = dst->ch_offset + dst->ch_len;
 	dst->pg_offset = dst->lun_offset + dst->lun_len;
 	dst->blk_offset = dst->pg_offset + dst->pg_len;
 
-	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
+	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
 	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
 	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
 	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index 5eb21a279361..81288aa9162a 100644
--- a/drivers/lightnvm/pblk-sysfs.c
+++ b/drivers/lightnvm/pblk-sysfs.c
@@ -128,7 +128,7 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
 			ppaf->blk_offset, ppaf->blk_len,
 			ppaf->pg_offset, ppaf->pg_len,
 			ppaf->pln_offset, ppaf->pln_len,
-			ppaf->sect_offset, ppaf->sect_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",
@@ -137,7 +137,7 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
 			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->sect_offset, geo_ppaf->sect_len);
+			geo_ppaf->sec_offset, geo_ppaf->sec_len);
 
 	return sz;
 }
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 1f32284b0aec..4f7a365436f1 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -957,7 +957,7 @@ static inline struct ppa_addr addr_to_gen_ppa(struct pblk *pblk, u64 paddr,
 	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->sect_offset;
+	ppa.g.sec = (paddr & ppaf->sec_mask) >> ppaf->sec_offset;
 
 	return ppa;
 }
@@ -973,7 +973,7 @@ static inline u64 pblk_dev_ppa_to_line_addr(struct pblk *pblk,
 	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->sect_offset;
+	paddr |= (u64)p.g.sec << ppaf->sec_offset;
 
 	return paddr;
 }
@@ -998,7 +998,7 @@ static inline struct ppa_addr pblk_ppa32_to_ppa64(struct pblk *pblk, u32 ppa32)
 		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->sect_offset;
+		ppa64.g.sec = (ppa32 & ppaf->sec_mask) >> ppaf->sec_offset;
 	}
 
 	return ppa64;
@@ -1022,7 +1022,7 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
 		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->sect_offset;
+		ppa32 |= ppa64.g.sec << ppaf->sec_offset;
 	}
 
 	return ppa32;
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index bd97672e0b4f..cca32da05316 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -262,21 +262,21 @@ static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
 	dst->blk_len = src->blk_len;
 	dst->pg_len = src->pg_len;
 	dst->pln_len = src->pln_len;
-	dst->sect_len = src->sec_len;
+	dst->sec_len = src->sec_len;
 
 	dst->ch_offset = src->ch_offset;
 	dst->lun_offset = src->lun_offset;
 	dst->blk_offset = src->blk_offset;
 	dst->pg_offset = src->pg_offset;
 	dst->pln_offset = src->pln_offset;
-	dst->sect_offset = src->sec_offset;
+	dst->sec_offset = src->sec_offset;
 
 	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
 	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
 	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
 	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
 	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
-	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
+	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
 }
 
 static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
@@ -956,7 +956,7 @@ static ssize_t nvm_dev_attr_show_ppaf(struct nvm_addr_format_12 *ppaf,
 				ppaf->pln_offset, ppaf->pln_len,
 				ppaf->blk_offset, ppaf->blk_len,
 				ppaf->pg_offset, ppaf->pg_len,
-				ppaf->sect_offset, ppaf->sect_len);
+				ppaf->sec_offset, ppaf->sec_len);
 }
 
 static ssize_t nvm_dev_attr_show_12(struct device *dev,
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 02f1fd617781..ccc5faa63cb7 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -163,14 +163,14 @@ struct nvm_addr_format_12 {
 	u8	blk_len;
 	u8	pg_len;
 	u8	pln_len;
-	u8	sect_len;
+	u8	sec_len;
 
 	u8	ch_offset;
 	u8	lun_offset;
 	u8	blk_offset;
 	u8	pg_offset;
 	u8	pln_offset;
-	u8	sect_offset;
+	u8	sec_offset;
 
 	u64	ch_mask;
 	u64	lun_mask;
@@ -399,7 +399,7 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
 	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
 	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
 	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
-	l.ppa |= ((u64)r.g.sec) << ppaf->sect_offset;
+	l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
 
 	return l;
 }
@@ -419,7 +419,7 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
 	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
 	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
 	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
-	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sect_offset;
+	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
 
 	return l;
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 07/20] lightnvm: rename sect_* to sec_*
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


Rename abbreviations for sector from sect_* to sec_* as most of the code
uses this format and it is confusing when using the different
structures.

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/lightnvm/pblk-init.c  | 8 ++++----
 drivers/lightnvm/pblk-sysfs.c | 4 ++--
 drivers/lightnvm/pblk.h       | 8 ++++----
 drivers/nvme/host/lightnvm.c  | 8 ++++----
 include/linux/lightnvm.h      | 8 ++++----
 5 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 455fc63a9409..6bf51ef8f516 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -179,16 +179,16 @@ static int pblk_set_addrf_12(struct nvm_geo *geo,
 	dst->blk_len = src->blk_len;
 	dst->pg_len = src->pg_len;
 	dst->pln_len = src->pln_len;
-	dst->sect_len = src->sect_len;
+	dst->sec_len = src->sec_len;
 
-	dst->sect_offset = 0;
-	dst->pln_offset = dst->sect_len;
+	dst->sec_offset = 0;
+	dst->pln_offset = dst->sec_len;
 	dst->ch_offset = dst->pln_offset + dst->pln_len;
 	dst->lun_offset = dst->ch_offset + dst->ch_len;
 	dst->pg_offset = dst->lun_offset + dst->lun_len;
 	dst->blk_offset = dst->pg_offset + dst->pg_len;
 
-	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
+	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
 	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
 	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
 	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index 5eb21a279361..81288aa9162a 100644
--- a/drivers/lightnvm/pblk-sysfs.c
+++ b/drivers/lightnvm/pblk-sysfs.c
@@ -128,7 +128,7 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
 			ppaf->blk_offset, ppaf->blk_len,
 			ppaf->pg_offset, ppaf->pg_len,
 			ppaf->pln_offset, ppaf->pln_len,
-			ppaf->sect_offset, ppaf->sect_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",
@@ -137,7 +137,7 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
 			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->sect_offset, geo_ppaf->sect_len);
+			geo_ppaf->sec_offset, geo_ppaf->sec_len);
 
 	return sz;
 }
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 1f32284b0aec..4f7a365436f1 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -957,7 +957,7 @@ static inline struct ppa_addr addr_to_gen_ppa(struct pblk *pblk, u64 paddr,
 	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->sect_offset;
+	ppa.g.sec = (paddr & ppaf->sec_mask) >> ppaf->sec_offset;
 
 	return ppa;
 }
@@ -973,7 +973,7 @@ static inline u64 pblk_dev_ppa_to_line_addr(struct pblk *pblk,
 	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->sect_offset;
+	paddr |= (u64)p.g.sec << ppaf->sec_offset;
 
 	return paddr;
 }
@@ -998,7 +998,7 @@ static inline struct ppa_addr pblk_ppa32_to_ppa64(struct pblk *pblk, u32 ppa32)
 		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->sect_offset;
+		ppa64.g.sec = (ppa32 & ppaf->sec_mask) >> ppaf->sec_offset;
 	}
 
 	return ppa64;
@@ -1022,7 +1022,7 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
 		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->sect_offset;
+		ppa32 |= ppa64.g.sec << ppaf->sec_offset;
 	}
 
 	return ppa32;
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index bd97672e0b4f..cca32da05316 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -262,21 +262,21 @@ static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
 	dst->blk_len = src->blk_len;
 	dst->pg_len = src->pg_len;
 	dst->pln_len = src->pln_len;
-	dst->sect_len = src->sec_len;
+	dst->sec_len = src->sec_len;
 
 	dst->ch_offset = src->ch_offset;
 	dst->lun_offset = src->lun_offset;
 	dst->blk_offset = src->blk_offset;
 	dst->pg_offset = src->pg_offset;
 	dst->pln_offset = src->pln_offset;
-	dst->sect_offset = src->sec_offset;
+	dst->sec_offset = src->sec_offset;
 
 	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
 	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
 	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
 	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
 	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
-	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
+	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
 }
 
 static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
@@ -956,7 +956,7 @@ static ssize_t nvm_dev_attr_show_ppaf(struct nvm_addr_format_12 *ppaf,
 				ppaf->pln_offset, ppaf->pln_len,
 				ppaf->blk_offset, ppaf->blk_len,
 				ppaf->pg_offset, ppaf->pg_len,
-				ppaf->sect_offset, ppaf->sect_len);
+				ppaf->sec_offset, ppaf->sec_len);
 }
 
 static ssize_t nvm_dev_attr_show_12(struct device *dev,
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 02f1fd617781..ccc5faa63cb7 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -163,14 +163,14 @@ struct nvm_addr_format_12 {
 	u8	blk_len;
 	u8	pg_len;
 	u8	pln_len;
-	u8	sect_len;
+	u8	sec_len;
 
 	u8	ch_offset;
 	u8	lun_offset;
 	u8	blk_offset;
 	u8	pg_offset;
 	u8	pln_offset;
-	u8	sect_offset;
+	u8	sec_offset;
 
 	u64	ch_mask;
 	u64	lun_mask;
@@ -399,7 +399,7 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
 	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
 	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
 	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
-	l.ppa |= ((u64)r.g.sec) << ppaf->sect_offset;
+	l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
 
 	return l;
 }
@@ -419,7 +419,7 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
 	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
 	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
 	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
-	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sect_offset;
+	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
 
 	return l;
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 08/20] lightnvm: complete geo structure with maxoc*
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

Complete the generic geometry structure with the maxoc and maxocpu
felds, present in the 2.0 spec.

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/nvme/host/lightnvm.c | 4 ++++
 include/linux/lightnvm.h     | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index cca32da05316..9c1f8225c4e1 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -318,6 +318,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
 	dev_geo->c.ws_min = sec_per_pg;
 	dev_geo->c.ws_opt = sec_per_pg;
 	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
+	dev_geo->c.maxoc = dev_geo->all_luns;	/* default to 1 chunk per LUN */
+	dev_geo->c.maxocpu = 1;			/* default to 1 chunk per LUN */
 
 	dev_geo->c.mccap = le32_to_cpu(src->mccap);
 
@@ -405,6 +407,8 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 	dev_geo->c.ws_min = le32_to_cpu(id->ws_min);
 	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
 	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
+	dev_geo->c.maxoc = le32_to_cpu(id->maxoc);
+	dev_geo->c.maxocpu = le32_to_cpu(id->maxocpu);
 
 	dev_geo->c.mccap = le32_to_cpu(id->mccap);
 
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index ccc5faa63cb7..e1c4292ea33d 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -215,6 +215,8 @@ struct nvm_common_geo {
 	u32	ws_min;		/* minimum write size */
 	u32	ws_opt;		/* optimal write size */
 	u32	mw_cunits;	/* distance required for successful read */
+	u32	maxoc;		/* maximum open chunks */
+	u32	maxocpu;	/* maximum open chunks per parallel unit */
 
 	/* device capabilities */
 	u32	mccap;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 08/20] lightnvm: complete geo structure with maxoc*
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


Complete the generic geometry structure with the maxoc and maxocpu
felds, present in the 2.0 spec.

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/nvme/host/lightnvm.c | 4 ++++
 include/linux/lightnvm.h     | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index cca32da05316..9c1f8225c4e1 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -318,6 +318,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
 	dev_geo->c.ws_min = sec_per_pg;
 	dev_geo->c.ws_opt = sec_per_pg;
 	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
+	dev_geo->c.maxoc = dev_geo->all_luns;	/* default to 1 chunk per LUN */
+	dev_geo->c.maxocpu = 1;			/* default to 1 chunk per LUN */
 
 	dev_geo->c.mccap = le32_to_cpu(src->mccap);
 
@@ -405,6 +407,8 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 	dev_geo->c.ws_min = le32_to_cpu(id->ws_min);
 	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
 	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
+	dev_geo->c.maxoc = le32_to_cpu(id->maxoc);
+	dev_geo->c.maxocpu = le32_to_cpu(id->maxocpu);
 
 	dev_geo->c.mccap = le32_to_cpu(id->mccap);
 
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index ccc5faa63cb7..e1c4292ea33d 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -215,6 +215,8 @@ struct nvm_common_geo {
 	u32	ws_min;		/* minimum write size */
 	u32	ws_opt;		/* optimal write size */
 	u32	mw_cunits;	/* distance required for successful read */
+	u32	maxoc;		/* maximum open chunks */
+	u32	maxocpu;	/* maximum open chunks per parallel unit */
 
 	/* device capabilities */
 	u32	mccap;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 09/20] lightnvm: use generic identify structure
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

Create a generic identify structure to collect the identify information
before knowing the spec. version. This forces different version paths to
cast the structure to their spec structure, thus making the code less
error prone and more maintainable.

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/nvme/host/lightnvm.c | 32 ++++++++++++++++++++------------
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 9c1f8225c4e1..70dc4740f0d3 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -170,6 +170,12 @@ struct nvme_nvm_id12 {
 	__u8			resv2[2880];
 } __packed;
 
+/* Generic identification structure */
+struct nvme_nvm_id {
+	__u8			ver_id;
+	__u8			resv[4095];
+} __packed;
+
 struct nvme_nvm_bb_tbl {
 	__u8	tblid[4];
 	__le16	verid;
@@ -279,9 +285,10 @@ static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
 	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
 }
 
-static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
+static int nvme_nvm_setup_12(struct nvme_nvm_id *gen_id,
 			     struct nvm_dev_geo *dev_geo)
 {
+	struct nvme_nvm_id12 *id = (struct nvme_nvm_id12 *)gen_id;
 	struct nvme_nvm_id12_grp *src;
 	int sec_per_pg, sec_per_pl, pg_per_blk;
 
@@ -380,9 +387,11 @@ static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
 	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
 }
 
-static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
+static int nvme_nvm_setup_20(struct nvme_nvm_id *gen_id,
 			     struct nvm_dev_geo *dev_geo)
 {
+	struct nvme_nvm_id20 *id = (struct nvme_nvm_id20 *)gen_id;
+
 	dev_geo->major_ver_id = id->mjr;
 	dev_geo->minor_ver_id = id->mnr;
 
@@ -427,19 +436,19 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 static int nvme_nvm_identity(struct nvm_dev *nvmdev)
 {
 	struct nvme_ns *ns = nvmdev->q->queuedata;
-	struct nvme_nvm_id12 *id;
+	struct nvme_nvm_id *nvme_nvm_id;
 	struct nvme_nvm_command c = {};
 	int ret;
 
 	c.identity.opcode = nvme_nvm_admin_identity;
 	c.identity.nsid = cpu_to_le32(ns->head->ns_id);
 
-	id = kmalloc(sizeof(struct nvme_nvm_id12), GFP_KERNEL);
-	if (!id)
+	nvme_nvm_id = kmalloc(sizeof(struct nvme_nvm_id), GFP_KERNEL);
+	if (!nvme_nvm_id)
 		return -ENOMEM;
 
 	ret = nvme_submit_sync_cmd(ns->ctrl->admin_q, (struct nvme_command *)&c,
-				id, sizeof(struct nvme_nvm_id12));
+				nvme_nvm_id, sizeof(struct nvme_nvm_id));
 	if (ret) {
 		ret = -EIO;
 		goto out;
@@ -449,22 +458,21 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev)
 	 * The 1.2 and 2.0 specifications share the first byte in their geometry
 	 * command to make it possible to know what version a device implements.
 	 */
-	switch (id->ver_id) {
+	switch (nvme_nvm_id->ver_id) {
 	case 1:
-		ret = nvme_nvm_setup_12(id, &nvmdev->dev_geo);
+		ret = nvme_nvm_setup_12(nvme_nvm_id, &nvmdev->dev_geo);
 		break;
 	case 2:
-		ret = nvme_nvm_setup_20((struct nvme_nvm_id20 *)id,
-							&nvmdev->dev_geo);
+		ret = nvme_nvm_setup_20(nvme_nvm_id, &nvmdev->dev_geo);
 		break;
 	default:
 		dev_err(ns->ctrl->device, "OCSSD revision not supported (%d)\n",
-							id->ver_id);
+							nvme_nvm_id->ver_id);
 		ret = -EINVAL;
 	}
 
 out:
-	kfree(id);
+	kfree(nvme_nvm_id);
 	return ret;
 }
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 09/20] lightnvm: use generic identify structure
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


Create a generic identify structure to collect the identify information
before knowing the spec. version. This forces different version paths to
cast the structure to their spec structure, thus making the code less
error prone and more maintainable.

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/nvme/host/lightnvm.c | 32 ++++++++++++++++++++------------
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 9c1f8225c4e1..70dc4740f0d3 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -170,6 +170,12 @@ struct nvme_nvm_id12 {
 	__u8			resv2[2880];
 } __packed;
 
+/* Generic identification structure */
+struct nvme_nvm_id {
+	__u8			ver_id;
+	__u8			resv[4095];
+} __packed;
+
 struct nvme_nvm_bb_tbl {
 	__u8	tblid[4];
 	__le16	verid;
@@ -279,9 +285,10 @@ static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
 	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
 }
 
-static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
+static int nvme_nvm_setup_12(struct nvme_nvm_id *gen_id,
 			     struct nvm_dev_geo *dev_geo)
 {
+	struct nvme_nvm_id12 *id = (struct nvme_nvm_id12 *)gen_id;
 	struct nvme_nvm_id12_grp *src;
 	int sec_per_pg, sec_per_pl, pg_per_blk;
 
@@ -380,9 +387,11 @@ static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
 	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
 }
 
-static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
+static int nvme_nvm_setup_20(struct nvme_nvm_id *gen_id,
 			     struct nvm_dev_geo *dev_geo)
 {
+	struct nvme_nvm_id20 *id = (struct nvme_nvm_id20 *)gen_id;
+
 	dev_geo->major_ver_id = id->mjr;
 	dev_geo->minor_ver_id = id->mnr;
 
@@ -427,19 +436,19 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 static int nvme_nvm_identity(struct nvm_dev *nvmdev)
 {
 	struct nvme_ns *ns = nvmdev->q->queuedata;
-	struct nvme_nvm_id12 *id;
+	struct nvme_nvm_id *nvme_nvm_id;
 	struct nvme_nvm_command c = {};
 	int ret;
 
 	c.identity.opcode = nvme_nvm_admin_identity;
 	c.identity.nsid = cpu_to_le32(ns->head->ns_id);
 
-	id = kmalloc(sizeof(struct nvme_nvm_id12), GFP_KERNEL);
-	if (!id)
+	nvme_nvm_id = kmalloc(sizeof(struct nvme_nvm_id), GFP_KERNEL);
+	if (!nvme_nvm_id)
 		return -ENOMEM;
 
 	ret = nvme_submit_sync_cmd(ns->ctrl->admin_q, (struct nvme_command *)&c,
-				id, sizeof(struct nvme_nvm_id12));
+				nvme_nvm_id, sizeof(struct nvme_nvm_id));
 	if (ret) {
 		ret = -EIO;
 		goto out;
@@ -449,22 +458,21 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev)
 	 * The 1.2 and 2.0 specifications share the first byte in their geometry
 	 * command to make it possible to know what version a device implements.
 	 */
-	switch (id->ver_id) {
+	switch (nvme_nvm_id->ver_id) {
 	case 1:
-		ret = nvme_nvm_setup_12(id, &nvmdev->dev_geo);
+		ret = nvme_nvm_setup_12(nvme_nvm_id, &nvmdev->dev_geo);
 		break;
 	case 2:
-		ret = nvme_nvm_setup_20((struct nvme_nvm_id20 *)id,
-							&nvmdev->dev_geo);
+		ret = nvme_nvm_setup_20(nvme_nvm_id, &nvmdev->dev_geo);
 		break;
 	default:
 		dev_err(ns->ctrl->device, "OCSSD revision not supported (%d)\n",
-							id->ver_id);
+							nvme_nvm_id->ver_id);
 		ret = -EINVAL;
 	}
 
 out:
-	kfree(id);
+	kfree(nvme_nvm_id);
 	return ret;
 }
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 10/20] lightnvm: pblk: rename ppaf* to addrf*
  2018-02-21  9:26 ` Javier González
  (?)
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, Javier González, linux-kernel, linux-nvme

SW4gcHJlcGFyYXRpb24gZm9yIDIuMCBzdXBwb3J0IGluIHBibGssIHJlbmFtZSB2YXJpYWJsZXMg
cmVmZXJyaW5nIHRvCnRoZSBhZGRyZXNzIGZvcm1hdCB0byBhZGRyZiBhbmQgcmVzZXJ2ZSBwcGFm
IGZvciB0aGUgMS4yIHBhdGguCgpTaWduZWQtb2ZmLWJ5OiBKYXZpZXIgR29uesOhbGV6IDxqYXZp
ZXJAY25leGxhYnMuY29tPgotLS0KIGRyaXZlcnMvbGlnaHRudm0vcGJsay1pbml0LmMgIHwgIDgg
KysrKy0tLS0KIGRyaXZlcnMvbGlnaHRudm0vcGJsay1zeXNmcy5jIHwgIDQgKystLQogZHJpdmVy
cy9saWdodG52bS9wYmxrLmggICAgICAgfCAxNiArKysrKysrKy0tLS0tLS0tCiAzIGZpbGVzIGNo
YW5nZWQsIDE0IGluc2VydGlvbnMoKyksIDE0IGRlbGV0aW9ucygtKQoKZGlmZiAtLWdpdCBhL2Ry
aXZlcnMvbGlnaHRudm0vcGJsay1pbml0LmMgYi9kcml2ZXJzL2xpZ2h0bnZtL3BibGstaW5pdC5j
CmluZGV4IDZiZjUxZWY4ZjUxNi4uNTZiNGFmYzI3YWRkIDEwMDY0NAotLS0gYS9kcml2ZXJzL2xp
Z2h0bnZtL3BibGstaW5pdC5jCisrKyBiL2RyaXZlcnMvbGlnaHRudm0vcGJsay1pbml0LmMKQEAg
LTgwLDcgKzgwLDcgQEAgc3RhdGljIHNpemVfdCBwYmxrX3RyYW5zX21hcF9zaXplKHN0cnVjdCBw
YmxrICpwYmxrKQogewogCWludCBlbnRyeV9zaXplID0gODsKIAotCWlmIChwYmxrLT5wcGFmX2Jp
dHNpemUgPCAzMikKKwlpZiAocGJsay0+YWRkcmZfbGVuIDwgMzIpCiAJCWVudHJ5X3NpemUgPSA0
OwogCiAJcmV0dXJuIGVudHJ5X3NpemUgKiBwYmxrLT5ybC5ucl9zZWNzOwpAQCAtMTk4LDcgKzE5
OCw3IEBAIHN0YXRpYyBpbnQgcGJsa19zZXRfYWRkcmZfMTIoc3RydWN0IG52bV9nZW8gKmdlbywK
IAlyZXR1cm4gZHN0LT5ibGtfb2Zmc2V0ICsgc3JjLT5ibGtfbGVuOwogfQogCi1zdGF0aWMgaW50
IHBibGtfc2V0X3BwYWYoc3RydWN0IHBibGsgKnBibGspCitzdGF0aWMgaW50IHBibGtfc2V0X2Fk
ZHJmKHN0cnVjdCBwYmxrICpwYmxrKQogewogCXN0cnVjdCBudm1fdGd0X2RldiAqZGV2ID0gcGJs
ay0+ZGV2OwogCXN0cnVjdCBudm1fZ2VvICpnZW8gPSAmZGV2LT5nZW87CkBAIC0yMTAsNyArMjEw
LDcgQEAgc3RhdGljIGludCBwYmxrX3NldF9wcGFmKHN0cnVjdCBwYmxrICpwYmxrKQogCQlyZXR1
cm4gLUVJTlZBTDsKIAl9CiAKLQlwYmxrLT5wcGFmX2JpdHNpemUgPSBwYmxrX3NldF9hZGRyZl8x
MihnZW8sICh2b2lkICopJnBibGstPnBwYWYpOworCXBibGstPmFkZHJmX2xlbiA9IHBibGtfc2V0
X2FkZHJmXzEyKGdlbywgKHZvaWQgKikmcGJsay0+YWRkcmYpOwogCiAJcmV0dXJuIDA7CiB9CkBA
IC0zMTksNyArMzE5LDcgQEAgc3RhdGljIGludCBwYmxrX2NvcmVfaW5pdChzdHJ1Y3QgcGJsayAq
cGJsaykKIAlpZiAoIXBibGstPnJfZW5kX3dxKQogCQlnb3RvIGZyZWVfYmJfd3E7CiAKLQlpZiAo
cGJsa19zZXRfcHBhZihwYmxrKSkKKwlpZiAocGJsa19zZXRfYWRkcmYocGJsaykpCiAJCWdvdG8g
ZnJlZV9yX2VuZF93cTsKIAogCWlmIChwYmxrX3J3Yl9pbml0KHBibGspKQpkaWZmIC0tZ2l0IGEv
ZHJpdmVycy9saWdodG52bS9wYmxrLXN5c2ZzLmMgYi9kcml2ZXJzL2xpZ2h0bnZtL3BibGstc3lz
ZnMuYwppbmRleCA4MTI4OGFhOTE2MmEuLmQzYjUwNzQxYjY5MSAxMDA2NDQKLS0tIGEvZHJpdmVy
cy9saWdodG52bS9wYmxrLXN5c2ZzLmMKKysrIGIvZHJpdmVycy9saWdodG52bS9wYmxrLXN5c2Zz
LmMKQEAgLTExNywxMiArMTE3LDEyIEBAIHN0YXRpYyBzc2l6ZV90IHBibGtfc3lzZnNfcHBhZihz
dHJ1Y3QgcGJsayAqcGJsaywgY2hhciAqcGFnZSkKIAlzdHJ1Y3QgbnZtX2FkZHJfZm9ybWF0XzEy
ICpnZW9fcHBhZjsKIAlzc2l6ZV90IHN6ID0gMDsKIAotCXBwYWYgPSAoc3RydWN0IG52bV9hZGRy
X2Zvcm1hdF8xMiAqKSZwYmxrLT5wcGFmOworCXBwYWYgPSAoc3RydWN0IG52bV9hZGRyX2Zvcm1h
dF8xMiAqKSZwYmxrLT5hZGRyZjsKIAlnZW9fcHBhZiA9IChzdHJ1Y3QgbnZtX2FkZHJfZm9ybWF0
XzEyICopJmdlby0+Yy5hZGRyZjsKIAogCXN6ID0gc25wcmludGYocGFnZSwgUEFHRV9TSVpFLAog
CQkicGJsazooczolZCljaDolZC8lZCxsdW46JWQvJWQsYmxrOiVkLyVkLHBnOiVkLyVkLHBsOiVk
LyVkLHNlYzolZC8lZFxuIiwKLQkJCXBibGstPnBwYWZfYml0c2l6ZSwKKwkJCXBibGstPmFkZHJm
X2xlbiwKIAkJCXBwYWYtPmNoX29mZnNldCwgcHBhZi0+Y2hfbGVuLAogCQkJcHBhZi0+bHVuX29m
ZnNldCwgcHBhZi0+bHVuX2xlbiwKIAkJCXBwYWYtPmJsa19vZmZzZXQsIHBwYWYtPmJsa19sZW4s
CmRpZmYgLS1naXQgYS9kcml2ZXJzL2xpZ2h0bnZtL3BibGsuaCBiL2RyaXZlcnMvbGlnaHRudm0v
cGJsay5oCmluZGV4IDRmN2EzNjU0MzZmMS4uNDZiMjlhNDkyZjc0IDEwMDY0NAotLS0gYS9kcml2
ZXJzL2xpZ2h0bnZtL3BibGsuaAorKysgYi9kcml2ZXJzL2xpZ2h0bnZtL3BibGsuaApAQCAtNTcw
LDggKzU3MCw4IEBAIHN0cnVjdCBwYmxrIHsKIAlzdHJ1Y3QgcGJsa19saW5lX21nbXQgbF9tZzsJ
CS8qIExpbmUgbWFuYWdlbWVudCAqLwogCXN0cnVjdCBwYmxrX2xpbmVfbWV0YSBsbTsJCS8qIExp
bmUgbWV0YWRhdGEgKi8KIAotCXN0cnVjdCBudm1fYWRkcl9mb3JtYXQgcHBhZjsKLQlpbnQgcHBh
Zl9iaXRzaXplOworCXN0cnVjdCBudm1fYWRkcl9mb3JtYXQgYWRkcmY7CisJaW50IGFkZHJmX2xl
bjsKIAogCXN0cnVjdCBwYmxrX3JiIHJ3YjsKIApAQCAtOTQ4LDcgKzk0OCw3IEBAIHN0YXRpYyBp
bmxpbmUgc3RydWN0IHBwYV9hZGRyIGFkZHJfdG9fZ2VuX3BwYShzdHJ1Y3QgcGJsayAqcGJsaywg
dTY0IHBhZGRyLAogCQkJCQkgICAgICB1NjQgbGluZV9pZCkKIHsKIAlzdHJ1Y3QgbnZtX2FkZHJf
Zm9ybWF0XzEyICpwcGFmID0KLQkJCQkoc3RydWN0IG52bV9hZGRyX2Zvcm1hdF8xMiAqKSZwYmxr
LT5wcGFmOworCQkJCShzdHJ1Y3QgbnZtX2FkZHJfZm9ybWF0XzEyICopJnBibGstPmFkZHJmOwog
CXN0cnVjdCBwcGFfYWRkciBwcGE7CiAKIAlwcGEucHBhID0gMDsKQEAgLTk2Niw3ICs5NjYsNyBA
QCBzdGF0aWMgaW5saW5lIHU2NCBwYmxrX2Rldl9wcGFfdG9fbGluZV9hZGRyKHN0cnVjdCBwYmxr
ICpwYmxrLAogCQkJCQkJCXN0cnVjdCBwcGFfYWRkciBwKQogewogCXN0cnVjdCBudm1fYWRkcl9m
b3JtYXRfMTIgKnBwYWYgPQotCQkJCShzdHJ1Y3QgbnZtX2FkZHJfZm9ybWF0XzEyICopJnBibGst
PnBwYWY7CisJCQkJKHN0cnVjdCBudm1fYWRkcl9mb3JtYXRfMTIgKikmcGJsay0+YWRkcmY7CiAJ
dTY0IHBhZGRyOwogCiAJcGFkZHIgPSAodTY0KXAuZy5jaCA8PCBwcGFmLT5jaF9vZmZzZXQ7CkBA
IC05OTEsNyArOTkxLDcgQEAgc3RhdGljIGlubGluZSBzdHJ1Y3QgcHBhX2FkZHIgcGJsa19wcGEz
Ml90b19wcGE2NChzdHJ1Y3QgcGJsayAqcGJsaywgdTMyIHBwYTMyKQogCQlwcGE2NC5jLmlzX2Nh
Y2hlZCA9IDE7CiAJfSBlbHNlIHsKIAkJc3RydWN0IG52bV9hZGRyX2Zvcm1hdF8xMiAqcHBhZiA9
Ci0JCQkJKHN0cnVjdCBudm1fYWRkcl9mb3JtYXRfMTIgKikmcGJsay0+cHBhZjsKKwkJCQkoc3Ry
dWN0IG52bV9hZGRyX2Zvcm1hdF8xMiAqKSZwYmxrLT5hZGRyZjsKIAogCQlwcGE2NC5nLmNoID0g
KHBwYTMyICYgcHBhZi0+Y2hfbWFzaykgPj4gcHBhZi0+Y2hfb2Zmc2V0OwogCQlwcGE2NC5nLmx1
biA9IChwcGEzMiAmIHBwYWYtPmx1bl9tYXNrKSA+PiBwcGFmLT5sdW5fb2Zmc2V0OwpAQCAtMTAx
NSw3ICsxMDE1LDcgQEAgc3RhdGljIGlubGluZSB1MzIgcGJsa19wcGE2NF90b19wcGEzMihzdHJ1
Y3QgcGJsayAqcGJsaywgc3RydWN0IHBwYV9hZGRyIHBwYTY0KQogCQlwcGEzMiB8PSAxVSA8PCAz
MTsKIAl9IGVsc2UgewogCQlzdHJ1Y3QgbnZtX2FkZHJfZm9ybWF0XzEyICpwcGFmID0KLQkJCQko
c3RydWN0IG52bV9hZGRyX2Zvcm1hdF8xMiAqKSZwYmxrLT5wcGFmOworCQkJCShzdHJ1Y3QgbnZt
X2FkZHJfZm9ybWF0XzEyICopJnBibGstPmFkZHJmOwogCiAJCXBwYTMyIHw9IHBwYTY0LmcuY2gg
PDwgcHBhZi0+Y2hfb2Zmc2V0OwogCQlwcGEzMiB8PSBwcGE2NC5nLmx1biA8PCBwcGFmLT5sdW5f
b2Zmc2V0OwpAQCAtMTAzMyw3ICsxMDMzLDcgQEAgc3RhdGljIGlubGluZSBzdHJ1Y3QgcHBhX2Fk
ZHIgcGJsa190cmFuc19tYXBfZ2V0KHN0cnVjdCBwYmxrICpwYmxrLAogewogCXN0cnVjdCBwcGFf
YWRkciBwcGE7CiAKLQlpZiAocGJsay0+cHBhZl9iaXRzaXplIDwgMzIpIHsKKwlpZiAocGJsay0+
YWRkcmZfbGVuIDwgMzIpIHsKIAkJdTMyICptYXAgPSAodTMyICopcGJsay0+dHJhbnNfbWFwOwog
CiAJCXBwYSA9IHBibGtfcHBhMzJfdG9fcHBhNjQocGJsaywgbWFwW2xiYV0pOwpAQCAtMTA0OSw3
ICsxMDQ5LDcgQEAgc3RhdGljIGlubGluZSBzdHJ1Y3QgcHBhX2FkZHIgcGJsa190cmFuc19tYXBf
Z2V0KHN0cnVjdCBwYmxrICpwYmxrLAogc3RhdGljIGlubGluZSB2b2lkIHBibGtfdHJhbnNfbWFw
X3NldChzdHJ1Y3QgcGJsayAqcGJsaywgc2VjdG9yX3QgbGJhLAogCQkJCQkJc3RydWN0IHBwYV9h
ZGRyIHBwYSkKIHsKLQlpZiAocGJsay0+cHBhZl9iaXRzaXplIDwgMzIpIHsKKwlpZiAocGJsay0+
YWRkcmZfbGVuIDwgMzIpIHsKIAkJdTMyICptYXAgPSAodTMyICopcGJsay0+dHJhbnNfbWFwOwog
CiAJCW1hcFtsYmFdID0gcGJsa19wcGE2NF90b19wcGEzMihwYmxrLCBwcGEpOwotLSAKMi43LjQK
CgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpMaW51eC1u
dm1lIG1haWxpbmcgbGlzdApMaW51eC1udm1lQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xp
c3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1udm1lCg==

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 10/20] lightnvm: pblk: rename ppaf* to addrf*
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

In preparation for 2.0 support in pblk, rename variables referring to
the address format to addrf and reserve ppaf for the 1.2 path.

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/lightnvm/pblk-init.c  |  8 ++++----
 drivers/lightnvm/pblk-sysfs.c |  4 ++--
 drivers/lightnvm/pblk.h       | 16 ++++++++--------
 3 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 6bf51ef8f516..56b4afc27add 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -80,7 +80,7 @@ static size_t pblk_trans_map_size(struct pblk *pblk)
 {
 	int entry_size = 8;
 
-	if (pblk->ppaf_bitsize < 32)
+	if (pblk->addrf_len < 32)
 		entry_size = 4;
 
 	return entry_size * pblk->rl.nr_secs;
@@ -198,7 +198,7 @@ static int pblk_set_addrf_12(struct nvm_geo *geo,
 	return dst->blk_offset + src->blk_len;
 }
 
-static int pblk_set_ppaf(struct pblk *pblk)
+static int pblk_set_addrf(struct pblk *pblk)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
@@ -210,7 +210,7 @@ static int pblk_set_ppaf(struct pblk *pblk)
 		return -EINVAL;
 	}
 
-	pblk->ppaf_bitsize = pblk_set_addrf_12(geo, (void *)&pblk->ppaf);
+	pblk->addrf_len = pblk_set_addrf_12(geo, (void *)&pblk->addrf);
 
 	return 0;
 }
@@ -319,7 +319,7 @@ static int pblk_core_init(struct pblk *pblk)
 	if (!pblk->r_end_wq)
 		goto free_bb_wq;
 
-	if (pblk_set_ppaf(pblk))
+	if (pblk_set_addrf(pblk))
 		goto free_r_end_wq;
 
 	if (pblk_rwb_init(pblk))
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index 81288aa9162a..d3b50741b691 100644
--- a/drivers/lightnvm/pblk-sysfs.c
+++ b/drivers/lightnvm/pblk-sysfs.c
@@ -117,12 +117,12 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
 	struct nvm_addr_format_12 *geo_ppaf;
 	ssize_t sz = 0;
 
-	ppaf = (struct nvm_addr_format_12 *)&pblk->ppaf;
+	ppaf = (struct nvm_addr_format_12 *)&pblk->addrf;
 	geo_ppaf = (struct nvm_addr_format_12 *)&geo->c.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",
-			pblk->ppaf_bitsize,
+			pblk->addrf_len,
 			ppaf->ch_offset, ppaf->ch_len,
 			ppaf->lun_offset, ppaf->lun_len,
 			ppaf->blk_offset, ppaf->blk_len,
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 4f7a365436f1..46b29a492f74 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -570,8 +570,8 @@ struct pblk {
 	struct pblk_line_mgmt l_mg;		/* Line management */
 	struct pblk_line_meta lm;		/* Line metadata */
 
-	struct nvm_addr_format ppaf;
-	int ppaf_bitsize;
+	struct nvm_addr_format addrf;
+	int addrf_len;
 
 	struct pblk_rb rwb;
 
@@ -948,7 +948,7 @@ 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->ppaf;
+				(struct nvm_addr_format_12 *)&pblk->addrf;
 	struct ppa_addr ppa;
 
 	ppa.ppa = 0;
@@ -966,7 +966,7 @@ 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->ppaf;
+				(struct nvm_addr_format_12 *)&pblk->addrf;
 	u64 paddr;
 
 	paddr = (u64)p.g.ch << ppaf->ch_offset;
@@ -991,7 +991,7 @@ static inline struct ppa_addr pblk_ppa32_to_ppa64(struct pblk *pblk, u32 ppa32)
 		ppa64.c.is_cached = 1;
 	} else {
 		struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&pblk->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;
@@ -1015,7 +1015,7 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
 		ppa32 |= 1U << 31;
 	} else {
 		struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&pblk->ppaf;
+				(struct nvm_addr_format_12 *)&pblk->addrf;
 
 		ppa32 |= ppa64.g.ch << ppaf->ch_offset;
 		ppa32 |= ppa64.g.lun << ppaf->lun_offset;
@@ -1033,7 +1033,7 @@ static inline struct ppa_addr pblk_trans_map_get(struct pblk *pblk,
 {
 	struct ppa_addr ppa;
 
-	if (pblk->ppaf_bitsize < 32) {
+	if (pblk->addrf_len < 32) {
 		u32 *map = (u32 *)pblk->trans_map;
 
 		ppa = pblk_ppa32_to_ppa64(pblk, map[lba]);
@@ -1049,7 +1049,7 @@ static inline struct ppa_addr pblk_trans_map_get(struct pblk *pblk,
 static inline void pblk_trans_map_set(struct pblk *pblk, sector_t lba,
 						struct ppa_addr ppa)
 {
-	if (pblk->ppaf_bitsize < 32) {
+	if (pblk->addrf_len < 32) {
 		u32 *map = (u32 *)pblk->trans_map;
 
 		map[lba] = pblk_ppa64_to_ppa32(pblk, ppa);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 10/20] lightnvm: pblk: rename ppaf* to addrf*
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


In preparation for 2.0 support in pblk, rename variables referring to
the address format to addrf and reserve ppaf for the 1.2 path.

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/lightnvm/pblk-init.c  |  8 ++++----
 drivers/lightnvm/pblk-sysfs.c |  4 ++--
 drivers/lightnvm/pblk.h       | 16 ++++++++--------
 3 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 6bf51ef8f516..56b4afc27add 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -80,7 +80,7 @@ static size_t pblk_trans_map_size(struct pblk *pblk)
 {
 	int entry_size = 8;
 
-	if (pblk->ppaf_bitsize < 32)
+	if (pblk->addrf_len < 32)
 		entry_size = 4;
 
 	return entry_size * pblk->rl.nr_secs;
@@ -198,7 +198,7 @@ static int pblk_set_addrf_12(struct nvm_geo *geo,
 	return dst->blk_offset + src->blk_len;
 }
 
-static int pblk_set_ppaf(struct pblk *pblk)
+static int pblk_set_addrf(struct pblk *pblk)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
@@ -210,7 +210,7 @@ static int pblk_set_ppaf(struct pblk *pblk)
 		return -EINVAL;
 	}
 
-	pblk->ppaf_bitsize = pblk_set_addrf_12(geo, (void *)&pblk->ppaf);
+	pblk->addrf_len = pblk_set_addrf_12(geo, (void *)&pblk->addrf);
 
 	return 0;
 }
@@ -319,7 +319,7 @@ static int pblk_core_init(struct pblk *pblk)
 	if (!pblk->r_end_wq)
 		goto free_bb_wq;
 
-	if (pblk_set_ppaf(pblk))
+	if (pblk_set_addrf(pblk))
 		goto free_r_end_wq;
 
 	if (pblk_rwb_init(pblk))
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index 81288aa9162a..d3b50741b691 100644
--- a/drivers/lightnvm/pblk-sysfs.c
+++ b/drivers/lightnvm/pblk-sysfs.c
@@ -117,12 +117,12 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
 	struct nvm_addr_format_12 *geo_ppaf;
 	ssize_t sz = 0;
 
-	ppaf = (struct nvm_addr_format_12 *)&pblk->ppaf;
+	ppaf = (struct nvm_addr_format_12 *)&pblk->addrf;
 	geo_ppaf = (struct nvm_addr_format_12 *)&geo->c.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",
-			pblk->ppaf_bitsize,
+			pblk->addrf_len,
 			ppaf->ch_offset, ppaf->ch_len,
 			ppaf->lun_offset, ppaf->lun_len,
 			ppaf->blk_offset, ppaf->blk_len,
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 4f7a365436f1..46b29a492f74 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -570,8 +570,8 @@ struct pblk {
 	struct pblk_line_mgmt l_mg;		/* Line management */
 	struct pblk_line_meta lm;		/* Line metadata */
 
-	struct nvm_addr_format ppaf;
-	int ppaf_bitsize;
+	struct nvm_addr_format addrf;
+	int addrf_len;
 
 	struct pblk_rb rwb;
 
@@ -948,7 +948,7 @@ 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->ppaf;
+				(struct nvm_addr_format_12 *)&pblk->addrf;
 	struct ppa_addr ppa;
 
 	ppa.ppa = 0;
@@ -966,7 +966,7 @@ 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->ppaf;
+				(struct nvm_addr_format_12 *)&pblk->addrf;
 	u64 paddr;
 
 	paddr = (u64)p.g.ch << ppaf->ch_offset;
@@ -991,7 +991,7 @@ static inline struct ppa_addr pblk_ppa32_to_ppa64(struct pblk *pblk, u32 ppa32)
 		ppa64.c.is_cached = 1;
 	} else {
 		struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&pblk->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;
@@ -1015,7 +1015,7 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
 		ppa32 |= 1U << 31;
 	} else {
 		struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&pblk->ppaf;
+				(struct nvm_addr_format_12 *)&pblk->addrf;
 
 		ppa32 |= ppa64.g.ch << ppaf->ch_offset;
 		ppa32 |= ppa64.g.lun << ppaf->lun_offset;
@@ -1033,7 +1033,7 @@ static inline struct ppa_addr pblk_trans_map_get(struct pblk *pblk,
 {
 	struct ppa_addr ppa;
 
-	if (pblk->ppaf_bitsize < 32) {
+	if (pblk->addrf_len < 32) {
 		u32 *map = (u32 *)pblk->trans_map;
 
 		ppa = pblk_ppa32_to_ppa64(pblk, map[lba]);
@@ -1049,7 +1049,7 @@ static inline struct ppa_addr pblk_trans_map_get(struct pblk *pblk,
 static inline void pblk_trans_map_set(struct pblk *pblk, sector_t lba,
 						struct ppa_addr ppa)
 {
-	if (pblk->ppaf_bitsize < 32) {
+	if (pblk->addrf_len < 32) {
 		u32 *map = (u32 *)pblk->trans_map;
 
 		map[lba] = pblk_ppa64_to_ppa32(pblk, ppa);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 11/20] lightnvm: pblk: check for supported version
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

At this point, only 1.2 spec is supported, thus check for it. Also,
since device-side L2P is only supported in the 1.2 spec, make sure to
only check its value under 1.2.

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/lightnvm/pblk-init.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 56b4afc27add..ec39800eea42 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -990,9 +990,15 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 	struct pblk *pblk;
 	int ret;
 
-	if (dev->geo.c.dom & NVM_RSP_L2P) {
+	if (geo->c.version != NVM_OCSSD_SPEC_12) {
+		pr_err("pblk: OCSSD version not supported (%u)\n",
+							geo->c.version);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (geo->c.version == NVM_OCSSD_SPEC_12 && geo->c.dom & NVM_RSP_L2P) {
 		pr_err("pblk: host-side L2P table not supported. (%x)\n",
-							dev->geo.c.dom);
+							geo->c.dom);
 		return ERR_PTR(-EINVAL);
 	}
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 11/20] lightnvm: pblk: check for supported version
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


At this point, only 1.2 spec is supported, thus check for it. Also,
since device-side L2P is only supported in the 1.2 spec, make sure to
only check its value under 1.2.

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/lightnvm/pblk-init.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 56b4afc27add..ec39800eea42 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -990,9 +990,15 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 	struct pblk *pblk;
 	int ret;
 
-	if (dev->geo.c.dom & NVM_RSP_L2P) {
+	if (geo->c.version != NVM_OCSSD_SPEC_12) {
+		pr_err("pblk: OCSSD version not supported (%u)\n",
+							geo->c.version);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (geo->c.version == NVM_OCSSD_SPEC_12 && geo->c.dom & NVM_RSP_L2P) {
 		pr_err("pblk: host-side L2P table not supported. (%x)\n",
-							dev->geo.c.dom);
+							geo->c.dom);
 		return ERR_PTR(-EINVAL);
 	}
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 12/20] lightnvm: complete 2.0 values in sysfs
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

Add missing geometry values to sysfs. Namely, maxoc and maxocpu.

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/nvme/host/lightnvm.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 70dc4740f0d3..88c71d0d0d8c 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -1059,6 +1059,10 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_min);
 	} else if (strcmp(attr->name, "ws_opt") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_opt);
+	} else if (strcmp(attr->name, "maxoc") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.maxoc);
+	} else if (strcmp(attr->name, "maxocpu") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.maxocpu);
 	} else if (strcmp(attr->name, "mw_cunits") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mw_cunits);
 	} else if (strcmp(attr->name, "write_typ") == 0) {
@@ -1158,6 +1162,8 @@ static NVM_DEV_ATTR_20_RO(chunks);
 static NVM_DEV_ATTR_20_RO(clba);
 static NVM_DEV_ATTR_20_RO(ws_min);
 static NVM_DEV_ATTR_20_RO(ws_opt);
+static NVM_DEV_ATTR_20_RO(maxoc);
+static NVM_DEV_ATTR_20_RO(maxocpu);
 static NVM_DEV_ATTR_20_RO(mw_cunits);
 static NVM_DEV_ATTR_20_RO(write_typ);
 static NVM_DEV_ATTR_20_RO(write_max);
@@ -1175,6 +1181,8 @@ static struct attribute *nvm_dev_attrs_20[] = {
 	&dev_attr_clba.attr,
 	&dev_attr_ws_min.attr,
 	&dev_attr_ws_opt.attr,
+	&dev_attr_maxoc.attr,
+	&dev_attr_maxocpu.attr,
 	&dev_attr_mw_cunits.attr,
 
 	&dev_attr_read_typ.attr,
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 12/20] lightnvm: complete 2.0 values in sysfs
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


Add missing geometry values to sysfs. Namely, maxoc and maxocpu.

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/nvme/host/lightnvm.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 70dc4740f0d3..88c71d0d0d8c 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -1059,6 +1059,10 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_min);
 	} else if (strcmp(attr->name, "ws_opt") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_opt);
+	} else if (strcmp(attr->name, "maxoc") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.maxoc);
+	} else if (strcmp(attr->name, "maxocpu") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.maxocpu);
 	} else if (strcmp(attr->name, "mw_cunits") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mw_cunits);
 	} else if (strcmp(attr->name, "write_typ") == 0) {
@@ -1158,6 +1162,8 @@ static NVM_DEV_ATTR_20_RO(chunks);
 static NVM_DEV_ATTR_20_RO(clba);
 static NVM_DEV_ATTR_20_RO(ws_min);
 static NVM_DEV_ATTR_20_RO(ws_opt);
+static NVM_DEV_ATTR_20_RO(maxoc);
+static NVM_DEV_ATTR_20_RO(maxocpu);
 static NVM_DEV_ATTR_20_RO(mw_cunits);
 static NVM_DEV_ATTR_20_RO(write_typ);
 static NVM_DEV_ATTR_20_RO(write_max);
@@ -1175,6 +1181,8 @@ static struct attribute *nvm_dev_attrs_20[] = {
 	&dev_attr_clba.attr,
 	&dev_attr_ws_min.attr,
 	&dev_attr_ws_opt.attr,
+	&dev_attr_maxoc.attr,
+	&dev_attr_maxocpu.attr,
 	&dev_attr_mw_cunits.attr,
 
 	&dev_attr_read_typ.attr,
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 13/20] lightnvm: add support for 2.0 address format
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

Add support for 2.0 address format. Also, align address bits for 1.2 and
2.0 to be able to operate on channel and luns without requiring a format
conversion. Use a generic address format for this purpose.

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/lightnvm/core.c  |  20 ++++-----
 include/linux/lightnvm.h | 105 ++++++++++++++++++++++++++++++++++-------------
 2 files changed, 86 insertions(+), 39 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index f70a907223e2..baec963b2c96 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -196,8 +196,8 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
 
 		for (j = 0; j < luns_in_chnl; j++) {
 			luns[lunid].ppa = 0;
-			luns[lunid].g.ch = i;
-			luns[lunid++].g.lun = j;
+			luns[lunid].a.ch = i;
+			luns[lunid++].a.lun = j;
 
 			lun_offs[j] = blun;
 			lun_roffs[j + blun] = blun;
@@ -563,22 +563,22 @@ static void nvm_unregister_map(struct nvm_dev *dev)
 static void nvm_map_to_dev(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
 {
 	struct nvm_dev_map *dev_map = tgt_dev->map;
-	struct nvm_ch_map *ch_map = &dev_map->chnls[p->g.ch];
-	int lun_off = ch_map->lun_offs[p->g.lun];
+	struct nvm_ch_map *ch_map = &dev_map->chnls[p->a.ch];
+	int lun_off = ch_map->lun_offs[p->a.lun];
 
-	p->g.ch += ch_map->ch_off;
-	p->g.lun += lun_off;
+	p->a.ch += ch_map->ch_off;
+	p->a.lun += lun_off;
 }
 
 static void nvm_map_to_tgt(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
 {
 	struct nvm_dev *dev = tgt_dev->parent;
 	struct nvm_dev_map *dev_rmap = dev->rmap;
-	struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[p->g.ch];
-	int lun_roff = ch_rmap->lun_offs[p->g.lun];
+	struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[p->a.ch];
+	int lun_roff = ch_rmap->lun_offs[p->a.lun];
 
-	p->g.ch -= ch_rmap->ch_off;
-	p->g.lun -= lun_roff;
+	p->a.ch -= ch_rmap->ch_off;
+	p->a.lun -= lun_roff;
 }
 
 static void nvm_ppa_tgt_to_dev(struct nvm_tgt_dev *tgt_dev,
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index e1c4292ea33d..cd310bf06051 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -16,12 +16,22 @@ enum {
 	NVM_IOTYPE_GC = 1,
 };
 
-#define NVM_BLK_BITS (16)
-#define NVM_PG_BITS  (16)
-#define NVM_SEC_BITS (8)
-#define NVM_PL_BITS  (8)
-#define NVM_LUN_BITS (8)
-#define NVM_CH_BITS  (7)
+/* common format */
+#define NVM_GEN_CH_BITS  (8)
+#define NVM_GEN_LUN_BITS (8)
+#define NVM_GEN_RESERVED (48)
+
+/* 1.2 format */
+#define NVM_12_BLK_BITS (16)
+#define NVM_12_PG_BITS  (16)
+#define NVM_12_PL_BITS  (4)
+#define NVM_12_SEC_BITS (4)
+#define NVM_12_RESERVED (8)
+
+/* 2.0 format */
+#define NVM_20_CHK_BITS (16)
+#define NVM_20_SEC_BITS (24)
+#define NVM_20_RESERVED (8)
 
 enum {
 	NVM_OCSSD_SPEC_12 = 12,
@@ -31,16 +41,33 @@ enum {
 struct ppa_addr {
 	/* Generic structure for all addresses */
 	union {
+		/* generic device format */
 		struct {
-			u64 blk		: NVM_BLK_BITS;
-			u64 pg		: NVM_PG_BITS;
-			u64 sec		: NVM_SEC_BITS;
-			u64 pl		: NVM_PL_BITS;
-			u64 lun		: NVM_LUN_BITS;
-			u64 ch		: NVM_CH_BITS;
-			u64 reserved	: 1;
+			u64 ch		: NVM_GEN_CH_BITS;
+			u64 lun		: NVM_GEN_LUN_BITS;
+			u64 reserved	: NVM_GEN_RESERVED;
+		} a;
+
+		/* 1.2 device format */
+		struct {
+			u64 ch		: NVM_GEN_CH_BITS;
+			u64 lun		: NVM_GEN_LUN_BITS;
+			u64 blk		: NVM_12_BLK_BITS;
+			u64 pg		: NVM_12_PG_BITS;
+			u64 pl		: NVM_12_PL_BITS;
+			u64 sec		: NVM_12_SEC_BITS;
+			u64 reserved	: NVM_12_RESERVED;
 		} g;
 
+		/* 2.0 device format */
+		struct {
+			u64 ch		: NVM_GEN_CH_BITS;
+			u64 lun		: NVM_GEN_LUN_BITS;
+			u64 chk		: NVM_20_CHK_BITS;
+			u64 sec		: NVM_20_SEC_BITS;
+			u64 reserved	: NVM_20_RESERVED;
+		} m;
+
 		struct {
 			u64 line	: 63;
 			u64 is_cached	: 1;
@@ -392,16 +419,26 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
 						  struct ppa_addr r)
 {
 	struct nvm_geo *geo = &tgt_dev->geo;
-	struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&geo->c.addrf;
 	struct ppa_addr l;
 
-	l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
-	l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
-	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
-	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
-	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
-	l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
+	if (geo->c.version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&geo->c.addrf;
+
+		l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
+		l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
+		l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
+		l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
+		l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
+		l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
+	} else {
+		struct nvm_addr_format *lbaf = &geo->c.addrf;
+
+		l.ppa = ((u64)r.m.ch) << lbaf->ch_offset;
+		l.ppa |= ((u64)r.m.lun) << lbaf->lun_offset;
+		l.ppa |= ((u64)r.m.chk) << lbaf->chk_offset;
+		l.ppa |= ((u64)r.m.sec) << lbaf->sec_offset;
+	}
 
 	return l;
 }
@@ -410,18 +447,28 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
 						  struct ppa_addr r)
 {
 	struct nvm_geo *geo = &tgt_dev->geo;
-	struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&geo->c.addrf;
 	struct ppa_addr l;
 
 	l.ppa = 0;
 
-	l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
-	l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
-	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
-	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
-	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
-	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
+	if (geo->c.version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&geo->c.addrf;
+
+		l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
+		l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
+		l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
+		l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
+		l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
+		l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
+	} else {
+		struct nvm_addr_format *lbaf = &geo->c.addrf;
+
+		l.m.ch = (r.ppa & lbaf->ch_mask) >> lbaf->ch_offset;
+		l.m.lun = (r.ppa & lbaf->lun_mask) >> lbaf->lun_offset;
+		l.m.chk = (r.ppa & lbaf->chk_mask) >> lbaf->chk_offset;
+		l.m.sec = (r.ppa & lbaf->sec_mask) >> lbaf->sec_offset;
+	}
 
 	return l;
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 13/20] lightnvm: add support for 2.0 address format
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


Add support for 2.0 address format. Also, align address bits for 1.2 and
2.0 to be able to operate on channel and luns without requiring a format
conversion. Use a generic address format for this purpose.

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/lightnvm/core.c  |  20 ++++-----
 include/linux/lightnvm.h | 105 ++++++++++++++++++++++++++++++++++-------------
 2 files changed, 86 insertions(+), 39 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index f70a907223e2..baec963b2c96 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -196,8 +196,8 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
 
 		for (j = 0; j < luns_in_chnl; j++) {
 			luns[lunid].ppa = 0;
-			luns[lunid].g.ch = i;
-			luns[lunid++].g.lun = j;
+			luns[lunid].a.ch = i;
+			luns[lunid++].a.lun = j;
 
 			lun_offs[j] = blun;
 			lun_roffs[j + blun] = blun;
@@ -563,22 +563,22 @@ static void nvm_unregister_map(struct nvm_dev *dev)
 static void nvm_map_to_dev(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
 {
 	struct nvm_dev_map *dev_map = tgt_dev->map;
-	struct nvm_ch_map *ch_map = &dev_map->chnls[p->g.ch];
-	int lun_off = ch_map->lun_offs[p->g.lun];
+	struct nvm_ch_map *ch_map = &dev_map->chnls[p->a.ch];
+	int lun_off = ch_map->lun_offs[p->a.lun];
 
-	p->g.ch += ch_map->ch_off;
-	p->g.lun += lun_off;
+	p->a.ch += ch_map->ch_off;
+	p->a.lun += lun_off;
 }
 
 static void nvm_map_to_tgt(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
 {
 	struct nvm_dev *dev = tgt_dev->parent;
 	struct nvm_dev_map *dev_rmap = dev->rmap;
-	struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[p->g.ch];
-	int lun_roff = ch_rmap->lun_offs[p->g.lun];
+	struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[p->a.ch];
+	int lun_roff = ch_rmap->lun_offs[p->a.lun];
 
-	p->g.ch -= ch_rmap->ch_off;
-	p->g.lun -= lun_roff;
+	p->a.ch -= ch_rmap->ch_off;
+	p->a.lun -= lun_roff;
 }
 
 static void nvm_ppa_tgt_to_dev(struct nvm_tgt_dev *tgt_dev,
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index e1c4292ea33d..cd310bf06051 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -16,12 +16,22 @@ enum {
 	NVM_IOTYPE_GC = 1,
 };
 
-#define NVM_BLK_BITS (16)
-#define NVM_PG_BITS  (16)
-#define NVM_SEC_BITS (8)
-#define NVM_PL_BITS  (8)
-#define NVM_LUN_BITS (8)
-#define NVM_CH_BITS  (7)
+/* common format */
+#define NVM_GEN_CH_BITS  (8)
+#define NVM_GEN_LUN_BITS (8)
+#define NVM_GEN_RESERVED (48)
+
+/* 1.2 format */
+#define NVM_12_BLK_BITS (16)
+#define NVM_12_PG_BITS  (16)
+#define NVM_12_PL_BITS  (4)
+#define NVM_12_SEC_BITS (4)
+#define NVM_12_RESERVED (8)
+
+/* 2.0 format */
+#define NVM_20_CHK_BITS (16)
+#define NVM_20_SEC_BITS (24)
+#define NVM_20_RESERVED (8)
 
 enum {
 	NVM_OCSSD_SPEC_12 = 12,
@@ -31,16 +41,33 @@ enum {
 struct ppa_addr {
 	/* Generic structure for all addresses */
 	union {
+		/* generic device format */
 		struct {
-			u64 blk		: NVM_BLK_BITS;
-			u64 pg		: NVM_PG_BITS;
-			u64 sec		: NVM_SEC_BITS;
-			u64 pl		: NVM_PL_BITS;
-			u64 lun		: NVM_LUN_BITS;
-			u64 ch		: NVM_CH_BITS;
-			u64 reserved	: 1;
+			u64 ch		: NVM_GEN_CH_BITS;
+			u64 lun		: NVM_GEN_LUN_BITS;
+			u64 reserved	: NVM_GEN_RESERVED;
+		} a;
+
+		/* 1.2 device format */
+		struct {
+			u64 ch		: NVM_GEN_CH_BITS;
+			u64 lun		: NVM_GEN_LUN_BITS;
+			u64 blk		: NVM_12_BLK_BITS;
+			u64 pg		: NVM_12_PG_BITS;
+			u64 pl		: NVM_12_PL_BITS;
+			u64 sec		: NVM_12_SEC_BITS;
+			u64 reserved	: NVM_12_RESERVED;
 		} g;
 
+		/* 2.0 device format */
+		struct {
+			u64 ch		: NVM_GEN_CH_BITS;
+			u64 lun		: NVM_GEN_LUN_BITS;
+			u64 chk		: NVM_20_CHK_BITS;
+			u64 sec		: NVM_20_SEC_BITS;
+			u64 reserved	: NVM_20_RESERVED;
+		} m;
+
 		struct {
 			u64 line	: 63;
 			u64 is_cached	: 1;
@@ -392,16 +419,26 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
 						  struct ppa_addr r)
 {
 	struct nvm_geo *geo = &tgt_dev->geo;
-	struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&geo->c.addrf;
 	struct ppa_addr l;
 
-	l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
-	l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
-	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
-	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
-	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
-	l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
+	if (geo->c.version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&geo->c.addrf;
+
+		l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
+		l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
+		l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
+		l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
+		l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
+		l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
+	} else {
+		struct nvm_addr_format *lbaf = &geo->c.addrf;
+
+		l.ppa = ((u64)r.m.ch) << lbaf->ch_offset;
+		l.ppa |= ((u64)r.m.lun) << lbaf->lun_offset;
+		l.ppa |= ((u64)r.m.chk) << lbaf->chk_offset;
+		l.ppa |= ((u64)r.m.sec) << lbaf->sec_offset;
+	}
 
 	return l;
 }
@@ -410,18 +447,28 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
 						  struct ppa_addr r)
 {
 	struct nvm_geo *geo = &tgt_dev->geo;
-	struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&geo->c.addrf;
 	struct ppa_addr l;
 
 	l.ppa = 0;
 
-	l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
-	l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
-	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
-	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
-	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
-	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
+	if (geo->c.version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&geo->c.addrf;
+
+		l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
+		l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
+		l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
+		l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
+		l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
+		l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
+	} else {
+		struct nvm_addr_format *lbaf = &geo->c.addrf;
+
+		l.m.ch = (r.ppa & lbaf->ch_mask) >> lbaf->ch_offset;
+		l.m.lun = (r.ppa & lbaf->lun_mask) >> lbaf->lun_offset;
+		l.m.chk = (r.ppa & lbaf->chk_mask) >> lbaf->chk_offset;
+		l.m.sec = (r.ppa & lbaf->sec_mask) >> lbaf->sec_offset;
+	}
 
 	return l;
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 14/20] lightnvm: make address conversions depend on generic device
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

On address conversions, use the generic device, instead of the target
device. This allows to use conversions outside of the target's realm.

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/lightnvm/core.c  | 4 ++--
 include/linux/lightnvm.h | 8 ++++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index baec963b2c96..59b62ca65596 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -588,7 +588,7 @@ static void nvm_ppa_tgt_to_dev(struct nvm_tgt_dev *tgt_dev,
 
 	for (i = 0; i < nr_ppas; i++) {
 		nvm_map_to_dev(tgt_dev, &ppa_list[i]);
-		ppa_list[i] = generic_to_dev_addr(tgt_dev, ppa_list[i]);
+		ppa_list[i] = generic_to_dev_addr(tgt_dev->parent, ppa_list[i]);
 	}
 }
 
@@ -598,7 +598,7 @@ static void nvm_ppa_dev_to_tgt(struct nvm_tgt_dev *tgt_dev,
 	int i;
 
 	for (i = 0; i < nr_ppas; i++) {
-		ppa_list[i] = dev_to_generic_addr(tgt_dev, ppa_list[i]);
+		ppa_list[i] = dev_to_generic_addr(tgt_dev->parent, ppa_list[i]);
 		nvm_map_to_tgt(tgt_dev, &ppa_list[i]);
 	}
 }
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index cd310bf06051..91340998f0c3 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -415,10 +415,10 @@ struct nvm_dev {
 	struct list_head targets;
 };
 
-static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
+static inline struct ppa_addr generic_to_dev_addr(struct nvm_dev *dev,
 						  struct ppa_addr r)
 {
-	struct nvm_geo *geo = &tgt_dev->geo;
+	struct nvm_dev_geo *geo = &dev->dev_geo;
 	struct ppa_addr l;
 
 	if (geo->c.version == NVM_OCSSD_SPEC_12) {
@@ -443,10 +443,10 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
 	return l;
 }
 
-static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
+static inline struct ppa_addr dev_to_generic_addr(struct nvm_dev *dev,
 						  struct ppa_addr r)
 {
-	struct nvm_geo *geo = &tgt_dev->geo;
+	struct nvm_dev_geo *geo = &dev->dev_geo;
 	struct ppa_addr l;
 
 	l.ppa = 0;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 14/20] lightnvm: make address conversions depend on generic device
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


On address conversions, use the generic device, instead of the target
device. This allows to use conversions outside of the target's realm.

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/lightnvm/core.c  | 4 ++--
 include/linux/lightnvm.h | 8 ++++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index baec963b2c96..59b62ca65596 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -588,7 +588,7 @@ static void nvm_ppa_tgt_to_dev(struct nvm_tgt_dev *tgt_dev,
 
 	for (i = 0; i < nr_ppas; i++) {
 		nvm_map_to_dev(tgt_dev, &ppa_list[i]);
-		ppa_list[i] = generic_to_dev_addr(tgt_dev, ppa_list[i]);
+		ppa_list[i] = generic_to_dev_addr(tgt_dev->parent, ppa_list[i]);
 	}
 }
 
@@ -598,7 +598,7 @@ static void nvm_ppa_dev_to_tgt(struct nvm_tgt_dev *tgt_dev,
 	int i;
 
 	for (i = 0; i < nr_ppas; i++) {
-		ppa_list[i] = dev_to_generic_addr(tgt_dev, ppa_list[i]);
+		ppa_list[i] = dev_to_generic_addr(tgt_dev->parent, ppa_list[i]);
 		nvm_map_to_tgt(tgt_dev, &ppa_list[i]);
 	}
 }
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index cd310bf06051..91340998f0c3 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -415,10 +415,10 @@ struct nvm_dev {
 	struct list_head targets;
 };
 
-static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
+static inline struct ppa_addr generic_to_dev_addr(struct nvm_dev *dev,
 						  struct ppa_addr r)
 {
-	struct nvm_geo *geo = &tgt_dev->geo;
+	struct nvm_dev_geo *geo = &dev->dev_geo;
 	struct ppa_addr l;
 
 	if (geo->c.version == NVM_OCSSD_SPEC_12) {
@@ -443,10 +443,10 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
 	return l;
 }
 
-static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
+static inline struct ppa_addr dev_to_generic_addr(struct nvm_dev *dev,
 						  struct ppa_addr r)
 {
-	struct nvm_geo *geo = &tgt_dev->geo;
+	struct nvm_dev_geo *geo = &dev->dev_geo;
 	struct ppa_addr l;
 
 	l.ppa = 0;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 15/20] nvme: make nvme_get_log_ext available
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

Make nvme_get_log_ext available outside of core.c.

This is in preparation for using it in lightnvm.c

Signed-off-by: Javier González <javier@cnexlabs.>
---
 drivers/nvme/host/nvme.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 1ca08f4993ba..505f797f8c6c 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -396,6 +396,9 @@ int nvme_reset_ctrl(struct nvme_ctrl *ctrl);
 int nvme_delete_ctrl(struct nvme_ctrl *ctrl);
 int nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl);
 
+int nvme_get_log_ext(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
+		     u8 log_page, void *log, size_t size, size_t offset);
+
 extern const struct attribute_group nvme_ns_id_attr_group;
 extern const struct block_device_operations nvme_ns_head_ops;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 15/20] nvme: make nvme_get_log_ext available
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


Make nvme_get_log_ext available outside of core.c.

This is in preparation for using it in lightnvm.c

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.>
---
 drivers/nvme/host/nvme.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 1ca08f4993ba..505f797f8c6c 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -396,6 +396,9 @@ int nvme_reset_ctrl(struct nvme_ctrl *ctrl);
 int nvme_delete_ctrl(struct nvme_ctrl *ctrl);
 int nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl);
 
+int nvme_get_log_ext(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
+		     u8 log_page, void *log, size_t size, size_t offset);
+
 extern const struct attribute_group nvme_ns_id_attr_group;
 extern const struct block_device_operations nvme_ns_head_ops;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 16/20] lightnvm: implement get log report chunk helpers
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb
  Cc: linux-block, linux-kernel, linux-nvme, Javier González,
	Javier González

From: Javier González <javier@javigon.com>

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

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/lightnvm/core.c      | 11 +++++++
 drivers/nvme/host/lightnvm.c | 74 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/lightnvm.h     | 24 ++++++++++++++
 3 files changed, 109 insertions(+)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 59b62ca65596..1d9d045c28ed 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -719,6 +719,17 @@ static void nvm_free_rqd_ppalist(struct nvm_tgt_dev *tgt_dev,
 	nvm_dev_dma_free(tgt_dev->parent, rqd->ppa_list, rqd->dma_ppa_list);
 }
 
+int nvm_get_chunk_meta(struct nvm_tgt_dev *tgt_dev, struct nvm_chk_meta *meta,
+		struct ppa_addr ppa, int nchks)
+{
+	struct nvm_dev *dev = tgt_dev->parent;
+
+	nvm_ppa_tgt_to_dev(tgt_dev, &ppa, 1);
+
+	return dev->ops->get_chk_meta(tgt_dev->parent, meta,
+						(sector_t)ppa.ppa, nchks);
+}
+EXPORT_SYMBOL(nvm_get_chunk_meta);
 
 int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *ppas,
 		       int nr_ppas, int type)
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 88c71d0d0d8c..20f1783e4e47 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -35,6 +35,10 @@ enum nvme_nvm_admin_opcode {
 	nvme_nvm_admin_set_bb_tbl	= 0xf1,
 };
 
+enum nvme_nvm_log_page {
+	NVME_NVM_LOG_REPORT_CHUNK	= 0xca,
+};
+
 struct nvme_nvm_ph_rw {
 	__u8			opcode;
 	__u8			flags;
@@ -242,6 +246,16 @@ struct nvme_nvm_id20 {
 	__u8			vs[1024];
 };
 
+struct nvme_nvm_chk_meta {
+	__u8	state;
+	__u8	type;
+	__u8	wi;
+	__u8	rsvd[5];
+	__le64	slba;
+	__le64	cnlb;
+	__le64	wp;
+};
+
 /*
  * Check we didn't inadvertently grow the command struct
  */
@@ -258,6 +272,9 @@ static inline void _nvme_nvm_check_size(void)
 	BUILD_BUG_ON(sizeof(struct nvme_nvm_bb_tbl) != 64);
 	BUILD_BUG_ON(sizeof(struct nvme_nvm_id20_addrf) != 8);
 	BUILD_BUG_ON(sizeof(struct nvme_nvm_id20) != NVME_IDENTIFY_DATA_SIZE);
+	BUILD_BUG_ON(sizeof(struct nvme_nvm_chk_meta) != 32);
+	BUILD_BUG_ON(sizeof(struct nvme_nvm_chk_meta) !=
+						sizeof(struct nvm_chk_meta));
 }
 
 static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
@@ -553,6 +570,61 @@ static int nvme_nvm_set_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr *ppas,
 	return ret;
 }
 
+/*
+ * Expect the lba in device format
+ */
+static int nvme_nvm_get_chk_meta(struct nvm_dev *ndev,
+				 struct nvm_chk_meta *meta,
+				 sector_t slba, int nchks)
+{
+	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
+	struct nvme_ns *ns = ndev->q->queuedata;
+	struct nvme_ctrl *ctrl = ns->ctrl;
+	struct nvme_nvm_chk_meta *dev_meta = (struct nvme_nvm_chk_meta *)meta;
+	struct ppa_addr ppa;
+	size_t left = nchks * sizeof(struct nvme_nvm_chk_meta);
+	size_t log_pos, offset, len;
+	int ret, i;
+
+	/* Normalize lba address space to obtain log offset */
+	ppa.ppa = slba;
+	ppa = dev_to_generic_addr(ndev, ppa);
+
+	log_pos = ppa.m.chk;
+	log_pos += ppa.m.lun * dev_geo->c.num_chk;
+	log_pos += ppa.m.ch * dev_geo->num_lun * dev_geo->c.num_chk;
+
+	offset = log_pos * sizeof(struct nvme_nvm_chk_meta);
+
+	while (left) {
+		len = min_t(unsigned int, left, ctrl->max_hw_sectors << 9);
+
+		ret = nvme_get_log_ext(ctrl, ns, NVME_NVM_LOG_REPORT_CHUNK,
+				dev_meta, len, offset);
+		if (ret) {
+			dev_err(ctrl->device, "Get REPORT CHUNK log error\n");
+			break;
+		}
+
+		for (i = 0; i < len; i += sizeof(struct nvme_nvm_chk_meta)) {
+			meta->state = dev_meta->state;
+			meta->type = dev_meta->type;
+			meta->wi = dev_meta->wi;
+			meta->slba = le64_to_cpu(dev_meta->slba);
+			meta->cnlb = le64_to_cpu(dev_meta->cnlb);
+			meta->wp = le64_to_cpu(dev_meta->wp);
+
+			meta++;
+			dev_meta++;
+		}
+
+		offset += len;
+		left -= len;
+	}
+
+	return ret;
+}
+
 static inline void nvme_nvm_rqtocmd(struct nvm_rq *rqd, struct nvme_ns *ns,
 				    struct nvme_nvm_command *c)
 {
@@ -684,6 +756,8 @@ static struct nvm_dev_ops nvme_nvm_dev_ops = {
 	.get_bb_tbl		= nvme_nvm_get_bb_tbl,
 	.set_bb_tbl		= nvme_nvm_set_bb_tbl,
 
+	.get_chk_meta		= nvme_nvm_get_chk_meta,
+
 	.submit_io		= nvme_nvm_submit_io,
 	.submit_io_sync		= nvme_nvm_submit_io_sync,
 
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 91340998f0c3..bc43700c37ec 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -81,10 +81,13 @@ struct nvm_rq;
 struct nvm_id;
 struct nvm_dev;
 struct nvm_tgt_dev;
+struct nvm_chk_meta;
 
 typedef int (nvm_id_fn)(struct nvm_dev *);
 typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, u8 *);
 typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct ppa_addr *, int, int);
+typedef int (nvm_get_chk_meta_fn)(struct nvm_dev *, struct nvm_chk_meta *,
+								sector_t, int);
 typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
 typedef int (nvm_submit_io_sync_fn)(struct nvm_dev *, struct nvm_rq *);
 typedef void *(nvm_create_dma_pool_fn)(struct nvm_dev *, char *);
@@ -98,6 +101,8 @@ struct nvm_dev_ops {
 	nvm_op_bb_tbl_fn	*get_bb_tbl;
 	nvm_op_set_bb_fn	*set_bb_tbl;
 
+	nvm_get_chk_meta_fn	*get_chk_meta;
+
 	nvm_submit_io_fn	*submit_io;
 	nvm_submit_io_sync_fn	*submit_io_sync;
 
@@ -292,6 +297,20 @@ struct nvm_dev_geo {
 	struct nvm_common_geo c;
 };
 
+/*
+ * Note: The structure size is linked to nvme_nvm_chk_meta such that the same
+ * buffer can be used when converting from little endian to cpu addressing.
+ */
+struct nvm_chk_meta {
+	u8	state;
+	u8	type;
+	u8	wi;
+	u8	rsvd[5];
+	u64	slba;
+	u64	cnlb;
+	u64	wp;
+};
+
 struct nvm_target {
 	struct list_head list;
 	struct nvm_tgt_dev *dev;
@@ -512,6 +531,11 @@ extern struct nvm_dev *nvm_alloc_dev(int);
 extern int nvm_register(struct nvm_dev *);
 extern void nvm_unregister(struct nvm_dev *);
 
+
+extern int nvm_get_chunk_meta(struct nvm_tgt_dev *tgt_dev,
+			      struct nvm_chk_meta *meta, struct ppa_addr ppa,
+			      int nchks);
+
 extern int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *, struct ppa_addr *,
 			      int, int);
 extern int nvm_submit_io(struct nvm_tgt_dev *, struct nvm_rq *);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 16/20] lightnvm: implement get log report chunk helpers
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


From: Javier Gonz?lez <javier@javigon.com>

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

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/lightnvm/core.c      | 11 +++++++
 drivers/nvme/host/lightnvm.c | 74 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/lightnvm.h     | 24 ++++++++++++++
 3 files changed, 109 insertions(+)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 59b62ca65596..1d9d045c28ed 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -719,6 +719,17 @@ static void nvm_free_rqd_ppalist(struct nvm_tgt_dev *tgt_dev,
 	nvm_dev_dma_free(tgt_dev->parent, rqd->ppa_list, rqd->dma_ppa_list);
 }
 
+int nvm_get_chunk_meta(struct nvm_tgt_dev *tgt_dev, struct nvm_chk_meta *meta,
+		struct ppa_addr ppa, int nchks)
+{
+	struct nvm_dev *dev = tgt_dev->parent;
+
+	nvm_ppa_tgt_to_dev(tgt_dev, &ppa, 1);
+
+	return dev->ops->get_chk_meta(tgt_dev->parent, meta,
+						(sector_t)ppa.ppa, nchks);
+}
+EXPORT_SYMBOL(nvm_get_chunk_meta);
 
 int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *ppas,
 		       int nr_ppas, int type)
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 88c71d0d0d8c..20f1783e4e47 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -35,6 +35,10 @@ enum nvme_nvm_admin_opcode {
 	nvme_nvm_admin_set_bb_tbl	= 0xf1,
 };
 
+enum nvme_nvm_log_page {
+	NVME_NVM_LOG_REPORT_CHUNK	= 0xca,
+};
+
 struct nvme_nvm_ph_rw {
 	__u8			opcode;
 	__u8			flags;
@@ -242,6 +246,16 @@ struct nvme_nvm_id20 {
 	__u8			vs[1024];
 };
 
+struct nvme_nvm_chk_meta {
+	__u8	state;
+	__u8	type;
+	__u8	wi;
+	__u8	rsvd[5];
+	__le64	slba;
+	__le64	cnlb;
+	__le64	wp;
+};
+
 /*
  * Check we didn't inadvertently grow the command struct
  */
@@ -258,6 +272,9 @@ static inline void _nvme_nvm_check_size(void)
 	BUILD_BUG_ON(sizeof(struct nvme_nvm_bb_tbl) != 64);
 	BUILD_BUG_ON(sizeof(struct nvme_nvm_id20_addrf) != 8);
 	BUILD_BUG_ON(sizeof(struct nvme_nvm_id20) != NVME_IDENTIFY_DATA_SIZE);
+	BUILD_BUG_ON(sizeof(struct nvme_nvm_chk_meta) != 32);
+	BUILD_BUG_ON(sizeof(struct nvme_nvm_chk_meta) !=
+						sizeof(struct nvm_chk_meta));
 }
 
 static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
@@ -553,6 +570,61 @@ static int nvme_nvm_set_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr *ppas,
 	return ret;
 }
 
+/*
+ * Expect the lba in device format
+ */
+static int nvme_nvm_get_chk_meta(struct nvm_dev *ndev,
+				 struct nvm_chk_meta *meta,
+				 sector_t slba, int nchks)
+{
+	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
+	struct nvme_ns *ns = ndev->q->queuedata;
+	struct nvme_ctrl *ctrl = ns->ctrl;
+	struct nvme_nvm_chk_meta *dev_meta = (struct nvme_nvm_chk_meta *)meta;
+	struct ppa_addr ppa;
+	size_t left = nchks * sizeof(struct nvme_nvm_chk_meta);
+	size_t log_pos, offset, len;
+	int ret, i;
+
+	/* Normalize lba address space to obtain log offset */
+	ppa.ppa = slba;
+	ppa = dev_to_generic_addr(ndev, ppa);
+
+	log_pos = ppa.m.chk;
+	log_pos += ppa.m.lun * dev_geo->c.num_chk;
+	log_pos += ppa.m.ch * dev_geo->num_lun * dev_geo->c.num_chk;
+
+	offset = log_pos * sizeof(struct nvme_nvm_chk_meta);
+
+	while (left) {
+		len = min_t(unsigned int, left, ctrl->max_hw_sectors << 9);
+
+		ret = nvme_get_log_ext(ctrl, ns, NVME_NVM_LOG_REPORT_CHUNK,
+				dev_meta, len, offset);
+		if (ret) {
+			dev_err(ctrl->device, "Get REPORT CHUNK log error\n");
+			break;
+		}
+
+		for (i = 0; i < len; i += sizeof(struct nvme_nvm_chk_meta)) {
+			meta->state = dev_meta->state;
+			meta->type = dev_meta->type;
+			meta->wi = dev_meta->wi;
+			meta->slba = le64_to_cpu(dev_meta->slba);
+			meta->cnlb = le64_to_cpu(dev_meta->cnlb);
+			meta->wp = le64_to_cpu(dev_meta->wp);
+
+			meta++;
+			dev_meta++;
+		}
+
+		offset += len;
+		left -= len;
+	}
+
+	return ret;
+}
+
 static inline void nvme_nvm_rqtocmd(struct nvm_rq *rqd, struct nvme_ns *ns,
 				    struct nvme_nvm_command *c)
 {
@@ -684,6 +756,8 @@ static struct nvm_dev_ops nvme_nvm_dev_ops = {
 	.get_bb_tbl		= nvme_nvm_get_bb_tbl,
 	.set_bb_tbl		= nvme_nvm_set_bb_tbl,
 
+	.get_chk_meta		= nvme_nvm_get_chk_meta,
+
 	.submit_io		= nvme_nvm_submit_io,
 	.submit_io_sync		= nvme_nvm_submit_io_sync,
 
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 91340998f0c3..bc43700c37ec 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -81,10 +81,13 @@ struct nvm_rq;
 struct nvm_id;
 struct nvm_dev;
 struct nvm_tgt_dev;
+struct nvm_chk_meta;
 
 typedef int (nvm_id_fn)(struct nvm_dev *);
 typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, u8 *);
 typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct ppa_addr *, int, int);
+typedef int (nvm_get_chk_meta_fn)(struct nvm_dev *, struct nvm_chk_meta *,
+								sector_t, int);
 typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
 typedef int (nvm_submit_io_sync_fn)(struct nvm_dev *, struct nvm_rq *);
 typedef void *(nvm_create_dma_pool_fn)(struct nvm_dev *, char *);
@@ -98,6 +101,8 @@ struct nvm_dev_ops {
 	nvm_op_bb_tbl_fn	*get_bb_tbl;
 	nvm_op_set_bb_fn	*set_bb_tbl;
 
+	nvm_get_chk_meta_fn	*get_chk_meta;
+
 	nvm_submit_io_fn	*submit_io;
 	nvm_submit_io_sync_fn	*submit_io_sync;
 
@@ -292,6 +297,20 @@ struct nvm_dev_geo {
 	struct nvm_common_geo c;
 };
 
+/*
+ * Note: The structure size is linked to nvme_nvm_chk_meta such that the same
+ * buffer can be used when converting from little endian to cpu addressing.
+ */
+struct nvm_chk_meta {
+	u8	state;
+	u8	type;
+	u8	wi;
+	u8	rsvd[5];
+	u64	slba;
+	u64	cnlb;
+	u64	wp;
+};
+
 struct nvm_target {
 	struct list_head list;
 	struct nvm_tgt_dev *dev;
@@ -512,6 +531,11 @@ extern struct nvm_dev *nvm_alloc_dev(int);
 extern int nvm_register(struct nvm_dev *);
 extern void nvm_unregister(struct nvm_dev *);
 
+
+extern int nvm_get_chunk_meta(struct nvm_tgt_dev *tgt_dev,
+			      struct nvm_chk_meta *meta, struct ppa_addr ppa,
+			      int nchks);
+
 extern int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *, struct ppa_addr *,
 			      int, int);
 extern int nvm_submit_io(struct nvm_tgt_dev *, struct nvm_rq *);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 17/20] lightnvm: define chunk states
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

Define chunk states as given in the 2.0 spec. Also, add an extra chunk
state that signals that the chunk is in use by the host. This allows for
the chunk metadata to be "owned" by a target when active, thus
completing the chunk state machine from the host perspective and
facilitating sanity checks. This state is transparent for the device.

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 include/linux/lightnvm.h | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index bc43700c37ec..4dfb85d08ab5 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -297,6 +297,20 @@ struct nvm_dev_geo {
 	struct nvm_common_geo c;
 };
 
+enum {
+	/* Chunk states */
+	NVM_CHK_ST_FREE =	1 << 0,
+	NVM_CHK_ST_CLOSED =	1 << 1,
+	NVM_CHK_ST_OPEN =	1 << 2,
+	NVM_CHK_ST_OFFLINE =	1 << 3,
+	NVM_CHK_ST_HOST_USE =	1 << 7,
+
+	/* Chunk types */
+	NVM_CHK_TP_W_SEQ =	1 << 0,
+	NVM_CHK_TP_W_RAN =	1 << 1,
+	NVM_CHK_TP_SZ_SPEC =	1 << 4,
+};
+
 /*
  * Note: The structure size is linked to nvme_nvm_chk_meta such that the same
  * buffer can be used when converting from little endian to cpu addressing.
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 17/20] lightnvm: define chunk states
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


Define chunk states as given in the 2.0 spec. Also, add an extra chunk
state that signals that the chunk is in use by the host. This allows for
the chunk metadata to be "owned" by a target when active, thus
completing the chunk state machine from the host perspective and
facilitating sanity checks. This state is transparent for the device.

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 include/linux/lightnvm.h | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index bc43700c37ec..4dfb85d08ab5 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -297,6 +297,20 @@ struct nvm_dev_geo {
 	struct nvm_common_geo c;
 };
 
+enum {
+	/* Chunk states */
+	NVM_CHK_ST_FREE =	1 << 0,
+	NVM_CHK_ST_CLOSED =	1 << 1,
+	NVM_CHK_ST_OPEN =	1 << 2,
+	NVM_CHK_ST_OFFLINE =	1 << 3,
+	NVM_CHK_ST_HOST_USE =	1 << 7,
+
+	/* Chunk types */
+	NVM_CHK_TP_W_SEQ =	1 << 0,
+	NVM_CHK_TP_W_RAN =	1 << 1,
+	NVM_CHK_TP_SZ_SPEC =	1 << 4,
+};
+
 /*
  * Note: The structure size is linked to nvme_nvm_chk_meta such that the same
  * buffer can be used when converting from little endian to cpu addressing.
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 18/20] lightnvm: pblk: implement get log report chunk
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb
  Cc: linux-block, linux-kernel, linux-nvme, Javier González,
	Javier González

From: Javier González <javier@javigon.com>

In preparation of pblk supporting 2.0, implement the get log report
chunk in pblk.

This patch only replicates de bad block functionality as the rest of the
metadata requires new pblk functionality (e.g., wear-index to implement
wear-leveling). This functionality will come in future patches.

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/lightnvm/pblk-core.c  | 121 +++++++++++++++++++++++----
 drivers/lightnvm/pblk-init.c  | 186 +++++++++++++++++++++++++++++++-----------
 drivers/lightnvm/pblk-sysfs.c |  67 +++++++++++++++
 drivers/lightnvm/pblk.h       |  20 +++++
 4 files changed, 330 insertions(+), 64 deletions(-)

diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index 7c726003a8d2..90aae45b2842 100644
--- a/drivers/lightnvm/pblk-core.c
+++ b/drivers/lightnvm/pblk-core.c
@@ -44,11 +44,12 @@ static void pblk_line_mark_bb(struct work_struct *work)
 }
 
 static void pblk_mark_bb(struct pblk *pblk, struct pblk_line *line,
-			 struct ppa_addr *ppa)
+			 struct ppa_addr ppa_addr)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
-	int pos = pblk_ppa_to_pos(geo, *ppa);
+	struct ppa_addr *ppa;
+	int pos = pblk_ppa_to_pos(geo, ppa_addr);
 
 	pr_debug("pblk: erase failed: line:%d, pos:%d\n", line->id, pos);
 	atomic_long_inc(&pblk->erase_failed);
@@ -58,6 +59,15 @@ static void pblk_mark_bb(struct pblk *pblk, struct pblk_line *line,
 		pr_err("pblk: attempted to erase bb: line:%d, pos:%d\n",
 							line->id, pos);
 
+	/* Not necessary to mark bad blocks on 2.0 spec. */
+	if (geo->c.version == NVM_OCSSD_SPEC_20)
+		return;
+
+	ppa = kmalloc(sizeof(struct ppa_addr), GFP_ATOMIC);
+	if (!ppa)
+		return;
+
+	*ppa = ppa_addr;
 	pblk_gen_run_ws(pblk, NULL, ppa, pblk_line_mark_bb,
 						GFP_ATOMIC, pblk->bb_wq);
 }
@@ -69,16 +79,8 @@ static void __pblk_end_io_erase(struct pblk *pblk, struct nvm_rq *rqd)
 	line = &pblk->lines[pblk_ppa_to_line(rqd->ppa_addr)];
 	atomic_dec(&line->left_seblks);
 
-	if (rqd->error) {
-		struct ppa_addr *ppa;
-
-		ppa = kmalloc(sizeof(struct ppa_addr), GFP_ATOMIC);
-		if (!ppa)
-			return;
-
-		*ppa = rqd->ppa_addr;
-		pblk_mark_bb(pblk, line, ppa);
-	}
+	if (rqd->error)
+		pblk_mark_bb(pblk, line, rqd->ppa_addr);
 
 	atomic_dec(&pblk->inflight_io);
 }
@@ -92,6 +94,50 @@ static void pblk_end_io_erase(struct nvm_rq *rqd)
 	mempool_free(rqd, pblk->e_rq_pool);
 }
 
+/*
+ * Get information for all chunks from the device.
+ *
+ * The caller is responsible for freeing the returned structure
+ */
+struct nvm_chk_meta *pblk_chunk_get_info(struct pblk *pblk)
+{
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	struct nvm_chk_meta *meta;
+	struct ppa_addr ppa;
+	unsigned long len;
+	int ret;
+
+	ppa.ppa = 0;
+
+	len = geo->all_chunks * sizeof(*meta);
+	meta = kzalloc(len, GFP_KERNEL);
+	if (!meta)
+		return ERR_PTR(-ENOMEM);
+
+	ret = nvm_get_chunk_meta(dev, meta, ppa, geo->all_chunks);
+	if (ret) {
+		pr_err("pblk: could not get chunk metadata (%d)\n", ret);
+		kfree(meta);
+		return ERR_PTR(-EIO);
+	}
+
+	return meta;
+}
+
+struct nvm_chk_meta *pblk_chunk_get_off(struct pblk *pblk,
+					      struct nvm_chk_meta *meta,
+					      struct ppa_addr ppa)
+{
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	int ch_off = ppa.m.ch * geo->c.num_chk * geo->num_lun;
+	int lun_off = ppa.m.lun * geo->c.num_chk;
+	int chk_off = ppa.m.chk;
+
+	return meta + ch_off + lun_off + chk_off;
+}
+
 void __pblk_map_invalidate(struct pblk *pblk, struct pblk_line *line,
 			   u64 paddr)
 {
@@ -1094,10 +1140,38 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
 	return 1;
 }
 
+static int pblk_prepare_new_line(struct pblk *pblk, struct pblk_line *line)
+{
+	struct pblk_line_meta *lm = &pblk->lm;
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	int blk_to_erase = atomic_read(&line->blk_in_line);
+	int i;
+
+	for (i = 0; i < lm->blk_per_line; i++) {
+		int state = line->chks[i].state;
+		struct pblk_lun *rlun = &pblk->luns[i];
+
+		/* Free chunks should not be erased */
+		if (state & NVM_CHK_ST_FREE) {
+			set_bit(pblk_ppa_to_pos(geo, rlun->chunk_bppa),
+					line->erase_bitmap);
+			blk_to_erase--;
+			line->chks[i].state = NVM_CHK_ST_HOST_USE;
+		}
+
+		WARN_ONCE(state & NVM_CHK_ST_OPEN,
+				"pblk: open chunk in new line: %d\n",
+				line->id);
+	}
+
+	return blk_to_erase;
+}
+
 static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
 {
 	struct pblk_line_meta *lm = &pblk->lm;
-	int blk_in_line = atomic_read(&line->blk_in_line);
+	int blk_to_erase;
 
 	line->map_bitmap = kzalloc(lm->sec_bitmap_len, GFP_ATOMIC);
 	if (!line->map_bitmap)
@@ -1110,7 +1184,21 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
 		return -ENOMEM;
 	}
 
+	/* Bad blocks do not need to be erased */
+	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
+
 	spin_lock(&line->lock);
+
+	/* If we have not written to this line, we need to mark up free chunks
+	 * as already erased
+	 */
+	if (line->state == PBLK_LINESTATE_NEW) {
+		blk_to_erase = pblk_prepare_new_line(pblk, line);
+		line->state = PBLK_LINESTATE_FREE;
+	} else {
+		blk_to_erase = atomic_read(&line->blk_in_line);
+	}
+
 	if (line->state != PBLK_LINESTATE_FREE) {
 		kfree(line->map_bitmap);
 		kfree(line->invalid_bitmap);
@@ -1122,15 +1210,12 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
 
 	line->state = PBLK_LINESTATE_OPEN;
 
-	atomic_set(&line->left_eblks, blk_in_line);
-	atomic_set(&line->left_seblks, blk_in_line);
+	atomic_set(&line->left_eblks, blk_to_erase);
+	atomic_set(&line->left_seblks, blk_to_erase);
 
 	line->meta_distance = lm->meta_distance;
 	spin_unlock(&line->lock);
 
-	/* Bad blocks do not need to be erased */
-	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
-
 	kref_init(&line->ref);
 
 	return 0;
diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index ec39800eea42..1618e923ef5f 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -401,6 +401,7 @@ static void pblk_line_meta_free(struct pblk_line *line)
 {
 	kfree(line->blk_bitmap);
 	kfree(line->erase_bitmap);
+	kfree(line->chks);
 }
 
 static void pblk_lines_free(struct pblk *pblk)
@@ -469,25 +470,15 @@ static void *pblk_bb_get_log(struct pblk *pblk)
 	return log;
 }
 
-static int pblk_bb_line(struct pblk *pblk, struct pblk_line *line,
-			u8 *bb_log, int blk_per_line)
+static void *pblk_chunk_get_log(struct pblk *pblk)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
-	int i, bb_cnt = 0;
 
-	for (i = 0; i < blk_per_line; i++) {
-		struct pblk_lun *rlun = &pblk->luns[i];
-		u8 *lun_bb_log = bb_log + i * blk_per_line;
-
-		if (lun_bb_log[line->id] == NVM_BLK_T_FREE)
-			continue;
-
-		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
-		bb_cnt++;
-	}
-
-	return bb_cnt;
+	if (geo->c.version == NVM_OCSSD_SPEC_12)
+		return pblk_bb_get_log(pblk);
+	else
+		return pblk_chunk_get_info(pblk);
 }
 
 static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
@@ -516,6 +507,7 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
 
 		rlun = &pblk->luns[i];
 		rlun->bppa = luns[lunid];
+		rlun->chunk_bppa = luns[i];
 
 		sema_init(&rlun->wr_sem, 1);
 	}
@@ -695,8 +687,125 @@ static int pblk_lines_alloc_metadata(struct pblk *pblk)
 	return -ENOMEM;
 }
 
-static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
-				void *chunk_log, long *nr_bad_blks)
+static int pblk_setup_line_meta_12(struct pblk *pblk, struct pblk_line *line,
+				   void *chunk_log)
+{
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	struct pblk_line_meta *lm = &pblk->lm;
+	int i, chk_per_lun, nr_bad_chks = 0;
+
+	chk_per_lun = geo->c.num_chk * geo->c.pln_mode;
+
+	for (i = 0; i < lm->blk_per_line; i++) {
+		struct pblk_chunk *chunk = &line->chks[i];
+		struct pblk_lun *rlun = &pblk->luns[i];
+		u8 *lun_bb_log = chunk_log + i * chk_per_lun;
+
+		/*
+		 * In 1.2 spec. chunk state is not persisted by the device. Thus
+		 * some of the values are reset each time pblk is instantiated.
+		 */
+		if (lun_bb_log[line->id] == NVM_BLK_T_FREE)
+			chunk->state =  NVM_CHK_ST_HOST_USE;
+		else
+			chunk->state = NVM_CHK_ST_OFFLINE;
+
+		chunk->type = NVM_CHK_TP_W_SEQ;
+		chunk->wi = 0;
+		chunk->slba = -1;
+		chunk->cnlb = geo->c.clba;
+		chunk->wp = 0;
+
+		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
+			continue;
+
+		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
+		nr_bad_chks++;
+	}
+
+	return nr_bad_chks;
+}
+
+static int pblk_setup_line_meta_20(struct pblk *pblk, struct pblk_line *line,
+				   struct nvm_chk_meta *meta)
+{
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	struct pblk_line_meta *lm = &pblk->lm;
+	int i, nr_bad_chks = 0;
+
+	for (i = 0; i < lm->blk_per_line; i++) {
+		struct pblk_chunk *chunk = &line->chks[i];
+		struct pblk_lun *rlun = &pblk->luns[i];
+		struct nvm_chk_meta *chunk_meta;
+		struct ppa_addr ppa;
+
+		ppa = rlun->chunk_bppa;
+		ppa.m.chk = line->id;
+		chunk_meta = pblk_chunk_get_off(pblk, meta, ppa);
+
+		chunk->state = chunk_meta->state;
+		chunk->type = chunk_meta->type;
+		chunk->wi = chunk_meta->wi;
+		chunk->slba = chunk_meta->slba;
+		chunk->cnlb = chunk_meta->cnlb;
+		chunk->wp = chunk_meta->wp;
+
+		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
+			continue;
+
+		if (chunk->type & NVM_CHK_TP_SZ_SPEC) {
+			WARN_ONCE(1, "pblk: custom-sized chunks unsupported\n");
+			continue;
+		}
+
+		set_bit(pblk_ppa_to_pos(geo, rlun->chunk_bppa),
+							line->blk_bitmap);
+		nr_bad_chks++;
+	}
+
+	return nr_bad_chks;
+}
+
+static long pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
+				 void *chunk_log, int line_id)
+{
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
+	struct pblk_line_meta *lm = &pblk->lm;
+	long nr_bad_chks, chk_in_line;
+
+	line->pblk = pblk;
+	line->id = line_id;
+	line->type = PBLK_LINETYPE_FREE;
+	line->state = PBLK_LINESTATE_NEW;
+	line->gc_group = PBLK_LINEGC_NONE;
+	line->vsc = &l_mg->vsc_list[line_id];
+	spin_lock_init(&line->lock);
+
+	if (geo->c.version == NVM_OCSSD_SPEC_12)
+		nr_bad_chks = pblk_setup_line_meta_12(pblk, line, chunk_log);
+	else
+		nr_bad_chks = pblk_setup_line_meta_20(pblk, line, chunk_log);
+
+	chk_in_line = lm->blk_per_line - nr_bad_chks;
+	if (nr_bad_chks < 0 || nr_bad_chks > lm->blk_per_line ||
+					chk_in_line < lm->min_blk_line) {
+		line->state = PBLK_LINESTATE_BAD;
+		list_add_tail(&line->list, &l_mg->bad_list);
+		return 0;
+	}
+
+	atomic_set(&line->blk_in_line, chk_in_line);
+	list_add_tail(&line->list, &l_mg->free_list);
+	l_mg->nr_free_lines++;
+
+	return chk_in_line;
+}
+
+static int pblk_alloc_line_meta(struct pblk *pblk, struct pblk_line *line)
 {
 	struct pblk_line_meta *lm = &pblk->lm;
 
@@ -710,7 +819,13 @@ static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
 		return -ENOMEM;
 	}
 
-	*nr_bad_blks = pblk_bb_line(pblk, line, chunk_log, lm->blk_per_line);
+	line->chks = kmalloc(lm->blk_per_line * sizeof(struct pblk_chunk),
+								GFP_KERNEL);
+	if (!line->chks) {
+		kfree(line->erase_bitmap);
+		kfree(line->blk_bitmap);
+		return -ENOMEM;
+	}
 
 	return 0;
 }
@@ -724,7 +839,7 @@ static int pblk_lines_init(struct pblk *pblk)
 	struct pblk_line *line;
 	void *chunk_log;
 	unsigned int smeta_len, emeta_len;
-	long nr_bad_blks = 0, nr_free_blks = 0;
+	long nr_free_chks = 0;
 	int bb_distance, max_write_ppas;
 	int i, ret;
 
@@ -743,6 +858,7 @@ static int pblk_lines_init(struct pblk *pblk)
 	l_mg->log_line = l_mg->data_line = NULL;
 	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
 	l_mg->nr_free_lines = 0;
+	atomic_set(&l_mg->sysfs_line_state, -1);
 	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
 
 	lm->sec_per_line = geo->c.clba * geo->all_luns;
@@ -841,47 +957,25 @@ static int pblk_lines_init(struct pblk *pblk)
 		goto fail_free_bb_aux;
 	}
 
-	chunk_log = pblk_bb_get_log(pblk);
+	chunk_log = pblk_chunk_get_log(pblk);
 	if (IS_ERR(chunk_log)) {
-		pr_err("pblk: could not get bad block log (%lu)\n",
+		pr_err("pblk: could not get chunk log (%lu)\n",
 							PTR_ERR(chunk_log));
 		ret = PTR_ERR(chunk_log);
 		goto fail_free_lines;
 	}
 
 	for (i = 0; i < l_mg->nr_lines; i++) {
-		int chk_in_line;
-
 		line = &pblk->lines[i];
 
-		line->pblk = pblk;
-		line->id = i;
-		line->type = PBLK_LINETYPE_FREE;
-		line->state = PBLK_LINESTATE_FREE;
-		line->gc_group = PBLK_LINEGC_NONE;
-		line->vsc = &l_mg->vsc_list[i];
-		spin_lock_init(&line->lock);
-
-		ret = pblk_setup_line_meta(pblk, line, chunk_log, &nr_bad_blks);
+		ret = pblk_alloc_line_meta(pblk, line);
 		if (ret)
 			goto fail_free_chunk_log;
 
-		chk_in_line = lm->blk_per_line - nr_bad_blks;
-		if (nr_bad_blks < 0 || nr_bad_blks > lm->blk_per_line ||
-					chk_in_line < lm->min_blk_line) {
-			line->state = PBLK_LINESTATE_BAD;
-			list_add_tail(&line->list, &l_mg->bad_list);
-			continue;
-		}
-
-		nr_free_blks += chk_in_line;
-		atomic_set(&line->blk_in_line, chk_in_line);
-
-		l_mg->nr_free_lines++;
-		list_add_tail(&line->list, &l_mg->free_list);
+		nr_free_chks += pblk_setup_line_meta(pblk, line, chunk_log, i);
 	}
 
-	pblk_set_provision(pblk, nr_free_blks);
+	pblk_set_provision(pblk, nr_free_chks);
 
 	kfree(chunk_log);
 	return 0;
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index d3b50741b691..191af0c6591e 100644
--- a/drivers/lightnvm/pblk-sysfs.c
+++ b/drivers/lightnvm/pblk-sysfs.c
@@ -142,6 +142,40 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
 	return sz;
 }
 
+static ssize_t pblk_sysfs_line_state_show(struct pblk *pblk, char *page)
+{
+	struct pblk_line_meta *lm = &pblk->lm;
+	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
+	struct pblk_line *line;
+	int line_id = atomic_read(&l_mg->sysfs_line_state);
+	ssize_t sz = 0;
+	int i;
+
+	if (line_id < 0 || line_id >= l_mg->nr_lines)
+		return 0;
+
+	sz = snprintf(page, PAGE_SIZE,
+		"line\tchunk\tstate\ttype\twear-index\tslba\t\tcnlb\twp\n");
+
+	line = &pblk->lines[line_id];
+
+	for (i = 0; i < lm->blk_per_line; i++) {
+		struct pblk_chunk *chunk = &line->chks[i];
+
+		sz += snprintf(page + sz, PAGE_SIZE - sz,
+				"%d\t%d\t%d\t%d\t%d\t\t%llu\t\t%llu\t%llu\n",
+				line->id, i,
+				chunk->state,
+				chunk->type,
+				chunk->wi,
+				chunk->slba,
+				chunk->cnlb,
+				chunk->wp);
+	}
+
+	return sz;
+}
+
 static ssize_t pblk_sysfs_lines(struct pblk *pblk, char *page)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
@@ -398,6 +432,29 @@ static ssize_t pblk_sysfs_stats_debug(struct pblk *pblk, char *page)
 }
 #endif
 
+
+static ssize_t pblk_sysfs_line_state_store(struct pblk *pblk, const char *page,
+					   size_t len)
+{
+	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
+	size_t c_len;
+	int line_id;
+
+	c_len = strcspn(page, "\n");
+	if (c_len >= len)
+		return -EINVAL;
+
+	if (kstrtouint(page, 0, &line_id))
+		return -EINVAL;
+
+	if (line_id < 0 || line_id >= l_mg->nr_lines)
+		return -EINVAL;
+
+	atomic_set(&l_mg->sysfs_line_state, line_id);
+
+	return len;
+}
+
 static ssize_t pblk_sysfs_gc_force(struct pblk *pblk, const char *page,
 				   size_t len)
 {
@@ -529,6 +586,11 @@ static struct attribute sys_lines_info_attr = {
 	.mode = 0444,
 };
 
+static struct attribute sys_line_state_attr = {
+	.name = "line_state",
+	.mode = 0644,
+};
+
 static struct attribute sys_gc_force = {
 	.name = "gc_force",
 	.mode = 0200,
@@ -572,6 +634,7 @@ static struct attribute *pblk_attrs[] = {
 	&sys_stats_ppaf_attr,
 	&sys_lines_attr,
 	&sys_lines_info_attr,
+	&sys_line_state_attr,
 	&sys_write_amp_mileage,
 	&sys_write_amp_trip,
 	&sys_padding_dist,
@@ -602,6 +665,8 @@ static ssize_t pblk_sysfs_show(struct kobject *kobj, struct attribute *attr,
 		return pblk_sysfs_lines(pblk, buf);
 	else if (strcmp(attr->name, "lines_info") == 0)
 		return pblk_sysfs_lines_info(pblk, buf);
+	else if (strcmp(attr->name, "line_state") == 0)
+		return pblk_sysfs_line_state_show(pblk, buf);
 	else if (strcmp(attr->name, "max_sec_per_write") == 0)
 		return pblk_sysfs_get_sec_per_write(pblk, buf);
 	else if (strcmp(attr->name, "write_amp_mileage") == 0)
@@ -628,6 +693,8 @@ static ssize_t pblk_sysfs_store(struct kobject *kobj, struct attribute *attr,
 		return pblk_sysfs_set_sec_per_write(pblk, buf, len);
 	else if (strcmp(attr->name, "write_amp_trip") == 0)
 		return pblk_sysfs_set_write_amp_trip(pblk, buf, len);
+	else if (strcmp(attr->name, "line_state") == 0)
+		return pblk_sysfs_line_state_store(pblk, buf, len);
 	else if (strcmp(attr->name, "padding_dist") == 0)
 		return pblk_sysfs_set_padding_dist(pblk, buf, len);
 	return 0;
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 46b29a492f74..c66fa0c28adf 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -201,6 +201,8 @@ struct pblk_rb {
 
 struct pblk_lun {
 	struct ppa_addr bppa;
+	struct ppa_addr chunk_bppa;
+
 	struct semaphore wr_sem;
 };
 
@@ -297,6 +299,7 @@ enum {
 	PBLK_LINETYPE_DATA = 2,
 
 	/* Line state */
+	PBLK_LINESTATE_NEW = 9,
 	PBLK_LINESTATE_FREE = 10,
 	PBLK_LINESTATE_OPEN = 11,
 	PBLK_LINESTATE_CLOSED = 12,
@@ -412,6 +415,15 @@ struct pblk_smeta {
 	struct line_smeta *buf;		/* smeta buffer in persistent format */
 };
 
+struct pblk_chunk {
+	int state;
+	int type;
+	int wi;
+	u64 slba;
+	u64 cnlb;
+	u64 wp;
+};
+
 struct pblk_line {
 	struct pblk *pblk;
 	unsigned int id;		/* Line number corresponds to the
@@ -426,6 +438,8 @@ struct pblk_line {
 
 	unsigned long *lun_bitmap;	/* Bitmap for LUNs mapped in line */
 
+	struct pblk_chunk *chks;	/* Chunks forming line */
+
 	struct pblk_smeta *smeta;	/* Start metadata */
 	struct pblk_emeta *emeta;	/* End medatada */
 
@@ -513,6 +527,8 @@ struct pblk_line_mgmt {
 	unsigned long d_seq_nr;		/* Data line unique sequence number */
 	unsigned long l_seq_nr;		/* Log line unique sequence number */
 
+	atomic_t sysfs_line_state;	/* Line being monitored in sysfs */
+
 	spinlock_t free_lock;
 	spinlock_t close_lock;
 	spinlock_t gc_lock;
@@ -729,6 +745,10 @@ void pblk_set_sec_per_write(struct pblk *pblk, int sec_per_write);
 int pblk_setup_w_rec_rq(struct pblk *pblk, struct nvm_rq *rqd,
 			struct pblk_c_ctx *c_ctx);
 void pblk_discard(struct pblk *pblk, struct bio *bio);
+struct nvm_chk_meta *pblk_chunk_get_info(struct pblk *pblk);
+struct nvm_chk_meta *pblk_chunk_get_off(struct pblk *pblk,
+					      struct nvm_chk_meta *lp,
+					      struct ppa_addr ppa);
 void pblk_log_write_err(struct pblk *pblk, struct nvm_rq *rqd);
 void pblk_log_read_err(struct pblk *pblk, struct nvm_rq *rqd);
 int pblk_submit_io(struct pblk *pblk, struct nvm_rq *rqd);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 18/20] lightnvm: pblk: implement get log report chunk
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


From: Javier Gonz?lez <javier@javigon.com>

In preparation of pblk supporting 2.0, implement the get log report
chunk in pblk.

This patch only replicates de bad block functionality as the rest of the
metadata requires new pblk functionality (e.g., wear-index to implement
wear-leveling). This functionality will come in future patches.

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/lightnvm/pblk-core.c  | 121 +++++++++++++++++++++++----
 drivers/lightnvm/pblk-init.c  | 186 +++++++++++++++++++++++++++++++-----------
 drivers/lightnvm/pblk-sysfs.c |  67 +++++++++++++++
 drivers/lightnvm/pblk.h       |  20 +++++
 4 files changed, 330 insertions(+), 64 deletions(-)

diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index 7c726003a8d2..90aae45b2842 100644
--- a/drivers/lightnvm/pblk-core.c
+++ b/drivers/lightnvm/pblk-core.c
@@ -44,11 +44,12 @@ static void pblk_line_mark_bb(struct work_struct *work)
 }
 
 static void pblk_mark_bb(struct pblk *pblk, struct pblk_line *line,
-			 struct ppa_addr *ppa)
+			 struct ppa_addr ppa_addr)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
-	int pos = pblk_ppa_to_pos(geo, *ppa);
+	struct ppa_addr *ppa;
+	int pos = pblk_ppa_to_pos(geo, ppa_addr);
 
 	pr_debug("pblk: erase failed: line:%d, pos:%d\n", line->id, pos);
 	atomic_long_inc(&pblk->erase_failed);
@@ -58,6 +59,15 @@ static void pblk_mark_bb(struct pblk *pblk, struct pblk_line *line,
 		pr_err("pblk: attempted to erase bb: line:%d, pos:%d\n",
 							line->id, pos);
 
+	/* Not necessary to mark bad blocks on 2.0 spec. */
+	if (geo->c.version == NVM_OCSSD_SPEC_20)
+		return;
+
+	ppa = kmalloc(sizeof(struct ppa_addr), GFP_ATOMIC);
+	if (!ppa)
+		return;
+
+	*ppa = ppa_addr;
 	pblk_gen_run_ws(pblk, NULL, ppa, pblk_line_mark_bb,
 						GFP_ATOMIC, pblk->bb_wq);
 }
@@ -69,16 +79,8 @@ static void __pblk_end_io_erase(struct pblk *pblk, struct nvm_rq *rqd)
 	line = &pblk->lines[pblk_ppa_to_line(rqd->ppa_addr)];
 	atomic_dec(&line->left_seblks);
 
-	if (rqd->error) {
-		struct ppa_addr *ppa;
-
-		ppa = kmalloc(sizeof(struct ppa_addr), GFP_ATOMIC);
-		if (!ppa)
-			return;
-
-		*ppa = rqd->ppa_addr;
-		pblk_mark_bb(pblk, line, ppa);
-	}
+	if (rqd->error)
+		pblk_mark_bb(pblk, line, rqd->ppa_addr);
 
 	atomic_dec(&pblk->inflight_io);
 }
@@ -92,6 +94,50 @@ static void pblk_end_io_erase(struct nvm_rq *rqd)
 	mempool_free(rqd, pblk->e_rq_pool);
 }
 
+/*
+ * Get information for all chunks from the device.
+ *
+ * The caller is responsible for freeing the returned structure
+ */
+struct nvm_chk_meta *pblk_chunk_get_info(struct pblk *pblk)
+{
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	struct nvm_chk_meta *meta;
+	struct ppa_addr ppa;
+	unsigned long len;
+	int ret;
+
+	ppa.ppa = 0;
+
+	len = geo->all_chunks * sizeof(*meta);
+	meta = kzalloc(len, GFP_KERNEL);
+	if (!meta)
+		return ERR_PTR(-ENOMEM);
+
+	ret = nvm_get_chunk_meta(dev, meta, ppa, geo->all_chunks);
+	if (ret) {
+		pr_err("pblk: could not get chunk metadata (%d)\n", ret);
+		kfree(meta);
+		return ERR_PTR(-EIO);
+	}
+
+	return meta;
+}
+
+struct nvm_chk_meta *pblk_chunk_get_off(struct pblk *pblk,
+					      struct nvm_chk_meta *meta,
+					      struct ppa_addr ppa)
+{
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	int ch_off = ppa.m.ch * geo->c.num_chk * geo->num_lun;
+	int lun_off = ppa.m.lun * geo->c.num_chk;
+	int chk_off = ppa.m.chk;
+
+	return meta + ch_off + lun_off + chk_off;
+}
+
 void __pblk_map_invalidate(struct pblk *pblk, struct pblk_line *line,
 			   u64 paddr)
 {
@@ -1094,10 +1140,38 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
 	return 1;
 }
 
+static int pblk_prepare_new_line(struct pblk *pblk, struct pblk_line *line)
+{
+	struct pblk_line_meta *lm = &pblk->lm;
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	int blk_to_erase = atomic_read(&line->blk_in_line);
+	int i;
+
+	for (i = 0; i < lm->blk_per_line; i++) {
+		int state = line->chks[i].state;
+		struct pblk_lun *rlun = &pblk->luns[i];
+
+		/* Free chunks should not be erased */
+		if (state & NVM_CHK_ST_FREE) {
+			set_bit(pblk_ppa_to_pos(geo, rlun->chunk_bppa),
+					line->erase_bitmap);
+			blk_to_erase--;
+			line->chks[i].state = NVM_CHK_ST_HOST_USE;
+		}
+
+		WARN_ONCE(state & NVM_CHK_ST_OPEN,
+				"pblk: open chunk in new line: %d\n",
+				line->id);
+	}
+
+	return blk_to_erase;
+}
+
 static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
 {
 	struct pblk_line_meta *lm = &pblk->lm;
-	int blk_in_line = atomic_read(&line->blk_in_line);
+	int blk_to_erase;
 
 	line->map_bitmap = kzalloc(lm->sec_bitmap_len, GFP_ATOMIC);
 	if (!line->map_bitmap)
@@ -1110,7 +1184,21 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
 		return -ENOMEM;
 	}
 
+	/* Bad blocks do not need to be erased */
+	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
+
 	spin_lock(&line->lock);
+
+	/* If we have not written to this line, we need to mark up free chunks
+	 * as already erased
+	 */
+	if (line->state == PBLK_LINESTATE_NEW) {
+		blk_to_erase = pblk_prepare_new_line(pblk, line);
+		line->state = PBLK_LINESTATE_FREE;
+	} else {
+		blk_to_erase = atomic_read(&line->blk_in_line);
+	}
+
 	if (line->state != PBLK_LINESTATE_FREE) {
 		kfree(line->map_bitmap);
 		kfree(line->invalid_bitmap);
@@ -1122,15 +1210,12 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
 
 	line->state = PBLK_LINESTATE_OPEN;
 
-	atomic_set(&line->left_eblks, blk_in_line);
-	atomic_set(&line->left_seblks, blk_in_line);
+	atomic_set(&line->left_eblks, blk_to_erase);
+	atomic_set(&line->left_seblks, blk_to_erase);
 
 	line->meta_distance = lm->meta_distance;
 	spin_unlock(&line->lock);
 
-	/* Bad blocks do not need to be erased */
-	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
-
 	kref_init(&line->ref);
 
 	return 0;
diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index ec39800eea42..1618e923ef5f 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -401,6 +401,7 @@ static void pblk_line_meta_free(struct pblk_line *line)
 {
 	kfree(line->blk_bitmap);
 	kfree(line->erase_bitmap);
+	kfree(line->chks);
 }
 
 static void pblk_lines_free(struct pblk *pblk)
@@ -469,25 +470,15 @@ static void *pblk_bb_get_log(struct pblk *pblk)
 	return log;
 }
 
-static int pblk_bb_line(struct pblk *pblk, struct pblk_line *line,
-			u8 *bb_log, int blk_per_line)
+static void *pblk_chunk_get_log(struct pblk *pblk)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
-	int i, bb_cnt = 0;
 
-	for (i = 0; i < blk_per_line; i++) {
-		struct pblk_lun *rlun = &pblk->luns[i];
-		u8 *lun_bb_log = bb_log + i * blk_per_line;
-
-		if (lun_bb_log[line->id] == NVM_BLK_T_FREE)
-			continue;
-
-		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
-		bb_cnt++;
-	}
-
-	return bb_cnt;
+	if (geo->c.version == NVM_OCSSD_SPEC_12)
+		return pblk_bb_get_log(pblk);
+	else
+		return pblk_chunk_get_info(pblk);
 }
 
 static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
@@ -516,6 +507,7 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
 
 		rlun = &pblk->luns[i];
 		rlun->bppa = luns[lunid];
+		rlun->chunk_bppa = luns[i];
 
 		sema_init(&rlun->wr_sem, 1);
 	}
@@ -695,8 +687,125 @@ static int pblk_lines_alloc_metadata(struct pblk *pblk)
 	return -ENOMEM;
 }
 
-static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
-				void *chunk_log, long *nr_bad_blks)
+static int pblk_setup_line_meta_12(struct pblk *pblk, struct pblk_line *line,
+				   void *chunk_log)
+{
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	struct pblk_line_meta *lm = &pblk->lm;
+	int i, chk_per_lun, nr_bad_chks = 0;
+
+	chk_per_lun = geo->c.num_chk * geo->c.pln_mode;
+
+	for (i = 0; i < lm->blk_per_line; i++) {
+		struct pblk_chunk *chunk = &line->chks[i];
+		struct pblk_lun *rlun = &pblk->luns[i];
+		u8 *lun_bb_log = chunk_log + i * chk_per_lun;
+
+		/*
+		 * In 1.2 spec. chunk state is not persisted by the device. Thus
+		 * some of the values are reset each time pblk is instantiated.
+		 */
+		if (lun_bb_log[line->id] == NVM_BLK_T_FREE)
+			chunk->state =  NVM_CHK_ST_HOST_USE;
+		else
+			chunk->state = NVM_CHK_ST_OFFLINE;
+
+		chunk->type = NVM_CHK_TP_W_SEQ;
+		chunk->wi = 0;
+		chunk->slba = -1;
+		chunk->cnlb = geo->c.clba;
+		chunk->wp = 0;
+
+		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
+			continue;
+
+		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
+		nr_bad_chks++;
+	}
+
+	return nr_bad_chks;
+}
+
+static int pblk_setup_line_meta_20(struct pblk *pblk, struct pblk_line *line,
+				   struct nvm_chk_meta *meta)
+{
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	struct pblk_line_meta *lm = &pblk->lm;
+	int i, nr_bad_chks = 0;
+
+	for (i = 0; i < lm->blk_per_line; i++) {
+		struct pblk_chunk *chunk = &line->chks[i];
+		struct pblk_lun *rlun = &pblk->luns[i];
+		struct nvm_chk_meta *chunk_meta;
+		struct ppa_addr ppa;
+
+		ppa = rlun->chunk_bppa;
+		ppa.m.chk = line->id;
+		chunk_meta = pblk_chunk_get_off(pblk, meta, ppa);
+
+		chunk->state = chunk_meta->state;
+		chunk->type = chunk_meta->type;
+		chunk->wi = chunk_meta->wi;
+		chunk->slba = chunk_meta->slba;
+		chunk->cnlb = chunk_meta->cnlb;
+		chunk->wp = chunk_meta->wp;
+
+		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
+			continue;
+
+		if (chunk->type & NVM_CHK_TP_SZ_SPEC) {
+			WARN_ONCE(1, "pblk: custom-sized chunks unsupported\n");
+			continue;
+		}
+
+		set_bit(pblk_ppa_to_pos(geo, rlun->chunk_bppa),
+							line->blk_bitmap);
+		nr_bad_chks++;
+	}
+
+	return nr_bad_chks;
+}
+
+static long pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
+				 void *chunk_log, int line_id)
+{
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
+	struct pblk_line_meta *lm = &pblk->lm;
+	long nr_bad_chks, chk_in_line;
+
+	line->pblk = pblk;
+	line->id = line_id;
+	line->type = PBLK_LINETYPE_FREE;
+	line->state = PBLK_LINESTATE_NEW;
+	line->gc_group = PBLK_LINEGC_NONE;
+	line->vsc = &l_mg->vsc_list[line_id];
+	spin_lock_init(&line->lock);
+
+	if (geo->c.version == NVM_OCSSD_SPEC_12)
+		nr_bad_chks = pblk_setup_line_meta_12(pblk, line, chunk_log);
+	else
+		nr_bad_chks = pblk_setup_line_meta_20(pblk, line, chunk_log);
+
+	chk_in_line = lm->blk_per_line - nr_bad_chks;
+	if (nr_bad_chks < 0 || nr_bad_chks > lm->blk_per_line ||
+					chk_in_line < lm->min_blk_line) {
+		line->state = PBLK_LINESTATE_BAD;
+		list_add_tail(&line->list, &l_mg->bad_list);
+		return 0;
+	}
+
+	atomic_set(&line->blk_in_line, chk_in_line);
+	list_add_tail(&line->list, &l_mg->free_list);
+	l_mg->nr_free_lines++;
+
+	return chk_in_line;
+}
+
+static int pblk_alloc_line_meta(struct pblk *pblk, struct pblk_line *line)
 {
 	struct pblk_line_meta *lm = &pblk->lm;
 
@@ -710,7 +819,13 @@ static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
 		return -ENOMEM;
 	}
 
-	*nr_bad_blks = pblk_bb_line(pblk, line, chunk_log, lm->blk_per_line);
+	line->chks = kmalloc(lm->blk_per_line * sizeof(struct pblk_chunk),
+								GFP_KERNEL);
+	if (!line->chks) {
+		kfree(line->erase_bitmap);
+		kfree(line->blk_bitmap);
+		return -ENOMEM;
+	}
 
 	return 0;
 }
@@ -724,7 +839,7 @@ static int pblk_lines_init(struct pblk *pblk)
 	struct pblk_line *line;
 	void *chunk_log;
 	unsigned int smeta_len, emeta_len;
-	long nr_bad_blks = 0, nr_free_blks = 0;
+	long nr_free_chks = 0;
 	int bb_distance, max_write_ppas;
 	int i, ret;
 
@@ -743,6 +858,7 @@ static int pblk_lines_init(struct pblk *pblk)
 	l_mg->log_line = l_mg->data_line = NULL;
 	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
 	l_mg->nr_free_lines = 0;
+	atomic_set(&l_mg->sysfs_line_state, -1);
 	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
 
 	lm->sec_per_line = geo->c.clba * geo->all_luns;
@@ -841,47 +957,25 @@ static int pblk_lines_init(struct pblk *pblk)
 		goto fail_free_bb_aux;
 	}
 
-	chunk_log = pblk_bb_get_log(pblk);
+	chunk_log = pblk_chunk_get_log(pblk);
 	if (IS_ERR(chunk_log)) {
-		pr_err("pblk: could not get bad block log (%lu)\n",
+		pr_err("pblk: could not get chunk log (%lu)\n",
 							PTR_ERR(chunk_log));
 		ret = PTR_ERR(chunk_log);
 		goto fail_free_lines;
 	}
 
 	for (i = 0; i < l_mg->nr_lines; i++) {
-		int chk_in_line;
-
 		line = &pblk->lines[i];
 
-		line->pblk = pblk;
-		line->id = i;
-		line->type = PBLK_LINETYPE_FREE;
-		line->state = PBLK_LINESTATE_FREE;
-		line->gc_group = PBLK_LINEGC_NONE;
-		line->vsc = &l_mg->vsc_list[i];
-		spin_lock_init(&line->lock);
-
-		ret = pblk_setup_line_meta(pblk, line, chunk_log, &nr_bad_blks);
+		ret = pblk_alloc_line_meta(pblk, line);
 		if (ret)
 			goto fail_free_chunk_log;
 
-		chk_in_line = lm->blk_per_line - nr_bad_blks;
-		if (nr_bad_blks < 0 || nr_bad_blks > lm->blk_per_line ||
-					chk_in_line < lm->min_blk_line) {
-			line->state = PBLK_LINESTATE_BAD;
-			list_add_tail(&line->list, &l_mg->bad_list);
-			continue;
-		}
-
-		nr_free_blks += chk_in_line;
-		atomic_set(&line->blk_in_line, chk_in_line);
-
-		l_mg->nr_free_lines++;
-		list_add_tail(&line->list, &l_mg->free_list);
+		nr_free_chks += pblk_setup_line_meta(pblk, line, chunk_log, i);
 	}
 
-	pblk_set_provision(pblk, nr_free_blks);
+	pblk_set_provision(pblk, nr_free_chks);
 
 	kfree(chunk_log);
 	return 0;
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index d3b50741b691..191af0c6591e 100644
--- a/drivers/lightnvm/pblk-sysfs.c
+++ b/drivers/lightnvm/pblk-sysfs.c
@@ -142,6 +142,40 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
 	return sz;
 }
 
+static ssize_t pblk_sysfs_line_state_show(struct pblk *pblk, char *page)
+{
+	struct pblk_line_meta *lm = &pblk->lm;
+	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
+	struct pblk_line *line;
+	int line_id = atomic_read(&l_mg->sysfs_line_state);
+	ssize_t sz = 0;
+	int i;
+
+	if (line_id < 0 || line_id >= l_mg->nr_lines)
+		return 0;
+
+	sz = snprintf(page, PAGE_SIZE,
+		"line\tchunk\tstate\ttype\twear-index\tslba\t\tcnlb\twp\n");
+
+	line = &pblk->lines[line_id];
+
+	for (i = 0; i < lm->blk_per_line; i++) {
+		struct pblk_chunk *chunk = &line->chks[i];
+
+		sz += snprintf(page + sz, PAGE_SIZE - sz,
+				"%d\t%d\t%d\t%d\t%d\t\t%llu\t\t%llu\t%llu\n",
+				line->id, i,
+				chunk->state,
+				chunk->type,
+				chunk->wi,
+				chunk->slba,
+				chunk->cnlb,
+				chunk->wp);
+	}
+
+	return sz;
+}
+
 static ssize_t pblk_sysfs_lines(struct pblk *pblk, char *page)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
@@ -398,6 +432,29 @@ static ssize_t pblk_sysfs_stats_debug(struct pblk *pblk, char *page)
 }
 #endif
 
+
+static ssize_t pblk_sysfs_line_state_store(struct pblk *pblk, const char *page,
+					   size_t len)
+{
+	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
+	size_t c_len;
+	int line_id;
+
+	c_len = strcspn(page, "\n");
+	if (c_len >= len)
+		return -EINVAL;
+
+	if (kstrtouint(page, 0, &line_id))
+		return -EINVAL;
+
+	if (line_id < 0 || line_id >= l_mg->nr_lines)
+		return -EINVAL;
+
+	atomic_set(&l_mg->sysfs_line_state, line_id);
+
+	return len;
+}
+
 static ssize_t pblk_sysfs_gc_force(struct pblk *pblk, const char *page,
 				   size_t len)
 {
@@ -529,6 +586,11 @@ static struct attribute sys_lines_info_attr = {
 	.mode = 0444,
 };
 
+static struct attribute sys_line_state_attr = {
+	.name = "line_state",
+	.mode = 0644,
+};
+
 static struct attribute sys_gc_force = {
 	.name = "gc_force",
 	.mode = 0200,
@@ -572,6 +634,7 @@ static struct attribute *pblk_attrs[] = {
 	&sys_stats_ppaf_attr,
 	&sys_lines_attr,
 	&sys_lines_info_attr,
+	&sys_line_state_attr,
 	&sys_write_amp_mileage,
 	&sys_write_amp_trip,
 	&sys_padding_dist,
@@ -602,6 +665,8 @@ static ssize_t pblk_sysfs_show(struct kobject *kobj, struct attribute *attr,
 		return pblk_sysfs_lines(pblk, buf);
 	else if (strcmp(attr->name, "lines_info") == 0)
 		return pblk_sysfs_lines_info(pblk, buf);
+	else if (strcmp(attr->name, "line_state") == 0)
+		return pblk_sysfs_line_state_show(pblk, buf);
 	else if (strcmp(attr->name, "max_sec_per_write") == 0)
 		return pblk_sysfs_get_sec_per_write(pblk, buf);
 	else if (strcmp(attr->name, "write_amp_mileage") == 0)
@@ -628,6 +693,8 @@ static ssize_t pblk_sysfs_store(struct kobject *kobj, struct attribute *attr,
 		return pblk_sysfs_set_sec_per_write(pblk, buf, len);
 	else if (strcmp(attr->name, "write_amp_trip") == 0)
 		return pblk_sysfs_set_write_amp_trip(pblk, buf, len);
+	else if (strcmp(attr->name, "line_state") == 0)
+		return pblk_sysfs_line_state_store(pblk, buf, len);
 	else if (strcmp(attr->name, "padding_dist") == 0)
 		return pblk_sysfs_set_padding_dist(pblk, buf, len);
 	return 0;
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 46b29a492f74..c66fa0c28adf 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -201,6 +201,8 @@ struct pblk_rb {
 
 struct pblk_lun {
 	struct ppa_addr bppa;
+	struct ppa_addr chunk_bppa;
+
 	struct semaphore wr_sem;
 };
 
@@ -297,6 +299,7 @@ enum {
 	PBLK_LINETYPE_DATA = 2,
 
 	/* Line state */
+	PBLK_LINESTATE_NEW = 9,
 	PBLK_LINESTATE_FREE = 10,
 	PBLK_LINESTATE_OPEN = 11,
 	PBLK_LINESTATE_CLOSED = 12,
@@ -412,6 +415,15 @@ struct pblk_smeta {
 	struct line_smeta *buf;		/* smeta buffer in persistent format */
 };
 
+struct pblk_chunk {
+	int state;
+	int type;
+	int wi;
+	u64 slba;
+	u64 cnlb;
+	u64 wp;
+};
+
 struct pblk_line {
 	struct pblk *pblk;
 	unsigned int id;		/* Line number corresponds to the
@@ -426,6 +438,8 @@ struct pblk_line {
 
 	unsigned long *lun_bitmap;	/* Bitmap for LUNs mapped in line */
 
+	struct pblk_chunk *chks;	/* Chunks forming line */
+
 	struct pblk_smeta *smeta;	/* Start metadata */
 	struct pblk_emeta *emeta;	/* End medatada */
 
@@ -513,6 +527,8 @@ struct pblk_line_mgmt {
 	unsigned long d_seq_nr;		/* Data line unique sequence number */
 	unsigned long l_seq_nr;		/* Log line unique sequence number */
 
+	atomic_t sysfs_line_state;	/* Line being monitored in sysfs */
+
 	spinlock_t free_lock;
 	spinlock_t close_lock;
 	spinlock_t gc_lock;
@@ -729,6 +745,10 @@ void pblk_set_sec_per_write(struct pblk *pblk, int sec_per_write);
 int pblk_setup_w_rec_rq(struct pblk *pblk, struct nvm_rq *rqd,
 			struct pblk_c_ctx *c_ctx);
 void pblk_discard(struct pblk *pblk, struct bio *bio);
+struct nvm_chk_meta *pblk_chunk_get_info(struct pblk *pblk);
+struct nvm_chk_meta *pblk_chunk_get_off(struct pblk *pblk,
+					      struct nvm_chk_meta *lp,
+					      struct ppa_addr ppa);
 void pblk_log_write_err(struct pblk *pblk, struct nvm_rq *rqd);
 void pblk_log_read_err(struct pblk *pblk, struct nvm_rq *rqd);
 int pblk_submit_io(struct pblk *pblk, struct nvm_rq *rqd);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 19/20] lightnvm: pblk: refactor init/exit sequences
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

Refactor init and exit sequences to improve readability. In the way, fix
bad free ordering on the init error path.

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/lightnvm/pblk-init.c | 503 ++++++++++++++++++++++---------------------
 1 file changed, 254 insertions(+), 249 deletions(-)

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 1618e923ef5f..c5c304a37554 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -103,7 +103,40 @@ static void pblk_l2p_free(struct pblk *pblk)
 	vfree(pblk->trans_map);
 }
 
-static int pblk_l2p_init(struct pblk *pblk)
+static int pblk_l2p_recover(struct pblk *pblk, bool factory_init)
+{
+	struct pblk_line *line = NULL;
+
+	if (factory_init) {
+		pblk_setup_uuid(pblk);
+	} else {
+		line = pblk_recov_l2p(pblk);
+		if (IS_ERR(line)) {
+			pr_err("pblk: could not recover l2p table\n");
+			return -EFAULT;
+		}
+	}
+
+#ifdef CONFIG_NVM_DEBUG
+	pr_info("pblk init: L2P CRC: %x\n", pblk_l2p_crc(pblk));
+#endif
+
+	/* Free full lines directly as GC has not been started yet */
+	pblk_gc_free_full_lines(pblk);
+
+	if (!line) {
+		/* Configure next line for user data */
+		line = pblk_line_get_first_data(pblk);
+		if (!line) {
+			pr_err("pblk: line list corrupted\n");
+			return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+
+static int pblk_l2p_init(struct pblk *pblk, bool factory_init)
 {
 	sector_t i;
 	struct ppa_addr ppa;
@@ -119,7 +152,7 @@ static int pblk_l2p_init(struct pblk *pblk)
 	for (i = 0; i < pblk->rl.nr_secs; i++)
 		pblk_trans_map_set(pblk, i, ppa);
 
-	return 0;
+	return pblk_l2p_recover(pblk, factory_init);
 }
 
 static void pblk_rwb_free(struct pblk *pblk)
@@ -268,86 +301,113 @@ static int pblk_core_init(struct pblk *pblk)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
+	int max_write_ppas;
+
+	atomic64_set(&pblk->user_wa, 0);
+	atomic64_set(&pblk->pad_wa, 0);
+	atomic64_set(&pblk->gc_wa, 0);
+	pblk->user_rst_wa = 0;
+	pblk->pad_rst_wa = 0;
+	pblk->gc_rst_wa = 0;
+
+	atomic_long_set(&pblk->nr_flush, 0);
+	pblk->nr_flush_rst = 0;
 
 	pblk->pgs_in_buffer = geo->c.mw_cunits * geo->c.ws_opt * geo->all_luns;
 
+	pblk->min_write_pgs = geo->c.ws_opt * (geo->c.csecs / PAGE_SIZE);
+	max_write_ppas = pblk->min_write_pgs * geo->all_luns;
+	pblk->max_write_pgs = (max_write_ppas < NVM_MAX_VLBA) ?
+				max_write_ppas : NVM_MAX_VLBA;
+	pblk_set_sec_per_write(pblk, pblk->min_write_pgs);
+
+	if (pblk->max_write_pgs > PBLK_MAX_REQ_ADDRS) {
+		pr_err("pblk: cannot support device max_phys_sect\n");
+		return -EINVAL;
+	}
+
+	pblk->pad_dist = kzalloc((pblk->min_write_pgs - 1) * sizeof(atomic64_t),
+								GFP_KERNEL);
+	if (!pblk->pad_dist)
+		return -ENOMEM;
+
 	if (pblk_init_global_caches(pblk))
-		return -ENOMEM;
+		goto fail_free_pad_dist;
 
 	/* Internal bios can be at most the sectors signaled by the device. */
 	pblk->page_bio_pool = mempool_create_page_pool(NVM_MAX_VLBA, 0);
 	if (!pblk->page_bio_pool)
-		goto free_global_caches;
+		goto fail_free_global_caches;
 
 	pblk->gen_ws_pool = mempool_create_slab_pool(PBLK_GEN_WS_POOL_SIZE,
 							pblk_ws_cache);
 	if (!pblk->gen_ws_pool)
-		goto free_page_bio_pool;
+		goto fail_free_page_bio_pool;
 
 	pblk->rec_pool = mempool_create_slab_pool(geo->all_luns,
 							pblk_rec_cache);
 	if (!pblk->rec_pool)
-		goto free_gen_ws_pool;
+		goto fail_free_gen_ws_pool;
 
 	pblk->r_rq_pool = mempool_create_slab_pool(geo->all_luns,
 							pblk_g_rq_cache);
 	if (!pblk->r_rq_pool)
-		goto free_rec_pool;
+		goto fail_free_rec_pool;
 
 	pblk->e_rq_pool = mempool_create_slab_pool(geo->all_luns,
 							pblk_g_rq_cache);
 	if (!pblk->e_rq_pool)
-		goto free_r_rq_pool;
+		goto fail_free_r_rq_pool;
 
 	pblk->w_rq_pool = mempool_create_slab_pool(geo->all_luns,
 							pblk_w_rq_cache);
 	if (!pblk->w_rq_pool)
-		goto free_e_rq_pool;
+		goto fail_free_e_rq_pool;
 
 	pblk->close_wq = alloc_workqueue("pblk-close-wq",
 			WQ_MEM_RECLAIM | WQ_UNBOUND, PBLK_NR_CLOSE_JOBS);
 	if (!pblk->close_wq)
-		goto free_w_rq_pool;
+		goto fail_free_w_rq_pool;
 
 	pblk->bb_wq = alloc_workqueue("pblk-bb-wq",
 			WQ_MEM_RECLAIM | WQ_UNBOUND, 0);
 	if (!pblk->bb_wq)
-		goto free_close_wq;
+		goto fail_free_close_wq;
 
 	pblk->r_end_wq = alloc_workqueue("pblk-read-end-wq",
 			WQ_MEM_RECLAIM | WQ_UNBOUND, 0);
 	if (!pblk->r_end_wq)
-		goto free_bb_wq;
+		goto fail_free_bb_wq;
 
 	if (pblk_set_addrf(pblk))
-		goto free_r_end_wq;
-
-	if (pblk_rwb_init(pblk))
-		goto free_r_end_wq;
+		goto fail_free_r_end_wq;
 
 	INIT_LIST_HEAD(&pblk->compl_list);
+
 	return 0;
 
-free_r_end_wq:
+fail_free_r_end_wq:
 	destroy_workqueue(pblk->r_end_wq);
-free_bb_wq:
+fail_free_bb_wq:
 	destroy_workqueue(pblk->bb_wq);
-free_close_wq:
+fail_free_close_wq:
 	destroy_workqueue(pblk->close_wq);
-free_w_rq_pool:
+fail_free_w_rq_pool:
 	mempool_destroy(pblk->w_rq_pool);
-free_e_rq_pool:
+fail_free_e_rq_pool:
 	mempool_destroy(pblk->e_rq_pool);
-free_r_rq_pool:
+fail_free_r_rq_pool:
 	mempool_destroy(pblk->r_rq_pool);
-free_rec_pool:
+fail_free_rec_pool:
 	mempool_destroy(pblk->rec_pool);
-free_gen_ws_pool:
+fail_free_gen_ws_pool:
 	mempool_destroy(pblk->gen_ws_pool);
-free_page_bio_pool:
+fail_free_page_bio_pool:
 	mempool_destroy(pblk->page_bio_pool);
-free_global_caches:
+fail_free_global_caches:
 	pblk_free_global_caches(pblk);
+fail_free_pad_dist:
+	kfree(pblk->pad_dist);
 	return -ENOMEM;
 }
 
@@ -369,9 +429,8 @@ static void pblk_core_free(struct pblk *pblk)
 	mempool_destroy(pblk->e_rq_pool);
 	mempool_destroy(pblk->w_rq_pool);
 
-	pblk_rwb_free(pblk);
-
 	pblk_free_global_caches(pblk);
+	kfree(pblk->pad_dist);
 }
 
 static void pblk_luns_free(struct pblk *pblk)
@@ -393,8 +452,6 @@ static void pblk_line_mg_free(struct pblk *pblk)
 		pblk_mfree(l_mg->eline_meta[i]->buf, l_mg->emeta_alloc_type);
 		kfree(l_mg->eline_meta[i]);
 	}
-
-	kfree(pblk->lines);
 }
 
 static void pblk_line_meta_free(struct pblk_line *line)
@@ -418,6 +475,10 @@ static void pblk_lines_free(struct pblk *pblk)
 		pblk_line_meta_free(line);
 	}
 	spin_unlock(&l_mg->free_lock);
+
+	pblk_line_mg_free(pblk);
+
+	kfree(pblk->lines);
 }
 
 static int pblk_bb_get_tbl(struct nvm_tgt_dev *dev, struct pblk_lun *rlun,
@@ -515,38 +576,6 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
 	return 0;
 }
 
-static int pblk_lines_configure(struct pblk *pblk, int flags)
-{
-	struct pblk_line *line = NULL;
-	int ret = 0;
-
-	if (!(flags & NVM_TARGET_FACTORY)) {
-		line = pblk_recov_l2p(pblk);
-		if (IS_ERR(line)) {
-			pr_err("pblk: could not recover l2p table\n");
-			ret = -EFAULT;
-		}
-	}
-
-#ifdef CONFIG_NVM_DEBUG
-	pr_info("pblk init: L2P CRC: %x\n", pblk_l2p_crc(pblk));
-#endif
-
-	/* Free full lines directly as GC has not been started yet */
-	pblk_gc_free_full_lines(pblk);
-
-	if (!line) {
-		/* Configure next line for user data */
-		line = pblk_line_get_first_data(pblk);
-		if (!line) {
-			pr_err("pblk: line list corrupted\n");
-			ret = -EFAULT;
-		}
-	}
-
-	return ret;
-}
-
 /* See comment over struct line_emeta definition */
 static unsigned int calc_emeta_len(struct pblk *pblk)
 {
@@ -612,81 +641,6 @@ static void pblk_set_provision(struct pblk *pblk, long nr_free_blks)
 	atomic_set(&pblk->rl.free_user_blocks, nr_free_blks);
 }
 
-static int pblk_lines_alloc_metadata(struct pblk *pblk)
-{
-	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
-	struct pblk_line_meta *lm = &pblk->lm;
-	int i;
-
-	/* smeta is always small enough to fit on a kmalloc memory allocation,
-	 * emeta depends on the number of LUNs allocated to the pblk instance
-	 */
-	for (i = 0; i < PBLK_DATA_LINES; i++) {
-		l_mg->sline_meta[i] = kmalloc(lm->smeta_len, GFP_KERNEL);
-		if (!l_mg->sline_meta[i])
-			goto fail_free_smeta;
-	}
-
-	/* emeta allocates three different buffers for managing metadata with
-	 * in-memory and in-media layouts
-	 */
-	for (i = 0; i < PBLK_DATA_LINES; i++) {
-		struct pblk_emeta *emeta;
-
-		emeta = kmalloc(sizeof(struct pblk_emeta), GFP_KERNEL);
-		if (!emeta)
-			goto fail_free_emeta;
-
-		if (lm->emeta_len[0] > KMALLOC_MAX_CACHE_SIZE) {
-			l_mg->emeta_alloc_type = PBLK_VMALLOC_META;
-
-			emeta->buf = vmalloc(lm->emeta_len[0]);
-			if (!emeta->buf) {
-				kfree(emeta);
-				goto fail_free_emeta;
-			}
-
-			emeta->nr_entries = lm->emeta_sec[0];
-			l_mg->eline_meta[i] = emeta;
-		} else {
-			l_mg->emeta_alloc_type = PBLK_KMALLOC_META;
-
-			emeta->buf = kmalloc(lm->emeta_len[0], GFP_KERNEL);
-			if (!emeta->buf) {
-				kfree(emeta);
-				goto fail_free_emeta;
-			}
-
-			emeta->nr_entries = lm->emeta_sec[0];
-			l_mg->eline_meta[i] = emeta;
-		}
-	}
-
-	l_mg->vsc_list = kcalloc(l_mg->nr_lines, sizeof(__le32), GFP_KERNEL);
-	if (!l_mg->vsc_list)
-		goto fail_free_emeta;
-
-	for (i = 0; i < l_mg->nr_lines; i++)
-		l_mg->vsc_list[i] = cpu_to_le32(EMPTY_ENTRY);
-
-	return 0;
-
-fail_free_emeta:
-	while (--i >= 0) {
-		if (l_mg->emeta_alloc_type == PBLK_VMALLOC_META)
-			vfree(l_mg->eline_meta[i]->buf);
-		else
-			kfree(l_mg->eline_meta[i]->buf);
-		kfree(l_mg->eline_meta[i]);
-	}
-
-fail_free_smeta:
-	for (i = 0; i < PBLK_DATA_LINES; i++)
-		kfree(l_mg->sline_meta[i]);
-
-	return -ENOMEM;
-}
-
 static int pblk_setup_line_meta_12(struct pblk *pblk, struct pblk_line *line,
 				   void *chunk_log)
 {
@@ -830,29 +784,13 @@ static int pblk_alloc_line_meta(struct pblk *pblk, struct pblk_line *line)
 	return 0;
 }
 
-static int pblk_lines_init(struct pblk *pblk)
+static int pblk_line_mg_init(struct pblk *pblk)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
 	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
 	struct pblk_line_meta *lm = &pblk->lm;
-	struct pblk_line *line;
-	void *chunk_log;
-	unsigned int smeta_len, emeta_len;
-	long nr_free_chks = 0;
-	int bb_distance, max_write_ppas;
-	int i, ret;
-
-	pblk->min_write_pgs = geo->c.ws_opt * (geo->c.csecs / PAGE_SIZE);
-	max_write_ppas = pblk->min_write_pgs * geo->all_luns;
-	pblk->max_write_pgs = min_t(int, max_write_ppas, NVM_MAX_VLBA);
-	pblk_set_sec_per_write(pblk, pblk->min_write_pgs);
-
-	if (pblk->max_write_pgs > PBLK_MAX_REQ_ADDRS) {
-		pr_err("pblk: vector list too big(%u > %u)\n",
-				pblk->max_write_pgs, PBLK_MAX_REQ_ADDRS);
-		return -EINVAL;
-	}
+	int i, bb_distance;
 
 	l_mg->nr_lines = geo->c.num_chk;
 	l_mg->log_line = l_mg->data_line = NULL;
@@ -861,6 +799,119 @@ static int pblk_lines_init(struct pblk *pblk)
 	atomic_set(&l_mg->sysfs_line_state, -1);
 	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
 
+	INIT_LIST_HEAD(&l_mg->free_list);
+	INIT_LIST_HEAD(&l_mg->corrupt_list);
+	INIT_LIST_HEAD(&l_mg->bad_list);
+	INIT_LIST_HEAD(&l_mg->gc_full_list);
+	INIT_LIST_HEAD(&l_mg->gc_high_list);
+	INIT_LIST_HEAD(&l_mg->gc_mid_list);
+	INIT_LIST_HEAD(&l_mg->gc_low_list);
+	INIT_LIST_HEAD(&l_mg->gc_empty_list);
+
+	INIT_LIST_HEAD(&l_mg->emeta_list);
+
+	l_mg->gc_lists[0] = &l_mg->gc_high_list;
+	l_mg->gc_lists[1] = &l_mg->gc_mid_list;
+	l_mg->gc_lists[2] = &l_mg->gc_low_list;
+
+	spin_lock_init(&l_mg->free_lock);
+	spin_lock_init(&l_mg->close_lock);
+	spin_lock_init(&l_mg->gc_lock);
+
+	l_mg->vsc_list = kcalloc(l_mg->nr_lines, sizeof(__le32), GFP_KERNEL);
+	if (!l_mg->vsc_list)
+		goto fail;
+
+	l_mg->bb_template = kzalloc(lm->sec_bitmap_len, GFP_KERNEL);
+	if (!l_mg->bb_template)
+		goto fail_free_vsc_list;
+
+	l_mg->bb_aux = kzalloc(lm->sec_bitmap_len, GFP_KERNEL);
+	if (!l_mg->bb_aux)
+		goto fail_free_bb_template;
+
+	/* smeta is always small enough to fit on a kmalloc memory allocation,
+	 * emeta depends on the number of LUNs allocated to the pblk instance
+	 */
+	for (i = 0; i < PBLK_DATA_LINES; i++) {
+		l_mg->sline_meta[i] = kmalloc(lm->smeta_len, GFP_KERNEL);
+		if (!l_mg->sline_meta[i])
+			goto fail_free_smeta;
+	}
+
+	/* emeta allocates three different buffers for managing metadata with
+	 * in-memory and in-media layouts
+	 */
+	for (i = 0; i < PBLK_DATA_LINES; i++) {
+		struct pblk_emeta *emeta;
+
+		emeta = kmalloc(sizeof(struct pblk_emeta), GFP_KERNEL);
+		if (!emeta)
+			goto fail_free_emeta;
+
+		if (lm->emeta_len[0] > KMALLOC_MAX_CACHE_SIZE) {
+			l_mg->emeta_alloc_type = PBLK_VMALLOC_META;
+
+			emeta->buf = vmalloc(lm->emeta_len[0]);
+			if (!emeta->buf) {
+				kfree(emeta);
+				goto fail_free_emeta;
+			}
+
+			emeta->nr_entries = lm->emeta_sec[0];
+			l_mg->eline_meta[i] = emeta;
+		} else {
+			l_mg->emeta_alloc_type = PBLK_KMALLOC_META;
+
+			emeta->buf = kmalloc(lm->emeta_len[0], GFP_KERNEL);
+			if (!emeta->buf) {
+				kfree(emeta);
+				goto fail_free_emeta;
+			}
+
+			emeta->nr_entries = lm->emeta_sec[0];
+			l_mg->eline_meta[i] = emeta;
+		}
+	}
+
+	for (i = 0; i < l_mg->nr_lines; i++)
+		l_mg->vsc_list[i] = cpu_to_le32(EMPTY_ENTRY);
+
+	bb_distance = (geo->all_luns) * geo->c.ws_opt;
+	for (i = 0; i < lm->sec_per_line; i += bb_distance)
+		bitmap_set(l_mg->bb_template, i, geo->c.ws_opt);
+
+	return 0;
+
+fail_free_emeta:
+	while (--i >= 0) {
+		if (l_mg->emeta_alloc_type == PBLK_VMALLOC_META)
+			vfree(l_mg->eline_meta[i]->buf);
+		else
+			kfree(l_mg->eline_meta[i]->buf);
+		kfree(l_mg->eline_meta[i]);
+	}
+fail_free_smeta:
+	kfree(l_mg->bb_aux);
+
+	for (i = 0; i < PBLK_DATA_LINES; i++)
+		kfree(l_mg->sline_meta[i]);
+fail_free_bb_template:
+	kfree(l_mg->bb_template);
+fail_free_vsc_list:
+	kfree(l_mg->vsc_list);
+fail:
+	return -ENOMEM;
+}
+
+static int pblk_line_meta_init(struct pblk *pblk)
+{
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	struct pblk_line_meta *lm = &pblk->lm;
+	unsigned int smeta_len, emeta_len;
+	int i;
+
 	lm->sec_per_line = geo->c.clba * geo->all_luns;
 	lm->blk_per_line = geo->all_luns;
 	lm->blk_bitmap_len = BITS_TO_LONGS(geo->all_luns) * sizeof(long);
@@ -911,58 +962,38 @@ static int pblk_lines_init(struct pblk *pblk)
 		return -EINVAL;
 	}
 
-	ret = pblk_lines_alloc_metadata(pblk);
+	return 0;
+}
+
+static int pblk_lines_init(struct pblk *pblk)
+{
+	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
+	struct pblk_line *line;
+	void *chunk_log;
+	long nr_free_chks = 0;
+	int i, ret;
+
+	ret = pblk_line_meta_init(pblk);
 	if (ret)
 		return ret;
 
-	l_mg->bb_template = kzalloc(lm->sec_bitmap_len, GFP_KERNEL);
-	if (!l_mg->bb_template) {
-		ret = -ENOMEM;
-		goto fail_free_meta;
-	}
-
-	l_mg->bb_aux = kzalloc(lm->sec_bitmap_len, GFP_KERNEL);
-	if (!l_mg->bb_aux) {
-		ret = -ENOMEM;
-		goto fail_free_bb_template;
-	}
-
-	bb_distance = (geo->all_luns) * geo->c.ws_opt;
-	for (i = 0; i < lm->sec_per_line; i += bb_distance)
-		bitmap_set(l_mg->bb_template, i, geo->c.ws_opt);
-
-	INIT_LIST_HEAD(&l_mg->free_list);
-	INIT_LIST_HEAD(&l_mg->corrupt_list);
-	INIT_LIST_HEAD(&l_mg->bad_list);
-	INIT_LIST_HEAD(&l_mg->gc_full_list);
-	INIT_LIST_HEAD(&l_mg->gc_high_list);
-	INIT_LIST_HEAD(&l_mg->gc_mid_list);
-	INIT_LIST_HEAD(&l_mg->gc_low_list);
-	INIT_LIST_HEAD(&l_mg->gc_empty_list);
-
-	INIT_LIST_HEAD(&l_mg->emeta_list);
-
-	l_mg->gc_lists[0] = &l_mg->gc_high_list;
-	l_mg->gc_lists[1] = &l_mg->gc_mid_list;
-	l_mg->gc_lists[2] = &l_mg->gc_low_list;
-
-	spin_lock_init(&l_mg->free_lock);
-	spin_lock_init(&l_mg->close_lock);
-	spin_lock_init(&l_mg->gc_lock);
-
-	pblk->lines = kcalloc(l_mg->nr_lines, sizeof(struct pblk_line),
-								GFP_KERNEL);
-	if (!pblk->lines) {
-		ret = -ENOMEM;
-		goto fail_free_bb_aux;
-	}
+	ret = pblk_line_mg_init(pblk);
+	if (ret)
+		return ret;
 
 	chunk_log = pblk_chunk_get_log(pblk);
 	if (IS_ERR(chunk_log)) {
 		pr_err("pblk: could not get chunk log (%lu)\n",
 							PTR_ERR(chunk_log));
 		ret = PTR_ERR(chunk_log);
-		goto fail_free_lines;
+		goto fail_free_meta;
+	}
+
+	pblk->lines = kcalloc(l_mg->nr_lines, sizeof(struct pblk_line),
+								GFP_KERNEL);
+	if (!pblk->lines) {
+		ret = -ENOMEM;
+		goto fail_free_chunk_log;
 	}
 
 	for (i = 0; i < l_mg->nr_lines; i++) {
@@ -970,7 +1001,7 @@ static int pblk_lines_init(struct pblk *pblk)
 
 		ret = pblk_alloc_line_meta(pblk, line);
 		if (ret)
-			goto fail_free_chunk_log;
+			goto fail_free_lines;
 
 		nr_free_chks += pblk_setup_line_meta(pblk, line, chunk_log, i);
 	}
@@ -980,16 +1011,12 @@ static int pblk_lines_init(struct pblk *pblk)
 	kfree(chunk_log);
 	return 0;
 
-fail_free_chunk_log:
-	kfree(chunk_log);
+fail_free_lines:
 	while (--i >= 0)
 		pblk_line_meta_free(&pblk->lines[i]);
-fail_free_lines:
 	kfree(pblk->lines);
-fail_free_bb_aux:
-	kfree(l_mg->bb_aux);
-fail_free_bb_template:
-	kfree(l_mg->bb_template);
+fail_free_chunk_log:
+	kfree(chunk_log);
 fail_free_meta:
 	pblk_line_mg_free(pblk);
 
@@ -1032,12 +1059,11 @@ static void pblk_writer_stop(struct pblk *pblk)
 
 static void pblk_free(struct pblk *pblk)
 {
-	pblk_luns_free(pblk);
 	pblk_lines_free(pblk);
-	kfree(pblk->pad_dist);
-	pblk_line_mg_free(pblk);
-	pblk_core_free(pblk);
 	pblk_l2p_free(pblk);
+	pblk_rwb_free(pblk);
+	pblk_core_free(pblk);
+	pblk_luns_free(pblk);
 
 	kfree(pblk);
 }
@@ -1108,19 +1134,6 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 	spin_lock_init(&pblk->trans_lock);
 	spin_lock_init(&pblk->lock);
 
-	if (flags & NVM_TARGET_FACTORY)
-		pblk_setup_uuid(pblk);
-
-	atomic64_set(&pblk->user_wa, 0);
-	atomic64_set(&pblk->pad_wa, 0);
-	atomic64_set(&pblk->gc_wa, 0);
-	pblk->user_rst_wa = 0;
-	pblk->pad_rst_wa = 0;
-	pblk->gc_rst_wa = 0;
-
-	atomic_long_set(&pblk->nr_flush, 0);
-	pblk->nr_flush_rst = 0;
-
 #ifdef CONFIG_NVM_DEBUG
 	atomic_long_set(&pblk->inflight_writes, 0);
 	atomic_long_set(&pblk->padded_writes, 0);
@@ -1144,48 +1157,42 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 	atomic_long_set(&pblk->write_failed, 0);
 	atomic_long_set(&pblk->erase_failed, 0);
 
+
 	ret = pblk_luns_init(pblk, dev->luns);
 	if (ret) {
 		pr_err("pblk: could not initialize luns\n");
 		goto fail;
 	}
 
-	ret = pblk_lines_init(pblk);
-	if (ret) {
-		pr_err("pblk: could not initialize lines\n");
-		goto fail_free_luns;
-	}
-
-	pblk->pad_dist = kzalloc((pblk->min_write_pgs - 1) * sizeof(atomic64_t),
-				 GFP_KERNEL);
-	if (!pblk->pad_dist) {
-		ret = -ENOMEM;
-		goto fail_free_line_meta;
-	}
-
 	ret = pblk_core_init(pblk);
 	if (ret) {
 		pr_err("pblk: could not initialize core\n");
-		goto fail_free_pad_dist;
+		goto fail_free_luns;
 	}
 
-	ret = pblk_l2p_init(pblk);
+	ret = pblk_lines_init(pblk);
 	if (ret) {
-		pr_err("pblk: could not initialize maps\n");
+		pr_err("pblk: could not initialize lines\n");
 		goto fail_free_core;
 	}
 
-	ret = pblk_lines_configure(pblk, flags);
+	ret = pblk_rwb_init(pblk);
 	if (ret) {
-		pr_err("pblk: could not configure lines\n");
-		goto fail_free_l2p;
+		pr_err("pblk: could not initialize write buffer\n");
+		goto fail_free_lines;
+	}
+
+	ret = pblk_l2p_init(pblk, flags & NVM_TARGET_FACTORY);
+	if (ret) {
+		pr_err("pblk: could not initialize maps\n");
+		goto fail_free_rwb;
 	}
 
 	ret = pblk_writer_init(pblk);
 	if (ret) {
 		if (ret != -EINTR)
 			pr_err("pblk: could not initialize write thread\n");
-		goto fail_free_lines;
+		goto fail_free_l2p;
 	}
 
 	ret = pblk_gc_init(pblk);
@@ -1220,16 +1227,14 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 
 fail_stop_writer:
 	pblk_writer_stop(pblk);
-fail_free_lines:
-	pblk_lines_free(pblk);
 fail_free_l2p:
 	pblk_l2p_free(pblk);
+fail_free_rwb:
+	pblk_rwb_free(pblk);
+fail_free_lines:
+	pblk_lines_free(pblk);
 fail_free_core:
 	pblk_core_free(pblk);
-fail_free_pad_dist:
-	kfree(pblk->pad_dist);
-fail_free_line_meta:
-	pblk_line_mg_free(pblk);
 fail_free_luns:
 	pblk_luns_free(pblk);
 fail:
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 19/20] lightnvm: pblk: refactor init/exit sequences
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


Refactor init and exit sequences to improve readability. In the way, fix
bad free ordering on the init error path.

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/lightnvm/pblk-init.c | 503 ++++++++++++++++++++++---------------------
 1 file changed, 254 insertions(+), 249 deletions(-)

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 1618e923ef5f..c5c304a37554 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -103,7 +103,40 @@ static void pblk_l2p_free(struct pblk *pblk)
 	vfree(pblk->trans_map);
 }
 
-static int pblk_l2p_init(struct pblk *pblk)
+static int pblk_l2p_recover(struct pblk *pblk, bool factory_init)
+{
+	struct pblk_line *line = NULL;
+
+	if (factory_init) {
+		pblk_setup_uuid(pblk);
+	} else {
+		line = pblk_recov_l2p(pblk);
+		if (IS_ERR(line)) {
+			pr_err("pblk: could not recover l2p table\n");
+			return -EFAULT;
+		}
+	}
+
+#ifdef CONFIG_NVM_DEBUG
+	pr_info("pblk init: L2P CRC: %x\n", pblk_l2p_crc(pblk));
+#endif
+
+	/* Free full lines directly as GC has not been started yet */
+	pblk_gc_free_full_lines(pblk);
+
+	if (!line) {
+		/* Configure next line for user data */
+		line = pblk_line_get_first_data(pblk);
+		if (!line) {
+			pr_err("pblk: line list corrupted\n");
+			return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+
+static int pblk_l2p_init(struct pblk *pblk, bool factory_init)
 {
 	sector_t i;
 	struct ppa_addr ppa;
@@ -119,7 +152,7 @@ static int pblk_l2p_init(struct pblk *pblk)
 	for (i = 0; i < pblk->rl.nr_secs; i++)
 		pblk_trans_map_set(pblk, i, ppa);
 
-	return 0;
+	return pblk_l2p_recover(pblk, factory_init);
 }
 
 static void pblk_rwb_free(struct pblk *pblk)
@@ -268,86 +301,113 @@ static int pblk_core_init(struct pblk *pblk)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
+	int max_write_ppas;
+
+	atomic64_set(&pblk->user_wa, 0);
+	atomic64_set(&pblk->pad_wa, 0);
+	atomic64_set(&pblk->gc_wa, 0);
+	pblk->user_rst_wa = 0;
+	pblk->pad_rst_wa = 0;
+	pblk->gc_rst_wa = 0;
+
+	atomic_long_set(&pblk->nr_flush, 0);
+	pblk->nr_flush_rst = 0;
 
 	pblk->pgs_in_buffer = geo->c.mw_cunits * geo->c.ws_opt * geo->all_luns;
 
+	pblk->min_write_pgs = geo->c.ws_opt * (geo->c.csecs / PAGE_SIZE);
+	max_write_ppas = pblk->min_write_pgs * geo->all_luns;
+	pblk->max_write_pgs = (max_write_ppas < NVM_MAX_VLBA) ?
+				max_write_ppas : NVM_MAX_VLBA;
+	pblk_set_sec_per_write(pblk, pblk->min_write_pgs);
+
+	if (pblk->max_write_pgs > PBLK_MAX_REQ_ADDRS) {
+		pr_err("pblk: cannot support device max_phys_sect\n");
+		return -EINVAL;
+	}
+
+	pblk->pad_dist = kzalloc((pblk->min_write_pgs - 1) * sizeof(atomic64_t),
+								GFP_KERNEL);
+	if (!pblk->pad_dist)
+		return -ENOMEM;
+
 	if (pblk_init_global_caches(pblk))
-		return -ENOMEM;
+		goto fail_free_pad_dist;
 
 	/* Internal bios can be at most the sectors signaled by the device. */
 	pblk->page_bio_pool = mempool_create_page_pool(NVM_MAX_VLBA, 0);
 	if (!pblk->page_bio_pool)
-		goto free_global_caches;
+		goto fail_free_global_caches;
 
 	pblk->gen_ws_pool = mempool_create_slab_pool(PBLK_GEN_WS_POOL_SIZE,
 							pblk_ws_cache);
 	if (!pblk->gen_ws_pool)
-		goto free_page_bio_pool;
+		goto fail_free_page_bio_pool;
 
 	pblk->rec_pool = mempool_create_slab_pool(geo->all_luns,
 							pblk_rec_cache);
 	if (!pblk->rec_pool)
-		goto free_gen_ws_pool;
+		goto fail_free_gen_ws_pool;
 
 	pblk->r_rq_pool = mempool_create_slab_pool(geo->all_luns,
 							pblk_g_rq_cache);
 	if (!pblk->r_rq_pool)
-		goto free_rec_pool;
+		goto fail_free_rec_pool;
 
 	pblk->e_rq_pool = mempool_create_slab_pool(geo->all_luns,
 							pblk_g_rq_cache);
 	if (!pblk->e_rq_pool)
-		goto free_r_rq_pool;
+		goto fail_free_r_rq_pool;
 
 	pblk->w_rq_pool = mempool_create_slab_pool(geo->all_luns,
 							pblk_w_rq_cache);
 	if (!pblk->w_rq_pool)
-		goto free_e_rq_pool;
+		goto fail_free_e_rq_pool;
 
 	pblk->close_wq = alloc_workqueue("pblk-close-wq",
 			WQ_MEM_RECLAIM | WQ_UNBOUND, PBLK_NR_CLOSE_JOBS);
 	if (!pblk->close_wq)
-		goto free_w_rq_pool;
+		goto fail_free_w_rq_pool;
 
 	pblk->bb_wq = alloc_workqueue("pblk-bb-wq",
 			WQ_MEM_RECLAIM | WQ_UNBOUND, 0);
 	if (!pblk->bb_wq)
-		goto free_close_wq;
+		goto fail_free_close_wq;
 
 	pblk->r_end_wq = alloc_workqueue("pblk-read-end-wq",
 			WQ_MEM_RECLAIM | WQ_UNBOUND, 0);
 	if (!pblk->r_end_wq)
-		goto free_bb_wq;
+		goto fail_free_bb_wq;
 
 	if (pblk_set_addrf(pblk))
-		goto free_r_end_wq;
-
-	if (pblk_rwb_init(pblk))
-		goto free_r_end_wq;
+		goto fail_free_r_end_wq;
 
 	INIT_LIST_HEAD(&pblk->compl_list);
+
 	return 0;
 
-free_r_end_wq:
+fail_free_r_end_wq:
 	destroy_workqueue(pblk->r_end_wq);
-free_bb_wq:
+fail_free_bb_wq:
 	destroy_workqueue(pblk->bb_wq);
-free_close_wq:
+fail_free_close_wq:
 	destroy_workqueue(pblk->close_wq);
-free_w_rq_pool:
+fail_free_w_rq_pool:
 	mempool_destroy(pblk->w_rq_pool);
-free_e_rq_pool:
+fail_free_e_rq_pool:
 	mempool_destroy(pblk->e_rq_pool);
-free_r_rq_pool:
+fail_free_r_rq_pool:
 	mempool_destroy(pblk->r_rq_pool);
-free_rec_pool:
+fail_free_rec_pool:
 	mempool_destroy(pblk->rec_pool);
-free_gen_ws_pool:
+fail_free_gen_ws_pool:
 	mempool_destroy(pblk->gen_ws_pool);
-free_page_bio_pool:
+fail_free_page_bio_pool:
 	mempool_destroy(pblk->page_bio_pool);
-free_global_caches:
+fail_free_global_caches:
 	pblk_free_global_caches(pblk);
+fail_free_pad_dist:
+	kfree(pblk->pad_dist);
 	return -ENOMEM;
 }
 
@@ -369,9 +429,8 @@ static void pblk_core_free(struct pblk *pblk)
 	mempool_destroy(pblk->e_rq_pool);
 	mempool_destroy(pblk->w_rq_pool);
 
-	pblk_rwb_free(pblk);
-
 	pblk_free_global_caches(pblk);
+	kfree(pblk->pad_dist);
 }
 
 static void pblk_luns_free(struct pblk *pblk)
@@ -393,8 +452,6 @@ static void pblk_line_mg_free(struct pblk *pblk)
 		pblk_mfree(l_mg->eline_meta[i]->buf, l_mg->emeta_alloc_type);
 		kfree(l_mg->eline_meta[i]);
 	}
-
-	kfree(pblk->lines);
 }
 
 static void pblk_line_meta_free(struct pblk_line *line)
@@ -418,6 +475,10 @@ static void pblk_lines_free(struct pblk *pblk)
 		pblk_line_meta_free(line);
 	}
 	spin_unlock(&l_mg->free_lock);
+
+	pblk_line_mg_free(pblk);
+
+	kfree(pblk->lines);
 }
 
 static int pblk_bb_get_tbl(struct nvm_tgt_dev *dev, struct pblk_lun *rlun,
@@ -515,38 +576,6 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
 	return 0;
 }
 
-static int pblk_lines_configure(struct pblk *pblk, int flags)
-{
-	struct pblk_line *line = NULL;
-	int ret = 0;
-
-	if (!(flags & NVM_TARGET_FACTORY)) {
-		line = pblk_recov_l2p(pblk);
-		if (IS_ERR(line)) {
-			pr_err("pblk: could not recover l2p table\n");
-			ret = -EFAULT;
-		}
-	}
-
-#ifdef CONFIG_NVM_DEBUG
-	pr_info("pblk init: L2P CRC: %x\n", pblk_l2p_crc(pblk));
-#endif
-
-	/* Free full lines directly as GC has not been started yet */
-	pblk_gc_free_full_lines(pblk);
-
-	if (!line) {
-		/* Configure next line for user data */
-		line = pblk_line_get_first_data(pblk);
-		if (!line) {
-			pr_err("pblk: line list corrupted\n");
-			ret = -EFAULT;
-		}
-	}
-
-	return ret;
-}
-
 /* See comment over struct line_emeta definition */
 static unsigned int calc_emeta_len(struct pblk *pblk)
 {
@@ -612,81 +641,6 @@ static void pblk_set_provision(struct pblk *pblk, long nr_free_blks)
 	atomic_set(&pblk->rl.free_user_blocks, nr_free_blks);
 }
 
-static int pblk_lines_alloc_metadata(struct pblk *pblk)
-{
-	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
-	struct pblk_line_meta *lm = &pblk->lm;
-	int i;
-
-	/* smeta is always small enough to fit on a kmalloc memory allocation,
-	 * emeta depends on the number of LUNs allocated to the pblk instance
-	 */
-	for (i = 0; i < PBLK_DATA_LINES; i++) {
-		l_mg->sline_meta[i] = kmalloc(lm->smeta_len, GFP_KERNEL);
-		if (!l_mg->sline_meta[i])
-			goto fail_free_smeta;
-	}
-
-	/* emeta allocates three different buffers for managing metadata with
-	 * in-memory and in-media layouts
-	 */
-	for (i = 0; i < PBLK_DATA_LINES; i++) {
-		struct pblk_emeta *emeta;
-
-		emeta = kmalloc(sizeof(struct pblk_emeta), GFP_KERNEL);
-		if (!emeta)
-			goto fail_free_emeta;
-
-		if (lm->emeta_len[0] > KMALLOC_MAX_CACHE_SIZE) {
-			l_mg->emeta_alloc_type = PBLK_VMALLOC_META;
-
-			emeta->buf = vmalloc(lm->emeta_len[0]);
-			if (!emeta->buf) {
-				kfree(emeta);
-				goto fail_free_emeta;
-			}
-
-			emeta->nr_entries = lm->emeta_sec[0];
-			l_mg->eline_meta[i] = emeta;
-		} else {
-			l_mg->emeta_alloc_type = PBLK_KMALLOC_META;
-
-			emeta->buf = kmalloc(lm->emeta_len[0], GFP_KERNEL);
-			if (!emeta->buf) {
-				kfree(emeta);
-				goto fail_free_emeta;
-			}
-
-			emeta->nr_entries = lm->emeta_sec[0];
-			l_mg->eline_meta[i] = emeta;
-		}
-	}
-
-	l_mg->vsc_list = kcalloc(l_mg->nr_lines, sizeof(__le32), GFP_KERNEL);
-	if (!l_mg->vsc_list)
-		goto fail_free_emeta;
-
-	for (i = 0; i < l_mg->nr_lines; i++)
-		l_mg->vsc_list[i] = cpu_to_le32(EMPTY_ENTRY);
-
-	return 0;
-
-fail_free_emeta:
-	while (--i >= 0) {
-		if (l_mg->emeta_alloc_type == PBLK_VMALLOC_META)
-			vfree(l_mg->eline_meta[i]->buf);
-		else
-			kfree(l_mg->eline_meta[i]->buf);
-		kfree(l_mg->eline_meta[i]);
-	}
-
-fail_free_smeta:
-	for (i = 0; i < PBLK_DATA_LINES; i++)
-		kfree(l_mg->sline_meta[i]);
-
-	return -ENOMEM;
-}
-
 static int pblk_setup_line_meta_12(struct pblk *pblk, struct pblk_line *line,
 				   void *chunk_log)
 {
@@ -830,29 +784,13 @@ static int pblk_alloc_line_meta(struct pblk *pblk, struct pblk_line *line)
 	return 0;
 }
 
-static int pblk_lines_init(struct pblk *pblk)
+static int pblk_line_mg_init(struct pblk *pblk)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
 	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
 	struct pblk_line_meta *lm = &pblk->lm;
-	struct pblk_line *line;
-	void *chunk_log;
-	unsigned int smeta_len, emeta_len;
-	long nr_free_chks = 0;
-	int bb_distance, max_write_ppas;
-	int i, ret;
-
-	pblk->min_write_pgs = geo->c.ws_opt * (geo->c.csecs / PAGE_SIZE);
-	max_write_ppas = pblk->min_write_pgs * geo->all_luns;
-	pblk->max_write_pgs = min_t(int, max_write_ppas, NVM_MAX_VLBA);
-	pblk_set_sec_per_write(pblk, pblk->min_write_pgs);
-
-	if (pblk->max_write_pgs > PBLK_MAX_REQ_ADDRS) {
-		pr_err("pblk: vector list too big(%u > %u)\n",
-				pblk->max_write_pgs, PBLK_MAX_REQ_ADDRS);
-		return -EINVAL;
-	}
+	int i, bb_distance;
 
 	l_mg->nr_lines = geo->c.num_chk;
 	l_mg->log_line = l_mg->data_line = NULL;
@@ -861,6 +799,119 @@ static int pblk_lines_init(struct pblk *pblk)
 	atomic_set(&l_mg->sysfs_line_state, -1);
 	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
 
+	INIT_LIST_HEAD(&l_mg->free_list);
+	INIT_LIST_HEAD(&l_mg->corrupt_list);
+	INIT_LIST_HEAD(&l_mg->bad_list);
+	INIT_LIST_HEAD(&l_mg->gc_full_list);
+	INIT_LIST_HEAD(&l_mg->gc_high_list);
+	INIT_LIST_HEAD(&l_mg->gc_mid_list);
+	INIT_LIST_HEAD(&l_mg->gc_low_list);
+	INIT_LIST_HEAD(&l_mg->gc_empty_list);
+
+	INIT_LIST_HEAD(&l_mg->emeta_list);
+
+	l_mg->gc_lists[0] = &l_mg->gc_high_list;
+	l_mg->gc_lists[1] = &l_mg->gc_mid_list;
+	l_mg->gc_lists[2] = &l_mg->gc_low_list;
+
+	spin_lock_init(&l_mg->free_lock);
+	spin_lock_init(&l_mg->close_lock);
+	spin_lock_init(&l_mg->gc_lock);
+
+	l_mg->vsc_list = kcalloc(l_mg->nr_lines, sizeof(__le32), GFP_KERNEL);
+	if (!l_mg->vsc_list)
+		goto fail;
+
+	l_mg->bb_template = kzalloc(lm->sec_bitmap_len, GFP_KERNEL);
+	if (!l_mg->bb_template)
+		goto fail_free_vsc_list;
+
+	l_mg->bb_aux = kzalloc(lm->sec_bitmap_len, GFP_KERNEL);
+	if (!l_mg->bb_aux)
+		goto fail_free_bb_template;
+
+	/* smeta is always small enough to fit on a kmalloc memory allocation,
+	 * emeta depends on the number of LUNs allocated to the pblk instance
+	 */
+	for (i = 0; i < PBLK_DATA_LINES; i++) {
+		l_mg->sline_meta[i] = kmalloc(lm->smeta_len, GFP_KERNEL);
+		if (!l_mg->sline_meta[i])
+			goto fail_free_smeta;
+	}
+
+	/* emeta allocates three different buffers for managing metadata with
+	 * in-memory and in-media layouts
+	 */
+	for (i = 0; i < PBLK_DATA_LINES; i++) {
+		struct pblk_emeta *emeta;
+
+		emeta = kmalloc(sizeof(struct pblk_emeta), GFP_KERNEL);
+		if (!emeta)
+			goto fail_free_emeta;
+
+		if (lm->emeta_len[0] > KMALLOC_MAX_CACHE_SIZE) {
+			l_mg->emeta_alloc_type = PBLK_VMALLOC_META;
+
+			emeta->buf = vmalloc(lm->emeta_len[0]);
+			if (!emeta->buf) {
+				kfree(emeta);
+				goto fail_free_emeta;
+			}
+
+			emeta->nr_entries = lm->emeta_sec[0];
+			l_mg->eline_meta[i] = emeta;
+		} else {
+			l_mg->emeta_alloc_type = PBLK_KMALLOC_META;
+
+			emeta->buf = kmalloc(lm->emeta_len[0], GFP_KERNEL);
+			if (!emeta->buf) {
+				kfree(emeta);
+				goto fail_free_emeta;
+			}
+
+			emeta->nr_entries = lm->emeta_sec[0];
+			l_mg->eline_meta[i] = emeta;
+		}
+	}
+
+	for (i = 0; i < l_mg->nr_lines; i++)
+		l_mg->vsc_list[i] = cpu_to_le32(EMPTY_ENTRY);
+
+	bb_distance = (geo->all_luns) * geo->c.ws_opt;
+	for (i = 0; i < lm->sec_per_line; i += bb_distance)
+		bitmap_set(l_mg->bb_template, i, geo->c.ws_opt);
+
+	return 0;
+
+fail_free_emeta:
+	while (--i >= 0) {
+		if (l_mg->emeta_alloc_type == PBLK_VMALLOC_META)
+			vfree(l_mg->eline_meta[i]->buf);
+		else
+			kfree(l_mg->eline_meta[i]->buf);
+		kfree(l_mg->eline_meta[i]);
+	}
+fail_free_smeta:
+	kfree(l_mg->bb_aux);
+
+	for (i = 0; i < PBLK_DATA_LINES; i++)
+		kfree(l_mg->sline_meta[i]);
+fail_free_bb_template:
+	kfree(l_mg->bb_template);
+fail_free_vsc_list:
+	kfree(l_mg->vsc_list);
+fail:
+	return -ENOMEM;
+}
+
+static int pblk_line_meta_init(struct pblk *pblk)
+{
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	struct pblk_line_meta *lm = &pblk->lm;
+	unsigned int smeta_len, emeta_len;
+	int i;
+
 	lm->sec_per_line = geo->c.clba * geo->all_luns;
 	lm->blk_per_line = geo->all_luns;
 	lm->blk_bitmap_len = BITS_TO_LONGS(geo->all_luns) * sizeof(long);
@@ -911,58 +962,38 @@ static int pblk_lines_init(struct pblk *pblk)
 		return -EINVAL;
 	}
 
-	ret = pblk_lines_alloc_metadata(pblk);
+	return 0;
+}
+
+static int pblk_lines_init(struct pblk *pblk)
+{
+	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
+	struct pblk_line *line;
+	void *chunk_log;
+	long nr_free_chks = 0;
+	int i, ret;
+
+	ret = pblk_line_meta_init(pblk);
 	if (ret)
 		return ret;
 
-	l_mg->bb_template = kzalloc(lm->sec_bitmap_len, GFP_KERNEL);
-	if (!l_mg->bb_template) {
-		ret = -ENOMEM;
-		goto fail_free_meta;
-	}
-
-	l_mg->bb_aux = kzalloc(lm->sec_bitmap_len, GFP_KERNEL);
-	if (!l_mg->bb_aux) {
-		ret = -ENOMEM;
-		goto fail_free_bb_template;
-	}
-
-	bb_distance = (geo->all_luns) * geo->c.ws_opt;
-	for (i = 0; i < lm->sec_per_line; i += bb_distance)
-		bitmap_set(l_mg->bb_template, i, geo->c.ws_opt);
-
-	INIT_LIST_HEAD(&l_mg->free_list);
-	INIT_LIST_HEAD(&l_mg->corrupt_list);
-	INIT_LIST_HEAD(&l_mg->bad_list);
-	INIT_LIST_HEAD(&l_mg->gc_full_list);
-	INIT_LIST_HEAD(&l_mg->gc_high_list);
-	INIT_LIST_HEAD(&l_mg->gc_mid_list);
-	INIT_LIST_HEAD(&l_mg->gc_low_list);
-	INIT_LIST_HEAD(&l_mg->gc_empty_list);
-
-	INIT_LIST_HEAD(&l_mg->emeta_list);
-
-	l_mg->gc_lists[0] = &l_mg->gc_high_list;
-	l_mg->gc_lists[1] = &l_mg->gc_mid_list;
-	l_mg->gc_lists[2] = &l_mg->gc_low_list;
-
-	spin_lock_init(&l_mg->free_lock);
-	spin_lock_init(&l_mg->close_lock);
-	spin_lock_init(&l_mg->gc_lock);
-
-	pblk->lines = kcalloc(l_mg->nr_lines, sizeof(struct pblk_line),
-								GFP_KERNEL);
-	if (!pblk->lines) {
-		ret = -ENOMEM;
-		goto fail_free_bb_aux;
-	}
+	ret = pblk_line_mg_init(pblk);
+	if (ret)
+		return ret;
 
 	chunk_log = pblk_chunk_get_log(pblk);
 	if (IS_ERR(chunk_log)) {
 		pr_err("pblk: could not get chunk log (%lu)\n",
 							PTR_ERR(chunk_log));
 		ret = PTR_ERR(chunk_log);
-		goto fail_free_lines;
+		goto fail_free_meta;
+	}
+
+	pblk->lines = kcalloc(l_mg->nr_lines, sizeof(struct pblk_line),
+								GFP_KERNEL);
+	if (!pblk->lines) {
+		ret = -ENOMEM;
+		goto fail_free_chunk_log;
 	}
 
 	for (i = 0; i < l_mg->nr_lines; i++) {
@@ -970,7 +1001,7 @@ static int pblk_lines_init(struct pblk *pblk)
 
 		ret = pblk_alloc_line_meta(pblk, line);
 		if (ret)
-			goto fail_free_chunk_log;
+			goto fail_free_lines;
 
 		nr_free_chks += pblk_setup_line_meta(pblk, line, chunk_log, i);
 	}
@@ -980,16 +1011,12 @@ static int pblk_lines_init(struct pblk *pblk)
 	kfree(chunk_log);
 	return 0;
 
-fail_free_chunk_log:
-	kfree(chunk_log);
+fail_free_lines:
 	while (--i >= 0)
 		pblk_line_meta_free(&pblk->lines[i]);
-fail_free_lines:
 	kfree(pblk->lines);
-fail_free_bb_aux:
-	kfree(l_mg->bb_aux);
-fail_free_bb_template:
-	kfree(l_mg->bb_template);
+fail_free_chunk_log:
+	kfree(chunk_log);
 fail_free_meta:
 	pblk_line_mg_free(pblk);
 
@@ -1032,12 +1059,11 @@ static void pblk_writer_stop(struct pblk *pblk)
 
 static void pblk_free(struct pblk *pblk)
 {
-	pblk_luns_free(pblk);
 	pblk_lines_free(pblk);
-	kfree(pblk->pad_dist);
-	pblk_line_mg_free(pblk);
-	pblk_core_free(pblk);
 	pblk_l2p_free(pblk);
+	pblk_rwb_free(pblk);
+	pblk_core_free(pblk);
+	pblk_luns_free(pblk);
 
 	kfree(pblk);
 }
@@ -1108,19 +1134,6 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 	spin_lock_init(&pblk->trans_lock);
 	spin_lock_init(&pblk->lock);
 
-	if (flags & NVM_TARGET_FACTORY)
-		pblk_setup_uuid(pblk);
-
-	atomic64_set(&pblk->user_wa, 0);
-	atomic64_set(&pblk->pad_wa, 0);
-	atomic64_set(&pblk->gc_wa, 0);
-	pblk->user_rst_wa = 0;
-	pblk->pad_rst_wa = 0;
-	pblk->gc_rst_wa = 0;
-
-	atomic_long_set(&pblk->nr_flush, 0);
-	pblk->nr_flush_rst = 0;
-
 #ifdef CONFIG_NVM_DEBUG
 	atomic_long_set(&pblk->inflight_writes, 0);
 	atomic_long_set(&pblk->padded_writes, 0);
@@ -1144,48 +1157,42 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 	atomic_long_set(&pblk->write_failed, 0);
 	atomic_long_set(&pblk->erase_failed, 0);
 
+
 	ret = pblk_luns_init(pblk, dev->luns);
 	if (ret) {
 		pr_err("pblk: could not initialize luns\n");
 		goto fail;
 	}
 
-	ret = pblk_lines_init(pblk);
-	if (ret) {
-		pr_err("pblk: could not initialize lines\n");
-		goto fail_free_luns;
-	}
-
-	pblk->pad_dist = kzalloc((pblk->min_write_pgs - 1) * sizeof(atomic64_t),
-				 GFP_KERNEL);
-	if (!pblk->pad_dist) {
-		ret = -ENOMEM;
-		goto fail_free_line_meta;
-	}
-
 	ret = pblk_core_init(pblk);
 	if (ret) {
 		pr_err("pblk: could not initialize core\n");
-		goto fail_free_pad_dist;
+		goto fail_free_luns;
 	}
 
-	ret = pblk_l2p_init(pblk);
+	ret = pblk_lines_init(pblk);
 	if (ret) {
-		pr_err("pblk: could not initialize maps\n");
+		pr_err("pblk: could not initialize lines\n");
 		goto fail_free_core;
 	}
 
-	ret = pblk_lines_configure(pblk, flags);
+	ret = pblk_rwb_init(pblk);
 	if (ret) {
-		pr_err("pblk: could not configure lines\n");
-		goto fail_free_l2p;
+		pr_err("pblk: could not initialize write buffer\n");
+		goto fail_free_lines;
+	}
+
+	ret = pblk_l2p_init(pblk, flags & NVM_TARGET_FACTORY);
+	if (ret) {
+		pr_err("pblk: could not initialize maps\n");
+		goto fail_free_rwb;
 	}
 
 	ret = pblk_writer_init(pblk);
 	if (ret) {
 		if (ret != -EINTR)
 			pr_err("pblk: could not initialize write thread\n");
-		goto fail_free_lines;
+		goto fail_free_l2p;
 	}
 
 	ret = pblk_gc_init(pblk);
@@ -1220,16 +1227,14 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 
 fail_stop_writer:
 	pblk_writer_stop(pblk);
-fail_free_lines:
-	pblk_lines_free(pblk);
 fail_free_l2p:
 	pblk_l2p_free(pblk);
+fail_free_rwb:
+	pblk_rwb_free(pblk);
+fail_free_lines:
+	pblk_lines_free(pblk);
 fail_free_core:
 	pblk_core_free(pblk);
-fail_free_pad_dist:
-	kfree(pblk->pad_dist);
-fail_free_line_meta:
-	pblk_line_mg_free(pblk);
 fail_free_luns:
 	pblk_luns_free(pblk);
 fail:
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 20/20] lightnvm: pblk: implement 2.0 support
  2018-02-21  9:26 ` Javier González
@ 2018-02-21  9:26   ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

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 <javier@cnexlabs.com>
---
 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 c5c304a37554..ce9aa4b3b09a 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->c.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->c.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->c.clba, pblk->min_write_pgs, &mod);
-	if (mod) {
-		pr_err("pblk: bad configuration of sectors/pages\n");
+	switch (geo->c.version) {
+	case NVM_OCSSD_SPEC_12:
+		div_u64_rem(geo->c.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->c.version);
 		return -EINVAL;
 	}
 
-	pblk->addrf_len = pblk_set_addrf_12(geo, (void *)&pblk->addrf);
-
 	return 0;
 }
 
@@ -1110,7 +1153,9 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 	struct pblk *pblk;
 	int ret;
 
-	if (geo->c.version != NVM_OCSSD_SPEC_12) {
+	/* pblk supports 1.2 and 2.0 versions */
+	if (!(geo->c.version == NVM_OCSSD_SPEC_12 ||
+					geo->c.version == NVM_OCSSD_SPEC_20)) {
 		pr_err("pblk: OCSSD version not supported (%u)\n",
 							geo->c.version);
 		return ERR_PTR(-EINVAL);
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index 191af0c6591e..60b8d931e4ba 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->c.addrf;
+	if (geo->c.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->c.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->c.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 c66fa0c28adf..b92a1145ad97 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -574,6 +574,18 @@ enum {
 	PBLK_STATE_STOPPED = 3,
 };
 
+/* Internal format to support not power-of-2 device formats (for now) */
+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;
@@ -586,7 +598,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;
@@ -967,17 +980,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->c.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.ch = chnls;
+
+		sector_div(paddr, uaddrf->ch_stripe);
+		div_u64_rem(paddr, uaddrf->lun_stripe, &luns);
+		ppa.m.lun = luns;
+
+		sector_div(paddr, uaddrf->lun_stripe);
+		ppa.m.sec += uaddrf->sec_stripe * paddr;
+	}
 
 	return ppa;
 }
@@ -985,15 +1024,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->c.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.ch * uaddrf->sec_stripe;
+		paddr += (u64)p.m.lun * 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;
 }
@@ -1010,15 +1066,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->c.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.ch = (ppa32 & lbaf->ch_mask) >>
+							lbaf->ch_offset;
+			ppa64.m.lun = (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;
@@ -1034,15 +1112,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->c.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.ch << lbaf->ch_offset;
+			ppa32 |= ppa64.m.lun << lbaf->lun_offset;
+			ppa32 |= ppa64.m.chk << lbaf->chk_offset;
+			ppa32 |= ppa64.m.sec << lbaf->sec_offset;
+		}
 	}
 
 	return ppa32;
@@ -1160,6 +1250,9 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type)
 	struct nvm_geo *geo = &dev->geo;
 	int flags;
 
+	if (geo->c.version == NVM_OCSSD_SPEC_20)
+		return 0;
+
 	flags = geo->c.pln_mode >> 1;
 
 	if (type == PBLK_WRITE)
@@ -1179,6 +1272,9 @@ static inline int pblk_set_read_mode(struct pblk *pblk, int type)
 	struct nvm_geo *geo = &dev->geo;
 	int flags;
 
+	if (geo->c.version == NVM_OCSSD_SPEC_20)
+		return 0;
+
 	flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
 	if (type == PBLK_READ_SEQUENTIAL)
 		flags |= geo->c.pln_mode >> 1;
@@ -1192,16 +1288,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->c.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.ch, p->m.lun, p->m.chk, p->m.sec);
 	}
 }
 
@@ -1211,13 +1312,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);
@@ -1233,16 +1334,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->c.num_pln &&
-				ppa->g.blk < geo->c.num_chk &&
-				ppa->g.pg < geo->c.num_pg &&
-				ppa->g.sec < geo->c.ws_min)
-			continue;
+		if (geo->c.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->c.num_pln &&
+					ppa->g.blk < geo->c.num_chk &&
+					ppa->g.pg < geo->c.num_pg &&
+					ppa->g.sec < geo->c.ws_min)
+				continue;
+		} else {
+			if (!ppa->c.is_cached &&
+					ppa->m.ch < geo->num_ch &&
+					ppa->m.lun < geo->num_lun &&
+					ppa->m.chk < geo->c.num_chk &&
+					ppa->m.sec < geo->c.clba)
+				continue;
+		}
 
-		print_ppa(ppa, "boundary", i);
+		print_ppa(geo, ppa, "boundary", i);
 
 		return 1;
 	}
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* [PATCH 20/20] lightnvm: pblk: implement 2.0 support
@ 2018-02-21  9:26   ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21  9:26 UTC (permalink / raw)


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 <javier at cnexlabs.com>
---
 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 c5c304a37554..ce9aa4b3b09a 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->c.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->c.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->c.clba, pblk->min_write_pgs, &mod);
-	if (mod) {
-		pr_err("pblk: bad configuration of sectors/pages\n");
+	switch (geo->c.version) {
+	case NVM_OCSSD_SPEC_12:
+		div_u64_rem(geo->c.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->c.version);
 		return -EINVAL;
 	}
 
-	pblk->addrf_len = pblk_set_addrf_12(geo, (void *)&pblk->addrf);
-
 	return 0;
 }
 
@@ -1110,7 +1153,9 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 	struct pblk *pblk;
 	int ret;
 
-	if (geo->c.version != NVM_OCSSD_SPEC_12) {
+	/* pblk supports 1.2 and 2.0 versions */
+	if (!(geo->c.version == NVM_OCSSD_SPEC_12 ||
+					geo->c.version == NVM_OCSSD_SPEC_20)) {
 		pr_err("pblk: OCSSD version not supported (%u)\n",
 							geo->c.version);
 		return ERR_PTR(-EINVAL);
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index 191af0c6591e..60b8d931e4ba 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->c.addrf;
+	if (geo->c.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->c.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->c.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 c66fa0c28adf..b92a1145ad97 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -574,6 +574,18 @@ enum {
 	PBLK_STATE_STOPPED = 3,
 };
 
+/* Internal format to support not power-of-2 device formats (for now) */
+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;
@@ -586,7 +598,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;
@@ -967,17 +980,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->c.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.ch = chnls;
+
+		sector_div(paddr, uaddrf->ch_stripe);
+		div_u64_rem(paddr, uaddrf->lun_stripe, &luns);
+		ppa.m.lun = luns;
+
+		sector_div(paddr, uaddrf->lun_stripe);
+		ppa.m.sec += uaddrf->sec_stripe * paddr;
+	}
 
 	return ppa;
 }
@@ -985,15 +1024,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->c.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.ch * uaddrf->sec_stripe;
+		paddr += (u64)p.m.lun * 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;
 }
@@ -1010,15 +1066,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->c.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.ch = (ppa32 & lbaf->ch_mask) >>
+							lbaf->ch_offset;
+			ppa64.m.lun = (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;
@@ -1034,15 +1112,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->c.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.ch << lbaf->ch_offset;
+			ppa32 |= ppa64.m.lun << lbaf->lun_offset;
+			ppa32 |= ppa64.m.chk << lbaf->chk_offset;
+			ppa32 |= ppa64.m.sec << lbaf->sec_offset;
+		}
 	}
 
 	return ppa32;
@@ -1160,6 +1250,9 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type)
 	struct nvm_geo *geo = &dev->geo;
 	int flags;
 
+	if (geo->c.version == NVM_OCSSD_SPEC_20)
+		return 0;
+
 	flags = geo->c.pln_mode >> 1;
 
 	if (type == PBLK_WRITE)
@@ -1179,6 +1272,9 @@ static inline int pblk_set_read_mode(struct pblk *pblk, int type)
 	struct nvm_geo *geo = &dev->geo;
 	int flags;
 
+	if (geo->c.version == NVM_OCSSD_SPEC_20)
+		return 0;
+
 	flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
 	if (type == PBLK_READ_SEQUENTIAL)
 		flags |= geo->c.pln_mode >> 1;
@@ -1192,16 +1288,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->c.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.ch, p->m.lun, p->m.chk, p->m.sec);
 	}
 }
 
@@ -1211,13 +1312,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);
@@ -1233,16 +1334,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->c.num_pln &&
-				ppa->g.blk < geo->c.num_chk &&
-				ppa->g.pg < geo->c.num_pg &&
-				ppa->g.sec < geo->c.ws_min)
-			continue;
+		if (geo->c.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->c.num_pln &&
+					ppa->g.blk < geo->c.num_chk &&
+					ppa->g.pg < geo->c.num_pg &&
+					ppa->g.sec < geo->c.ws_min)
+				continue;
+		} else {
+			if (!ppa->c.is_cached &&
+					ppa->m.ch < geo->num_ch &&
+					ppa->m.lun < geo->num_lun &&
+					ppa->m.chk < geo->c.num_chk &&
+					ppa->m.sec < geo->c.clba)
+				continue;
+		}
 
-		print_ppa(ppa, "boundary", i);
+		print_ppa(geo, ppa, "boundary", i);
 
 		return 1;
 	}
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 99+ messages in thread

* Re: [PATCH 20/20] lightnvm: pblk: implement 2.0 support
  2018-02-21  9:26   ` Javier González
@ 2018-02-21 14:30     ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21 14:30 UTC (permalink / raw)
  To: Javier González; +Cc: Matias Bjørling, linux-block, LKML, linux-nvme

[-- Attachment #1: Type: text/plain, Size: 16916 bytes --]

BTW, there is a V3 for this patch at least, adding holes in the mapping
bitmap to avoid the multiplications and divisions on the fast path, when
the media format is not a power of two. I'll send it this week; just
wanted to get this out for revision.

Javier

> On 21 Feb 2018, at 10.26, Javier González <jg@lightnvm.io> 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 <javier@cnexlabs.com>
> ---
> 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 c5c304a37554..ce9aa4b3b09a 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->c.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->c.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->c.clba, pblk->min_write_pgs, &mod);
> -	if (mod) {
> -		pr_err("pblk: bad configuration of sectors/pages\n");
> +	switch (geo->c.version) {
> +	case NVM_OCSSD_SPEC_12:
> +		div_u64_rem(geo->c.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->c.version);
> 		return -EINVAL;
> 	}
> 
> -	pblk->addrf_len = pblk_set_addrf_12(geo, (void *)&pblk->addrf);
> -
> 	return 0;
> }
> 
> @@ -1110,7 +1153,9 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
> 	struct pblk *pblk;
> 	int ret;
> 
> -	if (geo->c.version != NVM_OCSSD_SPEC_12) {
> +	/* pblk supports 1.2 and 2.0 versions */
> +	if (!(geo->c.version == NVM_OCSSD_SPEC_12 ||
> +					geo->c.version == NVM_OCSSD_SPEC_20)) {
> 		pr_err("pblk: OCSSD version not supported (%u)\n",
> 							geo->c.version);
> 		return ERR_PTR(-EINVAL);
> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
> index 191af0c6591e..60b8d931e4ba 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->c.addrf;
> +	if (geo->c.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->c.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->c.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 c66fa0c28adf..b92a1145ad97 100644
> --- a/drivers/lightnvm/pblk.h
> +++ b/drivers/lightnvm/pblk.h
> @@ -574,6 +574,18 @@ enum {
> 	PBLK_STATE_STOPPED = 3,
> };
> 
> +/* Internal format to support not power-of-2 device formats (for now) */
> +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;
> @@ -586,7 +598,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;
> @@ -967,17 +980,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->c.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.ch = chnls;
> +
> +		sector_div(paddr, uaddrf->ch_stripe);
> +		div_u64_rem(paddr, uaddrf->lun_stripe, &luns);
> +		ppa.m.lun = luns;
> +
> +		sector_div(paddr, uaddrf->lun_stripe);
> +		ppa.m.sec += uaddrf->sec_stripe * paddr;
> +	}
> 
> 	return ppa;
> }
> @@ -985,15 +1024,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->c.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.ch * uaddrf->sec_stripe;
> +		paddr += (u64)p.m.lun * 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;
> }
> @@ -1010,15 +1066,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->c.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.ch = (ppa32 & lbaf->ch_mask) >>
> +							lbaf->ch_offset;
> +			ppa64.m.lun = (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;
> @@ -1034,15 +1112,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->c.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.ch << lbaf->ch_offset;
> +			ppa32 |= ppa64.m.lun << lbaf->lun_offset;
> +			ppa32 |= ppa64.m.chk << lbaf->chk_offset;
> +			ppa32 |= ppa64.m.sec << lbaf->sec_offset;
> +		}
> 	}
> 
> 	return ppa32;
> @@ -1160,6 +1250,9 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type)
> 	struct nvm_geo *geo = &dev->geo;
> 	int flags;
> 
> +	if (geo->c.version == NVM_OCSSD_SPEC_20)
> +		return 0;
> +
> 	flags = geo->c.pln_mode >> 1;
> 
> 	if (type == PBLK_WRITE)
> @@ -1179,6 +1272,9 @@ static inline int pblk_set_read_mode(struct pblk *pblk, int type)
> 	struct nvm_geo *geo = &dev->geo;
> 	int flags;
> 
> +	if (geo->c.version == NVM_OCSSD_SPEC_20)
> +		return 0;
> +
> 	flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
> 	if (type == PBLK_READ_SEQUENTIAL)
> 		flags |= geo->c.pln_mode >> 1;
> @@ -1192,16 +1288,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->c.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.ch, p->m.lun, p->m.chk, p->m.sec);
> 	}
> }
> 
> @@ -1211,13 +1312,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);
> @@ -1233,16 +1334,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->c.num_pln &&
> -				ppa->g.blk < geo->c.num_chk &&
> -				ppa->g.pg < geo->c.num_pg &&
> -				ppa->g.sec < geo->c.ws_min)
> -			continue;
> +		if (geo->c.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->c.num_pln &&
> +					ppa->g.blk < geo->c.num_chk &&
> +					ppa->g.pg < geo->c.num_pg &&
> +					ppa->g.sec < geo->c.ws_min)
> +				continue;
> +		} else {
> +			if (!ppa->c.is_cached &&
> +					ppa->m.ch < geo->num_ch &&
> +					ppa->m.lun < geo->num_lun &&
> +					ppa->m.chk < geo->c.num_chk &&
> +					ppa->m.sec < geo->c.clba)
> +				continue;
> +		}
> 
> -		print_ppa(ppa, "boundary", i);
> +		print_ppa(geo, ppa, "boundary", i);
> 
> 		return 1;
> 	}
> --
> 2.7.4
> 
> 
> _______________________________________________
> Linux-nvme mailing list
> Linux-nvme@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-nvme

[-- Attachment #2: Message signed with OpenPGP --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 20/20] lightnvm: pblk: implement 2.0 support
@ 2018-02-21 14:30     ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-21 14:30 UTC (permalink / raw)


BTW, there is a V3 for this patch at least, adding holes in the mapping
bitmap to avoid the multiplications and divisions on the fast path, when
the media format is not a power of two. I'll send it this week; just
wanted to get this out for revision.

Javier

> On 21 Feb 2018,@10.26, Javier Gonz?lez <jg@lightnvm.io> 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 <javier at cnexlabs.com>
> ---
> 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 c5c304a37554..ce9aa4b3b09a 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->c.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->c.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->c.clba, pblk->min_write_pgs, &mod);
> -	if (mod) {
> -		pr_err("pblk: bad configuration of sectors/pages\n");
> +	switch (geo->c.version) {
> +	case NVM_OCSSD_SPEC_12:
> +		div_u64_rem(geo->c.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->c.version);
> 		return -EINVAL;
> 	}
> 
> -	pblk->addrf_len = pblk_set_addrf_12(geo, (void *)&pblk->addrf);
> -
> 	return 0;
> }
> 
> @@ -1110,7 +1153,9 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
> 	struct pblk *pblk;
> 	int ret;
> 
> -	if (geo->c.version != NVM_OCSSD_SPEC_12) {
> +	/* pblk supports 1.2 and 2.0 versions */
> +	if (!(geo->c.version == NVM_OCSSD_SPEC_12 ||
> +					geo->c.version == NVM_OCSSD_SPEC_20)) {
> 		pr_err("pblk: OCSSD version not supported (%u)\n",
> 							geo->c.version);
> 		return ERR_PTR(-EINVAL);
> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
> index 191af0c6591e..60b8d931e4ba 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->c.addrf;
> +	if (geo->c.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->c.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->c.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 c66fa0c28adf..b92a1145ad97 100644
> --- a/drivers/lightnvm/pblk.h
> +++ b/drivers/lightnvm/pblk.h
> @@ -574,6 +574,18 @@ enum {
> 	PBLK_STATE_STOPPED = 3,
> };
> 
> +/* Internal format to support not power-of-2 device formats (for now) */
> +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;
> @@ -586,7 +598,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;
> @@ -967,17 +980,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->c.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.ch = chnls;
> +
> +		sector_div(paddr, uaddrf->ch_stripe);
> +		div_u64_rem(paddr, uaddrf->lun_stripe, &luns);
> +		ppa.m.lun = luns;
> +
> +		sector_div(paddr, uaddrf->lun_stripe);
> +		ppa.m.sec += uaddrf->sec_stripe * paddr;
> +	}
> 
> 	return ppa;
> }
> @@ -985,15 +1024,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->c.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.ch * uaddrf->sec_stripe;
> +		paddr += (u64)p.m.lun * 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;
> }
> @@ -1010,15 +1066,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->c.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.ch = (ppa32 & lbaf->ch_mask) >>
> +							lbaf->ch_offset;
> +			ppa64.m.lun = (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;
> @@ -1034,15 +1112,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->c.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.ch << lbaf->ch_offset;
> +			ppa32 |= ppa64.m.lun << lbaf->lun_offset;
> +			ppa32 |= ppa64.m.chk << lbaf->chk_offset;
> +			ppa32 |= ppa64.m.sec << lbaf->sec_offset;
> +		}
> 	}
> 
> 	return ppa32;
> @@ -1160,6 +1250,9 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type)
> 	struct nvm_geo *geo = &dev->geo;
> 	int flags;
> 
> +	if (geo->c.version == NVM_OCSSD_SPEC_20)
> +		return 0;
> +
> 	flags = geo->c.pln_mode >> 1;
> 
> 	if (type == PBLK_WRITE)
> @@ -1179,6 +1272,9 @@ static inline int pblk_set_read_mode(struct pblk *pblk, int type)
> 	struct nvm_geo *geo = &dev->geo;
> 	int flags;
> 
> +	if (geo->c.version == NVM_OCSSD_SPEC_20)
> +		return 0;
> +
> 	flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
> 	if (type == PBLK_READ_SEQUENTIAL)
> 		flags |= geo->c.pln_mode >> 1;
> @@ -1192,16 +1288,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->c.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.ch, p->m.lun, p->m.chk, p->m.sec);
> 	}
> }
> 
> @@ -1211,13 +1312,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);
> @@ -1233,16 +1334,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->c.num_pln &&
> -				ppa->g.blk < geo->c.num_chk &&
> -				ppa->g.pg < geo->c.num_pg &&
> -				ppa->g.sec < geo->c.ws_min)
> -			continue;
> +		if (geo->c.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->c.num_pln &&
> +					ppa->g.blk < geo->c.num_chk &&
> +					ppa->g.pg < geo->c.num_pg &&
> +					ppa->g.sec < geo->c.ws_min)
> +				continue;
> +		} else {
> +			if (!ppa->c.is_cached &&
> +					ppa->m.ch < geo->num_ch &&
> +					ppa->m.lun < geo->num_lun &&
> +					ppa->m.chk < geo->c.num_chk &&
> +					ppa->m.sec < geo->c.clba)
> +				continue;
> +		}
> 
> -		print_ppa(ppa, "boundary", i);
> +		print_ppa(geo, ppa, "boundary", i);
> 
> 		return 1;
> 	}
> --
> 2.7.4
> 
> 
> _______________________________________________
> Linux-nvme mailing list
> Linux-nvme at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-nvme
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: Message signed with OpenPGP
URL: <http://lists.infradead.org/pipermail/linux-nvme/attachments/20180221/d75cd9f6/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 01/20] lightnvm: simplify geometry structure.
  2018-02-21  9:26   ` Javier González
@ 2018-02-22  7:25     ` Matias Bjørling
  -1 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:25 UTC (permalink / raw)
  To: Javier González
  Cc: linux-block, linux-kernel, linux-nvme, Javier González

On 02/21/2018 10:26 AM, Javier González wrote:
> Currently, the device geometry is stored redundantly in the nvm_id and
> nvm_geo structures at a device level. Moreover, when instantiating
> targets on a specific number of LUNs, these structures are replicated
> and manually modified to fit the instance channel and LUN partitioning.
> 
> Instead, create a generic geometry around two base structures:
> nvm_dev_geo, which describes the geometry of the whole device and
> nvm_geo, which describes the geometry of the instance. Since these share
> a big part of the geometry, create a nvm_common_geo structure that keeps
> the static geoometry values that are shared across instances.
> 
> As we introduce support for 2.0, these structures allow to abstract
> spec. specific values and present a common geometry to targets.
> 
> Signed-off-by: Javier González <javier@cnexlabs.com>
> ---
>   drivers/lightnvm/core.c          | 137 +++++++---------
>   drivers/lightnvm/pblk-core.c     |  16 +-
>   drivers/lightnvm/pblk-gc.c       |   2 +-
>   drivers/lightnvm/pblk-init.c     | 123 +++++++-------
>   drivers/lightnvm/pblk-read.c     |   2 +-
>   drivers/lightnvm/pblk-recovery.c |  14 +-
>   drivers/lightnvm/pblk-rl.c       |   2 +-
>   drivers/lightnvm/pblk-sysfs.c    |  39 +++--
>   drivers/lightnvm/pblk-write.c    |   2 +-
>   drivers/lightnvm/pblk.h          |  93 +++++------
>   drivers/nvme/host/lightnvm.c     | 339 +++++++++++++++++++++++----------------
>   include/linux/lightnvm.h         | 204 ++++++++++++-----------
>   12 files changed, 514 insertions(+), 459 deletions(-)
> 
> diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
> index 689c97b97775..42596afdf64c 100644
> --- a/drivers/lightnvm/core.c
> +++ b/drivers/lightnvm/core.c
> @@ -111,6 +111,7 @@ static void nvm_release_luns_err(struct nvm_dev *dev, int lun_begin,
>   static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
>   {
>   	struct nvm_dev *dev = tgt_dev->parent;
> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>   	struct nvm_dev_map *dev_map = tgt_dev->map;
>   	int i, j;
>   
> @@ -122,7 +123,7 @@ static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
>   		if (clear) {
>   			for (j = 0; j < ch_map->nr_luns; j++) {
>   				int lun = j + lun_offs[j];
> -				int lunid = (ch * dev->geo.nr_luns) + lun;
> +				int lunid = (ch * dev_geo->nr_luns) + lun;
>   
>   				WARN_ON(!test_and_clear_bit(lunid,
>   							dev->lun_map));
> @@ -143,19 +144,20 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>   					      u16 lun_begin, u16 lun_end,
>   					      u16 op)
>   {
> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>   	struct nvm_tgt_dev *tgt_dev = NULL;
>   	struct nvm_dev_map *dev_rmap = dev->rmap;
>   	struct nvm_dev_map *dev_map;
>   	struct ppa_addr *luns;
>   	int nr_luns = lun_end - lun_begin + 1;
>   	int luns_left = nr_luns;
> -	int nr_chnls = nr_luns / dev->geo.nr_luns;
> -	int nr_chnls_mod = nr_luns % dev->geo.nr_luns;
> -	int bch = lun_begin / dev->geo.nr_luns;
> -	int blun = lun_begin % dev->geo.nr_luns;
> +	int nr_chnls = nr_luns / dev_geo->nr_luns;
> +	int nr_chnls_mod = nr_luns % dev_geo->nr_luns;
> +	int bch = lun_begin / dev_geo->nr_luns;
> +	int blun = lun_begin % dev_geo->nr_luns;
>   	int lunid = 0;
>   	int lun_balanced = 1;
> -	int prev_nr_luns;
> +	int sec_per_lun, prev_nr_luns;
>   	int i, j;
>   
>   	nr_chnls = (nr_chnls_mod == 0) ? nr_chnls : nr_chnls + 1;
> @@ -173,15 +175,15 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>   	if (!luns)
>   		goto err_luns;
>   
> -	prev_nr_luns = (luns_left > dev->geo.nr_luns) ?
> -					dev->geo.nr_luns : luns_left;
> +	prev_nr_luns = (luns_left > dev_geo->nr_luns) ?
> +					dev_geo->nr_luns : luns_left;
>   	for (i = 0; i < nr_chnls; i++) {
>   		struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[i + bch];
>   		int *lun_roffs = ch_rmap->lun_offs;
>   		struct nvm_ch_map *ch_map = &dev_map->chnls[i];
>   		int *lun_offs;
> -		int luns_in_chnl = (luns_left > dev->geo.nr_luns) ?
> -					dev->geo.nr_luns : luns_left;
> +		int luns_in_chnl = (luns_left > dev_geo->nr_luns) ?
> +					dev_geo->nr_luns : luns_left;
>   
>   		if (lun_balanced && prev_nr_luns != luns_in_chnl)
>   			lun_balanced = 0;
> @@ -215,18 +217,22 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>   	if (!tgt_dev)
>   		goto err_ch;
>   
> -	memcpy(&tgt_dev->geo, &dev->geo, sizeof(struct nvm_geo));
>   	/* Target device only owns a portion of the physical device */
>   	tgt_dev->geo.nr_chnls = nr_chnls;
> -	tgt_dev->geo.all_luns = nr_luns;
>   	tgt_dev->geo.nr_luns = (lun_balanced) ? prev_nr_luns : -1;
> +	tgt_dev->geo.all_luns = nr_luns;
> +	tgt_dev->geo.all_chunks = nr_luns * dev_geo->c.num_chk;
> +
>   	tgt_dev->geo.op = op;
> -	tgt_dev->total_secs = nr_luns * tgt_dev->geo.sec_per_lun;
> +
> +	sec_per_lun = dev_geo->c.clba * dev_geo->c.num_chk;
> +	tgt_dev->geo.total_secs = nr_luns * sec_per_lun;
> +
> +	tgt_dev->geo.c = dev_geo->c;
> +
>   	tgt_dev->q = dev->q;
>   	tgt_dev->map = dev_map;
>   	tgt_dev->luns = luns;
> -	memcpy(&tgt_dev->identity, &dev->identity, sizeof(struct nvm_id));
> -
>   	tgt_dev->parent = dev;
>   
>   	return tgt_dev;
> @@ -268,12 +274,12 @@ static struct nvm_tgt_type *nvm_find_target_type(const char *name)
>   	return tt;
>   }
>   
> -static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
> +static int nvm_config_check_luns(struct nvm_dev_geo *dev_geo, int lun_begin,
>   				 int lun_end)
>   {
> -	if (lun_begin > lun_end || lun_end >= geo->all_luns) {
> +	if (lun_begin > lun_end || lun_end >= dev_geo->all_luns) {
>   		pr_err("nvm: lun out of bound (%u:%u > %u)\n",
> -			lun_begin, lun_end, geo->all_luns - 1);
> +			lun_begin, lun_end, dev_geo->all_luns - 1);
>   		return -EINVAL;
>   	}
>   
> @@ -283,24 +289,24 @@ static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
>   static int __nvm_config_simple(struct nvm_dev *dev,
>   			       struct nvm_ioctl_create_simple *s)
>   {
> -	struct nvm_geo *geo = &dev->geo;
> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>   
>   	if (s->lun_begin == -1 && s->lun_end == -1) {
>   		s->lun_begin = 0;
> -		s->lun_end = geo->all_luns - 1;
> +		s->lun_end = dev_geo->all_luns - 1;
>   	}
>   
> -	return nvm_config_check_luns(geo, s->lun_begin, s->lun_end);
> +	return nvm_config_check_luns(dev_geo, s->lun_begin, s->lun_end);
>   }
>   
>   static int __nvm_config_extended(struct nvm_dev *dev,
>   				 struct nvm_ioctl_create_extended *e)
>   {
> -	struct nvm_geo *geo = &dev->geo;
> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>   
>   	if (e->lun_begin == 0xFFFF && e->lun_end == 0xFFFF) {
>   		e->lun_begin = 0;
> -		e->lun_end = dev->geo.all_luns - 1;
> +		e->lun_end = dev_geo->all_luns - 1;
>   	}
>   
>   	/* op not set falls into target's default */
> @@ -313,7 +319,7 @@ static int __nvm_config_extended(struct nvm_dev *dev,
>   		return -EINVAL;
>   	}
>   
> -	return nvm_config_check_luns(geo, e->lun_begin, e->lun_end);
> +	return nvm_config_check_luns(dev_geo, e->lun_begin, e->lun_end);
>   }
>   
>   static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
> @@ -408,7 +414,7 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
>   	tqueue->queuedata = targetdata;
>   
>   	blk_queue_max_hw_sectors(tqueue,
> -			(dev->geo.sec_size >> 9) * NVM_MAX_VLBA);
> +			(dev->dev_geo.c.csecs >> 9) * NVM_MAX_VLBA);
>   
>   	set_capacity(tdisk, tt->capacity(targetdata));
>   	add_disk(tdisk);
> @@ -497,6 +503,7 @@ static int nvm_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove)
>   
>   static int nvm_register_map(struct nvm_dev *dev)
>   {
> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>   	struct nvm_dev_map *rmap;
>   	int i, j;
>   
> @@ -504,15 +511,15 @@ static int nvm_register_map(struct nvm_dev *dev)
>   	if (!rmap)
>   		goto err_rmap;
>   
> -	rmap->chnls = kcalloc(dev->geo.nr_chnls, sizeof(struct nvm_ch_map),
> +	rmap->chnls = kcalloc(dev_geo->nr_chnls, sizeof(struct nvm_ch_map),
>   								GFP_KERNEL);
>   	if (!rmap->chnls)
>   		goto err_chnls;
>   
> -	for (i = 0; i < dev->geo.nr_chnls; i++) {
> +	for (i = 0; i < dev_geo->nr_chnls; i++) {
>   		struct nvm_ch_map *ch_rmap;
>   		int *lun_roffs;
> -		int luns_in_chnl = dev->geo.nr_luns;
> +		int luns_in_chnl = dev_geo->nr_luns;
>   
>   		ch_rmap = &rmap->chnls[i];
>   
> @@ -543,10 +550,11 @@ static int nvm_register_map(struct nvm_dev *dev)
>   
>   static void nvm_unregister_map(struct nvm_dev *dev)
>   {
> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>   	struct nvm_dev_map *rmap = dev->rmap;
>   	int i;
>   
> -	for (i = 0; i < dev->geo.nr_chnls; i++)
> +	for (i = 0; i < dev_geo->nr_chnls; i++)
>   		kfree(rmap->chnls[i].lun_offs);
>   
>   	kfree(rmap->chnls);
> @@ -675,7 +683,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
>   	int i, plane_cnt, pl_idx;
>   	struct ppa_addr ppa;
>   
> -	if (geo->plane_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
> +	if (geo->c.pln_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
>   		rqd->nr_ppas = nr_ppas;
>   		rqd->ppa_addr = ppas[0];
>   
> @@ -689,7 +697,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
>   		return -ENOMEM;
>   	}
>   
> -	plane_cnt = geo->plane_mode;
> +	plane_cnt = geo->c.pln_mode;
>   	rqd->nr_ppas *= plane_cnt;
>   
>   	for (i = 0; i < nr_ppas; i++) {
> @@ -804,18 +812,18 @@ EXPORT_SYMBOL(nvm_end_io);
>    */
>   int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
>   {
> -	struct nvm_geo *geo = &dev->geo;
> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>   	int blk, offset, pl, blktype;
>   
> -	if (nr_blks != geo->nr_chks * geo->plane_mode)
> +	if (nr_blks != dev_geo->c.num_chk * dev_geo->c.pln_mode)
>   		return -EINVAL;
>   
> -	for (blk = 0; blk < geo->nr_chks; blk++) {
> -		offset = blk * geo->plane_mode;
> +	for (blk = 0; blk < dev_geo->c.num_chk; blk++) {
> +		offset = blk * dev_geo->c.pln_mode;
>   		blktype = blks[offset];
>   
>   		/* Bad blocks on any planes take precedence over other types */
> -		for (pl = 0; pl < geo->plane_mode; pl++) {
> +		for (pl = 0; pl < dev_geo->c.pln_mode; pl++) {
>   			if (blks[offset + pl] &
>   					(NVM_BLK_T_BAD|NVM_BLK_T_GRWN_BAD)) {
>   				blktype = blks[offset + pl];
> @@ -826,7 +834,7 @@ int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
>   		blks[blk] = blktype;
>   	}
>   
> -	return geo->nr_chks;
> +	return dev_geo->c.num_chk;
>   }
>   EXPORT_SYMBOL(nvm_bb_tbl_fold);
>   
> @@ -843,41 +851,10 @@ EXPORT_SYMBOL(nvm_get_tgt_bb_tbl);
>   
>   static int nvm_core_init(struct nvm_dev *dev)
>   {
> -	struct nvm_id *id = &dev->identity;
> -	struct nvm_geo *geo = &dev->geo;
> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>   	int ret;
>   
> -	memcpy(&geo->ppaf, &id->ppaf, sizeof(struct nvm_addr_format));
> -
> -	if (id->mtype != 0) {
> -		pr_err("nvm: memory type not supported\n");
> -		return -EINVAL;
> -	}
> -
> -	/* Whole device values */
> -	geo->nr_chnls = id->num_ch;
> -	geo->nr_luns = id->num_lun;
> -
> -	/* Generic device geometry values */
> -	geo->ws_min = id->ws_min;
> -	geo->ws_opt = id->ws_opt;
> -	geo->ws_seq = id->ws_seq;
> -	geo->ws_per_chk = id->ws_per_chk;
> -	geo->nr_chks = id->num_chk;
> -	geo->mccap = id->mccap;
> -
> -	geo->sec_per_chk = id->clba;
> -	geo->sec_per_lun = geo->sec_per_chk * geo->nr_chks;
> -	geo->all_luns = geo->nr_luns * geo->nr_chnls;
> -
> -	/* 1.2 spec device geometry values */
> -	geo->plane_mode = 1 << geo->ws_seq;
> -	geo->nr_planes = geo->ws_opt / geo->ws_min;
> -	geo->sec_per_pg = geo->ws_min;
> -	geo->sec_per_pl = geo->sec_per_pg * geo->nr_planes;
> -
> -	dev->total_secs = geo->all_luns * geo->sec_per_lun;
> -	dev->lun_map = kcalloc(BITS_TO_LONGS(geo->all_luns),
> +	dev->lun_map = kcalloc(BITS_TO_LONGS(dev_geo->all_luns),
>   					sizeof(unsigned long), GFP_KERNEL);
>   	if (!dev->lun_map)
>   		return -ENOMEM;
> @@ -912,19 +889,17 @@ static void nvm_free(struct nvm_dev *dev)
>   
>   static int nvm_init(struct nvm_dev *dev)
>   {
> -	struct nvm_geo *geo = &dev->geo;
> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>   	int ret = -EINVAL;
>   
> -	if (dev->ops->identity(dev, &dev->identity)) {
> +	if (dev->ops->identity(dev)) {
>   		pr_err("nvm: device could not be identified\n");
>   		goto err;
>   	}
>   
> -	if (dev->identity.ver_id != 1 && dev->identity.ver_id != 2) {
> -		pr_err("nvm: device ver_id %d not supported by kernel.\n",
> -				dev->identity.ver_id);
> -		goto err;
> -	}
> +	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
> +				dev_geo->ver_id,
> +				dev_geo->c.vmnt);
>   
>   	ret = nvm_core_init(dev);
>   	if (ret) {
> @@ -932,10 +907,10 @@ static int nvm_init(struct nvm_dev *dev)
>   		goto err;
>   	}
>   
> -	pr_info("nvm: registered %s [%u/%u/%u/%u/%u/%u]\n",
> -			dev->name, geo->sec_per_pg, geo->nr_planes,
> -			geo->ws_per_chk, geo->nr_chks,
> -			geo->all_luns, geo->nr_chnls);
> +	pr_info("nvm: registered %s [%u/%u/%u/%u/%u]\n",
> +			dev->name, dev_geo->c.ws_min, dev_geo->c.ws_opt,
> +			dev_geo->c.num_chk, dev_geo->all_luns,
> +			dev_geo->nr_chnls);
>   	return 0;
>   err:
>   	pr_err("nvm: failed to initialize nvm\n");
> diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
> index 22e61cd4f801..519af8b9eab7 100644
> --- a/drivers/lightnvm/pblk-core.c
> +++ b/drivers/lightnvm/pblk-core.c
> @@ -613,7 +613,7 @@ static int pblk_line_submit_emeta_io(struct pblk *pblk, struct pblk_line *line,
>   	memset(&rqd, 0, sizeof(struct nvm_rq));
>   
>   	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
> -	rq_len = rq_ppas * geo->sec_size;
> +	rq_len = rq_ppas * geo->c.csecs;
>   
>   	bio = pblk_bio_map_addr(pblk, emeta_buf, rq_ppas, rq_len,
>   					l_mg->emeta_alloc_type, GFP_KERNEL);
> @@ -722,7 +722,7 @@ u64 pblk_line_smeta_start(struct pblk *pblk, struct pblk_line *line)
>   	if (bit >= lm->blk_per_line)
>   		return -1;
>   
> -	return bit * geo->sec_per_pl;
> +	return bit * geo->c.ws_opt;
>   }
>   
>   static int pblk_line_submit_smeta_io(struct pblk *pblk, struct pblk_line *line,
> @@ -1035,19 +1035,19 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>   	/* Capture bad block information on line mapping bitmaps */
>   	while ((bit = find_next_bit(line->blk_bitmap, lm->blk_per_line,
>   					bit + 1)) < lm->blk_per_line) {
> -		off = bit * geo->sec_per_pl;
> +		off = bit * geo->c.ws_opt;
>   		bitmap_shift_left(l_mg->bb_aux, l_mg->bb_template, off,
>   							lm->sec_per_line);
>   		bitmap_or(line->map_bitmap, line->map_bitmap, l_mg->bb_aux,
>   							lm->sec_per_line);
> -		line->sec_in_line -= geo->sec_per_chk;
> +		line->sec_in_line -= geo->c.clba;
>   		if (bit >= lm->emeta_bb)
>   			nr_bb++;
>   	}
>   
>   	/* Mark smeta metadata sectors as bad sectors */
>   	bit = find_first_zero_bit(line->blk_bitmap, lm->blk_per_line);
> -	off = bit * geo->sec_per_pl;
> +	off = bit * geo->c.ws_opt;
>   	bitmap_set(line->map_bitmap, off, lm->smeta_sec);
>   	line->sec_in_line -= lm->smeta_sec;
>   	line->smeta_ssec = off;
> @@ -1066,10 +1066,10 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>   	emeta_secs = lm->emeta_sec[0];
>   	off = lm->sec_per_line;
>   	while (emeta_secs) {
> -		off -= geo->sec_per_pl;
> +		off -= geo->c.ws_opt;
>   		if (!test_bit(off, line->invalid_bitmap)) {
> -			bitmap_set(line->invalid_bitmap, off, geo->sec_per_pl);
> -			emeta_secs -= geo->sec_per_pl;
> +			bitmap_set(line->invalid_bitmap, off, geo->c.ws_opt);
> +			emeta_secs -= geo->c.ws_opt;
>   		}
>   	}
>   
> diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c
> index 320f99af99e9..16afea3f5541 100644
> --- a/drivers/lightnvm/pblk-gc.c
> +++ b/drivers/lightnvm/pblk-gc.c
> @@ -88,7 +88,7 @@ static void pblk_gc_line_ws(struct work_struct *work)
>   
>   	up(&gc->gc_sem);
>   
> -	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->sec_size);
> +	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->c.csecs);
>   	if (!gc_rq->data) {
>   		pr_err("pblk: could not GC line:%d (%d/%d)\n",
>   					line->id, *line->vsc, gc_rq->nr_secs);
> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
> index 5261702e9ff7..95ecb0ec736b 100644
> --- a/drivers/lightnvm/pblk-init.c
> +++ b/drivers/lightnvm/pblk-init.c
> @@ -146,7 +146,7 @@ static int pblk_rwb_init(struct pblk *pblk)
>   		return -ENOMEM;
>   
>   	power_size = get_count_order(nr_entries);
> -	power_seg_sz = get_count_order(geo->sec_size);
> +	power_seg_sz = get_count_order(geo->c.csecs);
>   
>   	return pblk_rb_init(&pblk->rwb, entries, power_size, power_seg_sz);
>   }
> @@ -154,11 +154,11 @@ static int pblk_rwb_init(struct pblk *pblk)
>   /* Minimum pages needed within a lun */
>   #define ADDR_POOL_SIZE 64
>   
> -static int pblk_set_ppaf(struct pblk *pblk)
> +static int pblk_set_addrf_12(struct nvm_geo *geo,
> +			     struct nvm_addr_format_12 *dst)
>   {
> -	struct nvm_tgt_dev *dev = pblk->dev;
> -	struct nvm_geo *geo = &dev->geo;
> -	struct nvm_addr_format ppaf = geo->ppaf;
> +	struct nvm_addr_format_12 *src =
> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>   	int power_len;
>   
>   	/* Re-calculate channel and lun format to adapt to configuration */
> @@ -167,34 +167,50 @@ static int pblk_set_ppaf(struct pblk *pblk)
>   		pr_err("pblk: supports only power-of-two channel config.\n");
>   		return -EINVAL;
>   	}
> -	ppaf.ch_len = power_len;
> +	dst->ch_len = power_len;
>   
>   	power_len = get_count_order(geo->nr_luns);
>   	if (1 << power_len != geo->nr_luns) {
>   		pr_err("pblk: supports only power-of-two LUN config.\n");
>   		return -EINVAL;
>   	}
> -	ppaf.lun_len = power_len;
> +	dst->lun_len = power_len;
>   
> -	pblk->ppaf.sec_offset = 0;
> -	pblk->ppaf.pln_offset = ppaf.sect_len;
> -	pblk->ppaf.ch_offset = pblk->ppaf.pln_offset + ppaf.pln_len;
> -	pblk->ppaf.lun_offset = pblk->ppaf.ch_offset + ppaf.ch_len;
> -	pblk->ppaf.pg_offset = pblk->ppaf.lun_offset + ppaf.lun_len;
> -	pblk->ppaf.blk_offset = pblk->ppaf.pg_offset + ppaf.pg_len;
> -	pblk->ppaf.sec_mask = (1ULL << ppaf.sect_len) - 1;
> -	pblk->ppaf.pln_mask = ((1ULL << ppaf.pln_len) - 1) <<
> -							pblk->ppaf.pln_offset;
> -	pblk->ppaf.ch_mask = ((1ULL << ppaf.ch_len) - 1) <<
> -							pblk->ppaf.ch_offset;
> -	pblk->ppaf.lun_mask = ((1ULL << ppaf.lun_len) - 1) <<
> -							pblk->ppaf.lun_offset;
> -	pblk->ppaf.pg_mask = ((1ULL << ppaf.pg_len) - 1) <<
> -							pblk->ppaf.pg_offset;
> -	pblk->ppaf.blk_mask = ((1ULL << ppaf.blk_len) - 1) <<
> -							pblk->ppaf.blk_offset;
> +	dst->blk_len = src->blk_len;
> +	dst->pg_len = src->pg_len;
> +	dst->pln_len = src->pln_len;
> +	dst->sect_len = src->sect_len;
>   
> -	pblk->ppaf_bitsize = pblk->ppaf.blk_offset + ppaf.blk_len;
> +	dst->sect_offset = 0;
> +	dst->pln_offset = dst->sect_len;
> +	dst->ch_offset = dst->pln_offset + dst->pln_len;
> +	dst->lun_offset = dst->ch_offset + dst->ch_len;
> +	dst->pg_offset = dst->lun_offset + dst->lun_len;
> +	dst->blk_offset = dst->pg_offset + dst->pg_len;
> +
> +	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
> +	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
> +	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
> +	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
> +
> +	return dst->blk_offset + src->blk_len;
> +}
> +
> +static int pblk_set_ppaf(struct pblk *pblk)
> +{
> +	struct nvm_tgt_dev *dev = pblk->dev;
> +	struct nvm_geo *geo = &dev->geo;
> +	int mod;
> +
> +	div_u64_rem(geo->c.clba, pblk->min_write_pgs, &mod);
> +	if (mod) {
> +		pr_err("pblk: bad configuration of sectors/pages\n");
> +		return -EINVAL;
> +	}
> +
> +	pblk->ppaf_bitsize = pblk_set_addrf_12(geo, (void *)&pblk->ppaf);
>   
>   	return 0;
>   }
> @@ -253,8 +269,7 @@ static int pblk_core_init(struct pblk *pblk)
>   	struct nvm_tgt_dev *dev = pblk->dev;
>   	struct nvm_geo *geo = &dev->geo;
>   
> -	pblk->pgs_in_buffer = NVM_MEM_PAGE_WRITE * geo->sec_per_pg *
> -						geo->nr_planes * geo->all_luns;
> +	pblk->pgs_in_buffer = geo->c.mw_cunits * geo->c.ws_opt * geo->all_luns;
>   
>   	if (pblk_init_global_caches(pblk))
>   		return -ENOMEM;
> @@ -433,7 +448,7 @@ static void *pblk_bb_get_log(struct pblk *pblk)
>   	int i, nr_blks, blk_per_lun;
>   	int ret;
>   
> -	blk_per_lun = geo->nr_chks * geo->plane_mode;
> +	blk_per_lun = geo->c.num_chk * geo->c.pln_mode;
>   	nr_blks = blk_per_lun * geo->all_luns;
>   
>   	log = kmalloc(nr_blks, GFP_KERNEL);
> @@ -551,18 +566,18 @@ static unsigned int calc_emeta_len(struct pblk *pblk)
>   	/* Round to sector size so that lba_list starts on its own sector */
>   	lm->emeta_sec[1] = DIV_ROUND_UP(
>   			sizeof(struct line_emeta) + lm->blk_bitmap_len +
> -			sizeof(struct wa_counters), geo->sec_size);
> -	lm->emeta_len[1] = lm->emeta_sec[1] * geo->sec_size;
> +			sizeof(struct wa_counters), geo->c.csecs);
> +	lm->emeta_len[1] = lm->emeta_sec[1] * geo->c.csecs;
>   
>   	/* Round to sector size so that vsc_list starts on its own sector */
>   	lm->dsec_per_line = lm->sec_per_line - lm->emeta_sec[0];
>   	lm->emeta_sec[2] = DIV_ROUND_UP(lm->dsec_per_line * sizeof(u64),
> -			geo->sec_size);
> -	lm->emeta_len[2] = lm->emeta_sec[2] * geo->sec_size;
> +			geo->c.csecs);
> +	lm->emeta_len[2] = lm->emeta_sec[2] * geo->c.csecs;
>   
>   	lm->emeta_sec[3] = DIV_ROUND_UP(l_mg->nr_lines * sizeof(u32),
> -			geo->sec_size);
> -	lm->emeta_len[3] = lm->emeta_sec[3] * geo->sec_size;
> +			geo->c.csecs);
> +	lm->emeta_len[3] = lm->emeta_sec[3] * geo->c.csecs;
>   
>   	lm->vsc_list_len = l_mg->nr_lines * sizeof(u32);
>   
> @@ -593,13 +608,13 @@ static void pblk_set_provision(struct pblk *pblk, long nr_free_blks)
>   	 * on user capacity consider only provisioned blocks
>   	 */
>   	pblk->rl.total_blocks = nr_free_blks;
> -	pblk->rl.nr_secs = nr_free_blks * geo->sec_per_chk;
> +	pblk->rl.nr_secs = nr_free_blks * geo->c.clba;
>   
>   	/* Consider sectors used for metadata */
>   	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
> -	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
> +	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
>   
> -	pblk->capacity = (provisioned - blk_meta) * geo->sec_per_chk;
> +	pblk->capacity = (provisioned - blk_meta) * geo->c.clba;
>   
>   	atomic_set(&pblk->rl.free_blocks, nr_free_blks);
>   	atomic_set(&pblk->rl.free_user_blocks, nr_free_blks);
> @@ -710,10 +725,10 @@ static int pblk_lines_init(struct pblk *pblk)
>   	void *chunk_log;
>   	unsigned int smeta_len, emeta_len;
>   	long nr_bad_blks = 0, nr_free_blks = 0;
> -	int bb_distance, max_write_ppas, mod;
> +	int bb_distance, max_write_ppas;
>   	int i, ret;
>   
> -	pblk->min_write_pgs = geo->sec_per_pl * (geo->sec_size / PAGE_SIZE);
> +	pblk->min_write_pgs = geo->c.ws_opt * (geo->c.csecs / PAGE_SIZE);
>   	max_write_ppas = pblk->min_write_pgs * geo->all_luns;
>   	pblk->max_write_pgs = min_t(int, max_write_ppas, NVM_MAX_VLBA);
>   	pblk_set_sec_per_write(pblk, pblk->min_write_pgs);
> @@ -724,19 +739,13 @@ static int pblk_lines_init(struct pblk *pblk)
>   		return -EINVAL;
>   	}
>   
> -	div_u64_rem(geo->sec_per_chk, pblk->min_write_pgs, &mod);
> -	if (mod) {
> -		pr_err("pblk: bad configuration of sectors/pages\n");
> -		return -EINVAL;
> -	}
> -
> -	l_mg->nr_lines = geo->nr_chks;
> +	l_mg->nr_lines = geo->c.num_chk;
>   	l_mg->log_line = l_mg->data_line = NULL;
>   	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
>   	l_mg->nr_free_lines = 0;
>   	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
>   
> -	lm->sec_per_line = geo->sec_per_chk * geo->all_luns;
> +	lm->sec_per_line = geo->c.clba * geo->all_luns;
>   	lm->blk_per_line = geo->all_luns;
>   	lm->blk_bitmap_len = BITS_TO_LONGS(geo->all_luns) * sizeof(long);
>   	lm->sec_bitmap_len = BITS_TO_LONGS(lm->sec_per_line) * sizeof(long);
> @@ -750,8 +759,8 @@ static int pblk_lines_init(struct pblk *pblk)
>   	 */
>   	i = 1;
>   add_smeta_page:
> -	lm->smeta_sec = i * geo->sec_per_pl;
> -	lm->smeta_len = lm->smeta_sec * geo->sec_size;
> +	lm->smeta_sec = i * geo->c.ws_opt;
> +	lm->smeta_len = lm->smeta_sec * geo->c.csecs;
>   
>   	smeta_len = sizeof(struct line_smeta) + lm->lun_bitmap_len;
>   	if (smeta_len > lm->smeta_len) {
> @@ -764,8 +773,8 @@ static int pblk_lines_init(struct pblk *pblk)
>   	 */
>   	i = 1;
>   add_emeta_page:
> -	lm->emeta_sec[0] = i * geo->sec_per_pl;
> -	lm->emeta_len[0] = lm->emeta_sec[0] * geo->sec_size;
> +	lm->emeta_sec[0] = i * geo->c.ws_opt;
> +	lm->emeta_len[0] = lm->emeta_sec[0] * geo->c.csecs;
>   
>   	emeta_len = calc_emeta_len(pblk);
>   	if (emeta_len > lm->emeta_len[0]) {
> @@ -778,7 +787,7 @@ static int pblk_lines_init(struct pblk *pblk)
>   	lm->min_blk_line = 1;
>   	if (geo->all_luns > 1)
>   		lm->min_blk_line += DIV_ROUND_UP(lm->smeta_sec +
> -					lm->emeta_sec[0], geo->sec_per_chk);
> +					lm->emeta_sec[0], geo->c.clba);
>   
>   	if (lm->min_blk_line > lm->blk_per_line) {
>   		pr_err("pblk: config. not supported. Min. LUN in line:%d\n",
> @@ -802,9 +811,9 @@ static int pblk_lines_init(struct pblk *pblk)
>   		goto fail_free_bb_template;
>   	}
>   
> -	bb_distance = (geo->all_luns) * geo->sec_per_pl;
> +	bb_distance = (geo->all_luns) * geo->c.ws_opt;
>   	for (i = 0; i < lm->sec_per_line; i += bb_distance)
> -		bitmap_set(l_mg->bb_template, i, geo->sec_per_pl);
> +		bitmap_set(l_mg->bb_template, i, geo->c.ws_opt);
>   
>   	INIT_LIST_HEAD(&l_mg->free_list);
>   	INIT_LIST_HEAD(&l_mg->corrupt_list);
> @@ -981,9 +990,9 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>   	struct pblk *pblk;
>   	int ret;
>   
> -	if (dev->identity.dom & NVM_RSP_L2P) {
> +	if (dev->geo.c.dom & NVM_RSP_L2P) {
>   		pr_err("pblk: host-side L2P table not supported. (%x)\n",
> -							dev->identity.dom);
> +							dev->geo.c.dom);
>   		return ERR_PTR(-EINVAL);
>   	}
>   
> @@ -1091,7 +1100,7 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>   
>   	blk_queue_write_cache(tqueue, true, false);
>   
> -	tqueue->limits.discard_granularity = geo->sec_per_chk * geo->sec_size;
> +	tqueue->limits.discard_granularity = geo->c.clba * geo->c.csecs;
>   	tqueue->limits.discard_alignment = 0;
>   	blk_queue_max_discard_sectors(tqueue, UINT_MAX >> 9);
>   	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, tqueue);
> diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c
> index 2f761283f43e..ebb6bae3a3b8 100644
> --- a/drivers/lightnvm/pblk-read.c
> +++ b/drivers/lightnvm/pblk-read.c
> @@ -563,7 +563,7 @@ int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq)
>   	if (!(gc_rq->secs_to_gc))
>   		goto out;
>   
> -	data_len = (gc_rq->secs_to_gc) * geo->sec_size;
> +	data_len = (gc_rq->secs_to_gc) * geo->c.csecs;
>   	bio = pblk_bio_map_addr(pblk, gc_rq->data, gc_rq->secs_to_gc, data_len,
>   						PBLK_VMALLOC_META, GFP_KERNEL);
>   	if (IS_ERR(bio)) {
> diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
> index aaab9a5c17cc..1574dbbfbb1c 100644
> --- a/drivers/lightnvm/pblk-recovery.c
> +++ b/drivers/lightnvm/pblk-recovery.c
> @@ -184,7 +184,7 @@ static int pblk_calc_sec_in_line(struct pblk *pblk, struct pblk_line *line)
>   	int nr_bb = bitmap_weight(line->blk_bitmap, lm->blk_per_line);
>   
>   	return lm->sec_per_line - lm->smeta_sec - lm->emeta_sec[0] -
> -				nr_bb * geo->sec_per_chk;
> +				nr_bb * geo->c.clba;
>   }
>   
>   struct pblk_recov_alloc {
> @@ -232,7 +232,7 @@ static int pblk_recov_read_oob(struct pblk *pblk, struct pblk_line *line,
>   	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>   	if (!rq_ppas)
>   		rq_ppas = pblk->min_write_pgs;
> -	rq_len = rq_ppas * geo->sec_size;
> +	rq_len = rq_ppas * geo->c.csecs;
>   
>   	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>   	if (IS_ERR(bio))
> @@ -351,7 +351,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
>   	if (!pad_rq)
>   		return -ENOMEM;
>   
> -	data = vzalloc(pblk->max_write_pgs * geo->sec_size);
> +	data = vzalloc(pblk->max_write_pgs * geo->c.csecs);
>   	if (!data) {
>   		ret = -ENOMEM;
>   		goto free_rq;
> @@ -368,7 +368,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
>   		goto fail_free_pad;
>   	}
>   
> -	rq_len = rq_ppas * geo->sec_size;
> +	rq_len = rq_ppas * geo->c.csecs;
>   
>   	meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, &dma_meta_list);
>   	if (!meta_list) {
> @@ -509,7 +509,7 @@ static int pblk_recov_scan_all_oob(struct pblk *pblk, struct pblk_line *line,
>   	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>   	if (!rq_ppas)
>   		rq_ppas = pblk->min_write_pgs;
> -	rq_len = rq_ppas * geo->sec_size;
> +	rq_len = rq_ppas * geo->c.csecs;
>   
>   	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>   	if (IS_ERR(bio))
> @@ -640,7 +640,7 @@ static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line,
>   	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>   	if (!rq_ppas)
>   		rq_ppas = pblk->min_write_pgs;
> -	rq_len = rq_ppas * geo->sec_size;
> +	rq_len = rq_ppas * geo->c.csecs;
>   
>   	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>   	if (IS_ERR(bio))
> @@ -745,7 +745,7 @@ static int pblk_recov_l2p_from_oob(struct pblk *pblk, struct pblk_line *line)
>   	ppa_list = (void *)(meta_list) + pblk_dma_meta_size;
>   	dma_ppa_list = dma_meta_list + pblk_dma_meta_size;
>   
> -	data = kcalloc(pblk->max_write_pgs, geo->sec_size, GFP_KERNEL);
> +	data = kcalloc(pblk->max_write_pgs, geo->c.csecs, GFP_KERNEL);
>   	if (!data) {
>   		ret = -ENOMEM;
>   		goto free_meta_list;
> diff --git a/drivers/lightnvm/pblk-rl.c b/drivers/lightnvm/pblk-rl.c
> index 0d457b162f23..bcab203477ec 100644
> --- a/drivers/lightnvm/pblk-rl.c
> +++ b/drivers/lightnvm/pblk-rl.c
> @@ -200,7 +200,7 @@ void pblk_rl_init(struct pblk_rl *rl, int budget)
>   
>   	/* Consider sectors used for metadata */
>   	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
> -	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
> +	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
>   
>   	rl->high = pblk->op_blks - blk_meta - lm->blk_per_line;
>   	rl->high_pw = get_count_order(rl->high);
> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
> index d93e9b1f083a..5eb21a279361 100644
> --- a/drivers/lightnvm/pblk-sysfs.c
> +++ b/drivers/lightnvm/pblk-sysfs.c
> @@ -113,26 +113,31 @@ 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;
>   
> -	sz = snprintf(page, PAGE_SIZE - sz,
> -		"g:(b:%d)blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
> -		pblk->ppaf_bitsize,
> -		pblk->ppaf.blk_offset, geo->ppaf.blk_len,
> -		pblk->ppaf.pg_offset, geo->ppaf.pg_len,
> -		pblk->ppaf.lun_offset, geo->ppaf.lun_len,
> -		pblk->ppaf.ch_offset, geo->ppaf.ch_len,
> -		pblk->ppaf.pln_offset, geo->ppaf.pln_len,
> -		pblk->ppaf.sec_offset, geo->ppaf.sect_len);
> +	ppaf = (struct nvm_addr_format_12 *)&pblk->ppaf;
> +	geo_ppaf = (struct nvm_addr_format_12 *)&geo->c.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",
> +			pblk->ppaf_bitsize,
> +			ppaf->ch_offset, ppaf->ch_len,
> +			ppaf->lun_offset, ppaf->lun_len,
> +			ppaf->blk_offset, ppaf->blk_len,
> +			ppaf->pg_offset, ppaf->pg_len,
> +			ppaf->pln_offset, ppaf->pln_len,
> +			ppaf->sect_offset, ppaf->sect_len);
>   
>   	sz += snprintf(page + sz, PAGE_SIZE - sz,
> -		"d:blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
> -		geo->ppaf.blk_offset, geo->ppaf.blk_len,
> -		geo->ppaf.pg_offset, geo->ppaf.pg_len,
> -		geo->ppaf.lun_offset, geo->ppaf.lun_len,
> -		geo->ppaf.ch_offset, geo->ppaf.ch_len,
> -		geo->ppaf.pln_offset, geo->ppaf.pln_len,
> -		geo->ppaf.sect_offset, geo->ppaf.sect_len);
> +		"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->sect_offset, geo_ppaf->sect_len);
>   
>   	return sz;
>   }
> @@ -288,7 +293,7 @@ static ssize_t pblk_sysfs_lines_info(struct pblk *pblk, char *page)
>   				"blk_line:%d, sec_line:%d, sec_blk:%d\n",
>   					lm->blk_per_line,
>   					lm->sec_per_line,
> -					geo->sec_per_chk);
> +					geo->c.clba);
>   
>   	return sz;
>   }
> diff --git a/drivers/lightnvm/pblk-write.c b/drivers/lightnvm/pblk-write.c
> index aae86ed60b98..c49b27539d5a 100644
> --- a/drivers/lightnvm/pblk-write.c
> +++ b/drivers/lightnvm/pblk-write.c
> @@ -333,7 +333,7 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line)
>   	m_ctx = nvm_rq_to_pdu(rqd);
>   	m_ctx->private = meta_line;
>   
> -	rq_len = rq_ppas * geo->sec_size;
> +	rq_len = rq_ppas * geo->c.csecs;
>   	data = ((void *)emeta->buf) + emeta->mem;
>   
>   	bio = pblk_bio_map_addr(pblk, data, rq_ppas, rq_len,
> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
> index 282dfc8780e8..67ffb53608f7 100644
> --- a/drivers/lightnvm/pblk.h
> +++ b/drivers/lightnvm/pblk.h
> @@ -551,21 +551,6 @@ struct pblk_line_meta {
>   	unsigned int meta_distance;	/* Distance between data and metadata */
>   };
>   
> -struct pblk_addr_format {
> -	u64	ch_mask;
> -	u64	lun_mask;
> -	u64	pln_mask;
> -	u64	blk_mask;
> -	u64	pg_mask;
> -	u64	sec_mask;
> -	u8	ch_offset;
> -	u8	lun_offset;
> -	u8	pln_offset;
> -	u8	blk_offset;
> -	u8	pg_offset;
> -	u8	sec_offset;
> -};
> -
>   enum {
>   	PBLK_STATE_RUNNING = 0,
>   	PBLK_STATE_STOPPING = 1,
> @@ -585,8 +570,8 @@ struct pblk {
>   	struct pblk_line_mgmt l_mg;		/* Line management */
>   	struct pblk_line_meta lm;		/* Line metadata */
>   
> +	struct nvm_addr_format ppaf;
>   	int ppaf_bitsize;
> -	struct pblk_addr_format ppaf;
>   
>   	struct pblk_rb rwb;
>   
> @@ -941,14 +926,12 @@ static inline int pblk_line_vsc(struct pblk_line *line)
>   	return le32_to_cpu(*line->vsc);
>   }
>   
> -#define NVM_MEM_PAGE_WRITE (8)
> -
>   static inline int pblk_pad_distance(struct pblk *pblk)
>   {
>   	struct nvm_tgt_dev *dev = pblk->dev;
>   	struct nvm_geo *geo = &dev->geo;
>   
> -	return NVM_MEM_PAGE_WRITE * geo->all_luns * geo->sec_per_pl;
> +	return geo->c.mw_cunits * geo->all_luns * geo->c.ws_opt;
>   }
>   
>   static inline int pblk_ppa_to_line(struct ppa_addr p)
> @@ -964,15 +947,17 @@ 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->ppaf;
>   	struct ppa_addr ppa;
>   
>   	ppa.ppa = 0;
>   	ppa.g.blk = line_id;
> -	ppa.g.pg = (paddr & pblk->ppaf.pg_mask) >> pblk->ppaf.pg_offset;
> -	ppa.g.lun = (paddr & pblk->ppaf.lun_mask) >> pblk->ppaf.lun_offset;
> -	ppa.g.ch = (paddr & pblk->ppaf.ch_mask) >> pblk->ppaf.ch_offset;
> -	ppa.g.pl = (paddr & pblk->ppaf.pln_mask) >> pblk->ppaf.pln_offset;
> -	ppa.g.sec = (paddr & pblk->ppaf.sec_mask) >> pblk->ppaf.sec_offset;
> +	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->sect_offset;
>   
>   	return ppa;
>   }
> @@ -980,13 +965,15 @@ 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->ppaf;
>   	u64 paddr;
>   
> -	paddr = (u64)p.g.pg << pblk->ppaf.pg_offset;
> -	paddr |= (u64)p.g.lun << pblk->ppaf.lun_offset;
> -	paddr |= (u64)p.g.ch << pblk->ppaf.ch_offset;
> -	paddr |= (u64)p.g.pl << pblk->ppaf.pln_offset;
> -	paddr |= (u64)p.g.sec << pblk->ppaf.sec_offset;
> +	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->sect_offset;
>   
>   	return paddr;
>   }
> @@ -1003,18 +990,15 @@ 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 {
> -		ppa64.g.blk = (ppa32 & pblk->ppaf.blk_mask) >>
> -							pblk->ppaf.blk_offset;
> -		ppa64.g.pg = (ppa32 & pblk->ppaf.pg_mask) >>
> -							pblk->ppaf.pg_offset;
> -		ppa64.g.lun = (ppa32 & pblk->ppaf.lun_mask) >>
> -							pblk->ppaf.lun_offset;
> -		ppa64.g.ch = (ppa32 & pblk->ppaf.ch_mask) >>
> -							pblk->ppaf.ch_offset;
> -		ppa64.g.pl = (ppa32 & pblk->ppaf.pln_mask) >>
> -							pblk->ppaf.pln_offset;
> -		ppa64.g.sec = (ppa32 & pblk->ppaf.sec_mask) >>
> -							pblk->ppaf.sec_offset;
> +		struct nvm_addr_format_12 *ppaf =
> +				(struct nvm_addr_format_12 *)&pblk->ppaf;
> +
> +		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->sect_offset;
>   	}
>   
>   	return ppa64;
> @@ -1030,12 +1014,15 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
>   		ppa32 |= ppa64.c.line;
>   		ppa32 |= 1U << 31;
>   	} else {
> -		ppa32 |= ppa64.g.blk << pblk->ppaf.blk_offset;
> -		ppa32 |= ppa64.g.pg << pblk->ppaf.pg_offset;
> -		ppa32 |= ppa64.g.lun << pblk->ppaf.lun_offset;
> -		ppa32 |= ppa64.g.ch << pblk->ppaf.ch_offset;
> -		ppa32 |= ppa64.g.pl << pblk->ppaf.pln_offset;
> -		ppa32 |= ppa64.g.sec << pblk->ppaf.sec_offset;
> +		struct nvm_addr_format_12 *ppaf =
> +				(struct nvm_addr_format_12 *)&pblk->ppaf;
> +
> +		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->sect_offset;
>   	}
>   
>   	return ppa32;
> @@ -1153,7 +1140,7 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type)
>   	struct nvm_geo *geo = &dev->geo;
>   	int flags;
>   
> -	flags = geo->plane_mode >> 1;
> +	flags = geo->c.pln_mode >> 1;
>   
>   	if (type == PBLK_WRITE)
>   		flags |= NVM_IO_SCRAMBLE_ENABLE;
> @@ -1174,7 +1161,7 @@ static inline int pblk_set_read_mode(struct pblk *pblk, int type)
>   
>   	flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
>   	if (type == PBLK_READ_SEQUENTIAL)
> -		flags |= geo->plane_mode >> 1;
> +		flags |= geo->c.pln_mode >> 1;
>   
>   	return flags;
>   }
> @@ -1229,10 +1216,10 @@ static inline int pblk_boundary_ppa_checks(struct nvm_tgt_dev *tgt_dev,
>   		if (!ppa->c.is_cached &&
>   				ppa->g.ch < geo->nr_chnls &&
>   				ppa->g.lun < geo->nr_luns &&
> -				ppa->g.pl < geo->nr_planes &&
> -				ppa->g.blk < geo->nr_chks &&
> -				ppa->g.pg < geo->ws_per_chk &&
> -				ppa->g.sec < geo->sec_per_pg)
> +				ppa->g.pl < geo->c.num_pln &&
> +				ppa->g.blk < geo->c.num_chk &&
> +				ppa->g.pg < geo->c.num_pg &&
> +				ppa->g.sec < geo->c.ws_min)
>   			continue;
>   
>   		print_ppa(ppa, "boundary", i);
> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
> index 839c0b96466a..c81e64cc20d7 100644
> --- a/drivers/nvme/host/lightnvm.c
> +++ b/drivers/nvme/host/lightnvm.c
> @@ -152,8 +152,8 @@ struct nvme_nvm_id12_addrf {
>   	__u8			blk_len;
>   	__u8			pg_offset;
>   	__u8			pg_len;
> -	__u8			sect_offset;
> -	__u8			sect_len;
> +	__u8			sec_offset;
> +	__u8			sec_len;
>   	__u8			res[4];
>   } __packed;
>   
> @@ -254,106 +254,157 @@ static inline void _nvme_nvm_check_size(void)
>   	BUILD_BUG_ON(sizeof(struct nvme_nvm_id20) != NVME_IDENTIFY_DATA_SIZE);
>   }
>   
> -static int init_grp(struct nvm_id *nvm_id, struct nvme_nvm_id12 *id12)
> +static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
> +				 struct nvme_nvm_id12_addrf *src)
> +{
> +	dst->ch_len = src->ch_len;
> +	dst->lun_len = src->lun_len;
> +	dst->blk_len = src->blk_len;
> +	dst->pg_len = src->pg_len;
> +	dst->pln_len = src->pln_len;
> +	dst->sect_len = src->sec_len;
> +
> +	dst->ch_offset = src->ch_offset;
> +	dst->lun_offset = src->lun_offset;
> +	dst->blk_offset = src->blk_offset;
> +	dst->pg_offset = src->pg_offset;
> +	dst->pln_offset = src->pln_offset;
> +	dst->sect_offset = src->sec_offset;
> +
> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
> +	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
> +	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
> +	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
> +	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
> +}
> +
> +static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
> +			     struct nvm_dev_geo *dev_geo)
>   {
>   	struct nvme_nvm_id12_grp *src;
>   	int sec_per_pg, sec_per_pl, pg_per_blk;
>   
> -	if (id12->cgrps != 1)
> +	if (id->cgrps != 1)
>   		return -EINVAL;
>   
> -	src = &id12->grp;
> +	src = &id->grp;
>   
> -	nvm_id->mtype = src->mtype;
> -	nvm_id->fmtype = src->fmtype;
> +	if (src->mtype != 0) {
> +		pr_err("nvm: memory type not supported\n");
> +		return -EINVAL;
> +	}
> +
> +	/* 1.2 spec. only reports a single version id - unfold */
> +	dev_geo->ver_id = id->ver_id;
>   
> -	nvm_id->num_ch = src->num_ch;
> -	nvm_id->num_lun = src->num_lun;
> +	dev_geo->nr_chnls = src->num_ch;
> +	dev_geo->nr_luns = src->num_lun;
> +	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
>   
> -	nvm_id->num_chk = le16_to_cpu(src->num_chk);
> -	nvm_id->csecs = le16_to_cpu(src->csecs);
> -	nvm_id->sos = le16_to_cpu(src->sos);
> +	dev_geo->c.num_chk = le16_to_cpu(src->num_chk);
> +	dev_geo->c.csecs = le16_to_cpu(src->csecs);
> +	dev_geo->c.sos = le16_to_cpu(src->sos);
>   
>   	pg_per_blk = le16_to_cpu(src->num_pg);
> -	sec_per_pg = le16_to_cpu(src->fpg_sz) / nvm_id->csecs;
> +	sec_per_pg = le16_to_cpu(src->fpg_sz) / dev_geo->c.csecs;
>   	sec_per_pl = sec_per_pg * src->num_pln;
> -	nvm_id->clba = sec_per_pl * pg_per_blk;
> -	nvm_id->ws_per_chk = pg_per_blk;
> -
> -	nvm_id->mpos = le32_to_cpu(src->mpos);
> -	nvm_id->cpar = le16_to_cpu(src->cpar);
> -	nvm_id->mccap = le32_to_cpu(src->mccap);
> -
> -	nvm_id->ws_opt = nvm_id->ws_min = sec_per_pg;
> -	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
> -
> -	if (nvm_id->mpos & 0x020202) {
> -		nvm_id->ws_seq = NVM_IO_DUAL_ACCESS;
> -		nvm_id->ws_opt <<= 1;
> -	} else if (nvm_id->mpos & 0x040404) {
> -		nvm_id->ws_seq = NVM_IO_QUAD_ACCESS;
> -		nvm_id->ws_opt <<= 2;
> +	dev_geo->c.clba = sec_per_pl * pg_per_blk;
> +
> +	dev_geo->c.ws_min = sec_per_pg;
> +	dev_geo->c.ws_opt = sec_per_pg;
> +	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
> +
> +	dev_geo->c.mccap = le32_to_cpu(src->mccap);
> +
> +	dev_geo->c.trdt = le32_to_cpu(src->trdt);
> +	dev_geo->c.trdm = le32_to_cpu(src->trdm);
> +	dev_geo->c.tprt = le32_to_cpu(src->tprt);
> +	dev_geo->c.tprm = le32_to_cpu(src->tprm);
> +	dev_geo->c.tbet = le32_to_cpu(src->tbet);
> +	dev_geo->c.tbem = le32_to_cpu(src->tbem);
> +
> +	/* 1.2 compatibility */
> +	dev_geo->c.vmnt = id->vmnt;
> +	dev_geo->c.cap = le32_to_cpu(id->cap);
> +	dev_geo->c.dom = le32_to_cpu(id->dom);
> +
> +	dev_geo->c.mtype = src->mtype;
> +	dev_geo->c.fmtype = src->fmtype;
> +
> +	dev_geo->c.cpar = le16_to_cpu(src->cpar);
> +	dev_geo->c.mpos = le32_to_cpu(src->mpos);
> +
> +	dev_geo->c.pln_mode = NVM_PLANE_SINGLE;
> +
> +	if (dev_geo->c.mpos & 0x020202) {
> +		dev_geo->c.pln_mode = NVM_PLANE_DOUBLE;
> +		dev_geo->c.ws_opt <<= 1;
> +	} else if (dev_geo->c.mpos & 0x040404) {
> +		dev_geo->c.pln_mode = NVM_PLANE_QUAD;
> +		dev_geo->c.ws_opt <<= 2;
>   	}
>   
> -	nvm_id->trdt = le32_to_cpu(src->trdt);
> -	nvm_id->trdm = le32_to_cpu(src->trdm);
> -	nvm_id->tprt = le32_to_cpu(src->tprt);
> -	nvm_id->tprm = le32_to_cpu(src->tprm);
> -	nvm_id->tbet = le32_to_cpu(src->tbet);
> -	nvm_id->tbem = le32_to_cpu(src->tbem);
> -
> -	/* 1.2 compatibility */
> -	nvm_id->num_pln = src->num_pln;
> -	nvm_id->num_pg = le16_to_cpu(src->num_pg);
> -	nvm_id->fpg_sz = le16_to_cpu(src->fpg_sz);
> +	dev_geo->c.num_pln = src->num_pln;
> +	dev_geo->c.num_pg = le16_to_cpu(src->num_pg);
> +	dev_geo->c.fpg_sz = le16_to_cpu(src->fpg_sz);
> +
> +	nvme_nvm_set_addr_12((struct nvm_addr_format_12 *)&dev_geo->c.addrf,
> +								&id->ppaf);
>   
>   	return 0;
>   }
>   
> -static int nvme_nvm_setup_12(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
> -		struct nvme_nvm_id12 *id)
> +static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
> +				 struct nvme_nvm_id20_addrf *src)
>   {
> -	nvm_id->ver_id = id->ver_id;
> -	nvm_id->vmnt = id->vmnt;
> -	nvm_id->cap = le32_to_cpu(id->cap);
> -	nvm_id->dom = le32_to_cpu(id->dom);
> -	memcpy(&nvm_id->ppaf, &id->ppaf,
> -					sizeof(struct nvm_addr_format));
> -
> -	return init_grp(nvm_id, id);
> +	dst->ch_len = src->grp_len;
> +	dst->lun_len = src->pu_len;
> +	dst->chk_len = src->chk_len;
> +	dst->sec_len = src->lba_len;
> +
> +	dst->sec_offset = 0;
> +	dst->chk_offset = dst->sec_len;
> +	dst->lun_offset = dst->chk_offset + dst->chk_len;
> +	dst->ch_offset = dst->lun_offset + dst->lun_len;
> +
> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
> +	dst->chk_mask = ((1ULL << dst->chk_len) - 1) << dst->chk_offset;
> +	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>   }
>   
> -static int nvme_nvm_setup_20(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
> -		struct nvme_nvm_id20 *id)
> +static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
> +			     struct nvm_dev_geo *dev_geo)
>   {
> -	nvm_id->ver_id = id->mjr;
> +	dev_geo->ver_id = id->mjr;
>   
> -	nvm_id->num_ch = le16_to_cpu(id->num_grp);
> -	nvm_id->num_lun = le16_to_cpu(id->num_pu);
> -	nvm_id->num_chk = le32_to_cpu(id->num_chk);
> -	nvm_id->clba = le32_to_cpu(id->clba);
> +	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
> +	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
> +	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
>   
> -	nvm_id->ws_min = le32_to_cpu(id->ws_min);
> -	nvm_id->ws_opt = le32_to_cpu(id->ws_opt);
> -	nvm_id->mw_cunits = le32_to_cpu(id->mw_cunits);
> +	dev_geo->c.num_chk = le32_to_cpu(id->num_chk);
> +	dev_geo->c.clba = le32_to_cpu(id->clba);
> +	dev_geo->c.csecs = -1;		/* Set by nvme identify */
> +	dev_geo->c.sos = -1;		/* Set bu nvme identify */
>   
> -	nvm_id->trdt = le32_to_cpu(id->trdt);
> -	nvm_id->trdm = le32_to_cpu(id->trdm);
> -	nvm_id->tprt = le32_to_cpu(id->twrt);
> -	nvm_id->tprm = le32_to_cpu(id->twrm);
> -	nvm_id->tbet = le32_to_cpu(id->tcrst);
> -	nvm_id->tbem = le32_to_cpu(id->tcrsm);
> +	dev_geo->c.ws_min = le32_to_cpu(id->ws_min);
> +	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
> +	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
>   
> -	/* calculated values */
> -	nvm_id->ws_per_chk = nvm_id->clba / nvm_id->ws_min;
> +	dev_geo->c.trdt = le32_to_cpu(id->trdt);
> +	dev_geo->c.trdm = le32_to_cpu(id->trdm);
> +	dev_geo->c.tprt = le32_to_cpu(id->twrt);
> +	dev_geo->c.tprm = le32_to_cpu(id->twrm);
> +	dev_geo->c.tbet = le32_to_cpu(id->tcrst);
> +	dev_geo->c.tbem = le32_to_cpu(id->tcrsm);
>   
> -	/* 1.2 compatibility */
> -	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
> +	nvme_nvm_set_addr_20(&dev_geo->c.addrf, &id->lbaf);
>   
>   	return 0;
>   }
>   
> -static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
> +static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>   {
>   	struct nvme_ns *ns = nvmdev->q->queuedata;
>   	struct nvme_nvm_id12 *id;
> @@ -380,18 +431,18 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
>   	 */
>   	switch (id->ver_id) {
>   	case 1:
> -		ret = nvme_nvm_setup_12(nvmdev, nvm_id, id);
> +		ret = nvme_nvm_setup_12(id, &nvmdev->dev_geo);
>   		break;
>   	case 2:
> -		ret = nvme_nvm_setup_20(nvmdev, nvm_id,
> -				(struct nvme_nvm_id20 *)id);
> +		ret = nvme_nvm_setup_20((struct nvme_nvm_id20 *)id,
> +							&nvmdev->dev_geo);
>   		break;
>   	default:
> -		dev_err(ns->ctrl->device,
> -			"OCSSD revision not supported (%d)\n",
> -			nvm_id->ver_id);
> +		dev_err(ns->ctrl->device, "OCSSD revision not supported (%d)\n",
> +							id->ver_id);
>   		ret = -EINVAL;
>   	}
> +
>   out:
>   	kfree(id);
>   	return ret;
> @@ -401,12 +452,12 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
>   								u8 *blks)
>   {
>   	struct request_queue *q = nvmdev->q;
> -	struct nvm_geo *geo = &nvmdev->geo;
> +	struct nvm_dev_geo *dev_geo = &nvmdev->dev_geo;
>   	struct nvme_ns *ns = q->queuedata;
>   	struct nvme_ctrl *ctrl = ns->ctrl;
>   	struct nvme_nvm_command c = {};
>   	struct nvme_nvm_bb_tbl *bb_tbl;
> -	int nr_blks = geo->nr_chks * geo->plane_mode;
> +	int nr_blks = dev_geo->c.num_chk * dev_geo->c.num_pln;
>   	int tblsz = sizeof(struct nvme_nvm_bb_tbl) + nr_blks;
>   	int ret = 0;
>   
> @@ -447,7 +498,7 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
>   		goto out;
>   	}
>   
> -	memcpy(blks, bb_tbl->blk, geo->nr_chks * geo->plane_mode);
> +	memcpy(blks, bb_tbl->blk, dev_geo->c.num_chk * dev_geo->c.num_pln);
>   out:
>   	kfree(bb_tbl);
>   	return ret;
> @@ -815,9 +866,10 @@ int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd, unsigned long arg)
>   void nvme_nvm_update_nvm_info(struct nvme_ns *ns)
>   {
>   	struct nvm_dev *ndev = ns->ndev;
> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>   
> -	ndev->identity.csecs = ndev->geo.sec_size = 1 << ns->lba_shift;
> -	ndev->identity.sos = ndev->geo.oob_size = ns->ms;
> +	dev_geo->c.csecs = 1 << ns->lba_shift;
> +	dev_geo->c.sos = ns->ms;
>   }
>   
>   int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node)
> @@ -850,23 +902,22 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>   {
>   	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>   	struct nvm_dev *ndev = ns->ndev;
> -	struct nvm_id *id;
> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>   	struct attribute *attr;
>   
>   	if (!ndev)
>   		return 0;
>   
> -	id = &ndev->identity;
>   	attr = &dattr->attr;
>   
>   	if (strcmp(attr->name, "version") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ver_id);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>   	} else if (strcmp(attr->name, "capabilities") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->cap);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
>   	} else if (strcmp(attr->name, "read_typ") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdt);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>   	} else if (strcmp(attr->name, "read_max") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdm);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdm);
>   	} else {
>   		return scnprintf(page,
>   				 PAGE_SIZE,
> @@ -875,75 +926,79 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>   	}
>   }
>   
> +static ssize_t nvm_dev_attr_show_ppaf(struct nvm_addr_format_12 *ppaf,
> +					 char *page)
> +{
> +	return scnprintf(page, PAGE_SIZE,
> +		"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
> +				ppaf->ch_offset, ppaf->ch_len,
> +				ppaf->lun_offset, ppaf->lun_len,
> +				ppaf->pln_offset, ppaf->pln_len,
> +				ppaf->blk_offset, ppaf->blk_len,
> +				ppaf->pg_offset, ppaf->pg_len,
> +				ppaf->sect_offset, ppaf->sect_len);
> +}
> +
>   static ssize_t nvm_dev_attr_show_12(struct device *dev,
>   		struct device_attribute *dattr, char *page)
>   {
>   	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>   	struct nvm_dev *ndev = ns->ndev;
> -	struct nvm_id *id;
> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>   	struct attribute *attr;
>   
>   	if (!ndev)
>   		return 0;
>   
> -	id = &ndev->identity;
>   	attr = &dattr->attr;
>   
>   	if (strcmp(attr->name, "vendor_opcode") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->vmnt);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.vmnt);
>   	} else if (strcmp(attr->name, "device_mode") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->dom);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.dom);
>   	/* kept for compatibility */
>   	} else if (strcmp(attr->name, "media_manager") == 0) {
>   		return scnprintf(page, PAGE_SIZE, "%s\n", "gennvm");
>   	} else if (strcmp(attr->name, "ppa_format") == 0) {
> -		return scnprintf(page, PAGE_SIZE,
> -			"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
> -			id->ppaf.ch_offset, id->ppaf.ch_len,
> -			id->ppaf.lun_offset, id->ppaf.lun_len,
> -			id->ppaf.pln_offset, id->ppaf.pln_len,
> -			id->ppaf.blk_offset, id->ppaf.blk_len,
> -			id->ppaf.pg_offset, id->ppaf.pg_len,
> -			id->ppaf.sect_offset, id->ppaf.sect_len);
> +		return nvm_dev_attr_show_ppaf((void *)&dev_geo->c.addrf, page);
>   	} else if (strcmp(attr->name, "media_type") == 0) {	/* u8 */
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->mtype);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mtype);
>   	} else if (strcmp(attr->name, "flash_media_type") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->fmtype);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fmtype);
>   	} else if (strcmp(attr->name, "num_channels") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
>   	} else if (strcmp(attr->name, "num_luns") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
>   	} else if (strcmp(attr->name, "num_planes") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pln);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pln);
>   	} else if (strcmp(attr->name, "num_blocks") == 0) {	/* u16 */
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
>   	} else if (strcmp(attr->name, "num_pages") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pg);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pg);
>   	} else if (strcmp(attr->name, "page_size") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->fpg_sz);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fpg_sz);
>   	} else if (strcmp(attr->name, "hw_sector_size") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->csecs);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.csecs);
>   	} else if (strcmp(attr->name, "oob_sector_size") == 0) {/* u32 */
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->sos);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.sos);
>   	} else if (strcmp(attr->name, "prog_typ") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
>   	} else if (strcmp(attr->name, "prog_max") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
>   	} else if (strcmp(attr->name, "erase_typ") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
>   	} else if (strcmp(attr->name, "erase_max") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>   	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mpos);
> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
>   	} else if (strcmp(attr->name, "media_capabilities") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mccap);
> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
>   	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
>   		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>   	} else {
> -		return scnprintf(page,
> -				 PAGE_SIZE,
> -				 "Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
> -				 attr->name);
> +		return scnprintf(page, PAGE_SIZE,
> +			"Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
> +			attr->name);
>   	}
>   }
>   
> @@ -952,42 +1007,40 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>   {
>   	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>   	struct nvm_dev *ndev = ns->ndev;
> -	struct nvm_id *id;
> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>   	struct attribute *attr;
>   
>   	if (!ndev)
>   		return 0;
>   
> -	id = &ndev->identity;
>   	attr = &dattr->attr;
>   
>   	if (strcmp(attr->name, "groups") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
>   	} else if (strcmp(attr->name, "punits") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
>   	} else if (strcmp(attr->name, "chunks") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
>   	} else if (strcmp(attr->name, "clba") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->clba);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.clba);
>   	} else if (strcmp(attr->name, "ws_min") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_min);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_min);
>   	} else if (strcmp(attr->name, "ws_opt") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_opt);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_opt);
>   	} else if (strcmp(attr->name, "mw_cunits") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->mw_cunits);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mw_cunits);
>   	} else if (strcmp(attr->name, "write_typ") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
>   	} else if (strcmp(attr->name, "write_max") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
>   	} else if (strcmp(attr->name, "reset_typ") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
>   	} else if (strcmp(attr->name, "reset_max") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>   	} else {
> -		return scnprintf(page,
> -				 PAGE_SIZE,
> -				 "Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
> -				 attr->name);
> +		return scnprintf(page, PAGE_SIZE,
> +			"Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
> +			attr->name);
>   	}
>   }
>   
> @@ -1106,10 +1159,13 @@ static const struct attribute_group nvm_dev_attr_group_20 = {
>   
>   int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>   {
> -	if (!ns->ndev)
> +	struct nvm_dev *ndev = ns->ndev;
> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
> +
> +	if (!ndev)
>   		return -EINVAL;
>   
> -	switch (ns->ndev->identity.ver_id) {
> +	switch (dev_geo->ver_id) {
>   	case 1:
>   		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
>   					&nvm_dev_attr_group_12);
> @@ -1123,7 +1179,10 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>   
>   void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
>   {
> -	switch (ns->ndev->identity.ver_id) {
> +	struct nvm_dev *ndev = ns->ndev;
> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
> +
> +	switch (dev_geo->ver_id) {
>   	case 1:
>   		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
>   					&nvm_dev_attr_group_12);
> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
> index e55b10573c99..18e3751b1632 100644
> --- a/include/linux/lightnvm.h
> +++ b/include/linux/lightnvm.h
> @@ -50,7 +50,7 @@ struct nvm_id;
>   struct nvm_dev;
>   struct nvm_tgt_dev;
>   
> -typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *);
> +typedef int (nvm_id_fn)(struct nvm_dev *);
>   typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, u8 *);
>   typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct ppa_addr *, int, int);
>   typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
> @@ -152,62 +152,107 @@ struct nvm_id_lp_tbl {
>   	struct nvm_id_lp_mlc mlc;
>   };
>   
> -struct nvm_addr_format {
> -	u8	ch_offset;
> +struct nvm_addr_format_12 {
>   	u8	ch_len;
> -	u8	lun_offset;
>   	u8	lun_len;
> -	u8	pln_offset;
> +	u8	blk_len;
> +	u8	pg_len;
>   	u8	pln_len;
> +	u8	sect_len;
> +
> +	u8	ch_offset;
> +	u8	lun_offset;
>   	u8	blk_offset;
> -	u8	blk_len;
>   	u8	pg_offset;
> -	u8	pg_len;
> +	u8	pln_offset;
>   	u8	sect_offset;
> -	u8	sect_len;
> +
> +	u64	ch_mask;
> +	u64	lun_mask;
> +	u64	blk_mask;
> +	u64	pg_mask;
> +	u64	pln_mask;
> +	u64	sec_mask;
> +};
> +
> +struct nvm_addr_format {
> +	u8	ch_len;
> +	u8	lun_len;
> +	u8	chk_len;
> +	u8	sec_len;
> +	u8	rsv_len[2];
> +
> +	u8	ch_offset;
> +	u8	lun_offset;
> +	u8	chk_offset;
> +	u8	sec_offset;
> +	u8	rsv_off[2];
> +
> +	u64	ch_mask;
> +	u64	lun_mask;
> +	u64	chk_mask;
> +	u64	sec_mask;
> +	u64	rsv_mask[2];
>   };
>   
> -struct nvm_id {
> -	u8	ver_id;
> +/* Device common geometry */
> +struct nvm_common_geo {
> +	/* chunk geometry */
> +	u32	num_chk;	/* chunks per lun */
> +	u32	clba;		/* sectors per chunk */
> +	u16	csecs;		/* sector size */
> +	u16	sos;		/* out-of-band area size */
> +
> +	/* device write constrains */
> +	u32	ws_min;		/* minimum write size */
> +	u32	ws_opt;		/* optimal write size */
> +	u32	mw_cunits;	/* distance required for successful read */
> +
> +	/* device capabilities */
> +	u32	mccap;
> +
> +	/* device timings */
> +	u32	trdt;		/* Avg. Tread (ns) */
> +	u32	trdm;		/* Max Tread (ns) */
> +	u32	tprt;		/* Avg. Tprog (ns) */
> +	u32	tprm;		/* Max Tprog (ns) */
> +	u32	tbet;		/* Avg. Terase (ns) */
> +	u32	tbem;		/* Max Terase (ns) */
> +
> +	/* generic address format */
> +	struct nvm_addr_format addrf;
> +
> +	/* 1.2 compatibility */
>   	u8	vmnt;
>   	u32	cap;
>   	u32	dom;
>   
> -	struct	nvm_addr_format ppaf;
> -
> -	u8	num_ch;
> -	u8	num_lun;
> -	u16	num_chk;
> -	u16	clba;
> -	u16	csecs;
> -	u16	sos;
> -
> -	u32	ws_min;
> -	u32	ws_opt;
> -	u32	mw_cunits;
> -
> -	u32	trdt;
> -	u32	trdm;
> -	u32	tprt;
> -	u32	tprm;
> -	u32	tbet;
> -	u32	tbem;
> -	u32	mpos;
> -	u32	mccap;
> -	u16	cpar;
> -
> -	/* calculated values */
> -	u16	ws_seq;
> -	u16	ws_per_chk;
> -
> -	/* 1.2 compatibility */
>   	u8	mtype;
>   	u8	fmtype;
>   
> +	u16	cpar;
> +	u32	mpos;
> +
>   	u8	num_pln;
> +	u8	pln_mode;
>   	u16	num_pg;
>   	u16	fpg_sz;
> -} __packed;
> +};
> +
> +/* Device identified geometry */
> +struct nvm_dev_geo {
> +	/* device reported version */
> +	u8	ver_id;
> +
> +	/* full device geometry */
> +	u16	nr_chnls;
> +	u16	nr_luns;
> +
> +	/* calculated values */
> +	u16	all_luns;
> +
> +	struct nvm_common_geo c;
> +};
>   
>   struct nvm_target {
>   	struct list_head list;
> @@ -274,36 +319,22 @@ enum {
>   	NVM_BLK_ST_BAD =	0x8,	/* Bad block */
>   };
>   
> -
> -/* Device generic information */
> +/* Instance geometry */
>   struct nvm_geo {
> -	/* generic geometry */
> +	/* instance specific geometry */
>   	int nr_chnls;
> -	int all_luns; /* across channels */
> -	int nr_luns; /* per channel */
> -	int nr_chks; /* per lun */
> -
> -	int sec_size;
> -	int oob_size;
> -	int mccap;
> -
> -	int sec_per_chk;
> -	int sec_per_lun;
> -
> -	int ws_min;
> -	int ws_opt;
> -	int ws_seq;
> -	int ws_per_chk;
> +	int nr_luns;		/* per channel */
>   
>   	int op;
>   
> -	struct nvm_addr_format ppaf;
> +	/* common geometry */
> +	struct nvm_common_geo c;
>   
> -	/* Legacy 1.2 specific geometry */
> -	int plane_mode; /* drive device in single, double or quad mode */
> -	int nr_planes;
> -	int sec_per_pg; /* only sectors for a single page */
> -	int sec_per_pl; /* all sectors across planes */
> +	/* calculated values */
> +	int all_luns;		/* across channels */
> +	int all_chunks;		/* across channels */
> +
> +	sector_t total_secs;	/* across channels */
>   };
>   
>   /* sub-device structure */
> @@ -314,9 +345,6 @@ struct nvm_tgt_dev {
>   	/* Base ppas for target LUNs */
>   	struct ppa_addr *luns;
>   
> -	sector_t total_secs;
> -
> -	struct nvm_id identity;
>   	struct request_queue *q;
>   
>   	struct nvm_dev *parent;
> @@ -329,15 +357,11 @@ struct nvm_dev {
>   	struct list_head devices;
>   
>   	/* Device information */
> -	struct nvm_geo geo;
> -
> -	unsigned long total_secs;
> +	struct nvm_dev_geo dev_geo;
>   
>   	unsigned long *lun_map;
>   	void *dma_pool;
>   
> -	struct nvm_id identity;
> -
>   	/* Backend device */
>   	struct request_queue *q;
>   	char name[DISK_NAME_LEN];
> @@ -357,14 +381,16 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
>   						  struct ppa_addr r)
>   {
>   	struct nvm_geo *geo = &tgt_dev->geo;
> +	struct nvm_addr_format_12 *ppaf =
> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>   	struct ppa_addr l;
>   
> -	l.ppa = ((u64)r.g.blk) << geo->ppaf.blk_offset;
> -	l.ppa |= ((u64)r.g.pg) << geo->ppaf.pg_offset;
> -	l.ppa |= ((u64)r.g.sec) << geo->ppaf.sect_offset;
> -	l.ppa |= ((u64)r.g.pl) << geo->ppaf.pln_offset;
> -	l.ppa |= ((u64)r.g.lun) << geo->ppaf.lun_offset;
> -	l.ppa |= ((u64)r.g.ch) << geo->ppaf.ch_offset;
> +	l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
> +	l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
> +	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
> +	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
> +	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
> +	l.ppa |= ((u64)r.g.sec) << ppaf->sect_offset;
>   
>   	return l;
>   }
> @@ -373,24 +399,18 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
>   						  struct ppa_addr r)
>   {
>   	struct nvm_geo *geo = &tgt_dev->geo;
> +	struct nvm_addr_format_12 *ppaf =
> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>   	struct ppa_addr l;
>   
>   	l.ppa = 0;
> -	/*
> -	 * (r.ppa << X offset) & X len bitmask. X eq. blk, pg, etc.
> -	 */
> -	l.g.blk = (r.ppa >> geo->ppaf.blk_offset) &
> -					(((1 << geo->ppaf.blk_len) - 1));
> -	l.g.pg |= (r.ppa >> geo->ppaf.pg_offset) &
> -					(((1 << geo->ppaf.pg_len) - 1));
> -	l.g.sec |= (r.ppa >> geo->ppaf.sect_offset) &
> -					(((1 << geo->ppaf.sect_len) - 1));
> -	l.g.pl |= (r.ppa >> geo->ppaf.pln_offset) &
> -					(((1 << geo->ppaf.pln_len) - 1));
> -	l.g.lun |= (r.ppa >> geo->ppaf.lun_offset) &
> -					(((1 << geo->ppaf.lun_len) - 1));
> -	l.g.ch |= (r.ppa >> geo->ppaf.ch_offset) &
> -					(((1 << geo->ppaf.ch_len) - 1));
> +
> +	l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
> +	l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
> +	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
> +	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
> +	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
> +	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sect_offset;
>   
>   	return l;
>   }
> 

Thanks for the patch. I appreciate the work, but it is not the way I 
want the 2.0 representation to go. The 2.0 variables should stay in the 
nvm_geo data structure, and then if any 1.2 variables are on the side, 
they can be in a substructure.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 01/20] lightnvm: simplify geometry structure.
@ 2018-02-22  7:25     ` Matias Bjørling
  0 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:25 UTC (permalink / raw)


On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
> Currently, the device geometry is stored redundantly in the nvm_id and
> nvm_geo structures at a device level. Moreover, when instantiating
> targets on a specific number of LUNs, these structures are replicated
> and manually modified to fit the instance channel and LUN partitioning.
> 
> Instead, create a generic geometry around two base structures:
> nvm_dev_geo, which describes the geometry of the whole device and
> nvm_geo, which describes the geometry of the instance. Since these share
> a big part of the geometry, create a nvm_common_geo structure that keeps
> the static geoometry values that are shared across instances.
> 
> As we introduce support for 2.0, these structures allow to abstract
> spec. specific values and present a common geometry to targets.
> 
> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
> ---
>   drivers/lightnvm/core.c          | 137 +++++++---------
>   drivers/lightnvm/pblk-core.c     |  16 +-
>   drivers/lightnvm/pblk-gc.c       |   2 +-
>   drivers/lightnvm/pblk-init.c     | 123 +++++++-------
>   drivers/lightnvm/pblk-read.c     |   2 +-
>   drivers/lightnvm/pblk-recovery.c |  14 +-
>   drivers/lightnvm/pblk-rl.c       |   2 +-
>   drivers/lightnvm/pblk-sysfs.c    |  39 +++--
>   drivers/lightnvm/pblk-write.c    |   2 +-
>   drivers/lightnvm/pblk.h          |  93 +++++------
>   drivers/nvme/host/lightnvm.c     | 339 +++++++++++++++++++++++----------------
>   include/linux/lightnvm.h         | 204 ++++++++++++-----------
>   12 files changed, 514 insertions(+), 459 deletions(-)
> 
> diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
> index 689c97b97775..42596afdf64c 100644
> --- a/drivers/lightnvm/core.c
> +++ b/drivers/lightnvm/core.c
> @@ -111,6 +111,7 @@ static void nvm_release_luns_err(struct nvm_dev *dev, int lun_begin,
>   static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
>   {
>   	struct nvm_dev *dev = tgt_dev->parent;
> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>   	struct nvm_dev_map *dev_map = tgt_dev->map;
>   	int i, j;
>   
> @@ -122,7 +123,7 @@ static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
>   		if (clear) {
>   			for (j = 0; j < ch_map->nr_luns; j++) {
>   				int lun = j + lun_offs[j];
> -				int lunid = (ch * dev->geo.nr_luns) + lun;
> +				int lunid = (ch * dev_geo->nr_luns) + lun;
>   
>   				WARN_ON(!test_and_clear_bit(lunid,
>   							dev->lun_map));
> @@ -143,19 +144,20 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>   					      u16 lun_begin, u16 lun_end,
>   					      u16 op)
>   {
> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>   	struct nvm_tgt_dev *tgt_dev = NULL;
>   	struct nvm_dev_map *dev_rmap = dev->rmap;
>   	struct nvm_dev_map *dev_map;
>   	struct ppa_addr *luns;
>   	int nr_luns = lun_end - lun_begin + 1;
>   	int luns_left = nr_luns;
> -	int nr_chnls = nr_luns / dev->geo.nr_luns;
> -	int nr_chnls_mod = nr_luns % dev->geo.nr_luns;
> -	int bch = lun_begin / dev->geo.nr_luns;
> -	int blun = lun_begin % dev->geo.nr_luns;
> +	int nr_chnls = nr_luns / dev_geo->nr_luns;
> +	int nr_chnls_mod = nr_luns % dev_geo->nr_luns;
> +	int bch = lun_begin / dev_geo->nr_luns;
> +	int blun = lun_begin % dev_geo->nr_luns;
>   	int lunid = 0;
>   	int lun_balanced = 1;
> -	int prev_nr_luns;
> +	int sec_per_lun, prev_nr_luns;
>   	int i, j;
>   
>   	nr_chnls = (nr_chnls_mod == 0) ? nr_chnls : nr_chnls + 1;
> @@ -173,15 +175,15 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>   	if (!luns)
>   		goto err_luns;
>   
> -	prev_nr_luns = (luns_left > dev->geo.nr_luns) ?
> -					dev->geo.nr_luns : luns_left;
> +	prev_nr_luns = (luns_left > dev_geo->nr_luns) ?
> +					dev_geo->nr_luns : luns_left;
>   	for (i = 0; i < nr_chnls; i++) {
>   		struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[i + bch];
>   		int *lun_roffs = ch_rmap->lun_offs;
>   		struct nvm_ch_map *ch_map = &dev_map->chnls[i];
>   		int *lun_offs;
> -		int luns_in_chnl = (luns_left > dev->geo.nr_luns) ?
> -					dev->geo.nr_luns : luns_left;
> +		int luns_in_chnl = (luns_left > dev_geo->nr_luns) ?
> +					dev_geo->nr_luns : luns_left;
>   
>   		if (lun_balanced && prev_nr_luns != luns_in_chnl)
>   			lun_balanced = 0;
> @@ -215,18 +217,22 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>   	if (!tgt_dev)
>   		goto err_ch;
>   
> -	memcpy(&tgt_dev->geo, &dev->geo, sizeof(struct nvm_geo));
>   	/* Target device only owns a portion of the physical device */
>   	tgt_dev->geo.nr_chnls = nr_chnls;
> -	tgt_dev->geo.all_luns = nr_luns;
>   	tgt_dev->geo.nr_luns = (lun_balanced) ? prev_nr_luns : -1;
> +	tgt_dev->geo.all_luns = nr_luns;
> +	tgt_dev->geo.all_chunks = nr_luns * dev_geo->c.num_chk;
> +
>   	tgt_dev->geo.op = op;
> -	tgt_dev->total_secs = nr_luns * tgt_dev->geo.sec_per_lun;
> +
> +	sec_per_lun = dev_geo->c.clba * dev_geo->c.num_chk;
> +	tgt_dev->geo.total_secs = nr_luns * sec_per_lun;
> +
> +	tgt_dev->geo.c = dev_geo->c;
> +
>   	tgt_dev->q = dev->q;
>   	tgt_dev->map = dev_map;
>   	tgt_dev->luns = luns;
> -	memcpy(&tgt_dev->identity, &dev->identity, sizeof(struct nvm_id));
> -
>   	tgt_dev->parent = dev;
>   
>   	return tgt_dev;
> @@ -268,12 +274,12 @@ static struct nvm_tgt_type *nvm_find_target_type(const char *name)
>   	return tt;
>   }
>   
> -static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
> +static int nvm_config_check_luns(struct nvm_dev_geo *dev_geo, int lun_begin,
>   				 int lun_end)
>   {
> -	if (lun_begin > lun_end || lun_end >= geo->all_luns) {
> +	if (lun_begin > lun_end || lun_end >= dev_geo->all_luns) {
>   		pr_err("nvm: lun out of bound (%u:%u > %u)\n",
> -			lun_begin, lun_end, geo->all_luns - 1);
> +			lun_begin, lun_end, dev_geo->all_luns - 1);
>   		return -EINVAL;
>   	}
>   
> @@ -283,24 +289,24 @@ static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
>   static int __nvm_config_simple(struct nvm_dev *dev,
>   			       struct nvm_ioctl_create_simple *s)
>   {
> -	struct nvm_geo *geo = &dev->geo;
> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>   
>   	if (s->lun_begin == -1 && s->lun_end == -1) {
>   		s->lun_begin = 0;
> -		s->lun_end = geo->all_luns - 1;
> +		s->lun_end = dev_geo->all_luns - 1;
>   	}
>   
> -	return nvm_config_check_luns(geo, s->lun_begin, s->lun_end);
> +	return nvm_config_check_luns(dev_geo, s->lun_begin, s->lun_end);
>   }
>   
>   static int __nvm_config_extended(struct nvm_dev *dev,
>   				 struct nvm_ioctl_create_extended *e)
>   {
> -	struct nvm_geo *geo = &dev->geo;
> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>   
>   	if (e->lun_begin == 0xFFFF && e->lun_end == 0xFFFF) {
>   		e->lun_begin = 0;
> -		e->lun_end = dev->geo.all_luns - 1;
> +		e->lun_end = dev_geo->all_luns - 1;
>   	}
>   
>   	/* op not set falls into target's default */
> @@ -313,7 +319,7 @@ static int __nvm_config_extended(struct nvm_dev *dev,
>   		return -EINVAL;
>   	}
>   
> -	return nvm_config_check_luns(geo, e->lun_begin, e->lun_end);
> +	return nvm_config_check_luns(dev_geo, e->lun_begin, e->lun_end);
>   }
>   
>   static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
> @@ -408,7 +414,7 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
>   	tqueue->queuedata = targetdata;
>   
>   	blk_queue_max_hw_sectors(tqueue,
> -			(dev->geo.sec_size >> 9) * NVM_MAX_VLBA);
> +			(dev->dev_geo.c.csecs >> 9) * NVM_MAX_VLBA);
>   
>   	set_capacity(tdisk, tt->capacity(targetdata));
>   	add_disk(tdisk);
> @@ -497,6 +503,7 @@ static int nvm_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove)
>   
>   static int nvm_register_map(struct nvm_dev *dev)
>   {
> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>   	struct nvm_dev_map *rmap;
>   	int i, j;
>   
> @@ -504,15 +511,15 @@ static int nvm_register_map(struct nvm_dev *dev)
>   	if (!rmap)
>   		goto err_rmap;
>   
> -	rmap->chnls = kcalloc(dev->geo.nr_chnls, sizeof(struct nvm_ch_map),
> +	rmap->chnls = kcalloc(dev_geo->nr_chnls, sizeof(struct nvm_ch_map),
>   								GFP_KERNEL);
>   	if (!rmap->chnls)
>   		goto err_chnls;
>   
> -	for (i = 0; i < dev->geo.nr_chnls; i++) {
> +	for (i = 0; i < dev_geo->nr_chnls; i++) {
>   		struct nvm_ch_map *ch_rmap;
>   		int *lun_roffs;
> -		int luns_in_chnl = dev->geo.nr_luns;
> +		int luns_in_chnl = dev_geo->nr_luns;
>   
>   		ch_rmap = &rmap->chnls[i];
>   
> @@ -543,10 +550,11 @@ static int nvm_register_map(struct nvm_dev *dev)
>   
>   static void nvm_unregister_map(struct nvm_dev *dev)
>   {
> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>   	struct nvm_dev_map *rmap = dev->rmap;
>   	int i;
>   
> -	for (i = 0; i < dev->geo.nr_chnls; i++)
> +	for (i = 0; i < dev_geo->nr_chnls; i++)
>   		kfree(rmap->chnls[i].lun_offs);
>   
>   	kfree(rmap->chnls);
> @@ -675,7 +683,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
>   	int i, plane_cnt, pl_idx;
>   	struct ppa_addr ppa;
>   
> -	if (geo->plane_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
> +	if (geo->c.pln_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
>   		rqd->nr_ppas = nr_ppas;
>   		rqd->ppa_addr = ppas[0];
>   
> @@ -689,7 +697,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
>   		return -ENOMEM;
>   	}
>   
> -	plane_cnt = geo->plane_mode;
> +	plane_cnt = geo->c.pln_mode;
>   	rqd->nr_ppas *= plane_cnt;
>   
>   	for (i = 0; i < nr_ppas; i++) {
> @@ -804,18 +812,18 @@ EXPORT_SYMBOL(nvm_end_io);
>    */
>   int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
>   {
> -	struct nvm_geo *geo = &dev->geo;
> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>   	int blk, offset, pl, blktype;
>   
> -	if (nr_blks != geo->nr_chks * geo->plane_mode)
> +	if (nr_blks != dev_geo->c.num_chk * dev_geo->c.pln_mode)
>   		return -EINVAL;
>   
> -	for (blk = 0; blk < geo->nr_chks; blk++) {
> -		offset = blk * geo->plane_mode;
> +	for (blk = 0; blk < dev_geo->c.num_chk; blk++) {
> +		offset = blk * dev_geo->c.pln_mode;
>   		blktype = blks[offset];
>   
>   		/* Bad blocks on any planes take precedence over other types */
> -		for (pl = 0; pl < geo->plane_mode; pl++) {
> +		for (pl = 0; pl < dev_geo->c.pln_mode; pl++) {
>   			if (blks[offset + pl] &
>   					(NVM_BLK_T_BAD|NVM_BLK_T_GRWN_BAD)) {
>   				blktype = blks[offset + pl];
> @@ -826,7 +834,7 @@ int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
>   		blks[blk] = blktype;
>   	}
>   
> -	return geo->nr_chks;
> +	return dev_geo->c.num_chk;
>   }
>   EXPORT_SYMBOL(nvm_bb_tbl_fold);
>   
> @@ -843,41 +851,10 @@ EXPORT_SYMBOL(nvm_get_tgt_bb_tbl);
>   
>   static int nvm_core_init(struct nvm_dev *dev)
>   {
> -	struct nvm_id *id = &dev->identity;
> -	struct nvm_geo *geo = &dev->geo;
> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>   	int ret;
>   
> -	memcpy(&geo->ppaf, &id->ppaf, sizeof(struct nvm_addr_format));
> -
> -	if (id->mtype != 0) {
> -		pr_err("nvm: memory type not supported\n");
> -		return -EINVAL;
> -	}
> -
> -	/* Whole device values */
> -	geo->nr_chnls = id->num_ch;
> -	geo->nr_luns = id->num_lun;
> -
> -	/* Generic device geometry values */
> -	geo->ws_min = id->ws_min;
> -	geo->ws_opt = id->ws_opt;
> -	geo->ws_seq = id->ws_seq;
> -	geo->ws_per_chk = id->ws_per_chk;
> -	geo->nr_chks = id->num_chk;
> -	geo->mccap = id->mccap;
> -
> -	geo->sec_per_chk = id->clba;
> -	geo->sec_per_lun = geo->sec_per_chk * geo->nr_chks;
> -	geo->all_luns = geo->nr_luns * geo->nr_chnls;
> -
> -	/* 1.2 spec device geometry values */
> -	geo->plane_mode = 1 << geo->ws_seq;
> -	geo->nr_planes = geo->ws_opt / geo->ws_min;
> -	geo->sec_per_pg = geo->ws_min;
> -	geo->sec_per_pl = geo->sec_per_pg * geo->nr_planes;
> -
> -	dev->total_secs = geo->all_luns * geo->sec_per_lun;
> -	dev->lun_map = kcalloc(BITS_TO_LONGS(geo->all_luns),
> +	dev->lun_map = kcalloc(BITS_TO_LONGS(dev_geo->all_luns),
>   					sizeof(unsigned long), GFP_KERNEL);
>   	if (!dev->lun_map)
>   		return -ENOMEM;
> @@ -912,19 +889,17 @@ static void nvm_free(struct nvm_dev *dev)
>   
>   static int nvm_init(struct nvm_dev *dev)
>   {
> -	struct nvm_geo *geo = &dev->geo;
> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>   	int ret = -EINVAL;
>   
> -	if (dev->ops->identity(dev, &dev->identity)) {
> +	if (dev->ops->identity(dev)) {
>   		pr_err("nvm: device could not be identified\n");
>   		goto err;
>   	}
>   
> -	if (dev->identity.ver_id != 1 && dev->identity.ver_id != 2) {
> -		pr_err("nvm: device ver_id %d not supported by kernel.\n",
> -				dev->identity.ver_id);
> -		goto err;
> -	}
> +	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
> +				dev_geo->ver_id,
> +				dev_geo->c.vmnt);
>   
>   	ret = nvm_core_init(dev);
>   	if (ret) {
> @@ -932,10 +907,10 @@ static int nvm_init(struct nvm_dev *dev)
>   		goto err;
>   	}
>   
> -	pr_info("nvm: registered %s [%u/%u/%u/%u/%u/%u]\n",
> -			dev->name, geo->sec_per_pg, geo->nr_planes,
> -			geo->ws_per_chk, geo->nr_chks,
> -			geo->all_luns, geo->nr_chnls);
> +	pr_info("nvm: registered %s [%u/%u/%u/%u/%u]\n",
> +			dev->name, dev_geo->c.ws_min, dev_geo->c.ws_opt,
> +			dev_geo->c.num_chk, dev_geo->all_luns,
> +			dev_geo->nr_chnls);
>   	return 0;
>   err:
>   	pr_err("nvm: failed to initialize nvm\n");
> diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
> index 22e61cd4f801..519af8b9eab7 100644
> --- a/drivers/lightnvm/pblk-core.c
> +++ b/drivers/lightnvm/pblk-core.c
> @@ -613,7 +613,7 @@ static int pblk_line_submit_emeta_io(struct pblk *pblk, struct pblk_line *line,
>   	memset(&rqd, 0, sizeof(struct nvm_rq));
>   
>   	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
> -	rq_len = rq_ppas * geo->sec_size;
> +	rq_len = rq_ppas * geo->c.csecs;
>   
>   	bio = pblk_bio_map_addr(pblk, emeta_buf, rq_ppas, rq_len,
>   					l_mg->emeta_alloc_type, GFP_KERNEL);
> @@ -722,7 +722,7 @@ u64 pblk_line_smeta_start(struct pblk *pblk, struct pblk_line *line)
>   	if (bit >= lm->blk_per_line)
>   		return -1;
>   
> -	return bit * geo->sec_per_pl;
> +	return bit * geo->c.ws_opt;
>   }
>   
>   static int pblk_line_submit_smeta_io(struct pblk *pblk, struct pblk_line *line,
> @@ -1035,19 +1035,19 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>   	/* Capture bad block information on line mapping bitmaps */
>   	while ((bit = find_next_bit(line->blk_bitmap, lm->blk_per_line,
>   					bit + 1)) < lm->blk_per_line) {
> -		off = bit * geo->sec_per_pl;
> +		off = bit * geo->c.ws_opt;
>   		bitmap_shift_left(l_mg->bb_aux, l_mg->bb_template, off,
>   							lm->sec_per_line);
>   		bitmap_or(line->map_bitmap, line->map_bitmap, l_mg->bb_aux,
>   							lm->sec_per_line);
> -		line->sec_in_line -= geo->sec_per_chk;
> +		line->sec_in_line -= geo->c.clba;
>   		if (bit >= lm->emeta_bb)
>   			nr_bb++;
>   	}
>   
>   	/* Mark smeta metadata sectors as bad sectors */
>   	bit = find_first_zero_bit(line->blk_bitmap, lm->blk_per_line);
> -	off = bit * geo->sec_per_pl;
> +	off = bit * geo->c.ws_opt;
>   	bitmap_set(line->map_bitmap, off, lm->smeta_sec);
>   	line->sec_in_line -= lm->smeta_sec;
>   	line->smeta_ssec = off;
> @@ -1066,10 +1066,10 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>   	emeta_secs = lm->emeta_sec[0];
>   	off = lm->sec_per_line;
>   	while (emeta_secs) {
> -		off -= geo->sec_per_pl;
> +		off -= geo->c.ws_opt;
>   		if (!test_bit(off, line->invalid_bitmap)) {
> -			bitmap_set(line->invalid_bitmap, off, geo->sec_per_pl);
> -			emeta_secs -= geo->sec_per_pl;
> +			bitmap_set(line->invalid_bitmap, off, geo->c.ws_opt);
> +			emeta_secs -= geo->c.ws_opt;
>   		}
>   	}
>   
> diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c
> index 320f99af99e9..16afea3f5541 100644
> --- a/drivers/lightnvm/pblk-gc.c
> +++ b/drivers/lightnvm/pblk-gc.c
> @@ -88,7 +88,7 @@ static void pblk_gc_line_ws(struct work_struct *work)
>   
>   	up(&gc->gc_sem);
>   
> -	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->sec_size);
> +	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->c.csecs);
>   	if (!gc_rq->data) {
>   		pr_err("pblk: could not GC line:%d (%d/%d)\n",
>   					line->id, *line->vsc, gc_rq->nr_secs);
> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
> index 5261702e9ff7..95ecb0ec736b 100644
> --- a/drivers/lightnvm/pblk-init.c
> +++ b/drivers/lightnvm/pblk-init.c
> @@ -146,7 +146,7 @@ static int pblk_rwb_init(struct pblk *pblk)
>   		return -ENOMEM;
>   
>   	power_size = get_count_order(nr_entries);
> -	power_seg_sz = get_count_order(geo->sec_size);
> +	power_seg_sz = get_count_order(geo->c.csecs);
>   
>   	return pblk_rb_init(&pblk->rwb, entries, power_size, power_seg_sz);
>   }
> @@ -154,11 +154,11 @@ static int pblk_rwb_init(struct pblk *pblk)
>   /* Minimum pages needed within a lun */
>   #define ADDR_POOL_SIZE 64
>   
> -static int pblk_set_ppaf(struct pblk *pblk)
> +static int pblk_set_addrf_12(struct nvm_geo *geo,
> +			     struct nvm_addr_format_12 *dst)
>   {
> -	struct nvm_tgt_dev *dev = pblk->dev;
> -	struct nvm_geo *geo = &dev->geo;
> -	struct nvm_addr_format ppaf = geo->ppaf;
> +	struct nvm_addr_format_12 *src =
> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>   	int power_len;
>   
>   	/* Re-calculate channel and lun format to adapt to configuration */
> @@ -167,34 +167,50 @@ static int pblk_set_ppaf(struct pblk *pblk)
>   		pr_err("pblk: supports only power-of-two channel config.\n");
>   		return -EINVAL;
>   	}
> -	ppaf.ch_len = power_len;
> +	dst->ch_len = power_len;
>   
>   	power_len = get_count_order(geo->nr_luns);
>   	if (1 << power_len != geo->nr_luns) {
>   		pr_err("pblk: supports only power-of-two LUN config.\n");
>   		return -EINVAL;
>   	}
> -	ppaf.lun_len = power_len;
> +	dst->lun_len = power_len;
>   
> -	pblk->ppaf.sec_offset = 0;
> -	pblk->ppaf.pln_offset = ppaf.sect_len;
> -	pblk->ppaf.ch_offset = pblk->ppaf.pln_offset + ppaf.pln_len;
> -	pblk->ppaf.lun_offset = pblk->ppaf.ch_offset + ppaf.ch_len;
> -	pblk->ppaf.pg_offset = pblk->ppaf.lun_offset + ppaf.lun_len;
> -	pblk->ppaf.blk_offset = pblk->ppaf.pg_offset + ppaf.pg_len;
> -	pblk->ppaf.sec_mask = (1ULL << ppaf.sect_len) - 1;
> -	pblk->ppaf.pln_mask = ((1ULL << ppaf.pln_len) - 1) <<
> -							pblk->ppaf.pln_offset;
> -	pblk->ppaf.ch_mask = ((1ULL << ppaf.ch_len) - 1) <<
> -							pblk->ppaf.ch_offset;
> -	pblk->ppaf.lun_mask = ((1ULL << ppaf.lun_len) - 1) <<
> -							pblk->ppaf.lun_offset;
> -	pblk->ppaf.pg_mask = ((1ULL << ppaf.pg_len) - 1) <<
> -							pblk->ppaf.pg_offset;
> -	pblk->ppaf.blk_mask = ((1ULL << ppaf.blk_len) - 1) <<
> -							pblk->ppaf.blk_offset;
> +	dst->blk_len = src->blk_len;
> +	dst->pg_len = src->pg_len;
> +	dst->pln_len = src->pln_len;
> +	dst->sect_len = src->sect_len;
>   
> -	pblk->ppaf_bitsize = pblk->ppaf.blk_offset + ppaf.blk_len;
> +	dst->sect_offset = 0;
> +	dst->pln_offset = dst->sect_len;
> +	dst->ch_offset = dst->pln_offset + dst->pln_len;
> +	dst->lun_offset = dst->ch_offset + dst->ch_len;
> +	dst->pg_offset = dst->lun_offset + dst->lun_len;
> +	dst->blk_offset = dst->pg_offset + dst->pg_len;
> +
> +	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
> +	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
> +	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
> +	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
> +
> +	return dst->blk_offset + src->blk_len;
> +}
> +
> +static int pblk_set_ppaf(struct pblk *pblk)
> +{
> +	struct nvm_tgt_dev *dev = pblk->dev;
> +	struct nvm_geo *geo = &dev->geo;
> +	int mod;
> +
> +	div_u64_rem(geo->c.clba, pblk->min_write_pgs, &mod);
> +	if (mod) {
> +		pr_err("pblk: bad configuration of sectors/pages\n");
> +		return -EINVAL;
> +	}
> +
> +	pblk->ppaf_bitsize = pblk_set_addrf_12(geo, (void *)&pblk->ppaf);
>   
>   	return 0;
>   }
> @@ -253,8 +269,7 @@ static int pblk_core_init(struct pblk *pblk)
>   	struct nvm_tgt_dev *dev = pblk->dev;
>   	struct nvm_geo *geo = &dev->geo;
>   
> -	pblk->pgs_in_buffer = NVM_MEM_PAGE_WRITE * geo->sec_per_pg *
> -						geo->nr_planes * geo->all_luns;
> +	pblk->pgs_in_buffer = geo->c.mw_cunits * geo->c.ws_opt * geo->all_luns;
>   
>   	if (pblk_init_global_caches(pblk))
>   		return -ENOMEM;
> @@ -433,7 +448,7 @@ static void *pblk_bb_get_log(struct pblk *pblk)
>   	int i, nr_blks, blk_per_lun;
>   	int ret;
>   
> -	blk_per_lun = geo->nr_chks * geo->plane_mode;
> +	blk_per_lun = geo->c.num_chk * geo->c.pln_mode;
>   	nr_blks = blk_per_lun * geo->all_luns;
>   
>   	log = kmalloc(nr_blks, GFP_KERNEL);
> @@ -551,18 +566,18 @@ static unsigned int calc_emeta_len(struct pblk *pblk)
>   	/* Round to sector size so that lba_list starts on its own sector */
>   	lm->emeta_sec[1] = DIV_ROUND_UP(
>   			sizeof(struct line_emeta) + lm->blk_bitmap_len +
> -			sizeof(struct wa_counters), geo->sec_size);
> -	lm->emeta_len[1] = lm->emeta_sec[1] * geo->sec_size;
> +			sizeof(struct wa_counters), geo->c.csecs);
> +	lm->emeta_len[1] = lm->emeta_sec[1] * geo->c.csecs;
>   
>   	/* Round to sector size so that vsc_list starts on its own sector */
>   	lm->dsec_per_line = lm->sec_per_line - lm->emeta_sec[0];
>   	lm->emeta_sec[2] = DIV_ROUND_UP(lm->dsec_per_line * sizeof(u64),
> -			geo->sec_size);
> -	lm->emeta_len[2] = lm->emeta_sec[2] * geo->sec_size;
> +			geo->c.csecs);
> +	lm->emeta_len[2] = lm->emeta_sec[2] * geo->c.csecs;
>   
>   	lm->emeta_sec[3] = DIV_ROUND_UP(l_mg->nr_lines * sizeof(u32),
> -			geo->sec_size);
> -	lm->emeta_len[3] = lm->emeta_sec[3] * geo->sec_size;
> +			geo->c.csecs);
> +	lm->emeta_len[3] = lm->emeta_sec[3] * geo->c.csecs;
>   
>   	lm->vsc_list_len = l_mg->nr_lines * sizeof(u32);
>   
> @@ -593,13 +608,13 @@ static void pblk_set_provision(struct pblk *pblk, long nr_free_blks)
>   	 * on user capacity consider only provisioned blocks
>   	 */
>   	pblk->rl.total_blocks = nr_free_blks;
> -	pblk->rl.nr_secs = nr_free_blks * geo->sec_per_chk;
> +	pblk->rl.nr_secs = nr_free_blks * geo->c.clba;
>   
>   	/* Consider sectors used for metadata */
>   	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
> -	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
> +	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
>   
> -	pblk->capacity = (provisioned - blk_meta) * geo->sec_per_chk;
> +	pblk->capacity = (provisioned - blk_meta) * geo->c.clba;
>   
>   	atomic_set(&pblk->rl.free_blocks, nr_free_blks);
>   	atomic_set(&pblk->rl.free_user_blocks, nr_free_blks);
> @@ -710,10 +725,10 @@ static int pblk_lines_init(struct pblk *pblk)
>   	void *chunk_log;
>   	unsigned int smeta_len, emeta_len;
>   	long nr_bad_blks = 0, nr_free_blks = 0;
> -	int bb_distance, max_write_ppas, mod;
> +	int bb_distance, max_write_ppas;
>   	int i, ret;
>   
> -	pblk->min_write_pgs = geo->sec_per_pl * (geo->sec_size / PAGE_SIZE);
> +	pblk->min_write_pgs = geo->c.ws_opt * (geo->c.csecs / PAGE_SIZE);
>   	max_write_ppas = pblk->min_write_pgs * geo->all_luns;
>   	pblk->max_write_pgs = min_t(int, max_write_ppas, NVM_MAX_VLBA);
>   	pblk_set_sec_per_write(pblk, pblk->min_write_pgs);
> @@ -724,19 +739,13 @@ static int pblk_lines_init(struct pblk *pblk)
>   		return -EINVAL;
>   	}
>   
> -	div_u64_rem(geo->sec_per_chk, pblk->min_write_pgs, &mod);
> -	if (mod) {
> -		pr_err("pblk: bad configuration of sectors/pages\n");
> -		return -EINVAL;
> -	}
> -
> -	l_mg->nr_lines = geo->nr_chks;
> +	l_mg->nr_lines = geo->c.num_chk;
>   	l_mg->log_line = l_mg->data_line = NULL;
>   	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
>   	l_mg->nr_free_lines = 0;
>   	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
>   
> -	lm->sec_per_line = geo->sec_per_chk * geo->all_luns;
> +	lm->sec_per_line = geo->c.clba * geo->all_luns;
>   	lm->blk_per_line = geo->all_luns;
>   	lm->blk_bitmap_len = BITS_TO_LONGS(geo->all_luns) * sizeof(long);
>   	lm->sec_bitmap_len = BITS_TO_LONGS(lm->sec_per_line) * sizeof(long);
> @@ -750,8 +759,8 @@ static int pblk_lines_init(struct pblk *pblk)
>   	 */
>   	i = 1;
>   add_smeta_page:
> -	lm->smeta_sec = i * geo->sec_per_pl;
> -	lm->smeta_len = lm->smeta_sec * geo->sec_size;
> +	lm->smeta_sec = i * geo->c.ws_opt;
> +	lm->smeta_len = lm->smeta_sec * geo->c.csecs;
>   
>   	smeta_len = sizeof(struct line_smeta) + lm->lun_bitmap_len;
>   	if (smeta_len > lm->smeta_len) {
> @@ -764,8 +773,8 @@ static int pblk_lines_init(struct pblk *pblk)
>   	 */
>   	i = 1;
>   add_emeta_page:
> -	lm->emeta_sec[0] = i * geo->sec_per_pl;
> -	lm->emeta_len[0] = lm->emeta_sec[0] * geo->sec_size;
> +	lm->emeta_sec[0] = i * geo->c.ws_opt;
> +	lm->emeta_len[0] = lm->emeta_sec[0] * geo->c.csecs;
>   
>   	emeta_len = calc_emeta_len(pblk);
>   	if (emeta_len > lm->emeta_len[0]) {
> @@ -778,7 +787,7 @@ static int pblk_lines_init(struct pblk *pblk)
>   	lm->min_blk_line = 1;
>   	if (geo->all_luns > 1)
>   		lm->min_blk_line += DIV_ROUND_UP(lm->smeta_sec +
> -					lm->emeta_sec[0], geo->sec_per_chk);
> +					lm->emeta_sec[0], geo->c.clba);
>   
>   	if (lm->min_blk_line > lm->blk_per_line) {
>   		pr_err("pblk: config. not supported. Min. LUN in line:%d\n",
> @@ -802,9 +811,9 @@ static int pblk_lines_init(struct pblk *pblk)
>   		goto fail_free_bb_template;
>   	}
>   
> -	bb_distance = (geo->all_luns) * geo->sec_per_pl;
> +	bb_distance = (geo->all_luns) * geo->c.ws_opt;
>   	for (i = 0; i < lm->sec_per_line; i += bb_distance)
> -		bitmap_set(l_mg->bb_template, i, geo->sec_per_pl);
> +		bitmap_set(l_mg->bb_template, i, geo->c.ws_opt);
>   
>   	INIT_LIST_HEAD(&l_mg->free_list);
>   	INIT_LIST_HEAD(&l_mg->corrupt_list);
> @@ -981,9 +990,9 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>   	struct pblk *pblk;
>   	int ret;
>   
> -	if (dev->identity.dom & NVM_RSP_L2P) {
> +	if (dev->geo.c.dom & NVM_RSP_L2P) {
>   		pr_err("pblk: host-side L2P table not supported. (%x)\n",
> -							dev->identity.dom);
> +							dev->geo.c.dom);
>   		return ERR_PTR(-EINVAL);
>   	}
>   
> @@ -1091,7 +1100,7 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>   
>   	blk_queue_write_cache(tqueue, true, false);
>   
> -	tqueue->limits.discard_granularity = geo->sec_per_chk * geo->sec_size;
> +	tqueue->limits.discard_granularity = geo->c.clba * geo->c.csecs;
>   	tqueue->limits.discard_alignment = 0;
>   	blk_queue_max_discard_sectors(tqueue, UINT_MAX >> 9);
>   	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, tqueue);
> diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c
> index 2f761283f43e..ebb6bae3a3b8 100644
> --- a/drivers/lightnvm/pblk-read.c
> +++ b/drivers/lightnvm/pblk-read.c
> @@ -563,7 +563,7 @@ int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq)
>   	if (!(gc_rq->secs_to_gc))
>   		goto out;
>   
> -	data_len = (gc_rq->secs_to_gc) * geo->sec_size;
> +	data_len = (gc_rq->secs_to_gc) * geo->c.csecs;
>   	bio = pblk_bio_map_addr(pblk, gc_rq->data, gc_rq->secs_to_gc, data_len,
>   						PBLK_VMALLOC_META, GFP_KERNEL);
>   	if (IS_ERR(bio)) {
> diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
> index aaab9a5c17cc..1574dbbfbb1c 100644
> --- a/drivers/lightnvm/pblk-recovery.c
> +++ b/drivers/lightnvm/pblk-recovery.c
> @@ -184,7 +184,7 @@ static int pblk_calc_sec_in_line(struct pblk *pblk, struct pblk_line *line)
>   	int nr_bb = bitmap_weight(line->blk_bitmap, lm->blk_per_line);
>   
>   	return lm->sec_per_line - lm->smeta_sec - lm->emeta_sec[0] -
> -				nr_bb * geo->sec_per_chk;
> +				nr_bb * geo->c.clba;
>   }
>   
>   struct pblk_recov_alloc {
> @@ -232,7 +232,7 @@ static int pblk_recov_read_oob(struct pblk *pblk, struct pblk_line *line,
>   	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>   	if (!rq_ppas)
>   		rq_ppas = pblk->min_write_pgs;
> -	rq_len = rq_ppas * geo->sec_size;
> +	rq_len = rq_ppas * geo->c.csecs;
>   
>   	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>   	if (IS_ERR(bio))
> @@ -351,7 +351,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
>   	if (!pad_rq)
>   		return -ENOMEM;
>   
> -	data = vzalloc(pblk->max_write_pgs * geo->sec_size);
> +	data = vzalloc(pblk->max_write_pgs * geo->c.csecs);
>   	if (!data) {
>   		ret = -ENOMEM;
>   		goto free_rq;
> @@ -368,7 +368,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
>   		goto fail_free_pad;
>   	}
>   
> -	rq_len = rq_ppas * geo->sec_size;
> +	rq_len = rq_ppas * geo->c.csecs;
>   
>   	meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, &dma_meta_list);
>   	if (!meta_list) {
> @@ -509,7 +509,7 @@ static int pblk_recov_scan_all_oob(struct pblk *pblk, struct pblk_line *line,
>   	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>   	if (!rq_ppas)
>   		rq_ppas = pblk->min_write_pgs;
> -	rq_len = rq_ppas * geo->sec_size;
> +	rq_len = rq_ppas * geo->c.csecs;
>   
>   	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>   	if (IS_ERR(bio))
> @@ -640,7 +640,7 @@ static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line,
>   	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>   	if (!rq_ppas)
>   		rq_ppas = pblk->min_write_pgs;
> -	rq_len = rq_ppas * geo->sec_size;
> +	rq_len = rq_ppas * geo->c.csecs;
>   
>   	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>   	if (IS_ERR(bio))
> @@ -745,7 +745,7 @@ static int pblk_recov_l2p_from_oob(struct pblk *pblk, struct pblk_line *line)
>   	ppa_list = (void *)(meta_list) + pblk_dma_meta_size;
>   	dma_ppa_list = dma_meta_list + pblk_dma_meta_size;
>   
> -	data = kcalloc(pblk->max_write_pgs, geo->sec_size, GFP_KERNEL);
> +	data = kcalloc(pblk->max_write_pgs, geo->c.csecs, GFP_KERNEL);
>   	if (!data) {
>   		ret = -ENOMEM;
>   		goto free_meta_list;
> diff --git a/drivers/lightnvm/pblk-rl.c b/drivers/lightnvm/pblk-rl.c
> index 0d457b162f23..bcab203477ec 100644
> --- a/drivers/lightnvm/pblk-rl.c
> +++ b/drivers/lightnvm/pblk-rl.c
> @@ -200,7 +200,7 @@ void pblk_rl_init(struct pblk_rl *rl, int budget)
>   
>   	/* Consider sectors used for metadata */
>   	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
> -	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
> +	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
>   
>   	rl->high = pblk->op_blks - blk_meta - lm->blk_per_line;
>   	rl->high_pw = get_count_order(rl->high);
> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
> index d93e9b1f083a..5eb21a279361 100644
> --- a/drivers/lightnvm/pblk-sysfs.c
> +++ b/drivers/lightnvm/pblk-sysfs.c
> @@ -113,26 +113,31 @@ 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;
>   
> -	sz = snprintf(page, PAGE_SIZE - sz,
> -		"g:(b:%d)blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
> -		pblk->ppaf_bitsize,
> -		pblk->ppaf.blk_offset, geo->ppaf.blk_len,
> -		pblk->ppaf.pg_offset, geo->ppaf.pg_len,
> -		pblk->ppaf.lun_offset, geo->ppaf.lun_len,
> -		pblk->ppaf.ch_offset, geo->ppaf.ch_len,
> -		pblk->ppaf.pln_offset, geo->ppaf.pln_len,
> -		pblk->ppaf.sec_offset, geo->ppaf.sect_len);
> +	ppaf = (struct nvm_addr_format_12 *)&pblk->ppaf;
> +	geo_ppaf = (struct nvm_addr_format_12 *)&geo->c.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",
> +			pblk->ppaf_bitsize,
> +			ppaf->ch_offset, ppaf->ch_len,
> +			ppaf->lun_offset, ppaf->lun_len,
> +			ppaf->blk_offset, ppaf->blk_len,
> +			ppaf->pg_offset, ppaf->pg_len,
> +			ppaf->pln_offset, ppaf->pln_len,
> +			ppaf->sect_offset, ppaf->sect_len);
>   
>   	sz += snprintf(page + sz, PAGE_SIZE - sz,
> -		"d:blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
> -		geo->ppaf.blk_offset, geo->ppaf.blk_len,
> -		geo->ppaf.pg_offset, geo->ppaf.pg_len,
> -		geo->ppaf.lun_offset, geo->ppaf.lun_len,
> -		geo->ppaf.ch_offset, geo->ppaf.ch_len,
> -		geo->ppaf.pln_offset, geo->ppaf.pln_len,
> -		geo->ppaf.sect_offset, geo->ppaf.sect_len);
> +		"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->sect_offset, geo_ppaf->sect_len);
>   
>   	return sz;
>   }
> @@ -288,7 +293,7 @@ static ssize_t pblk_sysfs_lines_info(struct pblk *pblk, char *page)
>   				"blk_line:%d, sec_line:%d, sec_blk:%d\n",
>   					lm->blk_per_line,
>   					lm->sec_per_line,
> -					geo->sec_per_chk);
> +					geo->c.clba);
>   
>   	return sz;
>   }
> diff --git a/drivers/lightnvm/pblk-write.c b/drivers/lightnvm/pblk-write.c
> index aae86ed60b98..c49b27539d5a 100644
> --- a/drivers/lightnvm/pblk-write.c
> +++ b/drivers/lightnvm/pblk-write.c
> @@ -333,7 +333,7 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line)
>   	m_ctx = nvm_rq_to_pdu(rqd);
>   	m_ctx->private = meta_line;
>   
> -	rq_len = rq_ppas * geo->sec_size;
> +	rq_len = rq_ppas * geo->c.csecs;
>   	data = ((void *)emeta->buf) + emeta->mem;
>   
>   	bio = pblk_bio_map_addr(pblk, data, rq_ppas, rq_len,
> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
> index 282dfc8780e8..67ffb53608f7 100644
> --- a/drivers/lightnvm/pblk.h
> +++ b/drivers/lightnvm/pblk.h
> @@ -551,21 +551,6 @@ struct pblk_line_meta {
>   	unsigned int meta_distance;	/* Distance between data and metadata */
>   };
>   
> -struct pblk_addr_format {
> -	u64	ch_mask;
> -	u64	lun_mask;
> -	u64	pln_mask;
> -	u64	blk_mask;
> -	u64	pg_mask;
> -	u64	sec_mask;
> -	u8	ch_offset;
> -	u8	lun_offset;
> -	u8	pln_offset;
> -	u8	blk_offset;
> -	u8	pg_offset;
> -	u8	sec_offset;
> -};
> -
>   enum {
>   	PBLK_STATE_RUNNING = 0,
>   	PBLK_STATE_STOPPING = 1,
> @@ -585,8 +570,8 @@ struct pblk {
>   	struct pblk_line_mgmt l_mg;		/* Line management */
>   	struct pblk_line_meta lm;		/* Line metadata */
>   
> +	struct nvm_addr_format ppaf;
>   	int ppaf_bitsize;
> -	struct pblk_addr_format ppaf;
>   
>   	struct pblk_rb rwb;
>   
> @@ -941,14 +926,12 @@ static inline int pblk_line_vsc(struct pblk_line *line)
>   	return le32_to_cpu(*line->vsc);
>   }
>   
> -#define NVM_MEM_PAGE_WRITE (8)
> -
>   static inline int pblk_pad_distance(struct pblk *pblk)
>   {
>   	struct nvm_tgt_dev *dev = pblk->dev;
>   	struct nvm_geo *geo = &dev->geo;
>   
> -	return NVM_MEM_PAGE_WRITE * geo->all_luns * geo->sec_per_pl;
> +	return geo->c.mw_cunits * geo->all_luns * geo->c.ws_opt;
>   }
>   
>   static inline int pblk_ppa_to_line(struct ppa_addr p)
> @@ -964,15 +947,17 @@ 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->ppaf;
>   	struct ppa_addr ppa;
>   
>   	ppa.ppa = 0;
>   	ppa.g.blk = line_id;
> -	ppa.g.pg = (paddr & pblk->ppaf.pg_mask) >> pblk->ppaf.pg_offset;
> -	ppa.g.lun = (paddr & pblk->ppaf.lun_mask) >> pblk->ppaf.lun_offset;
> -	ppa.g.ch = (paddr & pblk->ppaf.ch_mask) >> pblk->ppaf.ch_offset;
> -	ppa.g.pl = (paddr & pblk->ppaf.pln_mask) >> pblk->ppaf.pln_offset;
> -	ppa.g.sec = (paddr & pblk->ppaf.sec_mask) >> pblk->ppaf.sec_offset;
> +	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->sect_offset;
>   
>   	return ppa;
>   }
> @@ -980,13 +965,15 @@ 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->ppaf;
>   	u64 paddr;
>   
> -	paddr = (u64)p.g.pg << pblk->ppaf.pg_offset;
> -	paddr |= (u64)p.g.lun << pblk->ppaf.lun_offset;
> -	paddr |= (u64)p.g.ch << pblk->ppaf.ch_offset;
> -	paddr |= (u64)p.g.pl << pblk->ppaf.pln_offset;
> -	paddr |= (u64)p.g.sec << pblk->ppaf.sec_offset;
> +	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->sect_offset;
>   
>   	return paddr;
>   }
> @@ -1003,18 +990,15 @@ 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 {
> -		ppa64.g.blk = (ppa32 & pblk->ppaf.blk_mask) >>
> -							pblk->ppaf.blk_offset;
> -		ppa64.g.pg = (ppa32 & pblk->ppaf.pg_mask) >>
> -							pblk->ppaf.pg_offset;
> -		ppa64.g.lun = (ppa32 & pblk->ppaf.lun_mask) >>
> -							pblk->ppaf.lun_offset;
> -		ppa64.g.ch = (ppa32 & pblk->ppaf.ch_mask) >>
> -							pblk->ppaf.ch_offset;
> -		ppa64.g.pl = (ppa32 & pblk->ppaf.pln_mask) >>
> -							pblk->ppaf.pln_offset;
> -		ppa64.g.sec = (ppa32 & pblk->ppaf.sec_mask) >>
> -							pblk->ppaf.sec_offset;
> +		struct nvm_addr_format_12 *ppaf =
> +				(struct nvm_addr_format_12 *)&pblk->ppaf;
> +
> +		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->sect_offset;
>   	}
>   
>   	return ppa64;
> @@ -1030,12 +1014,15 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
>   		ppa32 |= ppa64.c.line;
>   		ppa32 |= 1U << 31;
>   	} else {
> -		ppa32 |= ppa64.g.blk << pblk->ppaf.blk_offset;
> -		ppa32 |= ppa64.g.pg << pblk->ppaf.pg_offset;
> -		ppa32 |= ppa64.g.lun << pblk->ppaf.lun_offset;
> -		ppa32 |= ppa64.g.ch << pblk->ppaf.ch_offset;
> -		ppa32 |= ppa64.g.pl << pblk->ppaf.pln_offset;
> -		ppa32 |= ppa64.g.sec << pblk->ppaf.sec_offset;
> +		struct nvm_addr_format_12 *ppaf =
> +				(struct nvm_addr_format_12 *)&pblk->ppaf;
> +
> +		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->sect_offset;
>   	}
>   
>   	return ppa32;
> @@ -1153,7 +1140,7 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type)
>   	struct nvm_geo *geo = &dev->geo;
>   	int flags;
>   
> -	flags = geo->plane_mode >> 1;
> +	flags = geo->c.pln_mode >> 1;
>   
>   	if (type == PBLK_WRITE)
>   		flags |= NVM_IO_SCRAMBLE_ENABLE;
> @@ -1174,7 +1161,7 @@ static inline int pblk_set_read_mode(struct pblk *pblk, int type)
>   
>   	flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
>   	if (type == PBLK_READ_SEQUENTIAL)
> -		flags |= geo->plane_mode >> 1;
> +		flags |= geo->c.pln_mode >> 1;
>   
>   	return flags;
>   }
> @@ -1229,10 +1216,10 @@ static inline int pblk_boundary_ppa_checks(struct nvm_tgt_dev *tgt_dev,
>   		if (!ppa->c.is_cached &&
>   				ppa->g.ch < geo->nr_chnls &&
>   				ppa->g.lun < geo->nr_luns &&
> -				ppa->g.pl < geo->nr_planes &&
> -				ppa->g.blk < geo->nr_chks &&
> -				ppa->g.pg < geo->ws_per_chk &&
> -				ppa->g.sec < geo->sec_per_pg)
> +				ppa->g.pl < geo->c.num_pln &&
> +				ppa->g.blk < geo->c.num_chk &&
> +				ppa->g.pg < geo->c.num_pg &&
> +				ppa->g.sec < geo->c.ws_min)
>   			continue;
>   
>   		print_ppa(ppa, "boundary", i);
> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
> index 839c0b96466a..c81e64cc20d7 100644
> --- a/drivers/nvme/host/lightnvm.c
> +++ b/drivers/nvme/host/lightnvm.c
> @@ -152,8 +152,8 @@ struct nvme_nvm_id12_addrf {
>   	__u8			blk_len;
>   	__u8			pg_offset;
>   	__u8			pg_len;
> -	__u8			sect_offset;
> -	__u8			sect_len;
> +	__u8			sec_offset;
> +	__u8			sec_len;
>   	__u8			res[4];
>   } __packed;
>   
> @@ -254,106 +254,157 @@ static inline void _nvme_nvm_check_size(void)
>   	BUILD_BUG_ON(sizeof(struct nvme_nvm_id20) != NVME_IDENTIFY_DATA_SIZE);
>   }
>   
> -static int init_grp(struct nvm_id *nvm_id, struct nvme_nvm_id12 *id12)
> +static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
> +				 struct nvme_nvm_id12_addrf *src)
> +{
> +	dst->ch_len = src->ch_len;
> +	dst->lun_len = src->lun_len;
> +	dst->blk_len = src->blk_len;
> +	dst->pg_len = src->pg_len;
> +	dst->pln_len = src->pln_len;
> +	dst->sect_len = src->sec_len;
> +
> +	dst->ch_offset = src->ch_offset;
> +	dst->lun_offset = src->lun_offset;
> +	dst->blk_offset = src->blk_offset;
> +	dst->pg_offset = src->pg_offset;
> +	dst->pln_offset = src->pln_offset;
> +	dst->sect_offset = src->sec_offset;
> +
> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
> +	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
> +	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
> +	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
> +	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
> +}
> +
> +static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
> +			     struct nvm_dev_geo *dev_geo)
>   {
>   	struct nvme_nvm_id12_grp *src;
>   	int sec_per_pg, sec_per_pl, pg_per_blk;
>   
> -	if (id12->cgrps != 1)
> +	if (id->cgrps != 1)
>   		return -EINVAL;
>   
> -	src = &id12->grp;
> +	src = &id->grp;
>   
> -	nvm_id->mtype = src->mtype;
> -	nvm_id->fmtype = src->fmtype;
> +	if (src->mtype != 0) {
> +		pr_err("nvm: memory type not supported\n");
> +		return -EINVAL;
> +	}
> +
> +	/* 1.2 spec. only reports a single version id - unfold */
> +	dev_geo->ver_id = id->ver_id;
>   
> -	nvm_id->num_ch = src->num_ch;
> -	nvm_id->num_lun = src->num_lun;
> +	dev_geo->nr_chnls = src->num_ch;
> +	dev_geo->nr_luns = src->num_lun;
> +	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
>   
> -	nvm_id->num_chk = le16_to_cpu(src->num_chk);
> -	nvm_id->csecs = le16_to_cpu(src->csecs);
> -	nvm_id->sos = le16_to_cpu(src->sos);
> +	dev_geo->c.num_chk = le16_to_cpu(src->num_chk);
> +	dev_geo->c.csecs = le16_to_cpu(src->csecs);
> +	dev_geo->c.sos = le16_to_cpu(src->sos);
>   
>   	pg_per_blk = le16_to_cpu(src->num_pg);
> -	sec_per_pg = le16_to_cpu(src->fpg_sz) / nvm_id->csecs;
> +	sec_per_pg = le16_to_cpu(src->fpg_sz) / dev_geo->c.csecs;
>   	sec_per_pl = sec_per_pg * src->num_pln;
> -	nvm_id->clba = sec_per_pl * pg_per_blk;
> -	nvm_id->ws_per_chk = pg_per_blk;
> -
> -	nvm_id->mpos = le32_to_cpu(src->mpos);
> -	nvm_id->cpar = le16_to_cpu(src->cpar);
> -	nvm_id->mccap = le32_to_cpu(src->mccap);
> -
> -	nvm_id->ws_opt = nvm_id->ws_min = sec_per_pg;
> -	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
> -
> -	if (nvm_id->mpos & 0x020202) {
> -		nvm_id->ws_seq = NVM_IO_DUAL_ACCESS;
> -		nvm_id->ws_opt <<= 1;
> -	} else if (nvm_id->mpos & 0x040404) {
> -		nvm_id->ws_seq = NVM_IO_QUAD_ACCESS;
> -		nvm_id->ws_opt <<= 2;
> +	dev_geo->c.clba = sec_per_pl * pg_per_blk;
> +
> +	dev_geo->c.ws_min = sec_per_pg;
> +	dev_geo->c.ws_opt = sec_per_pg;
> +	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
> +
> +	dev_geo->c.mccap = le32_to_cpu(src->mccap);
> +
> +	dev_geo->c.trdt = le32_to_cpu(src->trdt);
> +	dev_geo->c.trdm = le32_to_cpu(src->trdm);
> +	dev_geo->c.tprt = le32_to_cpu(src->tprt);
> +	dev_geo->c.tprm = le32_to_cpu(src->tprm);
> +	dev_geo->c.tbet = le32_to_cpu(src->tbet);
> +	dev_geo->c.tbem = le32_to_cpu(src->tbem);
> +
> +	/* 1.2 compatibility */
> +	dev_geo->c.vmnt = id->vmnt;
> +	dev_geo->c.cap = le32_to_cpu(id->cap);
> +	dev_geo->c.dom = le32_to_cpu(id->dom);
> +
> +	dev_geo->c.mtype = src->mtype;
> +	dev_geo->c.fmtype = src->fmtype;
> +
> +	dev_geo->c.cpar = le16_to_cpu(src->cpar);
> +	dev_geo->c.mpos = le32_to_cpu(src->mpos);
> +
> +	dev_geo->c.pln_mode = NVM_PLANE_SINGLE;
> +
> +	if (dev_geo->c.mpos & 0x020202) {
> +		dev_geo->c.pln_mode = NVM_PLANE_DOUBLE;
> +		dev_geo->c.ws_opt <<= 1;
> +	} else if (dev_geo->c.mpos & 0x040404) {
> +		dev_geo->c.pln_mode = NVM_PLANE_QUAD;
> +		dev_geo->c.ws_opt <<= 2;
>   	}
>   
> -	nvm_id->trdt = le32_to_cpu(src->trdt);
> -	nvm_id->trdm = le32_to_cpu(src->trdm);
> -	nvm_id->tprt = le32_to_cpu(src->tprt);
> -	nvm_id->tprm = le32_to_cpu(src->tprm);
> -	nvm_id->tbet = le32_to_cpu(src->tbet);
> -	nvm_id->tbem = le32_to_cpu(src->tbem);
> -
> -	/* 1.2 compatibility */
> -	nvm_id->num_pln = src->num_pln;
> -	nvm_id->num_pg = le16_to_cpu(src->num_pg);
> -	nvm_id->fpg_sz = le16_to_cpu(src->fpg_sz);
> +	dev_geo->c.num_pln = src->num_pln;
> +	dev_geo->c.num_pg = le16_to_cpu(src->num_pg);
> +	dev_geo->c.fpg_sz = le16_to_cpu(src->fpg_sz);
> +
> +	nvme_nvm_set_addr_12((struct nvm_addr_format_12 *)&dev_geo->c.addrf,
> +								&id->ppaf);
>   
>   	return 0;
>   }
>   
> -static int nvme_nvm_setup_12(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
> -		struct nvme_nvm_id12 *id)
> +static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
> +				 struct nvme_nvm_id20_addrf *src)
>   {
> -	nvm_id->ver_id = id->ver_id;
> -	nvm_id->vmnt = id->vmnt;
> -	nvm_id->cap = le32_to_cpu(id->cap);
> -	nvm_id->dom = le32_to_cpu(id->dom);
> -	memcpy(&nvm_id->ppaf, &id->ppaf,
> -					sizeof(struct nvm_addr_format));
> -
> -	return init_grp(nvm_id, id);
> +	dst->ch_len = src->grp_len;
> +	dst->lun_len = src->pu_len;
> +	dst->chk_len = src->chk_len;
> +	dst->sec_len = src->lba_len;
> +
> +	dst->sec_offset = 0;
> +	dst->chk_offset = dst->sec_len;
> +	dst->lun_offset = dst->chk_offset + dst->chk_len;
> +	dst->ch_offset = dst->lun_offset + dst->lun_len;
> +
> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
> +	dst->chk_mask = ((1ULL << dst->chk_len) - 1) << dst->chk_offset;
> +	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>   }
>   
> -static int nvme_nvm_setup_20(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
> -		struct nvme_nvm_id20 *id)
> +static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
> +			     struct nvm_dev_geo *dev_geo)
>   {
> -	nvm_id->ver_id = id->mjr;
> +	dev_geo->ver_id = id->mjr;
>   
> -	nvm_id->num_ch = le16_to_cpu(id->num_grp);
> -	nvm_id->num_lun = le16_to_cpu(id->num_pu);
> -	nvm_id->num_chk = le32_to_cpu(id->num_chk);
> -	nvm_id->clba = le32_to_cpu(id->clba);
> +	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
> +	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
> +	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
>   
> -	nvm_id->ws_min = le32_to_cpu(id->ws_min);
> -	nvm_id->ws_opt = le32_to_cpu(id->ws_opt);
> -	nvm_id->mw_cunits = le32_to_cpu(id->mw_cunits);
> +	dev_geo->c.num_chk = le32_to_cpu(id->num_chk);
> +	dev_geo->c.clba = le32_to_cpu(id->clba);
> +	dev_geo->c.csecs = -1;		/* Set by nvme identify */
> +	dev_geo->c.sos = -1;		/* Set bu nvme identify */
>   
> -	nvm_id->trdt = le32_to_cpu(id->trdt);
> -	nvm_id->trdm = le32_to_cpu(id->trdm);
> -	nvm_id->tprt = le32_to_cpu(id->twrt);
> -	nvm_id->tprm = le32_to_cpu(id->twrm);
> -	nvm_id->tbet = le32_to_cpu(id->tcrst);
> -	nvm_id->tbem = le32_to_cpu(id->tcrsm);
> +	dev_geo->c.ws_min = le32_to_cpu(id->ws_min);
> +	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
> +	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
>   
> -	/* calculated values */
> -	nvm_id->ws_per_chk = nvm_id->clba / nvm_id->ws_min;
> +	dev_geo->c.trdt = le32_to_cpu(id->trdt);
> +	dev_geo->c.trdm = le32_to_cpu(id->trdm);
> +	dev_geo->c.tprt = le32_to_cpu(id->twrt);
> +	dev_geo->c.tprm = le32_to_cpu(id->twrm);
> +	dev_geo->c.tbet = le32_to_cpu(id->tcrst);
> +	dev_geo->c.tbem = le32_to_cpu(id->tcrsm);
>   
> -	/* 1.2 compatibility */
> -	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
> +	nvme_nvm_set_addr_20(&dev_geo->c.addrf, &id->lbaf);
>   
>   	return 0;
>   }
>   
> -static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
> +static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>   {
>   	struct nvme_ns *ns = nvmdev->q->queuedata;
>   	struct nvme_nvm_id12 *id;
> @@ -380,18 +431,18 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
>   	 */
>   	switch (id->ver_id) {
>   	case 1:
> -		ret = nvme_nvm_setup_12(nvmdev, nvm_id, id);
> +		ret = nvme_nvm_setup_12(id, &nvmdev->dev_geo);
>   		break;
>   	case 2:
> -		ret = nvme_nvm_setup_20(nvmdev, nvm_id,
> -				(struct nvme_nvm_id20 *)id);
> +		ret = nvme_nvm_setup_20((struct nvme_nvm_id20 *)id,
> +							&nvmdev->dev_geo);
>   		break;
>   	default:
> -		dev_err(ns->ctrl->device,
> -			"OCSSD revision not supported (%d)\n",
> -			nvm_id->ver_id);
> +		dev_err(ns->ctrl->device, "OCSSD revision not supported (%d)\n",
> +							id->ver_id);
>   		ret = -EINVAL;
>   	}
> +
>   out:
>   	kfree(id);
>   	return ret;
> @@ -401,12 +452,12 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
>   								u8 *blks)
>   {
>   	struct request_queue *q = nvmdev->q;
> -	struct nvm_geo *geo = &nvmdev->geo;
> +	struct nvm_dev_geo *dev_geo = &nvmdev->dev_geo;
>   	struct nvme_ns *ns = q->queuedata;
>   	struct nvme_ctrl *ctrl = ns->ctrl;
>   	struct nvme_nvm_command c = {};
>   	struct nvme_nvm_bb_tbl *bb_tbl;
> -	int nr_blks = geo->nr_chks * geo->plane_mode;
> +	int nr_blks = dev_geo->c.num_chk * dev_geo->c.num_pln;
>   	int tblsz = sizeof(struct nvme_nvm_bb_tbl) + nr_blks;
>   	int ret = 0;
>   
> @@ -447,7 +498,7 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
>   		goto out;
>   	}
>   
> -	memcpy(blks, bb_tbl->blk, geo->nr_chks * geo->plane_mode);
> +	memcpy(blks, bb_tbl->blk, dev_geo->c.num_chk * dev_geo->c.num_pln);
>   out:
>   	kfree(bb_tbl);
>   	return ret;
> @@ -815,9 +866,10 @@ int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd, unsigned long arg)
>   void nvme_nvm_update_nvm_info(struct nvme_ns *ns)
>   {
>   	struct nvm_dev *ndev = ns->ndev;
> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>   
> -	ndev->identity.csecs = ndev->geo.sec_size = 1 << ns->lba_shift;
> -	ndev->identity.sos = ndev->geo.oob_size = ns->ms;
> +	dev_geo->c.csecs = 1 << ns->lba_shift;
> +	dev_geo->c.sos = ns->ms;
>   }
>   
>   int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node)
> @@ -850,23 +902,22 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>   {
>   	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>   	struct nvm_dev *ndev = ns->ndev;
> -	struct nvm_id *id;
> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>   	struct attribute *attr;
>   
>   	if (!ndev)
>   		return 0;
>   
> -	id = &ndev->identity;
>   	attr = &dattr->attr;
>   
>   	if (strcmp(attr->name, "version") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ver_id);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>   	} else if (strcmp(attr->name, "capabilities") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->cap);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
>   	} else if (strcmp(attr->name, "read_typ") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdt);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>   	} else if (strcmp(attr->name, "read_max") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdm);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdm);
>   	} else {
>   		return scnprintf(page,
>   				 PAGE_SIZE,
> @@ -875,75 +926,79 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>   	}
>   }
>   
> +static ssize_t nvm_dev_attr_show_ppaf(struct nvm_addr_format_12 *ppaf,
> +					 char *page)
> +{
> +	return scnprintf(page, PAGE_SIZE,
> +		"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
> +				ppaf->ch_offset, ppaf->ch_len,
> +				ppaf->lun_offset, ppaf->lun_len,
> +				ppaf->pln_offset, ppaf->pln_len,
> +				ppaf->blk_offset, ppaf->blk_len,
> +				ppaf->pg_offset, ppaf->pg_len,
> +				ppaf->sect_offset, ppaf->sect_len);
> +}
> +
>   static ssize_t nvm_dev_attr_show_12(struct device *dev,
>   		struct device_attribute *dattr, char *page)
>   {
>   	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>   	struct nvm_dev *ndev = ns->ndev;
> -	struct nvm_id *id;
> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>   	struct attribute *attr;
>   
>   	if (!ndev)
>   		return 0;
>   
> -	id = &ndev->identity;
>   	attr = &dattr->attr;
>   
>   	if (strcmp(attr->name, "vendor_opcode") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->vmnt);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.vmnt);
>   	} else if (strcmp(attr->name, "device_mode") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->dom);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.dom);
>   	/* kept for compatibility */
>   	} else if (strcmp(attr->name, "media_manager") == 0) {
>   		return scnprintf(page, PAGE_SIZE, "%s\n", "gennvm");
>   	} else if (strcmp(attr->name, "ppa_format") == 0) {
> -		return scnprintf(page, PAGE_SIZE,
> -			"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
> -			id->ppaf.ch_offset, id->ppaf.ch_len,
> -			id->ppaf.lun_offset, id->ppaf.lun_len,
> -			id->ppaf.pln_offset, id->ppaf.pln_len,
> -			id->ppaf.blk_offset, id->ppaf.blk_len,
> -			id->ppaf.pg_offset, id->ppaf.pg_len,
> -			id->ppaf.sect_offset, id->ppaf.sect_len);
> +		return nvm_dev_attr_show_ppaf((void *)&dev_geo->c.addrf, page);
>   	} else if (strcmp(attr->name, "media_type") == 0) {	/* u8 */
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->mtype);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mtype);
>   	} else if (strcmp(attr->name, "flash_media_type") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->fmtype);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fmtype);
>   	} else if (strcmp(attr->name, "num_channels") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
>   	} else if (strcmp(attr->name, "num_luns") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
>   	} else if (strcmp(attr->name, "num_planes") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pln);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pln);
>   	} else if (strcmp(attr->name, "num_blocks") == 0) {	/* u16 */
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
>   	} else if (strcmp(attr->name, "num_pages") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pg);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pg);
>   	} else if (strcmp(attr->name, "page_size") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->fpg_sz);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fpg_sz);
>   	} else if (strcmp(attr->name, "hw_sector_size") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->csecs);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.csecs);
>   	} else if (strcmp(attr->name, "oob_sector_size") == 0) {/* u32 */
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->sos);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.sos);
>   	} else if (strcmp(attr->name, "prog_typ") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
>   	} else if (strcmp(attr->name, "prog_max") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
>   	} else if (strcmp(attr->name, "erase_typ") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
>   	} else if (strcmp(attr->name, "erase_max") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>   	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mpos);
> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
>   	} else if (strcmp(attr->name, "media_capabilities") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mccap);
> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
>   	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
>   		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>   	} else {
> -		return scnprintf(page,
> -				 PAGE_SIZE,
> -				 "Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
> -				 attr->name);
> +		return scnprintf(page, PAGE_SIZE,
> +			"Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
> +			attr->name);
>   	}
>   }
>   
> @@ -952,42 +1007,40 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>   {
>   	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>   	struct nvm_dev *ndev = ns->ndev;
> -	struct nvm_id *id;
> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>   	struct attribute *attr;
>   
>   	if (!ndev)
>   		return 0;
>   
> -	id = &ndev->identity;
>   	attr = &dattr->attr;
>   
>   	if (strcmp(attr->name, "groups") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
>   	} else if (strcmp(attr->name, "punits") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
>   	} else if (strcmp(attr->name, "chunks") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
>   	} else if (strcmp(attr->name, "clba") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->clba);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.clba);
>   	} else if (strcmp(attr->name, "ws_min") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_min);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_min);
>   	} else if (strcmp(attr->name, "ws_opt") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_opt);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_opt);
>   	} else if (strcmp(attr->name, "mw_cunits") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->mw_cunits);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mw_cunits);
>   	} else if (strcmp(attr->name, "write_typ") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
>   	} else if (strcmp(attr->name, "write_max") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
>   	} else if (strcmp(attr->name, "reset_typ") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
>   	} else if (strcmp(attr->name, "reset_max") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>   	} else {
> -		return scnprintf(page,
> -				 PAGE_SIZE,
> -				 "Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
> -				 attr->name);
> +		return scnprintf(page, PAGE_SIZE,
> +			"Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
> +			attr->name);
>   	}
>   }
>   
> @@ -1106,10 +1159,13 @@ static const struct attribute_group nvm_dev_attr_group_20 = {
>   
>   int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>   {
> -	if (!ns->ndev)
> +	struct nvm_dev *ndev = ns->ndev;
> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
> +
> +	if (!ndev)
>   		return -EINVAL;
>   
> -	switch (ns->ndev->identity.ver_id) {
> +	switch (dev_geo->ver_id) {
>   	case 1:
>   		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
>   					&nvm_dev_attr_group_12);
> @@ -1123,7 +1179,10 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>   
>   void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
>   {
> -	switch (ns->ndev->identity.ver_id) {
> +	struct nvm_dev *ndev = ns->ndev;
> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
> +
> +	switch (dev_geo->ver_id) {
>   	case 1:
>   		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
>   					&nvm_dev_attr_group_12);
> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
> index e55b10573c99..18e3751b1632 100644
> --- a/include/linux/lightnvm.h
> +++ b/include/linux/lightnvm.h
> @@ -50,7 +50,7 @@ struct nvm_id;
>   struct nvm_dev;
>   struct nvm_tgt_dev;
>   
> -typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *);
> +typedef int (nvm_id_fn)(struct nvm_dev *);
>   typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, u8 *);
>   typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct ppa_addr *, int, int);
>   typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
> @@ -152,62 +152,107 @@ struct nvm_id_lp_tbl {
>   	struct nvm_id_lp_mlc mlc;
>   };
>   
> -struct nvm_addr_format {
> -	u8	ch_offset;
> +struct nvm_addr_format_12 {
>   	u8	ch_len;
> -	u8	lun_offset;
>   	u8	lun_len;
> -	u8	pln_offset;
> +	u8	blk_len;
> +	u8	pg_len;
>   	u8	pln_len;
> +	u8	sect_len;
> +
> +	u8	ch_offset;
> +	u8	lun_offset;
>   	u8	blk_offset;
> -	u8	blk_len;
>   	u8	pg_offset;
> -	u8	pg_len;
> +	u8	pln_offset;
>   	u8	sect_offset;
> -	u8	sect_len;
> +
> +	u64	ch_mask;
> +	u64	lun_mask;
> +	u64	blk_mask;
> +	u64	pg_mask;
> +	u64	pln_mask;
> +	u64	sec_mask;
> +};
> +
> +struct nvm_addr_format {
> +	u8	ch_len;
> +	u8	lun_len;
> +	u8	chk_len;
> +	u8	sec_len;
> +	u8	rsv_len[2];
> +
> +	u8	ch_offset;
> +	u8	lun_offset;
> +	u8	chk_offset;
> +	u8	sec_offset;
> +	u8	rsv_off[2];
> +
> +	u64	ch_mask;
> +	u64	lun_mask;
> +	u64	chk_mask;
> +	u64	sec_mask;
> +	u64	rsv_mask[2];
>   };
>   
> -struct nvm_id {
> -	u8	ver_id;
> +/* Device common geometry */
> +struct nvm_common_geo {
> +	/* chunk geometry */
> +	u32	num_chk;	/* chunks per lun */
> +	u32	clba;		/* sectors per chunk */
> +	u16	csecs;		/* sector size */
> +	u16	sos;		/* out-of-band area size */
> +
> +	/* device write constrains */
> +	u32	ws_min;		/* minimum write size */
> +	u32	ws_opt;		/* optimal write size */
> +	u32	mw_cunits;	/* distance required for successful read */
> +
> +	/* device capabilities */
> +	u32	mccap;
> +
> +	/* device timings */
> +	u32	trdt;		/* Avg. Tread (ns) */
> +	u32	trdm;		/* Max Tread (ns) */
> +	u32	tprt;		/* Avg. Tprog (ns) */
> +	u32	tprm;		/* Max Tprog (ns) */
> +	u32	tbet;		/* Avg. Terase (ns) */
> +	u32	tbem;		/* Max Terase (ns) */
> +
> +	/* generic address format */
> +	struct nvm_addr_format addrf;
> +
> +	/* 1.2 compatibility */
>   	u8	vmnt;
>   	u32	cap;
>   	u32	dom;
>   
> -	struct	nvm_addr_format ppaf;
> -
> -	u8	num_ch;
> -	u8	num_lun;
> -	u16	num_chk;
> -	u16	clba;
> -	u16	csecs;
> -	u16	sos;
> -
> -	u32	ws_min;
> -	u32	ws_opt;
> -	u32	mw_cunits;
> -
> -	u32	trdt;
> -	u32	trdm;
> -	u32	tprt;
> -	u32	tprm;
> -	u32	tbet;
> -	u32	tbem;
> -	u32	mpos;
> -	u32	mccap;
> -	u16	cpar;
> -
> -	/* calculated values */
> -	u16	ws_seq;
> -	u16	ws_per_chk;
> -
> -	/* 1.2 compatibility */
>   	u8	mtype;
>   	u8	fmtype;
>   
> +	u16	cpar;
> +	u32	mpos;
> +
>   	u8	num_pln;
> +	u8	pln_mode;
>   	u16	num_pg;
>   	u16	fpg_sz;
> -} __packed;
> +};
> +
> +/* Device identified geometry */
> +struct nvm_dev_geo {
> +	/* device reported version */
> +	u8	ver_id;
> +
> +	/* full device geometry */
> +	u16	nr_chnls;
> +	u16	nr_luns;
> +
> +	/* calculated values */
> +	u16	all_luns;
> +
> +	struct nvm_common_geo c;
> +};
>   
>   struct nvm_target {
>   	struct list_head list;
> @@ -274,36 +319,22 @@ enum {
>   	NVM_BLK_ST_BAD =	0x8,	/* Bad block */
>   };
>   
> -
> -/* Device generic information */
> +/* Instance geometry */
>   struct nvm_geo {
> -	/* generic geometry */
> +	/* instance specific geometry */
>   	int nr_chnls;
> -	int all_luns; /* across channels */
> -	int nr_luns; /* per channel */
> -	int nr_chks; /* per lun */
> -
> -	int sec_size;
> -	int oob_size;
> -	int mccap;
> -
> -	int sec_per_chk;
> -	int sec_per_lun;
> -
> -	int ws_min;
> -	int ws_opt;
> -	int ws_seq;
> -	int ws_per_chk;
> +	int nr_luns;		/* per channel */
>   
>   	int op;
>   
> -	struct nvm_addr_format ppaf;
> +	/* common geometry */
> +	struct nvm_common_geo c;
>   
> -	/* Legacy 1.2 specific geometry */
> -	int plane_mode; /* drive device in single, double or quad mode */
> -	int nr_planes;
> -	int sec_per_pg; /* only sectors for a single page */
> -	int sec_per_pl; /* all sectors across planes */
> +	/* calculated values */
> +	int all_luns;		/* across channels */
> +	int all_chunks;		/* across channels */
> +
> +	sector_t total_secs;	/* across channels */
>   };
>   
>   /* sub-device structure */
> @@ -314,9 +345,6 @@ struct nvm_tgt_dev {
>   	/* Base ppas for target LUNs */
>   	struct ppa_addr *luns;
>   
> -	sector_t total_secs;
> -
> -	struct nvm_id identity;
>   	struct request_queue *q;
>   
>   	struct nvm_dev *parent;
> @@ -329,15 +357,11 @@ struct nvm_dev {
>   	struct list_head devices;
>   
>   	/* Device information */
> -	struct nvm_geo geo;
> -
> -	unsigned long total_secs;
> +	struct nvm_dev_geo dev_geo;
>   
>   	unsigned long *lun_map;
>   	void *dma_pool;
>   
> -	struct nvm_id identity;
> -
>   	/* Backend device */
>   	struct request_queue *q;
>   	char name[DISK_NAME_LEN];
> @@ -357,14 +381,16 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
>   						  struct ppa_addr r)
>   {
>   	struct nvm_geo *geo = &tgt_dev->geo;
> +	struct nvm_addr_format_12 *ppaf =
> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>   	struct ppa_addr l;
>   
> -	l.ppa = ((u64)r.g.blk) << geo->ppaf.blk_offset;
> -	l.ppa |= ((u64)r.g.pg) << geo->ppaf.pg_offset;
> -	l.ppa |= ((u64)r.g.sec) << geo->ppaf.sect_offset;
> -	l.ppa |= ((u64)r.g.pl) << geo->ppaf.pln_offset;
> -	l.ppa |= ((u64)r.g.lun) << geo->ppaf.lun_offset;
> -	l.ppa |= ((u64)r.g.ch) << geo->ppaf.ch_offset;
> +	l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
> +	l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
> +	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
> +	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
> +	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
> +	l.ppa |= ((u64)r.g.sec) << ppaf->sect_offset;
>   
>   	return l;
>   }
> @@ -373,24 +399,18 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
>   						  struct ppa_addr r)
>   {
>   	struct nvm_geo *geo = &tgt_dev->geo;
> +	struct nvm_addr_format_12 *ppaf =
> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>   	struct ppa_addr l;
>   
>   	l.ppa = 0;
> -	/*
> -	 * (r.ppa << X offset) & X len bitmask. X eq. blk, pg, etc.
> -	 */
> -	l.g.blk = (r.ppa >> geo->ppaf.blk_offset) &
> -					(((1 << geo->ppaf.blk_len) - 1));
> -	l.g.pg |= (r.ppa >> geo->ppaf.pg_offset) &
> -					(((1 << geo->ppaf.pg_len) - 1));
> -	l.g.sec |= (r.ppa >> geo->ppaf.sect_offset) &
> -					(((1 << geo->ppaf.sect_len) - 1));
> -	l.g.pl |= (r.ppa >> geo->ppaf.pln_offset) &
> -					(((1 << geo->ppaf.pln_len) - 1));
> -	l.g.lun |= (r.ppa >> geo->ppaf.lun_offset) &
> -					(((1 << geo->ppaf.lun_len) - 1));
> -	l.g.ch |= (r.ppa >> geo->ppaf.ch_offset) &
> -					(((1 << geo->ppaf.ch_len) - 1));
> +
> +	l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
> +	l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
> +	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
> +	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
> +	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
> +	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sect_offset;
>   
>   	return l;
>   }
> 

Thanks for the patch. I appreciate the work, but it is not the way I 
want the 2.0 representation to go. The 2.0 variables should stay in the 
nvm_geo data structure, and then if any 1.2 variables are on the side, 
they can be in a substructure.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 02/20] lightnvm: add controller capabilities to 2.0
  2018-02-21  9:26   ` Javier González
@ 2018-02-22  7:26     ` Matias Bjørling
  -1 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:26 UTC (permalink / raw)
  To: Javier González
  Cc: linux-block, linux-kernel, linux-nvme, Javier González

On 02/21/2018 10:26 AM, Javier González wrote:
> Assign missing mccap value on 2.0 path
> 
> Signed-off-by: Javier González <javier@cnexlabs.com>
> ---
>   drivers/nvme/host/lightnvm.c | 2 ++
>   1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
> index c81e64cc20d7..969bb874850c 100644
> --- a/drivers/nvme/host/lightnvm.c
> +++ b/drivers/nvme/host/lightnvm.c
> @@ -392,6 +392,8 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>   	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
>   	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
>   
> +	dev_geo->c.mccap = le32_to_cpu(id->mccap);
> +
>   	dev_geo->c.trdt = le32_to_cpu(id->trdt);
>   	dev_geo->c.trdm = le32_to_cpu(id->trdm);
>   	dev_geo->c.tprt = le32_to_cpu(id->twrt);
> 

The mccap field between 1.2 and 2.0 is orthogonal. They represent two 
different capabilities fields. The mccap has to be interpreted if used.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 02/20] lightnvm: add controller capabilities to 2.0
@ 2018-02-22  7:26     ` Matias Bjørling
  0 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:26 UTC (permalink / raw)


On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
> Assign missing mccap value on 2.0 path
> 
> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
> ---
>   drivers/nvme/host/lightnvm.c | 2 ++
>   1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
> index c81e64cc20d7..969bb874850c 100644
> --- a/drivers/nvme/host/lightnvm.c
> +++ b/drivers/nvme/host/lightnvm.c
> @@ -392,6 +392,8 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>   	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
>   	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
>   
> +	dev_geo->c.mccap = le32_to_cpu(id->mccap);
> +
>   	dev_geo->c.trdt = le32_to_cpu(id->trdt);
>   	dev_geo->c.trdm = le32_to_cpu(id->trdm);
>   	dev_geo->c.tprt = le32_to_cpu(id->twrt);
> 

The mccap field between 1.2 and 2.0 is orthogonal. They represent two 
different capabilities fields. The mccap has to be interpreted if used.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 03/20] lightnvm: fix capabilities for 2.0 sysfs
  2018-02-21  9:26   ` Javier González
@ 2018-02-22  7:28     ` Matias Bjørling
  -1 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:28 UTC (permalink / raw)
  To: Javier González
  Cc: linux-block, linux-kernel, linux-nvme, Javier González

On 02/21/2018 10:26 AM, Javier González wrote:
> Both 1.2 and 2.0 specs define a field for media and controller
> capabilities. Also, 1.2 defines a separate field dedicated to device
> capabilities.
> 
> In 2.0 sysfs, this values have been mixed. Revert them to the right
> value.
> 
> Signed-off-by: Javier González <javier@cnexlabs.com>
> ---
>   drivers/nvme/host/lightnvm.c | 18 +++++++++---------
>   1 file changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
> index 969bb874850c..598abba66f52 100644
> --- a/drivers/nvme/host/lightnvm.c
> +++ b/drivers/nvme/host/lightnvm.c
> @@ -914,8 +914,8 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>   
>   	if (strcmp(attr->name, "version") == 0) {
>   		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
> -	} else if (strcmp(attr->name, "capabilities") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
> +	} else if (strcmp(attr->name, "media_capabilities") == 0) {
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
>   	} else if (strcmp(attr->name, "read_typ") == 0) {
>   		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>   	} else if (strcmp(attr->name, "read_max") == 0) {
> @@ -993,8 +993,8 @@ static ssize_t nvm_dev_attr_show_12(struct device *dev,
>   		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>   	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
>   		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
> -	} else if (strcmp(attr->name, "media_capabilities") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
> +	} else if (strcmp(attr->name, "capabilities") == 0) {
> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.cap);
>   	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
>   		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>   	} else {
> @@ -1055,7 +1055,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>   
>   /* general attributes */
>   static NVM_DEV_ATTR_RO(version);
> -static NVM_DEV_ATTR_RO(capabilities);
> +static NVM_DEV_ATTR_RO(media_capabilities);
>   
>   static NVM_DEV_ATTR_RO(read_typ);
>   static NVM_DEV_ATTR_RO(read_max);
> @@ -1080,12 +1080,12 @@ static NVM_DEV_ATTR_12_RO(prog_max);
>   static NVM_DEV_ATTR_12_RO(erase_typ);
>   static NVM_DEV_ATTR_12_RO(erase_max);
>   static NVM_DEV_ATTR_12_RO(multiplane_modes);
> -static NVM_DEV_ATTR_12_RO(media_capabilities);
> +static NVM_DEV_ATTR_12_RO(capabilities);
>   static NVM_DEV_ATTR_12_RO(max_phys_secs);
>   
>   static struct attribute *nvm_dev_attrs_12[] = {
>   	&dev_attr_version.attr,
> -	&dev_attr_capabilities.attr,
> +	&dev_attr_media_capabilities.attr,
>   
>   	&dev_attr_vendor_opcode.attr,
>   	&dev_attr_device_mode.attr,
> @@ -1108,7 +1108,7 @@ static struct attribute *nvm_dev_attrs_12[] = {
>   	&dev_attr_erase_typ.attr,
>   	&dev_attr_erase_max.attr,
>   	&dev_attr_multiplane_modes.attr,
> -	&dev_attr_media_capabilities.attr,
> +	&dev_attr_capabilities.attr,
>   	&dev_attr_max_phys_secs.attr,
>   
>   	NULL,
> @@ -1134,7 +1134,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
>   
>   static struct attribute *nvm_dev_attrs_20[] = {
>   	&dev_attr_version.attr,
> -	&dev_attr_capabilities.attr,
> +	&dev_attr_media_capabilities.attr,
>   
>   	&dev_attr_groups.attr,
>   	&dev_attr_punits.attr,
> 

With the mccap changes, it should make sense to keep the capabilities as is.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 03/20] lightnvm: fix capabilities for 2.0 sysfs
@ 2018-02-22  7:28     ` Matias Bjørling
  0 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:28 UTC (permalink / raw)


On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
> Both 1.2 and 2.0 specs define a field for media and controller
> capabilities. Also, 1.2 defines a separate field dedicated to device
> capabilities.
> 
> In 2.0 sysfs, this values have been mixed. Revert them to the right
> value.
> 
> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
> ---
>   drivers/nvme/host/lightnvm.c | 18 +++++++++---------
>   1 file changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
> index 969bb874850c..598abba66f52 100644
> --- a/drivers/nvme/host/lightnvm.c
> +++ b/drivers/nvme/host/lightnvm.c
> @@ -914,8 +914,8 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>   
>   	if (strcmp(attr->name, "version") == 0) {
>   		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
> -	} else if (strcmp(attr->name, "capabilities") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
> +	} else if (strcmp(attr->name, "media_capabilities") == 0) {
> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
>   	} else if (strcmp(attr->name, "read_typ") == 0) {
>   		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>   	} else if (strcmp(attr->name, "read_max") == 0) {
> @@ -993,8 +993,8 @@ static ssize_t nvm_dev_attr_show_12(struct device *dev,
>   		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>   	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
>   		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
> -	} else if (strcmp(attr->name, "media_capabilities") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
> +	} else if (strcmp(attr->name, "capabilities") == 0) {
> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.cap);
>   	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
>   		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>   	} else {
> @@ -1055,7 +1055,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>   
>   /* general attributes */
>   static NVM_DEV_ATTR_RO(version);
> -static NVM_DEV_ATTR_RO(capabilities);
> +static NVM_DEV_ATTR_RO(media_capabilities);
>   
>   static NVM_DEV_ATTR_RO(read_typ);
>   static NVM_DEV_ATTR_RO(read_max);
> @@ -1080,12 +1080,12 @@ static NVM_DEV_ATTR_12_RO(prog_max);
>   static NVM_DEV_ATTR_12_RO(erase_typ);
>   static NVM_DEV_ATTR_12_RO(erase_max);
>   static NVM_DEV_ATTR_12_RO(multiplane_modes);
> -static NVM_DEV_ATTR_12_RO(media_capabilities);
> +static NVM_DEV_ATTR_12_RO(capabilities);
>   static NVM_DEV_ATTR_12_RO(max_phys_secs);
>   
>   static struct attribute *nvm_dev_attrs_12[] = {
>   	&dev_attr_version.attr,
> -	&dev_attr_capabilities.attr,
> +	&dev_attr_media_capabilities.attr,
>   
>   	&dev_attr_vendor_opcode.attr,
>   	&dev_attr_device_mode.attr,
> @@ -1108,7 +1108,7 @@ static struct attribute *nvm_dev_attrs_12[] = {
>   	&dev_attr_erase_typ.attr,
>   	&dev_attr_erase_max.attr,
>   	&dev_attr_multiplane_modes.attr,
> -	&dev_attr_media_capabilities.attr,
> +	&dev_attr_capabilities.attr,
>   	&dev_attr_max_phys_secs.attr,
>   
>   	NULL,
> @@ -1134,7 +1134,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
>   
>   static struct attribute *nvm_dev_attrs_20[] = {
>   	&dev_attr_version.attr,
> -	&dev_attr_capabilities.attr,
> +	&dev_attr_media_capabilities.attr,
>   
>   	&dev_attr_groups.attr,
>   	&dev_attr_punits.attr,
> 

With the mccap changes, it should make sense to keep the capabilities as is.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 04/20] lightnvm: add minor version to generic geometry
  2018-02-21  9:26   ` Javier González
@ 2018-02-22  7:34     ` Matias Bjørling
  -1 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:34 UTC (permalink / raw)
  To: Javier González
  Cc: linux-block, linux-kernel, linux-nvme, Javier González

On 02/21/2018 10:26 AM, Javier González wrote:
> Separate the version between major and minor on the generic geometry.
> Also, add a "subversion" entry to sysfs to expose the minor version
> without breaking user space.
> 
> Signed-off-by: Javier González <javier@cnexlabs.com>
> ---
>   drivers/lightnvm/core.c      |  4 ++--
>   drivers/nvme/host/lightnvm.c | 25 ++++++++++++++++++++-----
>   include/linux/lightnvm.h     |  3 ++-
>   3 files changed, 24 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
> index 42596afdf64c..dc9ec6baff45 100644
> --- a/drivers/lightnvm/core.c
> +++ b/drivers/lightnvm/core.c
> @@ -897,8 +897,8 @@ static int nvm_init(struct nvm_dev *dev)
>   		goto err;
>   	}
>   
> -	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
> -				dev_geo->ver_id,
> +	pr_debug("nvm: ver:%u.%u nvm_vendor:%x\n",
> +				dev_geo->major_ver_id, dev_geo->minor_ver_id,
>   				dev_geo->c.vmnt);
>   
>   	ret = nvm_core_init(dev);
> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
> index 598abba66f52..71b4ac57a668 100644
> --- a/drivers/nvme/host/lightnvm.c
> +++ b/drivers/nvme/host/lightnvm.c
> @@ -296,7 +296,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>   	}
>   
>   	/* 1.2 spec. only reports a single version id - unfold */
> -	dev_geo->ver_id = id->ver_id;
> +	dev_geo->major_ver_id = id->ver_id;
> +	dev_geo->minor_ver_id = 2;
>   
>   	dev_geo->nr_chnls = src->num_ch;
>   	dev_geo->nr_luns = src->num_lun;
> @@ -377,7 +378,14 @@ static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
>   static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>   			     struct nvm_dev_geo *dev_geo)
>   {
> -	dev_geo->ver_id = id->mjr;
> +	dev_geo->major_ver_id = id->mjr;
> +	dev_geo->minor_ver_id = id->mnr;
> +
> +	if (!(dev_geo->major_ver_id == 2 && dev_geo->minor_ver_id == 0)) {
> +		pr_err("nvm: OCSSD version not supported (v%d.%d)\n",
> +				dev_geo->major_ver_id, dev_geo->minor_ver_id);
> +		return -EINVAL;
> +	}
>   
>   	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
>   	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
> @@ -913,7 +921,11 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>   	attr = &dattr->attr;
>   
>   	if (strcmp(attr->name, "version") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
> +		return scnprintf(page, PAGE_SIZE, "%u\n",
> +						dev_geo->major_ver_id);
> +	} else if (strcmp(attr->name, "subversion") == 0) {
> +		return scnprintf(page, PAGE_SIZE, "%u\n",
> +						dev_geo->minor_ver_id);
>   	} else if (strcmp(attr->name, "media_capabilities") == 0) {
>   		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
>   	} else if (strcmp(attr->name, "read_typ") == 0) {
> @@ -1055,6 +1067,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>   
>   /* general attributes */
>   static NVM_DEV_ATTR_RO(version);
> +static NVM_DEV_ATTR_RO(subversion);
>   static NVM_DEV_ATTR_RO(media_capabilities);
>   
>   static NVM_DEV_ATTR_RO(read_typ);
> @@ -1085,6 +1098,7 @@ static NVM_DEV_ATTR_12_RO(max_phys_secs);
>   
>   static struct attribute *nvm_dev_attrs_12[] = {
>   	&dev_attr_version.attr,
> +	&dev_attr_subversion.attr,
>   	&dev_attr_media_capabilities.attr,
>   
>   	&dev_attr_vendor_opcode.attr,
> @@ -1134,6 +1148,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
>   
>   static struct attribute *nvm_dev_attrs_20[] = {
>   	&dev_attr_version.attr,
> +	&dev_attr_subversion.attr,
>   	&dev_attr_media_capabilities.attr,
>   
>   	&dev_attr_groups.attr,
> @@ -1167,7 +1182,7 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>   	if (!ndev)
>   		return -EINVAL;
>   
> -	switch (dev_geo->ver_id) {
> +	switch (dev_geo->major_ver_id) {
>   	case 1:
>   		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
>   					&nvm_dev_attr_group_12);
> @@ -1184,7 +1199,7 @@ void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
>   	struct nvm_dev *ndev = ns->ndev;
>   	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>   
> -	switch (dev_geo->ver_id) {
> +	switch (dev_geo->major_ver_id) {
>   	case 1:
>   		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
>   					&nvm_dev_attr_group_12);
> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
> index 18e3751b1632..5af0b8837095 100644
> --- a/include/linux/lightnvm.h
> +++ b/include/linux/lightnvm.h
> @@ -242,7 +242,8 @@ struct nvm_common_geo {
>   /* Device identified geometry */
>   struct nvm_dev_geo {
>   	/* device reported version */
> -	u8	ver_id;
> +	u8	major_ver_id;
> +	u8	minor_ver_id;
>   
>   	/* full device geometry */
>   	u16	nr_chnls;
> 

Looks fairly good to me. Did you consider putting in the major and minor 
version id into the version attribute? e.g., keep 1 as 1, and have 
version 2 be exposed as 2.0?

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 04/20] lightnvm: add minor version to generic geometry
@ 2018-02-22  7:34     ` Matias Bjørling
  0 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:34 UTC (permalink / raw)


On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
> Separate the version between major and minor on the generic geometry.
> Also, add a "subversion" entry to sysfs to expose the minor version
> without breaking user space.
> 
> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
> ---
>   drivers/lightnvm/core.c      |  4 ++--
>   drivers/nvme/host/lightnvm.c | 25 ++++++++++++++++++++-----
>   include/linux/lightnvm.h     |  3 ++-
>   3 files changed, 24 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
> index 42596afdf64c..dc9ec6baff45 100644
> --- a/drivers/lightnvm/core.c
> +++ b/drivers/lightnvm/core.c
> @@ -897,8 +897,8 @@ static int nvm_init(struct nvm_dev *dev)
>   		goto err;
>   	}
>   
> -	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
> -				dev_geo->ver_id,
> +	pr_debug("nvm: ver:%u.%u nvm_vendor:%x\n",
> +				dev_geo->major_ver_id, dev_geo->minor_ver_id,
>   				dev_geo->c.vmnt);
>   
>   	ret = nvm_core_init(dev);
> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
> index 598abba66f52..71b4ac57a668 100644
> --- a/drivers/nvme/host/lightnvm.c
> +++ b/drivers/nvme/host/lightnvm.c
> @@ -296,7 +296,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>   	}
>   
>   	/* 1.2 spec. only reports a single version id - unfold */
> -	dev_geo->ver_id = id->ver_id;
> +	dev_geo->major_ver_id = id->ver_id;
> +	dev_geo->minor_ver_id = 2;
>   
>   	dev_geo->nr_chnls = src->num_ch;
>   	dev_geo->nr_luns = src->num_lun;
> @@ -377,7 +378,14 @@ static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
>   static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>   			     struct nvm_dev_geo *dev_geo)
>   {
> -	dev_geo->ver_id = id->mjr;
> +	dev_geo->major_ver_id = id->mjr;
> +	dev_geo->minor_ver_id = id->mnr;
> +
> +	if (!(dev_geo->major_ver_id == 2 && dev_geo->minor_ver_id == 0)) {
> +		pr_err("nvm: OCSSD version not supported (v%d.%d)\n",
> +				dev_geo->major_ver_id, dev_geo->minor_ver_id);
> +		return -EINVAL;
> +	}
>   
>   	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
>   	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
> @@ -913,7 +921,11 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>   	attr = &dattr->attr;
>   
>   	if (strcmp(attr->name, "version") == 0) {
> -		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
> +		return scnprintf(page, PAGE_SIZE, "%u\n",
> +						dev_geo->major_ver_id);
> +	} else if (strcmp(attr->name, "subversion") == 0) {
> +		return scnprintf(page, PAGE_SIZE, "%u\n",
> +						dev_geo->minor_ver_id);
>   	} else if (strcmp(attr->name, "media_capabilities") == 0) {
>   		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
>   	} else if (strcmp(attr->name, "read_typ") == 0) {
> @@ -1055,6 +1067,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>   
>   /* general attributes */
>   static NVM_DEV_ATTR_RO(version);
> +static NVM_DEV_ATTR_RO(subversion);
>   static NVM_DEV_ATTR_RO(media_capabilities);
>   
>   static NVM_DEV_ATTR_RO(read_typ);
> @@ -1085,6 +1098,7 @@ static NVM_DEV_ATTR_12_RO(max_phys_secs);
>   
>   static struct attribute *nvm_dev_attrs_12[] = {
>   	&dev_attr_version.attr,
> +	&dev_attr_subversion.attr,
>   	&dev_attr_media_capabilities.attr,
>   
>   	&dev_attr_vendor_opcode.attr,
> @@ -1134,6 +1148,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
>   
>   static struct attribute *nvm_dev_attrs_20[] = {
>   	&dev_attr_version.attr,
> +	&dev_attr_subversion.attr,
>   	&dev_attr_media_capabilities.attr,
>   
>   	&dev_attr_groups.attr,
> @@ -1167,7 +1182,7 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>   	if (!ndev)
>   		return -EINVAL;
>   
> -	switch (dev_geo->ver_id) {
> +	switch (dev_geo->major_ver_id) {
>   	case 1:
>   		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
>   					&nvm_dev_attr_group_12);
> @@ -1184,7 +1199,7 @@ void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
>   	struct nvm_dev *ndev = ns->ndev;
>   	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>   
> -	switch (dev_geo->ver_id) {
> +	switch (dev_geo->major_ver_id) {
>   	case 1:
>   		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
>   					&nvm_dev_attr_group_12);
> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
> index 18e3751b1632..5af0b8837095 100644
> --- a/include/linux/lightnvm.h
> +++ b/include/linux/lightnvm.h
> @@ -242,7 +242,8 @@ struct nvm_common_geo {
>   /* Device identified geometry */
>   struct nvm_dev_geo {
>   	/* device reported version */
> -	u8	ver_id;
> +	u8	major_ver_id;
> +	u8	minor_ver_id;
>   
>   	/* full device geometry */
>   	u16	nr_chnls;
> 

Looks fairly good to me. Did you consider putting in the major and minor 
version id into the version attribute? e.g., keep 1 as 1, and have 
version 2 be exposed as 2.0?

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 07/20] lightnvm: rename sect_* to sec_*
  2018-02-21  9:26   ` Javier González
@ 2018-02-22  7:43     ` Matias Bjørling
  -1 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:43 UTC (permalink / raw)
  To: Javier González
  Cc: linux-block, linux-kernel, linux-nvme, Javier González

On 02/21/2018 10:26 AM, Javier González wrote:
> Rename abbreviations for sector from sect_* to sec_* as most of the code
> uses this format and it is confusing when using the different
> structures.
> 
> Signed-off-by: Javier González <javier@cnexlabs.com>
> ---
>   drivers/lightnvm/pblk-init.c  | 8 ++++----
>   drivers/lightnvm/pblk-sysfs.c | 4 ++--
>   drivers/lightnvm/pblk.h       | 8 ++++----
>   drivers/nvme/host/lightnvm.c  | 8 ++++----
>   include/linux/lightnvm.h      | 8 ++++----
>   5 files changed, 18 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
> index 455fc63a9409..6bf51ef8f516 100644
> --- a/drivers/lightnvm/pblk-init.c
> +++ b/drivers/lightnvm/pblk-init.c
> @@ -179,16 +179,16 @@ static int pblk_set_addrf_12(struct nvm_geo *geo,
>   	dst->blk_len = src->blk_len;
>   	dst->pg_len = src->pg_len;
>   	dst->pln_len = src->pln_len;
> -	dst->sect_len = src->sect_len;
> +	dst->sec_len = src->sec_len;
>   
> -	dst->sect_offset = 0;
> -	dst->pln_offset = dst->sect_len;
> +	dst->sec_offset = 0;
> +	dst->pln_offset = dst->sec_len;
>   	dst->ch_offset = dst->pln_offset + dst->pln_len;
>   	dst->lun_offset = dst->ch_offset + dst->ch_len;
>   	dst->pg_offset = dst->lun_offset + dst->lun_len;
>   	dst->blk_offset = dst->pg_offset + dst->pg_len;
>   
> -	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
> +	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>   	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
>   	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>   	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
> index 5eb21a279361..81288aa9162a 100644
> --- a/drivers/lightnvm/pblk-sysfs.c
> +++ b/drivers/lightnvm/pblk-sysfs.c
> @@ -128,7 +128,7 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
>   			ppaf->blk_offset, ppaf->blk_len,
>   			ppaf->pg_offset, ppaf->pg_len,
>   			ppaf->pln_offset, ppaf->pln_len,
> -			ppaf->sect_offset, ppaf->sect_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",
> @@ -137,7 +137,7 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
>   			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->sect_offset, geo_ppaf->sect_len);
> +			geo_ppaf->sec_offset, geo_ppaf->sec_len);
>   
>   	return sz;
>   }
> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
> index 1f32284b0aec..4f7a365436f1 100644
> --- a/drivers/lightnvm/pblk.h
> +++ b/drivers/lightnvm/pblk.h
> @@ -957,7 +957,7 @@ static inline struct ppa_addr addr_to_gen_ppa(struct pblk *pblk, u64 paddr,
>   	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->sect_offset;
> +	ppa.g.sec = (paddr & ppaf->sec_mask) >> ppaf->sec_offset;
>   
>   	return ppa;
>   }
> @@ -973,7 +973,7 @@ static inline u64 pblk_dev_ppa_to_line_addr(struct pblk *pblk,
>   	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->sect_offset;
> +	paddr |= (u64)p.g.sec << ppaf->sec_offset;
>   
>   	return paddr;
>   }
> @@ -998,7 +998,7 @@ static inline struct ppa_addr pblk_ppa32_to_ppa64(struct pblk *pblk, u32 ppa32)
>   		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->sect_offset;
> +		ppa64.g.sec = (ppa32 & ppaf->sec_mask) >> ppaf->sec_offset;
>   	}
>   
>   	return ppa64;
> @@ -1022,7 +1022,7 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
>   		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->sect_offset;
> +		ppa32 |= ppa64.g.sec << ppaf->sec_offset;
>   	}
>   
>   	return ppa32;
> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
> index bd97672e0b4f..cca32da05316 100644
> --- a/drivers/nvme/host/lightnvm.c
> +++ b/drivers/nvme/host/lightnvm.c
> @@ -262,21 +262,21 @@ static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
>   	dst->blk_len = src->blk_len;
>   	dst->pg_len = src->pg_len;
>   	dst->pln_len = src->pln_len;
> -	dst->sect_len = src->sec_len;
> +	dst->sec_len = src->sec_len;
>   
>   	dst->ch_offset = src->ch_offset;
>   	dst->lun_offset = src->lun_offset;
>   	dst->blk_offset = src->blk_offset;
>   	dst->pg_offset = src->pg_offset;
>   	dst->pln_offset = src->pln_offset;
> -	dst->sect_offset = src->sec_offset;
> +	dst->sec_offset = src->sec_offset;
>   
>   	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>   	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>   	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
>   	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
>   	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
> -	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
> +	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>   }
>   
>   static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
> @@ -956,7 +956,7 @@ static ssize_t nvm_dev_attr_show_ppaf(struct nvm_addr_format_12 *ppaf,
>   				ppaf->pln_offset, ppaf->pln_len,
>   				ppaf->blk_offset, ppaf->blk_len,
>   				ppaf->pg_offset, ppaf->pg_len,
> -				ppaf->sect_offset, ppaf->sect_len);
> +				ppaf->sec_offset, ppaf->sec_len);
>   }
>   
>   static ssize_t nvm_dev_attr_show_12(struct device *dev,
> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
> index 02f1fd617781..ccc5faa63cb7 100644
> --- a/include/linux/lightnvm.h
> +++ b/include/linux/lightnvm.h
> @@ -163,14 +163,14 @@ struct nvm_addr_format_12 {
>   	u8	blk_len;
>   	u8	pg_len;
>   	u8	pln_len;
> -	u8	sect_len;
> +	u8	sec_len;
>   
>   	u8	ch_offset;
>   	u8	lun_offset;
>   	u8	blk_offset;
>   	u8	pg_offset;
>   	u8	pln_offset;
> -	u8	sect_offset;
> +	u8	sec_offset;
>   
>   	u64	ch_mask;
>   	u64	lun_mask;
> @@ -399,7 +399,7 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
>   	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
>   	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
>   	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
> -	l.ppa |= ((u64)r.g.sec) << ppaf->sect_offset;
> +	l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
>   
>   	return l;
>   }
> @@ -419,7 +419,7 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
>   	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
>   	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
>   	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
> -	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sect_offset;
> +	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
>   
>   	return l;
>   }
> 

Looks good, I'll pick up when rebased. This could properly be part of 
another patch set with cleanups, as it is not 2.0 specific.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 07/20] lightnvm: rename sect_* to sec_*
@ 2018-02-22  7:43     ` Matias Bjørling
  0 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:43 UTC (permalink / raw)


On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
> Rename abbreviations for sector from sect_* to sec_* as most of the code
> uses this format and it is confusing when using the different
> structures.
> 
> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
> ---
>   drivers/lightnvm/pblk-init.c  | 8 ++++----
>   drivers/lightnvm/pblk-sysfs.c | 4 ++--
>   drivers/lightnvm/pblk.h       | 8 ++++----
>   drivers/nvme/host/lightnvm.c  | 8 ++++----
>   include/linux/lightnvm.h      | 8 ++++----
>   5 files changed, 18 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
> index 455fc63a9409..6bf51ef8f516 100644
> --- a/drivers/lightnvm/pblk-init.c
> +++ b/drivers/lightnvm/pblk-init.c
> @@ -179,16 +179,16 @@ static int pblk_set_addrf_12(struct nvm_geo *geo,
>   	dst->blk_len = src->blk_len;
>   	dst->pg_len = src->pg_len;
>   	dst->pln_len = src->pln_len;
> -	dst->sect_len = src->sect_len;
> +	dst->sec_len = src->sec_len;
>   
> -	dst->sect_offset = 0;
> -	dst->pln_offset = dst->sect_len;
> +	dst->sec_offset = 0;
> +	dst->pln_offset = dst->sec_len;
>   	dst->ch_offset = dst->pln_offset + dst->pln_len;
>   	dst->lun_offset = dst->ch_offset + dst->ch_len;
>   	dst->pg_offset = dst->lun_offset + dst->lun_len;
>   	dst->blk_offset = dst->pg_offset + dst->pg_len;
>   
> -	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
> +	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>   	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
>   	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>   	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
> index 5eb21a279361..81288aa9162a 100644
> --- a/drivers/lightnvm/pblk-sysfs.c
> +++ b/drivers/lightnvm/pblk-sysfs.c
> @@ -128,7 +128,7 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
>   			ppaf->blk_offset, ppaf->blk_len,
>   			ppaf->pg_offset, ppaf->pg_len,
>   			ppaf->pln_offset, ppaf->pln_len,
> -			ppaf->sect_offset, ppaf->sect_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",
> @@ -137,7 +137,7 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
>   			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->sect_offset, geo_ppaf->sect_len);
> +			geo_ppaf->sec_offset, geo_ppaf->sec_len);
>   
>   	return sz;
>   }
> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
> index 1f32284b0aec..4f7a365436f1 100644
> --- a/drivers/lightnvm/pblk.h
> +++ b/drivers/lightnvm/pblk.h
> @@ -957,7 +957,7 @@ static inline struct ppa_addr addr_to_gen_ppa(struct pblk *pblk, u64 paddr,
>   	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->sect_offset;
> +	ppa.g.sec = (paddr & ppaf->sec_mask) >> ppaf->sec_offset;
>   
>   	return ppa;
>   }
> @@ -973,7 +973,7 @@ static inline u64 pblk_dev_ppa_to_line_addr(struct pblk *pblk,
>   	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->sect_offset;
> +	paddr |= (u64)p.g.sec << ppaf->sec_offset;
>   
>   	return paddr;
>   }
> @@ -998,7 +998,7 @@ static inline struct ppa_addr pblk_ppa32_to_ppa64(struct pblk *pblk, u32 ppa32)
>   		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->sect_offset;
> +		ppa64.g.sec = (ppa32 & ppaf->sec_mask) >> ppaf->sec_offset;
>   	}
>   
>   	return ppa64;
> @@ -1022,7 +1022,7 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
>   		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->sect_offset;
> +		ppa32 |= ppa64.g.sec << ppaf->sec_offset;
>   	}
>   
>   	return ppa32;
> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
> index bd97672e0b4f..cca32da05316 100644
> --- a/drivers/nvme/host/lightnvm.c
> +++ b/drivers/nvme/host/lightnvm.c
> @@ -262,21 +262,21 @@ static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
>   	dst->blk_len = src->blk_len;
>   	dst->pg_len = src->pg_len;
>   	dst->pln_len = src->pln_len;
> -	dst->sect_len = src->sec_len;
> +	dst->sec_len = src->sec_len;
>   
>   	dst->ch_offset = src->ch_offset;
>   	dst->lun_offset = src->lun_offset;
>   	dst->blk_offset = src->blk_offset;
>   	dst->pg_offset = src->pg_offset;
>   	dst->pln_offset = src->pln_offset;
> -	dst->sect_offset = src->sec_offset;
> +	dst->sec_offset = src->sec_offset;
>   
>   	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>   	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>   	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
>   	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
>   	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
> -	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
> +	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>   }
>   
>   static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
> @@ -956,7 +956,7 @@ static ssize_t nvm_dev_attr_show_ppaf(struct nvm_addr_format_12 *ppaf,
>   				ppaf->pln_offset, ppaf->pln_len,
>   				ppaf->blk_offset, ppaf->blk_len,
>   				ppaf->pg_offset, ppaf->pg_len,
> -				ppaf->sect_offset, ppaf->sect_len);
> +				ppaf->sec_offset, ppaf->sec_len);
>   }
>   
>   static ssize_t nvm_dev_attr_show_12(struct device *dev,
> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
> index 02f1fd617781..ccc5faa63cb7 100644
> --- a/include/linux/lightnvm.h
> +++ b/include/linux/lightnvm.h
> @@ -163,14 +163,14 @@ struct nvm_addr_format_12 {
>   	u8	blk_len;
>   	u8	pg_len;
>   	u8	pln_len;
> -	u8	sect_len;
> +	u8	sec_len;
>   
>   	u8	ch_offset;
>   	u8	lun_offset;
>   	u8	blk_offset;
>   	u8	pg_offset;
>   	u8	pln_offset;
> -	u8	sect_offset;
> +	u8	sec_offset;
>   
>   	u64	ch_mask;
>   	u64	lun_mask;
> @@ -399,7 +399,7 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
>   	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
>   	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
>   	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
> -	l.ppa |= ((u64)r.g.sec) << ppaf->sect_offset;
> +	l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
>   
>   	return l;
>   }
> @@ -419,7 +419,7 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
>   	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
>   	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
>   	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
> -	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sect_offset;
> +	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
>   
>   	return l;
>   }
> 

Looks good, I'll pick up when rebased. This could properly be part of 
another patch set with cleanups, as it is not 2.0 specific.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 01/20] lightnvm: simplify geometry structure.
  2018-02-22  7:25     ` Matias Bjørling
@ 2018-02-22  7:44       ` Javier Gonzalez
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier Gonzalez @ 2018-02-22  7:44 UTC (permalink / raw)
  To: Matias Bjørling; +Cc: linux-block, linux-kernel, linux-nvme

[-- Attachment #1: Type: text/plain, Size: 71160 bytes --]


> On 22 Feb 2018, at 08.25, Matias Bjørling <mb@lightnvm.io> wrote:
> 
> On 02/21/2018 10:26 AM, Javier González wrote:
>> Currently, the device geometry is stored redundantly in the nvm_id and
>> nvm_geo structures at a device level. Moreover, when instantiating
>> targets on a specific number of LUNs, these structures are replicated
>> and manually modified to fit the instance channel and LUN partitioning.
>> Instead, create a generic geometry around two base structures:
>> nvm_dev_geo, which describes the geometry of the whole device and
>> nvm_geo, which describes the geometry of the instance. Since these share
>> a big part of the geometry, create a nvm_common_geo structure that keeps
>> the static geoometry values that are shared across instances.
>> As we introduce support for 2.0, these structures allow to abstract
>> spec. specific values and present a common geometry to targets.
>> Signed-off-by: Javier González <javier@cnexlabs.com>
>> ---
>>  drivers/lightnvm/core.c          | 137 +++++++---------
>>  drivers/lightnvm/pblk-core.c     |  16 +-
>>  drivers/lightnvm/pblk-gc.c       |   2 +-
>>  drivers/lightnvm/pblk-init.c     | 123 +++++++-------
>>  drivers/lightnvm/pblk-read.c     |   2 +-
>>  drivers/lightnvm/pblk-recovery.c |  14 +-
>>  drivers/lightnvm/pblk-rl.c       |   2 +-
>>  drivers/lightnvm/pblk-sysfs.c    |  39 +++--
>>  drivers/lightnvm/pblk-write.c    |   2 +-
>>  drivers/lightnvm/pblk.h          |  93 +++++------
>>  drivers/nvme/host/lightnvm.c     | 339 +++++++++++++++++++++++----------------
>>  include/linux/lightnvm.h         | 204 ++++++++++++-----------
>>  12 files changed, 514 insertions(+), 459 deletions(-)
>> diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
>> index 689c97b97775..42596afdf64c 100644
>> --- a/drivers/lightnvm/core.c
>> +++ b/drivers/lightnvm/core.c
>> @@ -111,6 +111,7 @@ static void nvm_release_luns_err(struct nvm_dev *dev, int lun_begin,
>>  static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
>>  {
>>  	struct nvm_dev *dev = tgt_dev->parent;
>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>  	struct nvm_dev_map *dev_map = tgt_dev->map;
>>  	int i, j;
>>  @@ -122,7 +123,7 @@ static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
>>  		if (clear) {
>>  			for (j = 0; j < ch_map->nr_luns; j++) {
>>  				int lun = j + lun_offs[j];
>> -				int lunid = (ch * dev->geo.nr_luns) + lun;
>> +				int lunid = (ch * dev_geo->nr_luns) + lun;
>>    				WARN_ON(!test_and_clear_bit(lunid,
>>  							dev->lun_map));
>> @@ -143,19 +144,20 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>>  					      u16 lun_begin, u16 lun_end,
>>  					      u16 op)
>>  {
>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>  	struct nvm_tgt_dev *tgt_dev = NULL;
>>  	struct nvm_dev_map *dev_rmap = dev->rmap;
>>  	struct nvm_dev_map *dev_map;
>>  	struct ppa_addr *luns;
>>  	int nr_luns = lun_end - lun_begin + 1;
>>  	int luns_left = nr_luns;
>> -	int nr_chnls = nr_luns / dev->geo.nr_luns;
>> -	int nr_chnls_mod = nr_luns % dev->geo.nr_luns;
>> -	int bch = lun_begin / dev->geo.nr_luns;
>> -	int blun = lun_begin % dev->geo.nr_luns;
>> +	int nr_chnls = nr_luns / dev_geo->nr_luns;
>> +	int nr_chnls_mod = nr_luns % dev_geo->nr_luns;
>> +	int bch = lun_begin / dev_geo->nr_luns;
>> +	int blun = lun_begin % dev_geo->nr_luns;
>>  	int lunid = 0;
>>  	int lun_balanced = 1;
>> -	int prev_nr_luns;
>> +	int sec_per_lun, prev_nr_luns;
>>  	int i, j;
>>    	nr_chnls = (nr_chnls_mod == 0) ? nr_chnls : nr_chnls + 1;
>> @@ -173,15 +175,15 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>>  	if (!luns)
>>  		goto err_luns;
>>  -	prev_nr_luns = (luns_left > dev->geo.nr_luns) ?
>> -					dev->geo.nr_luns : luns_left;
>> +	prev_nr_luns = (luns_left > dev_geo->nr_luns) ?
>> +					dev_geo->nr_luns : luns_left;
>>  	for (i = 0; i < nr_chnls; i++) {
>>  		struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[i + bch];
>>  		int *lun_roffs = ch_rmap->lun_offs;
>>  		struct nvm_ch_map *ch_map = &dev_map->chnls[i];
>>  		int *lun_offs;
>> -		int luns_in_chnl = (luns_left > dev->geo.nr_luns) ?
>> -					dev->geo.nr_luns : luns_left;
>> +		int luns_in_chnl = (luns_left > dev_geo->nr_luns) ?
>> +					dev_geo->nr_luns : luns_left;
>>    		if (lun_balanced && prev_nr_luns != luns_in_chnl)
>>  			lun_balanced = 0;
>> @@ -215,18 +217,22 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>>  	if (!tgt_dev)
>>  		goto err_ch;
>>  -	memcpy(&tgt_dev->geo, &dev->geo, sizeof(struct nvm_geo));
>>  	/* Target device only owns a portion of the physical device */
>>  	tgt_dev->geo.nr_chnls = nr_chnls;
>> -	tgt_dev->geo.all_luns = nr_luns;
>>  	tgt_dev->geo.nr_luns = (lun_balanced) ? prev_nr_luns : -1;
>> +	tgt_dev->geo.all_luns = nr_luns;
>> +	tgt_dev->geo.all_chunks = nr_luns * dev_geo->c.num_chk;
>> +
>>  	tgt_dev->geo.op = op;
>> -	tgt_dev->total_secs = nr_luns * tgt_dev->geo.sec_per_lun;
>> +
>> +	sec_per_lun = dev_geo->c.clba * dev_geo->c.num_chk;
>> +	tgt_dev->geo.total_secs = nr_luns * sec_per_lun;
>> +
>> +	tgt_dev->geo.c = dev_geo->c;
>> +
>>  	tgt_dev->q = dev->q;
>>  	tgt_dev->map = dev_map;
>>  	tgt_dev->luns = luns;
>> -	memcpy(&tgt_dev->identity, &dev->identity, sizeof(struct nvm_id));
>> -
>>  	tgt_dev->parent = dev;
>>    	return tgt_dev;
>> @@ -268,12 +274,12 @@ static struct nvm_tgt_type *nvm_find_target_type(const char *name)
>>  	return tt;
>>  }
>>  -static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
>> +static int nvm_config_check_luns(struct nvm_dev_geo *dev_geo, int lun_begin,
>>  				 int lun_end)
>>  {
>> -	if (lun_begin > lun_end || lun_end >= geo->all_luns) {
>> +	if (lun_begin > lun_end || lun_end >= dev_geo->all_luns) {
>>  		pr_err("nvm: lun out of bound (%u:%u > %u)\n",
>> -			lun_begin, lun_end, geo->all_luns - 1);
>> +			lun_begin, lun_end, dev_geo->all_luns - 1);
>>  		return -EINVAL;
>>  	}
>>  @@ -283,24 +289,24 @@ static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
>>  static int __nvm_config_simple(struct nvm_dev *dev,
>>  			       struct nvm_ioctl_create_simple *s)
>>  {
>> -	struct nvm_geo *geo = &dev->geo;
>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>    	if (s->lun_begin == -1 && s->lun_end == -1) {
>>  		s->lun_begin = 0;
>> -		s->lun_end = geo->all_luns - 1;
>> +		s->lun_end = dev_geo->all_luns - 1;
>>  	}
>>  -	return nvm_config_check_luns(geo, s->lun_begin, s->lun_end);
>> +	return nvm_config_check_luns(dev_geo, s->lun_begin, s->lun_end);
>>  }
>>    static int __nvm_config_extended(struct nvm_dev *dev,
>>  				 struct nvm_ioctl_create_extended *e)
>>  {
>> -	struct nvm_geo *geo = &dev->geo;
>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>    	if (e->lun_begin == 0xFFFF && e->lun_end == 0xFFFF) {
>>  		e->lun_begin = 0;
>> -		e->lun_end = dev->geo.all_luns - 1;
>> +		e->lun_end = dev_geo->all_luns - 1;
>>  	}
>>    	/* op not set falls into target's default */
>> @@ -313,7 +319,7 @@ static int __nvm_config_extended(struct nvm_dev *dev,
>>  		return -EINVAL;
>>  	}
>>  -	return nvm_config_check_luns(geo, e->lun_begin, e->lun_end);
>> +	return nvm_config_check_luns(dev_geo, e->lun_begin, e->lun_end);
>>  }
>>    static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
>> @@ -408,7 +414,7 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
>>  	tqueue->queuedata = targetdata;
>>    	blk_queue_max_hw_sectors(tqueue,
>> -			(dev->geo.sec_size >> 9) * NVM_MAX_VLBA);
>> +			(dev->dev_geo.c.csecs >> 9) * NVM_MAX_VLBA);
>>    	set_capacity(tdisk, tt->capacity(targetdata));
>>  	add_disk(tdisk);
>> @@ -497,6 +503,7 @@ static int nvm_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove)
>>    static int nvm_register_map(struct nvm_dev *dev)
>>  {
>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>  	struct nvm_dev_map *rmap;
>>  	int i, j;
>>  @@ -504,15 +511,15 @@ static int nvm_register_map(struct nvm_dev *dev)
>>  	if (!rmap)
>>  		goto err_rmap;
>>  -	rmap->chnls = kcalloc(dev->geo.nr_chnls, sizeof(struct nvm_ch_map),
>> +	rmap->chnls = kcalloc(dev_geo->nr_chnls, sizeof(struct nvm_ch_map),
>>  								GFP_KERNEL);
>>  	if (!rmap->chnls)
>>  		goto err_chnls;
>>  -	for (i = 0; i < dev->geo.nr_chnls; i++) {
>> +	for (i = 0; i < dev_geo->nr_chnls; i++) {
>>  		struct nvm_ch_map *ch_rmap;
>>  		int *lun_roffs;
>> -		int luns_in_chnl = dev->geo.nr_luns;
>> +		int luns_in_chnl = dev_geo->nr_luns;
>>    		ch_rmap = &rmap->chnls[i];
>>  @@ -543,10 +550,11 @@ static int nvm_register_map(struct nvm_dev *dev)
>>    static void nvm_unregister_map(struct nvm_dev *dev)
>>  {
>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>  	struct nvm_dev_map *rmap = dev->rmap;
>>  	int i;
>>  -	for (i = 0; i < dev->geo.nr_chnls; i++)
>> +	for (i = 0; i < dev_geo->nr_chnls; i++)
>>  		kfree(rmap->chnls[i].lun_offs);
>>    	kfree(rmap->chnls);
>> @@ -675,7 +683,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
>>  	int i, plane_cnt, pl_idx;
>>  	struct ppa_addr ppa;
>>  -	if (geo->plane_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
>> +	if (geo->c.pln_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
>>  		rqd->nr_ppas = nr_ppas;
>>  		rqd->ppa_addr = ppas[0];
>>  @@ -689,7 +697,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
>>  		return -ENOMEM;
>>  	}
>>  -	plane_cnt = geo->plane_mode;
>> +	plane_cnt = geo->c.pln_mode;
>>  	rqd->nr_ppas *= plane_cnt;
>>    	for (i = 0; i < nr_ppas; i++) {
>> @@ -804,18 +812,18 @@ EXPORT_SYMBOL(nvm_end_io);
>>   */
>>  int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
>>  {
>> -	struct nvm_geo *geo = &dev->geo;
>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>  	int blk, offset, pl, blktype;
>>  -	if (nr_blks != geo->nr_chks * geo->plane_mode)
>> +	if (nr_blks != dev_geo->c.num_chk * dev_geo->c.pln_mode)
>>  		return -EINVAL;
>>  -	for (blk = 0; blk < geo->nr_chks; blk++) {
>> -		offset = blk * geo->plane_mode;
>> +	for (blk = 0; blk < dev_geo->c.num_chk; blk++) {
>> +		offset = blk * dev_geo->c.pln_mode;
>>  		blktype = blks[offset];
>>    		/* Bad blocks on any planes take precedence over other types */
>> -		for (pl = 0; pl < geo->plane_mode; pl++) {
>> +		for (pl = 0; pl < dev_geo->c.pln_mode; pl++) {
>>  			if (blks[offset + pl] &
>>  					(NVM_BLK_T_BAD|NVM_BLK_T_GRWN_BAD)) {
>>  				blktype = blks[offset + pl];
>> @@ -826,7 +834,7 @@ int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
>>  		blks[blk] = blktype;
>>  	}
>>  -	return geo->nr_chks;
>> +	return dev_geo->c.num_chk;
>>  }
>>  EXPORT_SYMBOL(nvm_bb_tbl_fold);
>>  @@ -843,41 +851,10 @@ EXPORT_SYMBOL(nvm_get_tgt_bb_tbl);
>>    static int nvm_core_init(struct nvm_dev *dev)
>>  {
>> -	struct nvm_id *id = &dev->identity;
>> -	struct nvm_geo *geo = &dev->geo;
>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>  	int ret;
>>  -	memcpy(&geo->ppaf, &id->ppaf, sizeof(struct nvm_addr_format));
>> -
>> -	if (id->mtype != 0) {
>> -		pr_err("nvm: memory type not supported\n");
>> -		return -EINVAL;
>> -	}
>> -
>> -	/* Whole device values */
>> -	geo->nr_chnls = id->num_ch;
>> -	geo->nr_luns = id->num_lun;
>> -
>> -	/* Generic device geometry values */
>> -	geo->ws_min = id->ws_min;
>> -	geo->ws_opt = id->ws_opt;
>> -	geo->ws_seq = id->ws_seq;
>> -	geo->ws_per_chk = id->ws_per_chk;
>> -	geo->nr_chks = id->num_chk;
>> -	geo->mccap = id->mccap;
>> -
>> -	geo->sec_per_chk = id->clba;
>> -	geo->sec_per_lun = geo->sec_per_chk * geo->nr_chks;
>> -	geo->all_luns = geo->nr_luns * geo->nr_chnls;
>> -
>> -	/* 1.2 spec device geometry values */
>> -	geo->plane_mode = 1 << geo->ws_seq;
>> -	geo->nr_planes = geo->ws_opt / geo->ws_min;
>> -	geo->sec_per_pg = geo->ws_min;
>> -	geo->sec_per_pl = geo->sec_per_pg * geo->nr_planes;
>> -
>> -	dev->total_secs = geo->all_luns * geo->sec_per_lun;
>> -	dev->lun_map = kcalloc(BITS_TO_LONGS(geo->all_luns),
>> +	dev->lun_map = kcalloc(BITS_TO_LONGS(dev_geo->all_luns),
>>  					sizeof(unsigned long), GFP_KERNEL);
>>  	if (!dev->lun_map)
>>  		return -ENOMEM;
>> @@ -912,19 +889,17 @@ static void nvm_free(struct nvm_dev *dev)
>>    static int nvm_init(struct nvm_dev *dev)
>>  {
>> -	struct nvm_geo *geo = &dev->geo;
>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>  	int ret = -EINVAL;
>>  -	if (dev->ops->identity(dev, &dev->identity)) {
>> +	if (dev->ops->identity(dev)) {
>>  		pr_err("nvm: device could not be identified\n");
>>  		goto err;
>>  	}
>>  -	if (dev->identity.ver_id != 1 && dev->identity.ver_id != 2) {
>> -		pr_err("nvm: device ver_id %d not supported by kernel.\n",
>> -				dev->identity.ver_id);
>> -		goto err;
>> -	}
>> +	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
>> +				dev_geo->ver_id,
>> +				dev_geo->c.vmnt);
>>    	ret = nvm_core_init(dev);
>>  	if (ret) {
>> @@ -932,10 +907,10 @@ static int nvm_init(struct nvm_dev *dev)
>>  		goto err;
>>  	}
>>  -	pr_info("nvm: registered %s [%u/%u/%u/%u/%u/%u]\n",
>> -			dev->name, geo->sec_per_pg, geo->nr_planes,
>> -			geo->ws_per_chk, geo->nr_chks,
>> -			geo->all_luns, geo->nr_chnls);
>> +	pr_info("nvm: registered %s [%u/%u/%u/%u/%u]\n",
>> +			dev->name, dev_geo->c.ws_min, dev_geo->c.ws_opt,
>> +			dev_geo->c.num_chk, dev_geo->all_luns,
>> +			dev_geo->nr_chnls);
>>  	return 0;
>>  err:
>>  	pr_err("nvm: failed to initialize nvm\n");
>> diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
>> index 22e61cd4f801..519af8b9eab7 100644
>> --- a/drivers/lightnvm/pblk-core.c
>> +++ b/drivers/lightnvm/pblk-core.c
>> @@ -613,7 +613,7 @@ static int pblk_line_submit_emeta_io(struct pblk *pblk, struct pblk_line *line,
>>  	memset(&rqd, 0, sizeof(struct nvm_rq));
>>    	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>> -	rq_len = rq_ppas * geo->sec_size;
>> +	rq_len = rq_ppas * geo->c.csecs;
>>    	bio = pblk_bio_map_addr(pblk, emeta_buf, rq_ppas, rq_len,
>>  					l_mg->emeta_alloc_type, GFP_KERNEL);
>> @@ -722,7 +722,7 @@ u64 pblk_line_smeta_start(struct pblk *pblk, struct pblk_line *line)
>>  	if (bit >= lm->blk_per_line)
>>  		return -1;
>>  -	return bit * geo->sec_per_pl;
>> +	return bit * geo->c.ws_opt;
>>  }
>>    static int pblk_line_submit_smeta_io(struct pblk *pblk, struct pblk_line *line,
>> @@ -1035,19 +1035,19 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>>  	/* Capture bad block information on line mapping bitmaps */
>>  	while ((bit = find_next_bit(line->blk_bitmap, lm->blk_per_line,
>>  					bit + 1)) < lm->blk_per_line) {
>> -		off = bit * geo->sec_per_pl;
>> +		off = bit * geo->c.ws_opt;
>>  		bitmap_shift_left(l_mg->bb_aux, l_mg->bb_template, off,
>>  							lm->sec_per_line);
>>  		bitmap_or(line->map_bitmap, line->map_bitmap, l_mg->bb_aux,
>>  							lm->sec_per_line);
>> -		line->sec_in_line -= geo->sec_per_chk;
>> +		line->sec_in_line -= geo->c.clba;
>>  		if (bit >= lm->emeta_bb)
>>  			nr_bb++;
>>  	}
>>    	/* Mark smeta metadata sectors as bad sectors */
>>  	bit = find_first_zero_bit(line->blk_bitmap, lm->blk_per_line);
>> -	off = bit * geo->sec_per_pl;
>> +	off = bit * geo->c.ws_opt;
>>  	bitmap_set(line->map_bitmap, off, lm->smeta_sec);
>>  	line->sec_in_line -= lm->smeta_sec;
>>  	line->smeta_ssec = off;
>> @@ -1066,10 +1066,10 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>>  	emeta_secs = lm->emeta_sec[0];
>>  	off = lm->sec_per_line;
>>  	while (emeta_secs) {
>> -		off -= geo->sec_per_pl;
>> +		off -= geo->c.ws_opt;
>>  		if (!test_bit(off, line->invalid_bitmap)) {
>> -			bitmap_set(line->invalid_bitmap, off, geo->sec_per_pl);
>> -			emeta_secs -= geo->sec_per_pl;
>> +			bitmap_set(line->invalid_bitmap, off, geo->c.ws_opt);
>> +			emeta_secs -= geo->c.ws_opt;
>>  		}
>>  	}
>>  diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c
>> index 320f99af99e9..16afea3f5541 100644
>> --- a/drivers/lightnvm/pblk-gc.c
>> +++ b/drivers/lightnvm/pblk-gc.c
>> @@ -88,7 +88,7 @@ static void pblk_gc_line_ws(struct work_struct *work)
>>    	up(&gc->gc_sem);
>>  -	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->sec_size);
>> +	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->c.csecs);
>>  	if (!gc_rq->data) {
>>  		pr_err("pblk: could not GC line:%d (%d/%d)\n",
>>  					line->id, *line->vsc, gc_rq->nr_secs);
>> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
>> index 5261702e9ff7..95ecb0ec736b 100644
>> --- a/drivers/lightnvm/pblk-init.c
>> +++ b/drivers/lightnvm/pblk-init.c
>> @@ -146,7 +146,7 @@ static int pblk_rwb_init(struct pblk *pblk)
>>  		return -ENOMEM;
>>    	power_size = get_count_order(nr_entries);
>> -	power_seg_sz = get_count_order(geo->sec_size);
>> +	power_seg_sz = get_count_order(geo->c.csecs);
>>    	return pblk_rb_init(&pblk->rwb, entries, power_size, power_seg_sz);
>>  }
>> @@ -154,11 +154,11 @@ static int pblk_rwb_init(struct pblk *pblk)
>>  /* Minimum pages needed within a lun */
>>  #define ADDR_POOL_SIZE 64
>>  -static int pblk_set_ppaf(struct pblk *pblk)
>> +static int pblk_set_addrf_12(struct nvm_geo *geo,
>> +			     struct nvm_addr_format_12 *dst)
>>  {
>> -	struct nvm_tgt_dev *dev = pblk->dev;
>> -	struct nvm_geo *geo = &dev->geo;
>> -	struct nvm_addr_format ppaf = geo->ppaf;
>> +	struct nvm_addr_format_12 *src =
>> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>>  	int power_len;
>>    	/* Re-calculate channel and lun format to adapt to configuration */
>> @@ -167,34 +167,50 @@ static int pblk_set_ppaf(struct pblk *pblk)
>>  		pr_err("pblk: supports only power-of-two channel config.\n");
>>  		return -EINVAL;
>>  	}
>> -	ppaf.ch_len = power_len;
>> +	dst->ch_len = power_len;
>>    	power_len = get_count_order(geo->nr_luns);
>>  	if (1 << power_len != geo->nr_luns) {
>>  		pr_err("pblk: supports only power-of-two LUN config.\n");
>>  		return -EINVAL;
>>  	}
>> -	ppaf.lun_len = power_len;
>> +	dst->lun_len = power_len;
>>  -	pblk->ppaf.sec_offset = 0;
>> -	pblk->ppaf.pln_offset = ppaf.sect_len;
>> -	pblk->ppaf.ch_offset = pblk->ppaf.pln_offset + ppaf.pln_len;
>> -	pblk->ppaf.lun_offset = pblk->ppaf.ch_offset + ppaf.ch_len;
>> -	pblk->ppaf.pg_offset = pblk->ppaf.lun_offset + ppaf.lun_len;
>> -	pblk->ppaf.blk_offset = pblk->ppaf.pg_offset + ppaf.pg_len;
>> -	pblk->ppaf.sec_mask = (1ULL << ppaf.sect_len) - 1;
>> -	pblk->ppaf.pln_mask = ((1ULL << ppaf.pln_len) - 1) <<
>> -							pblk->ppaf.pln_offset;
>> -	pblk->ppaf.ch_mask = ((1ULL << ppaf.ch_len) - 1) <<
>> -							pblk->ppaf.ch_offset;
>> -	pblk->ppaf.lun_mask = ((1ULL << ppaf.lun_len) - 1) <<
>> -							pblk->ppaf.lun_offset;
>> -	pblk->ppaf.pg_mask = ((1ULL << ppaf.pg_len) - 1) <<
>> -							pblk->ppaf.pg_offset;
>> -	pblk->ppaf.blk_mask = ((1ULL << ppaf.blk_len) - 1) <<
>> -							pblk->ppaf.blk_offset;
>> +	dst->blk_len = src->blk_len;
>> +	dst->pg_len = src->pg_len;
>> +	dst->pln_len = src->pln_len;
>> +	dst->sect_len = src->sect_len;
>>  -	pblk->ppaf_bitsize = pblk->ppaf.blk_offset + ppaf.blk_len;
>> +	dst->sect_offset = 0;
>> +	dst->pln_offset = dst->sect_len;
>> +	dst->ch_offset = dst->pln_offset + dst->pln_len;
>> +	dst->lun_offset = dst->ch_offset + dst->ch_len;
>> +	dst->pg_offset = dst->lun_offset + dst->lun_len;
>> +	dst->blk_offset = dst->pg_offset + dst->pg_len;
>> +
>> +	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
>> +	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
>> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>> +	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
>> +	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
>> +
>> +	return dst->blk_offset + src->blk_len;
>> +}
>> +
>> +static int pblk_set_ppaf(struct pblk *pblk)
>> +{
>> +	struct nvm_tgt_dev *dev = pblk->dev;
>> +	struct nvm_geo *geo = &dev->geo;
>> +	int mod;
>> +
>> +	div_u64_rem(geo->c.clba, pblk->min_write_pgs, &mod);
>> +	if (mod) {
>> +		pr_err("pblk: bad configuration of sectors/pages\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	pblk->ppaf_bitsize = pblk_set_addrf_12(geo, (void *)&pblk->ppaf);
>>    	return 0;
>>  }
>> @@ -253,8 +269,7 @@ static int pblk_core_init(struct pblk *pblk)
>>  	struct nvm_tgt_dev *dev = pblk->dev;
>>  	struct nvm_geo *geo = &dev->geo;
>>  -	pblk->pgs_in_buffer = NVM_MEM_PAGE_WRITE * geo->sec_per_pg *
>> -						geo->nr_planes * geo->all_luns;
>> +	pblk->pgs_in_buffer = geo->c.mw_cunits * geo->c.ws_opt * geo->all_luns;
>>    	if (pblk_init_global_caches(pblk))
>>  		return -ENOMEM;
>> @@ -433,7 +448,7 @@ static void *pblk_bb_get_log(struct pblk *pblk)
>>  	int i, nr_blks, blk_per_lun;
>>  	int ret;
>>  -	blk_per_lun = geo->nr_chks * geo->plane_mode;
>> +	blk_per_lun = geo->c.num_chk * geo->c.pln_mode;
>>  	nr_blks = blk_per_lun * geo->all_luns;
>>    	log = kmalloc(nr_blks, GFP_KERNEL);
>> @@ -551,18 +566,18 @@ static unsigned int calc_emeta_len(struct pblk *pblk)
>>  	/* Round to sector size so that lba_list starts on its own sector */
>>  	lm->emeta_sec[1] = DIV_ROUND_UP(
>>  			sizeof(struct line_emeta) + lm->blk_bitmap_len +
>> -			sizeof(struct wa_counters), geo->sec_size);
>> -	lm->emeta_len[1] = lm->emeta_sec[1] * geo->sec_size;
>> +			sizeof(struct wa_counters), geo->c.csecs);
>> +	lm->emeta_len[1] = lm->emeta_sec[1] * geo->c.csecs;
>>    	/* Round to sector size so that vsc_list starts on its own sector */
>>  	lm->dsec_per_line = lm->sec_per_line - lm->emeta_sec[0];
>>  	lm->emeta_sec[2] = DIV_ROUND_UP(lm->dsec_per_line * sizeof(u64),
>> -			geo->sec_size);
>> -	lm->emeta_len[2] = lm->emeta_sec[2] * geo->sec_size;
>> +			geo->c.csecs);
>> +	lm->emeta_len[2] = lm->emeta_sec[2] * geo->c.csecs;
>>    	lm->emeta_sec[3] = DIV_ROUND_UP(l_mg->nr_lines * sizeof(u32),
>> -			geo->sec_size);
>> -	lm->emeta_len[3] = lm->emeta_sec[3] * geo->sec_size;
>> +			geo->c.csecs);
>> +	lm->emeta_len[3] = lm->emeta_sec[3] * geo->c.csecs;
>>    	lm->vsc_list_len = l_mg->nr_lines * sizeof(u32);
>>  @@ -593,13 +608,13 @@ static void pblk_set_provision(struct pblk *pblk, long nr_free_blks)
>>  	 * on user capacity consider only provisioned blocks
>>  	 */
>>  	pblk->rl.total_blocks = nr_free_blks;
>> -	pblk->rl.nr_secs = nr_free_blks * geo->sec_per_chk;
>> +	pblk->rl.nr_secs = nr_free_blks * geo->c.clba;
>>    	/* Consider sectors used for metadata */
>>  	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
>> -	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
>> +	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
>>  -	pblk->capacity = (provisioned - blk_meta) * geo->sec_per_chk;
>> +	pblk->capacity = (provisioned - blk_meta) * geo->c.clba;
>>    	atomic_set(&pblk->rl.free_blocks, nr_free_blks);
>>  	atomic_set(&pblk->rl.free_user_blocks, nr_free_blks);
>> @@ -710,10 +725,10 @@ static int pblk_lines_init(struct pblk *pblk)
>>  	void *chunk_log;
>>  	unsigned int smeta_len, emeta_len;
>>  	long nr_bad_blks = 0, nr_free_blks = 0;
>> -	int bb_distance, max_write_ppas, mod;
>> +	int bb_distance, max_write_ppas;
>>  	int i, ret;
>>  -	pblk->min_write_pgs = geo->sec_per_pl * (geo->sec_size / PAGE_SIZE);
>> +	pblk->min_write_pgs = geo->c.ws_opt * (geo->c.csecs / PAGE_SIZE);
>>  	max_write_ppas = pblk->min_write_pgs * geo->all_luns;
>>  	pblk->max_write_pgs = min_t(int, max_write_ppas, NVM_MAX_VLBA);
>>  	pblk_set_sec_per_write(pblk, pblk->min_write_pgs);
>> @@ -724,19 +739,13 @@ static int pblk_lines_init(struct pblk *pblk)
>>  		return -EINVAL;
>>  	}
>>  -	div_u64_rem(geo->sec_per_chk, pblk->min_write_pgs, &mod);
>> -	if (mod) {
>> -		pr_err("pblk: bad configuration of sectors/pages\n");
>> -		return -EINVAL;
>> -	}
>> -
>> -	l_mg->nr_lines = geo->nr_chks;
>> +	l_mg->nr_lines = geo->c.num_chk;
>>  	l_mg->log_line = l_mg->data_line = NULL;
>>  	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
>>  	l_mg->nr_free_lines = 0;
>>  	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
>>  -	lm->sec_per_line = geo->sec_per_chk * geo->all_luns;
>> +	lm->sec_per_line = geo->c.clba * geo->all_luns;
>>  	lm->blk_per_line = geo->all_luns;
>>  	lm->blk_bitmap_len = BITS_TO_LONGS(geo->all_luns) * sizeof(long);
>>  	lm->sec_bitmap_len = BITS_TO_LONGS(lm->sec_per_line) * sizeof(long);
>> @@ -750,8 +759,8 @@ static int pblk_lines_init(struct pblk *pblk)
>>  	 */
>>  	i = 1;
>>  add_smeta_page:
>> -	lm->smeta_sec = i * geo->sec_per_pl;
>> -	lm->smeta_len = lm->smeta_sec * geo->sec_size;
>> +	lm->smeta_sec = i * geo->c.ws_opt;
>> +	lm->smeta_len = lm->smeta_sec * geo->c.csecs;
>>    	smeta_len = sizeof(struct line_smeta) + lm->lun_bitmap_len;
>>  	if (smeta_len > lm->smeta_len) {
>> @@ -764,8 +773,8 @@ static int pblk_lines_init(struct pblk *pblk)
>>  	 */
>>  	i = 1;
>>  add_emeta_page:
>> -	lm->emeta_sec[0] = i * geo->sec_per_pl;
>> -	lm->emeta_len[0] = lm->emeta_sec[0] * geo->sec_size;
>> +	lm->emeta_sec[0] = i * geo->c.ws_opt;
>> +	lm->emeta_len[0] = lm->emeta_sec[0] * geo->c.csecs;
>>    	emeta_len = calc_emeta_len(pblk);
>>  	if (emeta_len > lm->emeta_len[0]) {
>> @@ -778,7 +787,7 @@ static int pblk_lines_init(struct pblk *pblk)
>>  	lm->min_blk_line = 1;
>>  	if (geo->all_luns > 1)
>>  		lm->min_blk_line += DIV_ROUND_UP(lm->smeta_sec +
>> -					lm->emeta_sec[0], geo->sec_per_chk);
>> +					lm->emeta_sec[0], geo->c.clba);
>>    	if (lm->min_blk_line > lm->blk_per_line) {
>>  		pr_err("pblk: config. not supported. Min. LUN in line:%d\n",
>> @@ -802,9 +811,9 @@ static int pblk_lines_init(struct pblk *pblk)
>>  		goto fail_free_bb_template;
>>  	}
>>  -	bb_distance = (geo->all_luns) * geo->sec_per_pl;
>> +	bb_distance = (geo->all_luns) * geo->c.ws_opt;
>>  	for (i = 0; i < lm->sec_per_line; i += bb_distance)
>> -		bitmap_set(l_mg->bb_template, i, geo->sec_per_pl);
>> +		bitmap_set(l_mg->bb_template, i, geo->c.ws_opt);
>>    	INIT_LIST_HEAD(&l_mg->free_list);
>>  	INIT_LIST_HEAD(&l_mg->corrupt_list);
>> @@ -981,9 +990,9 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>>  	struct pblk *pblk;
>>  	int ret;
>>  -	if (dev->identity.dom & NVM_RSP_L2P) {
>> +	if (dev->geo.c.dom & NVM_RSP_L2P) {
>>  		pr_err("pblk: host-side L2P table not supported. (%x)\n",
>> -							dev->identity.dom);
>> +							dev->geo.c.dom);
>>  		return ERR_PTR(-EINVAL);
>>  	}
>>  @@ -1091,7 +1100,7 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>>    	blk_queue_write_cache(tqueue, true, false);
>>  -	tqueue->limits.discard_granularity = geo->sec_per_chk * geo->sec_size;
>> +	tqueue->limits.discard_granularity = geo->c.clba * geo->c.csecs;
>>  	tqueue->limits.discard_alignment = 0;
>>  	blk_queue_max_discard_sectors(tqueue, UINT_MAX >> 9);
>>  	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, tqueue);
>> diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c
>> index 2f761283f43e..ebb6bae3a3b8 100644
>> --- a/drivers/lightnvm/pblk-read.c
>> +++ b/drivers/lightnvm/pblk-read.c
>> @@ -563,7 +563,7 @@ int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq)
>>  	if (!(gc_rq->secs_to_gc))
>>  		goto out;
>>  -	data_len = (gc_rq->secs_to_gc) * geo->sec_size;
>> +	data_len = (gc_rq->secs_to_gc) * geo->c.csecs;
>>  	bio = pblk_bio_map_addr(pblk, gc_rq->data, gc_rq->secs_to_gc, data_len,
>>  						PBLK_VMALLOC_META, GFP_KERNEL);
>>  	if (IS_ERR(bio)) {
>> diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
>> index aaab9a5c17cc..1574dbbfbb1c 100644
>> --- a/drivers/lightnvm/pblk-recovery.c
>> +++ b/drivers/lightnvm/pblk-recovery.c
>> @@ -184,7 +184,7 @@ static int pblk_calc_sec_in_line(struct pblk *pblk, struct pblk_line *line)
>>  	int nr_bb = bitmap_weight(line->blk_bitmap, lm->blk_per_line);
>>    	return lm->sec_per_line - lm->smeta_sec - lm->emeta_sec[0] -
>> -				nr_bb * geo->sec_per_chk;
>> +				nr_bb * geo->c.clba;
>>  }
>>    struct pblk_recov_alloc {
>> @@ -232,7 +232,7 @@ static int pblk_recov_read_oob(struct pblk *pblk, struct pblk_line *line,
>>  	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>  	if (!rq_ppas)
>>  		rq_ppas = pblk->min_write_pgs;
>> -	rq_len = rq_ppas * geo->sec_size;
>> +	rq_len = rq_ppas * geo->c.csecs;
>>    	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>>  	if (IS_ERR(bio))
>> @@ -351,7 +351,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
>>  	if (!pad_rq)
>>  		return -ENOMEM;
>>  -	data = vzalloc(pblk->max_write_pgs * geo->sec_size);
>> +	data = vzalloc(pblk->max_write_pgs * geo->c.csecs);
>>  	if (!data) {
>>  		ret = -ENOMEM;
>>  		goto free_rq;
>> @@ -368,7 +368,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
>>  		goto fail_free_pad;
>>  	}
>>  -	rq_len = rq_ppas * geo->sec_size;
>> +	rq_len = rq_ppas * geo->c.csecs;
>>    	meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, &dma_meta_list);
>>  	if (!meta_list) {
>> @@ -509,7 +509,7 @@ static int pblk_recov_scan_all_oob(struct pblk *pblk, struct pblk_line *line,
>>  	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>  	if (!rq_ppas)
>>  		rq_ppas = pblk->min_write_pgs;
>> -	rq_len = rq_ppas * geo->sec_size;
>> +	rq_len = rq_ppas * geo->c.csecs;
>>    	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>>  	if (IS_ERR(bio))
>> @@ -640,7 +640,7 @@ static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line,
>>  	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>  	if (!rq_ppas)
>>  		rq_ppas = pblk->min_write_pgs;
>> -	rq_len = rq_ppas * geo->sec_size;
>> +	rq_len = rq_ppas * geo->c.csecs;
>>    	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>>  	if (IS_ERR(bio))
>> @@ -745,7 +745,7 @@ static int pblk_recov_l2p_from_oob(struct pblk *pblk, struct pblk_line *line)
>>  	ppa_list = (void *)(meta_list) + pblk_dma_meta_size;
>>  	dma_ppa_list = dma_meta_list + pblk_dma_meta_size;
>>  -	data = kcalloc(pblk->max_write_pgs, geo->sec_size, GFP_KERNEL);
>> +	data = kcalloc(pblk->max_write_pgs, geo->c.csecs, GFP_KERNEL);
>>  	if (!data) {
>>  		ret = -ENOMEM;
>>  		goto free_meta_list;
>> diff --git a/drivers/lightnvm/pblk-rl.c b/drivers/lightnvm/pblk-rl.c
>> index 0d457b162f23..bcab203477ec 100644
>> --- a/drivers/lightnvm/pblk-rl.c
>> +++ b/drivers/lightnvm/pblk-rl.c
>> @@ -200,7 +200,7 @@ void pblk_rl_init(struct pblk_rl *rl, int budget)
>>    	/* Consider sectors used for metadata */
>>  	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
>> -	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
>> +	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
>>    	rl->high = pblk->op_blks - blk_meta - lm->blk_per_line;
>>  	rl->high_pw = get_count_order(rl->high);
>> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
>> index d93e9b1f083a..5eb21a279361 100644
>> --- a/drivers/lightnvm/pblk-sysfs.c
>> +++ b/drivers/lightnvm/pblk-sysfs.c
>> @@ -113,26 +113,31 @@ 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;
>>  -	sz = snprintf(page, PAGE_SIZE - sz,
>> -		"g:(b:%d)blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
>> -		pblk->ppaf_bitsize,
>> -		pblk->ppaf.blk_offset, geo->ppaf.blk_len,
>> -		pblk->ppaf.pg_offset, geo->ppaf.pg_len,
>> -		pblk->ppaf.lun_offset, geo->ppaf.lun_len,
>> -		pblk->ppaf.ch_offset, geo->ppaf.ch_len,
>> -		pblk->ppaf.pln_offset, geo->ppaf.pln_len,
>> -		pblk->ppaf.sec_offset, geo->ppaf.sect_len);
>> +	ppaf = (struct nvm_addr_format_12 *)&pblk->ppaf;
>> +	geo_ppaf = (struct nvm_addr_format_12 *)&geo->c.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",
>> +			pblk->ppaf_bitsize,
>> +			ppaf->ch_offset, ppaf->ch_len,
>> +			ppaf->lun_offset, ppaf->lun_len,
>> +			ppaf->blk_offset, ppaf->blk_len,
>> +			ppaf->pg_offset, ppaf->pg_len,
>> +			ppaf->pln_offset, ppaf->pln_len,
>> +			ppaf->sect_offset, ppaf->sect_len);
>>    	sz += snprintf(page + sz, PAGE_SIZE - sz,
>> -		"d:blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
>> -		geo->ppaf.blk_offset, geo->ppaf.blk_len,
>> -		geo->ppaf.pg_offset, geo->ppaf.pg_len,
>> -		geo->ppaf.lun_offset, geo->ppaf.lun_len,
>> -		geo->ppaf.ch_offset, geo->ppaf.ch_len,
>> -		geo->ppaf.pln_offset, geo->ppaf.pln_len,
>> -		geo->ppaf.sect_offset, geo->ppaf.sect_len);
>> +		"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->sect_offset, geo_ppaf->sect_len);
>>    	return sz;
>>  }
>> @@ -288,7 +293,7 @@ static ssize_t pblk_sysfs_lines_info(struct pblk *pblk, char *page)
>>  				"blk_line:%d, sec_line:%d, sec_blk:%d\n",
>>  					lm->blk_per_line,
>>  					lm->sec_per_line,
>> -					geo->sec_per_chk);
>> +					geo->c.clba);
>>    	return sz;
>>  }
>> diff --git a/drivers/lightnvm/pblk-write.c b/drivers/lightnvm/pblk-write.c
>> index aae86ed60b98..c49b27539d5a 100644
>> --- a/drivers/lightnvm/pblk-write.c
>> +++ b/drivers/lightnvm/pblk-write.c
>> @@ -333,7 +333,7 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line)
>>  	m_ctx = nvm_rq_to_pdu(rqd);
>>  	m_ctx->private = meta_line;
>>  -	rq_len = rq_ppas * geo->sec_size;
>> +	rq_len = rq_ppas * geo->c.csecs;
>>  	data = ((void *)emeta->buf) + emeta->mem;
>>    	bio = pblk_bio_map_addr(pblk, data, rq_ppas, rq_len,
>> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
>> index 282dfc8780e8..67ffb53608f7 100644
>> --- a/drivers/lightnvm/pblk.h
>> +++ b/drivers/lightnvm/pblk.h
>> @@ -551,21 +551,6 @@ struct pblk_line_meta {
>>  	unsigned int meta_distance;	/* Distance between data and metadata */
>>  };
>>  -struct pblk_addr_format {
>> -	u64	ch_mask;
>> -	u64	lun_mask;
>> -	u64	pln_mask;
>> -	u64	blk_mask;
>> -	u64	pg_mask;
>> -	u64	sec_mask;
>> -	u8	ch_offset;
>> -	u8	lun_offset;
>> -	u8	pln_offset;
>> -	u8	blk_offset;
>> -	u8	pg_offset;
>> -	u8	sec_offset;
>> -};
>> -
>>  enum {
>>  	PBLK_STATE_RUNNING = 0,
>>  	PBLK_STATE_STOPPING = 1,
>> @@ -585,8 +570,8 @@ struct pblk {
>>  	struct pblk_line_mgmt l_mg;		/* Line management */
>>  	struct pblk_line_meta lm;		/* Line metadata */
>>  +	struct nvm_addr_format ppaf;
>>  	int ppaf_bitsize;
>> -	struct pblk_addr_format ppaf;
>>    	struct pblk_rb rwb;
>>  @@ -941,14 +926,12 @@ static inline int pblk_line_vsc(struct pblk_line *line)
>>  	return le32_to_cpu(*line->vsc);
>>  }
>>  -#define NVM_MEM_PAGE_WRITE (8)
>> -
>>  static inline int pblk_pad_distance(struct pblk *pblk)
>>  {
>>  	struct nvm_tgt_dev *dev = pblk->dev;
>>  	struct nvm_geo *geo = &dev->geo;
>>  -	return NVM_MEM_PAGE_WRITE * geo->all_luns * geo->sec_per_pl;
>> +	return geo->c.mw_cunits * geo->all_luns * geo->c.ws_opt;
>>  }
>>    static inline int pblk_ppa_to_line(struct ppa_addr p)
>> @@ -964,15 +947,17 @@ 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->ppaf;
>>  	struct ppa_addr ppa;
>>    	ppa.ppa = 0;
>>  	ppa.g.blk = line_id;
>> -	ppa.g.pg = (paddr & pblk->ppaf.pg_mask) >> pblk->ppaf.pg_offset;
>> -	ppa.g.lun = (paddr & pblk->ppaf.lun_mask) >> pblk->ppaf.lun_offset;
>> -	ppa.g.ch = (paddr & pblk->ppaf.ch_mask) >> pblk->ppaf.ch_offset;
>> -	ppa.g.pl = (paddr & pblk->ppaf.pln_mask) >> pblk->ppaf.pln_offset;
>> -	ppa.g.sec = (paddr & pblk->ppaf.sec_mask) >> pblk->ppaf.sec_offset;
>> +	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->sect_offset;
>>    	return ppa;
>>  }
>> @@ -980,13 +965,15 @@ 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->ppaf;
>>  	u64 paddr;
>>  -	paddr = (u64)p.g.pg << pblk->ppaf.pg_offset;
>> -	paddr |= (u64)p.g.lun << pblk->ppaf.lun_offset;
>> -	paddr |= (u64)p.g.ch << pblk->ppaf.ch_offset;
>> -	paddr |= (u64)p.g.pl << pblk->ppaf.pln_offset;
>> -	paddr |= (u64)p.g.sec << pblk->ppaf.sec_offset;
>> +	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->sect_offset;
>>    	return paddr;
>>  }
>> @@ -1003,18 +990,15 @@ 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 {
>> -		ppa64.g.blk = (ppa32 & pblk->ppaf.blk_mask) >>
>> -							pblk->ppaf.blk_offset;
>> -		ppa64.g.pg = (ppa32 & pblk->ppaf.pg_mask) >>
>> -							pblk->ppaf.pg_offset;
>> -		ppa64.g.lun = (ppa32 & pblk->ppaf.lun_mask) >>
>> -							pblk->ppaf.lun_offset;
>> -		ppa64.g.ch = (ppa32 & pblk->ppaf.ch_mask) >>
>> -							pblk->ppaf.ch_offset;
>> -		ppa64.g.pl = (ppa32 & pblk->ppaf.pln_mask) >>
>> -							pblk->ppaf.pln_offset;
>> -		ppa64.g.sec = (ppa32 & pblk->ppaf.sec_mask) >>
>> -							pblk->ppaf.sec_offset;
>> +		struct nvm_addr_format_12 *ppaf =
>> +				(struct nvm_addr_format_12 *)&pblk->ppaf;
>> +
>> +		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->sect_offset;
>>  	}
>>    	return ppa64;
>> @@ -1030,12 +1014,15 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
>>  		ppa32 |= ppa64.c.line;
>>  		ppa32 |= 1U << 31;
>>  	} else {
>> -		ppa32 |= ppa64.g.blk << pblk->ppaf.blk_offset;
>> -		ppa32 |= ppa64.g.pg << pblk->ppaf.pg_offset;
>> -		ppa32 |= ppa64.g.lun << pblk->ppaf.lun_offset;
>> -		ppa32 |= ppa64.g.ch << pblk->ppaf.ch_offset;
>> -		ppa32 |= ppa64.g.pl << pblk->ppaf.pln_offset;
>> -		ppa32 |= ppa64.g.sec << pblk->ppaf.sec_offset;
>> +		struct nvm_addr_format_12 *ppaf =
>> +				(struct nvm_addr_format_12 *)&pblk->ppaf;
>> +
>> +		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->sect_offset;
>>  	}
>>    	return ppa32;
>> @@ -1153,7 +1140,7 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type)
>>  	struct nvm_geo *geo = &dev->geo;
>>  	int flags;
>>  -	flags = geo->plane_mode >> 1;
>> +	flags = geo->c.pln_mode >> 1;
>>    	if (type == PBLK_WRITE)
>>  		flags |= NVM_IO_SCRAMBLE_ENABLE;
>> @@ -1174,7 +1161,7 @@ static inline int pblk_set_read_mode(struct pblk *pblk, int type)
>>    	flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
>>  	if (type == PBLK_READ_SEQUENTIAL)
>> -		flags |= geo->plane_mode >> 1;
>> +		flags |= geo->c.pln_mode >> 1;
>>    	return flags;
>>  }
>> @@ -1229,10 +1216,10 @@ static inline int pblk_boundary_ppa_checks(struct nvm_tgt_dev *tgt_dev,
>>  		if (!ppa->c.is_cached &&
>>  				ppa->g.ch < geo->nr_chnls &&
>>  				ppa->g.lun < geo->nr_luns &&
>> -				ppa->g.pl < geo->nr_planes &&
>> -				ppa->g.blk < geo->nr_chks &&
>> -				ppa->g.pg < geo->ws_per_chk &&
>> -				ppa->g.sec < geo->sec_per_pg)
>> +				ppa->g.pl < geo->c.num_pln &&
>> +				ppa->g.blk < geo->c.num_chk &&
>> +				ppa->g.pg < geo->c.num_pg &&
>> +				ppa->g.sec < geo->c.ws_min)
>>  			continue;
>>    		print_ppa(ppa, "boundary", i);
>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>> index 839c0b96466a..c81e64cc20d7 100644
>> --- a/drivers/nvme/host/lightnvm.c
>> +++ b/drivers/nvme/host/lightnvm.c
>> @@ -152,8 +152,8 @@ struct nvme_nvm_id12_addrf {
>>  	__u8			blk_len;
>>  	__u8			pg_offset;
>>  	__u8			pg_len;
>> -	__u8			sect_offset;
>> -	__u8			sect_len;
>> +	__u8			sec_offset;
>> +	__u8			sec_len;
>>  	__u8			res[4];
>>  } __packed;
>>  @@ -254,106 +254,157 @@ static inline void _nvme_nvm_check_size(void)
>>  	BUILD_BUG_ON(sizeof(struct nvme_nvm_id20) != NVME_IDENTIFY_DATA_SIZE);
>>  }
>>  -static int init_grp(struct nvm_id *nvm_id, struct nvme_nvm_id12 *id12)
>> +static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
>> +				 struct nvme_nvm_id12_addrf *src)
>> +{
>> +	dst->ch_len = src->ch_len;
>> +	dst->lun_len = src->lun_len;
>> +	dst->blk_len = src->blk_len;
>> +	dst->pg_len = src->pg_len;
>> +	dst->pln_len = src->pln_len;
>> +	dst->sect_len = src->sec_len;
>> +
>> +	dst->ch_offset = src->ch_offset;
>> +	dst->lun_offset = src->lun_offset;
>> +	dst->blk_offset = src->blk_offset;
>> +	dst->pg_offset = src->pg_offset;
>> +	dst->pln_offset = src->pln_offset;
>> +	dst->sect_offset = src->sec_offset;
>> +
>> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>> +	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
>> +	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
>> +	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
>> +	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
>> +}
>> +
>> +static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>> +			     struct nvm_dev_geo *dev_geo)
>>  {
>>  	struct nvme_nvm_id12_grp *src;
>>  	int sec_per_pg, sec_per_pl, pg_per_blk;
>>  -	if (id12->cgrps != 1)
>> +	if (id->cgrps != 1)
>>  		return -EINVAL;
>>  -	src = &id12->grp;
>> +	src = &id->grp;
>>  -	nvm_id->mtype = src->mtype;
>> -	nvm_id->fmtype = src->fmtype;
>> +	if (src->mtype != 0) {
>> +		pr_err("nvm: memory type not supported\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	/* 1.2 spec. only reports a single version id - unfold */
>> +	dev_geo->ver_id = id->ver_id;
>>  -	nvm_id->num_ch = src->num_ch;
>> -	nvm_id->num_lun = src->num_lun;
>> +	dev_geo->nr_chnls = src->num_ch;
>> +	dev_geo->nr_luns = src->num_lun;
>> +	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
>>  -	nvm_id->num_chk = le16_to_cpu(src->num_chk);
>> -	nvm_id->csecs = le16_to_cpu(src->csecs);
>> -	nvm_id->sos = le16_to_cpu(src->sos);
>> +	dev_geo->c.num_chk = le16_to_cpu(src->num_chk);
>> +	dev_geo->c.csecs = le16_to_cpu(src->csecs);
>> +	dev_geo->c.sos = le16_to_cpu(src->sos);
>>    	pg_per_blk = le16_to_cpu(src->num_pg);
>> -	sec_per_pg = le16_to_cpu(src->fpg_sz) / nvm_id->csecs;
>> +	sec_per_pg = le16_to_cpu(src->fpg_sz) / dev_geo->c.csecs;
>>  	sec_per_pl = sec_per_pg * src->num_pln;
>> -	nvm_id->clba = sec_per_pl * pg_per_blk;
>> -	nvm_id->ws_per_chk = pg_per_blk;
>> -
>> -	nvm_id->mpos = le32_to_cpu(src->mpos);
>> -	nvm_id->cpar = le16_to_cpu(src->cpar);
>> -	nvm_id->mccap = le32_to_cpu(src->mccap);
>> -
>> -	nvm_id->ws_opt = nvm_id->ws_min = sec_per_pg;
>> -	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
>> -
>> -	if (nvm_id->mpos & 0x020202) {
>> -		nvm_id->ws_seq = NVM_IO_DUAL_ACCESS;
>> -		nvm_id->ws_opt <<= 1;
>> -	} else if (nvm_id->mpos & 0x040404) {
>> -		nvm_id->ws_seq = NVM_IO_QUAD_ACCESS;
>> -		nvm_id->ws_opt <<= 2;
>> +	dev_geo->c.clba = sec_per_pl * pg_per_blk;
>> +
>> +	dev_geo->c.ws_min = sec_per_pg;
>> +	dev_geo->c.ws_opt = sec_per_pg;
>> +	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
>> +
>> +	dev_geo->c.mccap = le32_to_cpu(src->mccap);
>> +
>> +	dev_geo->c.trdt = le32_to_cpu(src->trdt);
>> +	dev_geo->c.trdm = le32_to_cpu(src->trdm);
>> +	dev_geo->c.tprt = le32_to_cpu(src->tprt);
>> +	dev_geo->c.tprm = le32_to_cpu(src->tprm);
>> +	dev_geo->c.tbet = le32_to_cpu(src->tbet);
>> +	dev_geo->c.tbem = le32_to_cpu(src->tbem);
>> +
>> +	/* 1.2 compatibility */
>> +	dev_geo->c.vmnt = id->vmnt;
>> +	dev_geo->c.cap = le32_to_cpu(id->cap);
>> +	dev_geo->c.dom = le32_to_cpu(id->dom);
>> +
>> +	dev_geo->c.mtype = src->mtype;
>> +	dev_geo->c.fmtype = src->fmtype;
>> +
>> +	dev_geo->c.cpar = le16_to_cpu(src->cpar);
>> +	dev_geo->c.mpos = le32_to_cpu(src->mpos);
>> +
>> +	dev_geo->c.pln_mode = NVM_PLANE_SINGLE;
>> +
>> +	if (dev_geo->c.mpos & 0x020202) {
>> +		dev_geo->c.pln_mode = NVM_PLANE_DOUBLE;
>> +		dev_geo->c.ws_opt <<= 1;
>> +	} else if (dev_geo->c.mpos & 0x040404) {
>> +		dev_geo->c.pln_mode = NVM_PLANE_QUAD;
>> +		dev_geo->c.ws_opt <<= 2;
>>  	}
>>  -	nvm_id->trdt = le32_to_cpu(src->trdt);
>> -	nvm_id->trdm = le32_to_cpu(src->trdm);
>> -	nvm_id->tprt = le32_to_cpu(src->tprt);
>> -	nvm_id->tprm = le32_to_cpu(src->tprm);
>> -	nvm_id->tbet = le32_to_cpu(src->tbet);
>> -	nvm_id->tbem = le32_to_cpu(src->tbem);
>> -
>> -	/* 1.2 compatibility */
>> -	nvm_id->num_pln = src->num_pln;
>> -	nvm_id->num_pg = le16_to_cpu(src->num_pg);
>> -	nvm_id->fpg_sz = le16_to_cpu(src->fpg_sz);
>> +	dev_geo->c.num_pln = src->num_pln;
>> +	dev_geo->c.num_pg = le16_to_cpu(src->num_pg);
>> +	dev_geo->c.fpg_sz = le16_to_cpu(src->fpg_sz);
>> +
>> +	nvme_nvm_set_addr_12((struct nvm_addr_format_12 *)&dev_geo->c.addrf,
>> +								&id->ppaf);
>>    	return 0;
>>  }
>>  -static int nvme_nvm_setup_12(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
>> -		struct nvme_nvm_id12 *id)
>> +static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
>> +				 struct nvme_nvm_id20_addrf *src)
>>  {
>> -	nvm_id->ver_id = id->ver_id;
>> -	nvm_id->vmnt = id->vmnt;
>> -	nvm_id->cap = le32_to_cpu(id->cap);
>> -	nvm_id->dom = le32_to_cpu(id->dom);
>> -	memcpy(&nvm_id->ppaf, &id->ppaf,
>> -					sizeof(struct nvm_addr_format));
>> -
>> -	return init_grp(nvm_id, id);
>> +	dst->ch_len = src->grp_len;
>> +	dst->lun_len = src->pu_len;
>> +	dst->chk_len = src->chk_len;
>> +	dst->sec_len = src->lba_len;
>> +
>> +	dst->sec_offset = 0;
>> +	dst->chk_offset = dst->sec_len;
>> +	dst->lun_offset = dst->chk_offset + dst->chk_len;
>> +	dst->ch_offset = dst->lun_offset + dst->lun_len;
>> +
>> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>> +	dst->chk_mask = ((1ULL << dst->chk_len) - 1) << dst->chk_offset;
>> +	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>>  }
>>  -static int nvme_nvm_setup_20(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
>> -		struct nvme_nvm_id20 *id)
>> +static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>> +			     struct nvm_dev_geo *dev_geo)
>>  {
>> -	nvm_id->ver_id = id->mjr;
>> +	dev_geo->ver_id = id->mjr;
>>  -	nvm_id->num_ch = le16_to_cpu(id->num_grp);
>> -	nvm_id->num_lun = le16_to_cpu(id->num_pu);
>> -	nvm_id->num_chk = le32_to_cpu(id->num_chk);
>> -	nvm_id->clba = le32_to_cpu(id->clba);
>> +	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
>> +	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
>> +	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
>>  -	nvm_id->ws_min = le32_to_cpu(id->ws_min);
>> -	nvm_id->ws_opt = le32_to_cpu(id->ws_opt);
>> -	nvm_id->mw_cunits = le32_to_cpu(id->mw_cunits);
>> +	dev_geo->c.num_chk = le32_to_cpu(id->num_chk);
>> +	dev_geo->c.clba = le32_to_cpu(id->clba);
>> +	dev_geo->c.csecs = -1;		/* Set by nvme identify */
>> +	dev_geo->c.sos = -1;		/* Set bu nvme identify */
>>  -	nvm_id->trdt = le32_to_cpu(id->trdt);
>> -	nvm_id->trdm = le32_to_cpu(id->trdm);
>> -	nvm_id->tprt = le32_to_cpu(id->twrt);
>> -	nvm_id->tprm = le32_to_cpu(id->twrm);
>> -	nvm_id->tbet = le32_to_cpu(id->tcrst);
>> -	nvm_id->tbem = le32_to_cpu(id->tcrsm);
>> +	dev_geo->c.ws_min = le32_to_cpu(id->ws_min);
>> +	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
>> +	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
>>  -	/* calculated values */
>> -	nvm_id->ws_per_chk = nvm_id->clba / nvm_id->ws_min;
>> +	dev_geo->c.trdt = le32_to_cpu(id->trdt);
>> +	dev_geo->c.trdm = le32_to_cpu(id->trdm);
>> +	dev_geo->c.tprt = le32_to_cpu(id->twrt);
>> +	dev_geo->c.tprm = le32_to_cpu(id->twrm);
>> +	dev_geo->c.tbet = le32_to_cpu(id->tcrst);
>> +	dev_geo->c.tbem = le32_to_cpu(id->tcrsm);
>>  -	/* 1.2 compatibility */
>> -	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
>> +	nvme_nvm_set_addr_20(&dev_geo->c.addrf, &id->lbaf);
>>    	return 0;
>>  }
>>  -static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
>> +static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>>  {
>>  	struct nvme_ns *ns = nvmdev->q->queuedata;
>>  	struct nvme_nvm_id12 *id;
>> @@ -380,18 +431,18 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
>>  	 */
>>  	switch (id->ver_id) {
>>  	case 1:
>> -		ret = nvme_nvm_setup_12(nvmdev, nvm_id, id);
>> +		ret = nvme_nvm_setup_12(id, &nvmdev->dev_geo);
>>  		break;
>>  	case 2:
>> -		ret = nvme_nvm_setup_20(nvmdev, nvm_id,
>> -				(struct nvme_nvm_id20 *)id);
>> +		ret = nvme_nvm_setup_20((struct nvme_nvm_id20 *)id,
>> +							&nvmdev->dev_geo);
>>  		break;
>>  	default:
>> -		dev_err(ns->ctrl->device,
>> -			"OCSSD revision not supported (%d)\n",
>> -			nvm_id->ver_id);
>> +		dev_err(ns->ctrl->device, "OCSSD revision not supported (%d)\n",
>> +							id->ver_id);
>>  		ret = -EINVAL;
>>  	}
>> +
>>  out:
>>  	kfree(id);
>>  	return ret;
>> @@ -401,12 +452,12 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
>>  								u8 *blks)
>>  {
>>  	struct request_queue *q = nvmdev->q;
>> -	struct nvm_geo *geo = &nvmdev->geo;
>> +	struct nvm_dev_geo *dev_geo = &nvmdev->dev_geo;
>>  	struct nvme_ns *ns = q->queuedata;
>>  	struct nvme_ctrl *ctrl = ns->ctrl;
>>  	struct nvme_nvm_command c = {};
>>  	struct nvme_nvm_bb_tbl *bb_tbl;
>> -	int nr_blks = geo->nr_chks * geo->plane_mode;
>> +	int nr_blks = dev_geo->c.num_chk * dev_geo->c.num_pln;
>>  	int tblsz = sizeof(struct nvme_nvm_bb_tbl) + nr_blks;
>>  	int ret = 0;
>>  @@ -447,7 +498,7 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
>>  		goto out;
>>  	}
>>  -	memcpy(blks, bb_tbl->blk, geo->nr_chks * geo->plane_mode);
>> +	memcpy(blks, bb_tbl->blk, dev_geo->c.num_chk * dev_geo->c.num_pln);
>>  out:
>>  	kfree(bb_tbl);
>>  	return ret;
>> @@ -815,9 +866,10 @@ int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd, unsigned long arg)
>>  void nvme_nvm_update_nvm_info(struct nvme_ns *ns)
>>  {
>>  	struct nvm_dev *ndev = ns->ndev;
>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>  -	ndev->identity.csecs = ndev->geo.sec_size = 1 << ns->lba_shift;
>> -	ndev->identity.sos = ndev->geo.oob_size = ns->ms;
>> +	dev_geo->c.csecs = 1 << ns->lba_shift;
>> +	dev_geo->c.sos = ns->ms;
>>  }
>>    int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node)
>> @@ -850,23 +902,22 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>  {
>>  	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>>  	struct nvm_dev *ndev = ns->ndev;
>> -	struct nvm_id *id;
>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>  	struct attribute *attr;
>>    	if (!ndev)
>>  		return 0;
>>  -	id = &ndev->identity;
>>  	attr = &dattr->attr;
>>    	if (strcmp(attr->name, "version") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ver_id);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>>  	} else if (strcmp(attr->name, "capabilities") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->cap);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
>>  	} else if (strcmp(attr->name, "read_typ") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdt);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>>  	} else if (strcmp(attr->name, "read_max") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdm);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdm);
>>  	} else {
>>  		return scnprintf(page,
>>  				 PAGE_SIZE,
>> @@ -875,75 +926,79 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>  	}
>>  }
>>  +static ssize_t nvm_dev_attr_show_ppaf(struct nvm_addr_format_12 *ppaf,
>> +					 char *page)
>> +{
>> +	return scnprintf(page, PAGE_SIZE,
>> +		"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
>> +				ppaf->ch_offset, ppaf->ch_len,
>> +				ppaf->lun_offset, ppaf->lun_len,
>> +				ppaf->pln_offset, ppaf->pln_len,
>> +				ppaf->blk_offset, ppaf->blk_len,
>> +				ppaf->pg_offset, ppaf->pg_len,
>> +				ppaf->sect_offset, ppaf->sect_len);
>> +}
>> +
>>  static ssize_t nvm_dev_attr_show_12(struct device *dev,
>>  		struct device_attribute *dattr, char *page)
>>  {
>>  	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>>  	struct nvm_dev *ndev = ns->ndev;
>> -	struct nvm_id *id;
>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>  	struct attribute *attr;
>>    	if (!ndev)
>>  		return 0;
>>  -	id = &ndev->identity;
>>  	attr = &dattr->attr;
>>    	if (strcmp(attr->name, "vendor_opcode") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->vmnt);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.vmnt);
>>  	} else if (strcmp(attr->name, "device_mode") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->dom);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.dom);
>>  	/* kept for compatibility */
>>  	} else if (strcmp(attr->name, "media_manager") == 0) {
>>  		return scnprintf(page, PAGE_SIZE, "%s\n", "gennvm");
>>  	} else if (strcmp(attr->name, "ppa_format") == 0) {
>> -		return scnprintf(page, PAGE_SIZE,
>> -			"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
>> -			id->ppaf.ch_offset, id->ppaf.ch_len,
>> -			id->ppaf.lun_offset, id->ppaf.lun_len,
>> -			id->ppaf.pln_offset, id->ppaf.pln_len,
>> -			id->ppaf.blk_offset, id->ppaf.blk_len,
>> -			id->ppaf.pg_offset, id->ppaf.pg_len,
>> -			id->ppaf.sect_offset, id->ppaf.sect_len);
>> +		return nvm_dev_attr_show_ppaf((void *)&dev_geo->c.addrf, page);
>>  	} else if (strcmp(attr->name, "media_type") == 0) {	/* u8 */
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->mtype);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mtype);
>>  	} else if (strcmp(attr->name, "flash_media_type") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->fmtype);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fmtype);
>>  	} else if (strcmp(attr->name, "num_channels") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
>>  	} else if (strcmp(attr->name, "num_luns") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
>>  	} else if (strcmp(attr->name, "num_planes") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pln);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pln);
>>  	} else if (strcmp(attr->name, "num_blocks") == 0) {	/* u16 */
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
>>  	} else if (strcmp(attr->name, "num_pages") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pg);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pg);
>>  	} else if (strcmp(attr->name, "page_size") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->fpg_sz);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fpg_sz);
>>  	} else if (strcmp(attr->name, "hw_sector_size") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->csecs);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.csecs);
>>  	} else if (strcmp(attr->name, "oob_sector_size") == 0) {/* u32 */
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->sos);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.sos);
>>  	} else if (strcmp(attr->name, "prog_typ") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
>>  	} else if (strcmp(attr->name, "prog_max") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
>>  	} else if (strcmp(attr->name, "erase_typ") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
>>  	} else if (strcmp(attr->name, "erase_max") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>  	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mpos);
>> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
>>  	} else if (strcmp(attr->name, "media_capabilities") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mccap);
>> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
>>  	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
>>  		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>>  	} else {
>> -		return scnprintf(page,
>> -				 PAGE_SIZE,
>> -				 "Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
>> -				 attr->name);
>> +		return scnprintf(page, PAGE_SIZE,
>> +			"Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
>> +			attr->name);
>>  	}
>>  }
>>  @@ -952,42 +1007,40 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>>  {
>>  	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>>  	struct nvm_dev *ndev = ns->ndev;
>> -	struct nvm_id *id;
>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>  	struct attribute *attr;
>>    	if (!ndev)
>>  		return 0;
>>  -	id = &ndev->identity;
>>  	attr = &dattr->attr;
>>    	if (strcmp(attr->name, "groups") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
>>  	} else if (strcmp(attr->name, "punits") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
>>  	} else if (strcmp(attr->name, "chunks") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
>>  	} else if (strcmp(attr->name, "clba") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->clba);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.clba);
>>  	} else if (strcmp(attr->name, "ws_min") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_min);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_min);
>>  	} else if (strcmp(attr->name, "ws_opt") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_opt);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_opt);
>>  	} else if (strcmp(attr->name, "mw_cunits") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->mw_cunits);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mw_cunits);
>>  	} else if (strcmp(attr->name, "write_typ") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
>>  	} else if (strcmp(attr->name, "write_max") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
>>  	} else if (strcmp(attr->name, "reset_typ") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
>>  	} else if (strcmp(attr->name, "reset_max") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>  	} else {
>> -		return scnprintf(page,
>> -				 PAGE_SIZE,
>> -				 "Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
>> -				 attr->name);
>> +		return scnprintf(page, PAGE_SIZE,
>> +			"Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
>> +			attr->name);
>>  	}
>>  }
>>  @@ -1106,10 +1159,13 @@ static const struct attribute_group nvm_dev_attr_group_20 = {
>>    int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>>  {
>> -	if (!ns->ndev)
>> +	struct nvm_dev *ndev = ns->ndev;
>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>> +
>> +	if (!ndev)
>>  		return -EINVAL;
>>  -	switch (ns->ndev->identity.ver_id) {
>> +	switch (dev_geo->ver_id) {
>>  	case 1:
>>  		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
>>  					&nvm_dev_attr_group_12);
>> @@ -1123,7 +1179,10 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>>    void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
>>  {
>> -	switch (ns->ndev->identity.ver_id) {
>> +	struct nvm_dev *ndev = ns->ndev;
>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>> +
>> +	switch (dev_geo->ver_id) {
>>  	case 1:
>>  		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
>>  					&nvm_dev_attr_group_12);
>> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
>> index e55b10573c99..18e3751b1632 100644
>> --- a/include/linux/lightnvm.h
>> +++ b/include/linux/lightnvm.h
>> @@ -50,7 +50,7 @@ struct nvm_id;
>>  struct nvm_dev;
>>  struct nvm_tgt_dev;
>>  -typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *);
>> +typedef int (nvm_id_fn)(struct nvm_dev *);
>>  typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, u8 *);
>>  typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct ppa_addr *, int, int);
>>  typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
>> @@ -152,62 +152,107 @@ struct nvm_id_lp_tbl {
>>  	struct nvm_id_lp_mlc mlc;
>>  };
>>  -struct nvm_addr_format {
>> -	u8	ch_offset;
>> +struct nvm_addr_format_12 {
>>  	u8	ch_len;
>> -	u8	lun_offset;
>>  	u8	lun_len;
>> -	u8	pln_offset;
>> +	u8	blk_len;
>> +	u8	pg_len;
>>  	u8	pln_len;
>> +	u8	sect_len;
>> +
>> +	u8	ch_offset;
>> +	u8	lun_offset;
>>  	u8	blk_offset;
>> -	u8	blk_len;
>>  	u8	pg_offset;
>> -	u8	pg_len;
>> +	u8	pln_offset;
>>  	u8	sect_offset;
>> -	u8	sect_len;
>> +
>> +	u64	ch_mask;
>> +	u64	lun_mask;
>> +	u64	blk_mask;
>> +	u64	pg_mask;
>> +	u64	pln_mask;
>> +	u64	sec_mask;
>> +};
>> +
>> +struct nvm_addr_format {
>> +	u8	ch_len;
>> +	u8	lun_len;
>> +	u8	chk_len;
>> +	u8	sec_len;
>> +	u8	rsv_len[2];
>> +
>> +	u8	ch_offset;
>> +	u8	lun_offset;
>> +	u8	chk_offset;
>> +	u8	sec_offset;
>> +	u8	rsv_off[2];
>> +
>> +	u64	ch_mask;
>> +	u64	lun_mask;
>> +	u64	chk_mask;
>> +	u64	sec_mask;
>> +	u64	rsv_mask[2];
>>  };
>>  -struct nvm_id {
>> -	u8	ver_id;
>> +/* Device common geometry */
>> +struct nvm_common_geo {
>> +	/* chunk geometry */
>> +	u32	num_chk;	/* chunks per lun */
>> +	u32	clba;		/* sectors per chunk */
>> +	u16	csecs;		/* sector size */
>> +	u16	sos;		/* out-of-band area size */
>> +
>> +	/* device write constrains */
>> +	u32	ws_min;		/* minimum write size */
>> +	u32	ws_opt;		/* optimal write size */
>> +	u32	mw_cunits;	/* distance required for successful read */
>> +
>> +	/* device capabilities */
>> +	u32	mccap;
>> +
>> +	/* device timings */
>> +	u32	trdt;		/* Avg. Tread (ns) */
>> +	u32	trdm;		/* Max Tread (ns) */
>> +	u32	tprt;		/* Avg. Tprog (ns) */
>> +	u32	tprm;		/* Max Tprog (ns) */
>> +	u32	tbet;		/* Avg. Terase (ns) */
>> +	u32	tbem;		/* Max Terase (ns) */
>> +
>> +	/* generic address format */
>> +	struct nvm_addr_format addrf;
>> +
>> +	/* 1.2 compatibility */
>>  	u8	vmnt;
>>  	u32	cap;
>>  	u32	dom;
>>  -	struct	nvm_addr_format ppaf;
>> -
>> -	u8	num_ch;
>> -	u8	num_lun;
>> -	u16	num_chk;
>> -	u16	clba;
>> -	u16	csecs;
>> -	u16	sos;
>> -
>> -	u32	ws_min;
>> -	u32	ws_opt;
>> -	u32	mw_cunits;
>> -
>> -	u32	trdt;
>> -	u32	trdm;
>> -	u32	tprt;
>> -	u32	tprm;
>> -	u32	tbet;
>> -	u32	tbem;
>> -	u32	mpos;
>> -	u32	mccap;
>> -	u16	cpar;
>> -
>> -	/* calculated values */
>> -	u16	ws_seq;
>> -	u16	ws_per_chk;
>> -
>> -	/* 1.2 compatibility */
>>  	u8	mtype;
>>  	u8	fmtype;
>>  +	u16	cpar;
>> +	u32	mpos;
>> +
>>  	u8	num_pln;
>> +	u8	pln_mode;
>>  	u16	num_pg;
>>  	u16	fpg_sz;
>> -} __packed;
>> +};
>> +
>> +/* Device identified geometry */
>> +struct nvm_dev_geo {
>> +	/* device reported version */
>> +	u8	ver_id;
>> +
>> +	/* full device geometry */
>> +	u16	nr_chnls;
>> +	u16	nr_luns;
>> +
>> +	/* calculated values */
>> +	u16	all_luns;
>> +
>> +	struct nvm_common_geo c;
>> +};
>>    struct nvm_target {
>>  	struct list_head list;
>> @@ -274,36 +319,22 @@ enum {
>>  	NVM_BLK_ST_BAD =	0x8,	/* Bad block */
>>  };
>>  -
>> -/* Device generic information */
>> +/* Instance geometry */
>>  struct nvm_geo {
>> -	/* generic geometry */
>> +	/* instance specific geometry */
>>  	int nr_chnls;
>> -	int all_luns; /* across channels */
>> -	int nr_luns; /* per channel */
>> -	int nr_chks; /* per lun */
>> -
>> -	int sec_size;
>> -	int oob_size;
>> -	int mccap;
>> -
>> -	int sec_per_chk;
>> -	int sec_per_lun;
>> -
>> -	int ws_min;
>> -	int ws_opt;
>> -	int ws_seq;
>> -	int ws_per_chk;
>> +	int nr_luns;		/* per channel */
>>    	int op;
>>  -	struct nvm_addr_format ppaf;
>> +	/* common geometry */
>> +	struct nvm_common_geo c;
>>  -	/* Legacy 1.2 specific geometry */
>> -	int plane_mode; /* drive device in single, double or quad mode */
>> -	int nr_planes;
>> -	int sec_per_pg; /* only sectors for a single page */
>> -	int sec_per_pl; /* all sectors across planes */
>> +	/* calculated values */
>> +	int all_luns;		/* across channels */
>> +	int all_chunks;		/* across channels */
>> +
>> +	sector_t total_secs;	/* across channels */
>>  };
>>    /* sub-device structure */
>> @@ -314,9 +345,6 @@ struct nvm_tgt_dev {
>>  	/* Base ppas for target LUNs */
>>  	struct ppa_addr *luns;
>>  -	sector_t total_secs;
>> -
>> -	struct nvm_id identity;
>>  	struct request_queue *q;
>>    	struct nvm_dev *parent;
>> @@ -329,15 +357,11 @@ struct nvm_dev {
>>  	struct list_head devices;
>>    	/* Device information */
>> -	struct nvm_geo geo;
>> -
>> -	unsigned long total_secs;
>> +	struct nvm_dev_geo dev_geo;
>>    	unsigned long *lun_map;
>>  	void *dma_pool;
>>  -	struct nvm_id identity;
>> -
>>  	/* Backend device */
>>  	struct request_queue *q;
>>  	char name[DISK_NAME_LEN];
>> @@ -357,14 +381,16 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
>>  						  struct ppa_addr r)
>>  {
>>  	struct nvm_geo *geo = &tgt_dev->geo;
>> +	struct nvm_addr_format_12 *ppaf =
>> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>>  	struct ppa_addr l;
>>  -	l.ppa = ((u64)r.g.blk) << geo->ppaf.blk_offset;
>> -	l.ppa |= ((u64)r.g.pg) << geo->ppaf.pg_offset;
>> -	l.ppa |= ((u64)r.g.sec) << geo->ppaf.sect_offset;
>> -	l.ppa |= ((u64)r.g.pl) << geo->ppaf.pln_offset;
>> -	l.ppa |= ((u64)r.g.lun) << geo->ppaf.lun_offset;
>> -	l.ppa |= ((u64)r.g.ch) << geo->ppaf.ch_offset;
>> +	l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
>> +	l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
>> +	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
>> +	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
>> +	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
>> +	l.ppa |= ((u64)r.g.sec) << ppaf->sect_offset;
>>    	return l;
>>  }
>> @@ -373,24 +399,18 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
>>  						  struct ppa_addr r)
>>  {
>>  	struct nvm_geo *geo = &tgt_dev->geo;
>> +	struct nvm_addr_format_12 *ppaf =
>> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>>  	struct ppa_addr l;
>>    	l.ppa = 0;
>> -	/*
>> -	 * (r.ppa << X offset) & X len bitmask. X eq. blk, pg, etc.
>> -	 */
>> -	l.g.blk = (r.ppa >> geo->ppaf.blk_offset) &
>> -					(((1 << geo->ppaf.blk_len) - 1));
>> -	l.g.pg |= (r.ppa >> geo->ppaf.pg_offset) &
>> -					(((1 << geo->ppaf.pg_len) - 1));
>> -	l.g.sec |= (r.ppa >> geo->ppaf.sect_offset) &
>> -					(((1 << geo->ppaf.sect_len) - 1));
>> -	l.g.pl |= (r.ppa >> geo->ppaf.pln_offset) &
>> -					(((1 << geo->ppaf.pln_len) - 1));
>> -	l.g.lun |= (r.ppa >> geo->ppaf.lun_offset) &
>> -					(((1 << geo->ppaf.lun_len) - 1));
>> -	l.g.ch |= (r.ppa >> geo->ppaf.ch_offset) &
>> -					(((1 << geo->ppaf.ch_len) - 1));
>> +
>> +	l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
>> +	l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
>> +	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
>> +	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
>> +	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
>> +	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sect_offset;
>>    	return l;
>>  }
> 
> Thanks for the patch. I appreciate the work, but it is not the way I
> want the 2.0 representation to go. The 2.0 variables should stay in
> the nvm_geo data structure, and then if any 1.2 variables are on the
> side, they can be in a substructure.

I don't understand. Everything is in nvm_geo, with the only different
that there is nvm_common_geo, which contains the shared geometry between
all instances. As mentioned before, if only having nvm_geo, then we are
truncating the structure for each instance with different channel/lun
values, which is very from a target perspective (the target can access
the underlying device's values, which is _very_ error prone). This
structure represents all 2.0 variables as they are.I can move all 1.2
variables to a sub structure if that helps.

If this is not it, can you explain in detail what the problem is? In
pblk, I don't want to deal with a device-centric structure and variables
spread out across what was identity and nvm_geo, I want a single
structure that contains everything, which is the motivation for this
patch.

Javier


[-- Attachment #2: Message signed with OpenPGP --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 01/20] lightnvm: simplify geometry structure.
@ 2018-02-22  7:44       ` Javier Gonzalez
  0 siblings, 0 replies; 99+ messages in thread
From: Javier Gonzalez @ 2018-02-22  7:44 UTC (permalink / raw)



> On 22 Feb 2018,@08.25, Matias Bj?rling <mb@lightnvm.io> wrote:
> 
> On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
>> Currently, the device geometry is stored redundantly in the nvm_id and
>> nvm_geo structures at a device level. Moreover, when instantiating
>> targets on a specific number of LUNs, these structures are replicated
>> and manually modified to fit the instance channel and LUN partitioning.
>> Instead, create a generic geometry around two base structures:
>> nvm_dev_geo, which describes the geometry of the whole device and
>> nvm_geo, which describes the geometry of the instance. Since these share
>> a big part of the geometry, create a nvm_common_geo structure that keeps
>> the static geoometry values that are shared across instances.
>> As we introduce support for 2.0, these structures allow to abstract
>> spec. specific values and present a common geometry to targets.
>> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
>> ---
>>  drivers/lightnvm/core.c          | 137 +++++++---------
>>  drivers/lightnvm/pblk-core.c     |  16 +-
>>  drivers/lightnvm/pblk-gc.c       |   2 +-
>>  drivers/lightnvm/pblk-init.c     | 123 +++++++-------
>>  drivers/lightnvm/pblk-read.c     |   2 +-
>>  drivers/lightnvm/pblk-recovery.c |  14 +-
>>  drivers/lightnvm/pblk-rl.c       |   2 +-
>>  drivers/lightnvm/pblk-sysfs.c    |  39 +++--
>>  drivers/lightnvm/pblk-write.c    |   2 +-
>>  drivers/lightnvm/pblk.h          |  93 +++++------
>>  drivers/nvme/host/lightnvm.c     | 339 +++++++++++++++++++++++----------------
>>  include/linux/lightnvm.h         | 204 ++++++++++++-----------
>>  12 files changed, 514 insertions(+), 459 deletions(-)
>> diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
>> index 689c97b97775..42596afdf64c 100644
>> --- a/drivers/lightnvm/core.c
>> +++ b/drivers/lightnvm/core.c
>> @@ -111,6 +111,7 @@ static void nvm_release_luns_err(struct nvm_dev *dev, int lun_begin,
>>  static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
>>  {
>>  	struct nvm_dev *dev = tgt_dev->parent;
>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>  	struct nvm_dev_map *dev_map = tgt_dev->map;
>>  	int i, j;
>>  @@ -122,7 +123,7 @@ static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
>>  		if (clear) {
>>  			for (j = 0; j < ch_map->nr_luns; j++) {
>>  				int lun = j + lun_offs[j];
>> -				int lunid = (ch * dev->geo.nr_luns) + lun;
>> +				int lunid = (ch * dev_geo->nr_luns) + lun;
>>    				WARN_ON(!test_and_clear_bit(lunid,
>>  							dev->lun_map));
>> @@ -143,19 +144,20 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>>  					      u16 lun_begin, u16 lun_end,
>>  					      u16 op)
>>  {
>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>  	struct nvm_tgt_dev *tgt_dev = NULL;
>>  	struct nvm_dev_map *dev_rmap = dev->rmap;
>>  	struct nvm_dev_map *dev_map;
>>  	struct ppa_addr *luns;
>>  	int nr_luns = lun_end - lun_begin + 1;
>>  	int luns_left = nr_luns;
>> -	int nr_chnls = nr_luns / dev->geo.nr_luns;
>> -	int nr_chnls_mod = nr_luns % dev->geo.nr_luns;
>> -	int bch = lun_begin / dev->geo.nr_luns;
>> -	int blun = lun_begin % dev->geo.nr_luns;
>> +	int nr_chnls = nr_luns / dev_geo->nr_luns;
>> +	int nr_chnls_mod = nr_luns % dev_geo->nr_luns;
>> +	int bch = lun_begin / dev_geo->nr_luns;
>> +	int blun = lun_begin % dev_geo->nr_luns;
>>  	int lunid = 0;
>>  	int lun_balanced = 1;
>> -	int prev_nr_luns;
>> +	int sec_per_lun, prev_nr_luns;
>>  	int i, j;
>>    	nr_chnls = (nr_chnls_mod == 0) ? nr_chnls : nr_chnls + 1;
>> @@ -173,15 +175,15 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>>  	if (!luns)
>>  		goto err_luns;
>>  -	prev_nr_luns = (luns_left > dev->geo.nr_luns) ?
>> -					dev->geo.nr_luns : luns_left;
>> +	prev_nr_luns = (luns_left > dev_geo->nr_luns) ?
>> +					dev_geo->nr_luns : luns_left;
>>  	for (i = 0; i < nr_chnls; i++) {
>>  		struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[i + bch];
>>  		int *lun_roffs = ch_rmap->lun_offs;
>>  		struct nvm_ch_map *ch_map = &dev_map->chnls[i];
>>  		int *lun_offs;
>> -		int luns_in_chnl = (luns_left > dev->geo.nr_luns) ?
>> -					dev->geo.nr_luns : luns_left;
>> +		int luns_in_chnl = (luns_left > dev_geo->nr_luns) ?
>> +					dev_geo->nr_luns : luns_left;
>>    		if (lun_balanced && prev_nr_luns != luns_in_chnl)
>>  			lun_balanced = 0;
>> @@ -215,18 +217,22 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>>  	if (!tgt_dev)
>>  		goto err_ch;
>>  -	memcpy(&tgt_dev->geo, &dev->geo, sizeof(struct nvm_geo));
>>  	/* Target device only owns a portion of the physical device */
>>  	tgt_dev->geo.nr_chnls = nr_chnls;
>> -	tgt_dev->geo.all_luns = nr_luns;
>>  	tgt_dev->geo.nr_luns = (lun_balanced) ? prev_nr_luns : -1;
>> +	tgt_dev->geo.all_luns = nr_luns;
>> +	tgt_dev->geo.all_chunks = nr_luns * dev_geo->c.num_chk;
>> +
>>  	tgt_dev->geo.op = op;
>> -	tgt_dev->total_secs = nr_luns * tgt_dev->geo.sec_per_lun;
>> +
>> +	sec_per_lun = dev_geo->c.clba * dev_geo->c.num_chk;
>> +	tgt_dev->geo.total_secs = nr_luns * sec_per_lun;
>> +
>> +	tgt_dev->geo.c = dev_geo->c;
>> +
>>  	tgt_dev->q = dev->q;
>>  	tgt_dev->map = dev_map;
>>  	tgt_dev->luns = luns;
>> -	memcpy(&tgt_dev->identity, &dev->identity, sizeof(struct nvm_id));
>> -
>>  	tgt_dev->parent = dev;
>>    	return tgt_dev;
>> @@ -268,12 +274,12 @@ static struct nvm_tgt_type *nvm_find_target_type(const char *name)
>>  	return tt;
>>  }
>>  -static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
>> +static int nvm_config_check_luns(struct nvm_dev_geo *dev_geo, int lun_begin,
>>  				 int lun_end)
>>  {
>> -	if (lun_begin > lun_end || lun_end >= geo->all_luns) {
>> +	if (lun_begin > lun_end || lun_end >= dev_geo->all_luns) {
>>  		pr_err("nvm: lun out of bound (%u:%u > %u)\n",
>> -			lun_begin, lun_end, geo->all_luns - 1);
>> +			lun_begin, lun_end, dev_geo->all_luns - 1);
>>  		return -EINVAL;
>>  	}
>>  @@ -283,24 +289,24 @@ static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
>>  static int __nvm_config_simple(struct nvm_dev *dev,
>>  			       struct nvm_ioctl_create_simple *s)
>>  {
>> -	struct nvm_geo *geo = &dev->geo;
>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>    	if (s->lun_begin == -1 && s->lun_end == -1) {
>>  		s->lun_begin = 0;
>> -		s->lun_end = geo->all_luns - 1;
>> +		s->lun_end = dev_geo->all_luns - 1;
>>  	}
>>  -	return nvm_config_check_luns(geo, s->lun_begin, s->lun_end);
>> +	return nvm_config_check_luns(dev_geo, s->lun_begin, s->lun_end);
>>  }
>>    static int __nvm_config_extended(struct nvm_dev *dev,
>>  				 struct nvm_ioctl_create_extended *e)
>>  {
>> -	struct nvm_geo *geo = &dev->geo;
>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>    	if (e->lun_begin == 0xFFFF && e->lun_end == 0xFFFF) {
>>  		e->lun_begin = 0;
>> -		e->lun_end = dev->geo.all_luns - 1;
>> +		e->lun_end = dev_geo->all_luns - 1;
>>  	}
>>    	/* op not set falls into target's default */
>> @@ -313,7 +319,7 @@ static int __nvm_config_extended(struct nvm_dev *dev,
>>  		return -EINVAL;
>>  	}
>>  -	return nvm_config_check_luns(geo, e->lun_begin, e->lun_end);
>> +	return nvm_config_check_luns(dev_geo, e->lun_begin, e->lun_end);
>>  }
>>    static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
>> @@ -408,7 +414,7 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
>>  	tqueue->queuedata = targetdata;
>>    	blk_queue_max_hw_sectors(tqueue,
>> -			(dev->geo.sec_size >> 9) * NVM_MAX_VLBA);
>> +			(dev->dev_geo.c.csecs >> 9) * NVM_MAX_VLBA);
>>    	set_capacity(tdisk, tt->capacity(targetdata));
>>  	add_disk(tdisk);
>> @@ -497,6 +503,7 @@ static int nvm_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove)
>>    static int nvm_register_map(struct nvm_dev *dev)
>>  {
>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>  	struct nvm_dev_map *rmap;
>>  	int i, j;
>>  @@ -504,15 +511,15 @@ static int nvm_register_map(struct nvm_dev *dev)
>>  	if (!rmap)
>>  		goto err_rmap;
>>  -	rmap->chnls = kcalloc(dev->geo.nr_chnls, sizeof(struct nvm_ch_map),
>> +	rmap->chnls = kcalloc(dev_geo->nr_chnls, sizeof(struct nvm_ch_map),
>>  								GFP_KERNEL);
>>  	if (!rmap->chnls)
>>  		goto err_chnls;
>>  -	for (i = 0; i < dev->geo.nr_chnls; i++) {
>> +	for (i = 0; i < dev_geo->nr_chnls; i++) {
>>  		struct nvm_ch_map *ch_rmap;
>>  		int *lun_roffs;
>> -		int luns_in_chnl = dev->geo.nr_luns;
>> +		int luns_in_chnl = dev_geo->nr_luns;
>>    		ch_rmap = &rmap->chnls[i];
>>  @@ -543,10 +550,11 @@ static int nvm_register_map(struct nvm_dev *dev)
>>    static void nvm_unregister_map(struct nvm_dev *dev)
>>  {
>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>  	struct nvm_dev_map *rmap = dev->rmap;
>>  	int i;
>>  -	for (i = 0; i < dev->geo.nr_chnls; i++)
>> +	for (i = 0; i < dev_geo->nr_chnls; i++)
>>  		kfree(rmap->chnls[i].lun_offs);
>>    	kfree(rmap->chnls);
>> @@ -675,7 +683,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
>>  	int i, plane_cnt, pl_idx;
>>  	struct ppa_addr ppa;
>>  -	if (geo->plane_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
>> +	if (geo->c.pln_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
>>  		rqd->nr_ppas = nr_ppas;
>>  		rqd->ppa_addr = ppas[0];
>>  @@ -689,7 +697,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
>>  		return -ENOMEM;
>>  	}
>>  -	plane_cnt = geo->plane_mode;
>> +	plane_cnt = geo->c.pln_mode;
>>  	rqd->nr_ppas *= plane_cnt;
>>    	for (i = 0; i < nr_ppas; i++) {
>> @@ -804,18 +812,18 @@ EXPORT_SYMBOL(nvm_end_io);
>>   */
>>  int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
>>  {
>> -	struct nvm_geo *geo = &dev->geo;
>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>  	int blk, offset, pl, blktype;
>>  -	if (nr_blks != geo->nr_chks * geo->plane_mode)
>> +	if (nr_blks != dev_geo->c.num_chk * dev_geo->c.pln_mode)
>>  		return -EINVAL;
>>  -	for (blk = 0; blk < geo->nr_chks; blk++) {
>> -		offset = blk * geo->plane_mode;
>> +	for (blk = 0; blk < dev_geo->c.num_chk; blk++) {
>> +		offset = blk * dev_geo->c.pln_mode;
>>  		blktype = blks[offset];
>>    		/* Bad blocks on any planes take precedence over other types */
>> -		for (pl = 0; pl < geo->plane_mode; pl++) {
>> +		for (pl = 0; pl < dev_geo->c.pln_mode; pl++) {
>>  			if (blks[offset + pl] &
>>  					(NVM_BLK_T_BAD|NVM_BLK_T_GRWN_BAD)) {
>>  				blktype = blks[offset + pl];
>> @@ -826,7 +834,7 @@ int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
>>  		blks[blk] = blktype;
>>  	}
>>  -	return geo->nr_chks;
>> +	return dev_geo->c.num_chk;
>>  }
>>  EXPORT_SYMBOL(nvm_bb_tbl_fold);
>>  @@ -843,41 +851,10 @@ EXPORT_SYMBOL(nvm_get_tgt_bb_tbl);
>>    static int nvm_core_init(struct nvm_dev *dev)
>>  {
>> -	struct nvm_id *id = &dev->identity;
>> -	struct nvm_geo *geo = &dev->geo;
>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>  	int ret;
>>  -	memcpy(&geo->ppaf, &id->ppaf, sizeof(struct nvm_addr_format));
>> -
>> -	if (id->mtype != 0) {
>> -		pr_err("nvm: memory type not supported\n");
>> -		return -EINVAL;
>> -	}
>> -
>> -	/* Whole device values */
>> -	geo->nr_chnls = id->num_ch;
>> -	geo->nr_luns = id->num_lun;
>> -
>> -	/* Generic device geometry values */
>> -	geo->ws_min = id->ws_min;
>> -	geo->ws_opt = id->ws_opt;
>> -	geo->ws_seq = id->ws_seq;
>> -	geo->ws_per_chk = id->ws_per_chk;
>> -	geo->nr_chks = id->num_chk;
>> -	geo->mccap = id->mccap;
>> -
>> -	geo->sec_per_chk = id->clba;
>> -	geo->sec_per_lun = geo->sec_per_chk * geo->nr_chks;
>> -	geo->all_luns = geo->nr_luns * geo->nr_chnls;
>> -
>> -	/* 1.2 spec device geometry values */
>> -	geo->plane_mode = 1 << geo->ws_seq;
>> -	geo->nr_planes = geo->ws_opt / geo->ws_min;
>> -	geo->sec_per_pg = geo->ws_min;
>> -	geo->sec_per_pl = geo->sec_per_pg * geo->nr_planes;
>> -
>> -	dev->total_secs = geo->all_luns * geo->sec_per_lun;
>> -	dev->lun_map = kcalloc(BITS_TO_LONGS(geo->all_luns),
>> +	dev->lun_map = kcalloc(BITS_TO_LONGS(dev_geo->all_luns),
>>  					sizeof(unsigned long), GFP_KERNEL);
>>  	if (!dev->lun_map)
>>  		return -ENOMEM;
>> @@ -912,19 +889,17 @@ static void nvm_free(struct nvm_dev *dev)
>>    static int nvm_init(struct nvm_dev *dev)
>>  {
>> -	struct nvm_geo *geo = &dev->geo;
>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>  	int ret = -EINVAL;
>>  -	if (dev->ops->identity(dev, &dev->identity)) {
>> +	if (dev->ops->identity(dev)) {
>>  		pr_err("nvm: device could not be identified\n");
>>  		goto err;
>>  	}
>>  -	if (dev->identity.ver_id != 1 && dev->identity.ver_id != 2) {
>> -		pr_err("nvm: device ver_id %d not supported by kernel.\n",
>> -				dev->identity.ver_id);
>> -		goto err;
>> -	}
>> +	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
>> +				dev_geo->ver_id,
>> +				dev_geo->c.vmnt);
>>    	ret = nvm_core_init(dev);
>>  	if (ret) {
>> @@ -932,10 +907,10 @@ static int nvm_init(struct nvm_dev *dev)
>>  		goto err;
>>  	}
>>  -	pr_info("nvm: registered %s [%u/%u/%u/%u/%u/%u]\n",
>> -			dev->name, geo->sec_per_pg, geo->nr_planes,
>> -			geo->ws_per_chk, geo->nr_chks,
>> -			geo->all_luns, geo->nr_chnls);
>> +	pr_info("nvm: registered %s [%u/%u/%u/%u/%u]\n",
>> +			dev->name, dev_geo->c.ws_min, dev_geo->c.ws_opt,
>> +			dev_geo->c.num_chk, dev_geo->all_luns,
>> +			dev_geo->nr_chnls);
>>  	return 0;
>>  err:
>>  	pr_err("nvm: failed to initialize nvm\n");
>> diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
>> index 22e61cd4f801..519af8b9eab7 100644
>> --- a/drivers/lightnvm/pblk-core.c
>> +++ b/drivers/lightnvm/pblk-core.c
>> @@ -613,7 +613,7 @@ static int pblk_line_submit_emeta_io(struct pblk *pblk, struct pblk_line *line,
>>  	memset(&rqd, 0, sizeof(struct nvm_rq));
>>    	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>> -	rq_len = rq_ppas * geo->sec_size;
>> +	rq_len = rq_ppas * geo->c.csecs;
>>    	bio = pblk_bio_map_addr(pblk, emeta_buf, rq_ppas, rq_len,
>>  					l_mg->emeta_alloc_type, GFP_KERNEL);
>> @@ -722,7 +722,7 @@ u64 pblk_line_smeta_start(struct pblk *pblk, struct pblk_line *line)
>>  	if (bit >= lm->blk_per_line)
>>  		return -1;
>>  -	return bit * geo->sec_per_pl;
>> +	return bit * geo->c.ws_opt;
>>  }
>>    static int pblk_line_submit_smeta_io(struct pblk *pblk, struct pblk_line *line,
>> @@ -1035,19 +1035,19 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>>  	/* Capture bad block information on line mapping bitmaps */
>>  	while ((bit = find_next_bit(line->blk_bitmap, lm->blk_per_line,
>>  					bit + 1)) < lm->blk_per_line) {
>> -		off = bit * geo->sec_per_pl;
>> +		off = bit * geo->c.ws_opt;
>>  		bitmap_shift_left(l_mg->bb_aux, l_mg->bb_template, off,
>>  							lm->sec_per_line);
>>  		bitmap_or(line->map_bitmap, line->map_bitmap, l_mg->bb_aux,
>>  							lm->sec_per_line);
>> -		line->sec_in_line -= geo->sec_per_chk;
>> +		line->sec_in_line -= geo->c.clba;
>>  		if (bit >= lm->emeta_bb)
>>  			nr_bb++;
>>  	}
>>    	/* Mark smeta metadata sectors as bad sectors */
>>  	bit = find_first_zero_bit(line->blk_bitmap, lm->blk_per_line);
>> -	off = bit * geo->sec_per_pl;
>> +	off = bit * geo->c.ws_opt;
>>  	bitmap_set(line->map_bitmap, off, lm->smeta_sec);
>>  	line->sec_in_line -= lm->smeta_sec;
>>  	line->smeta_ssec = off;
>> @@ -1066,10 +1066,10 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>>  	emeta_secs = lm->emeta_sec[0];
>>  	off = lm->sec_per_line;
>>  	while (emeta_secs) {
>> -		off -= geo->sec_per_pl;
>> +		off -= geo->c.ws_opt;
>>  		if (!test_bit(off, line->invalid_bitmap)) {
>> -			bitmap_set(line->invalid_bitmap, off, geo->sec_per_pl);
>> -			emeta_secs -= geo->sec_per_pl;
>> +			bitmap_set(line->invalid_bitmap, off, geo->c.ws_opt);
>> +			emeta_secs -= geo->c.ws_opt;
>>  		}
>>  	}
>>  diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c
>> index 320f99af99e9..16afea3f5541 100644
>> --- a/drivers/lightnvm/pblk-gc.c
>> +++ b/drivers/lightnvm/pblk-gc.c
>> @@ -88,7 +88,7 @@ static void pblk_gc_line_ws(struct work_struct *work)
>>    	up(&gc->gc_sem);
>>  -	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->sec_size);
>> +	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->c.csecs);
>>  	if (!gc_rq->data) {
>>  		pr_err("pblk: could not GC line:%d (%d/%d)\n",
>>  					line->id, *line->vsc, gc_rq->nr_secs);
>> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
>> index 5261702e9ff7..95ecb0ec736b 100644
>> --- a/drivers/lightnvm/pblk-init.c
>> +++ b/drivers/lightnvm/pblk-init.c
>> @@ -146,7 +146,7 @@ static int pblk_rwb_init(struct pblk *pblk)
>>  		return -ENOMEM;
>>    	power_size = get_count_order(nr_entries);
>> -	power_seg_sz = get_count_order(geo->sec_size);
>> +	power_seg_sz = get_count_order(geo->c.csecs);
>>    	return pblk_rb_init(&pblk->rwb, entries, power_size, power_seg_sz);
>>  }
>> @@ -154,11 +154,11 @@ static int pblk_rwb_init(struct pblk *pblk)
>>  /* Minimum pages needed within a lun */
>>  #define ADDR_POOL_SIZE 64
>>  -static int pblk_set_ppaf(struct pblk *pblk)
>> +static int pblk_set_addrf_12(struct nvm_geo *geo,
>> +			     struct nvm_addr_format_12 *dst)
>>  {
>> -	struct nvm_tgt_dev *dev = pblk->dev;
>> -	struct nvm_geo *geo = &dev->geo;
>> -	struct nvm_addr_format ppaf = geo->ppaf;
>> +	struct nvm_addr_format_12 *src =
>> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>>  	int power_len;
>>    	/* Re-calculate channel and lun format to adapt to configuration */
>> @@ -167,34 +167,50 @@ static int pblk_set_ppaf(struct pblk *pblk)
>>  		pr_err("pblk: supports only power-of-two channel config.\n");
>>  		return -EINVAL;
>>  	}
>> -	ppaf.ch_len = power_len;
>> +	dst->ch_len = power_len;
>>    	power_len = get_count_order(geo->nr_luns);
>>  	if (1 << power_len != geo->nr_luns) {
>>  		pr_err("pblk: supports only power-of-two LUN config.\n");
>>  		return -EINVAL;
>>  	}
>> -	ppaf.lun_len = power_len;
>> +	dst->lun_len = power_len;
>>  -	pblk->ppaf.sec_offset = 0;
>> -	pblk->ppaf.pln_offset = ppaf.sect_len;
>> -	pblk->ppaf.ch_offset = pblk->ppaf.pln_offset + ppaf.pln_len;
>> -	pblk->ppaf.lun_offset = pblk->ppaf.ch_offset + ppaf.ch_len;
>> -	pblk->ppaf.pg_offset = pblk->ppaf.lun_offset + ppaf.lun_len;
>> -	pblk->ppaf.blk_offset = pblk->ppaf.pg_offset + ppaf.pg_len;
>> -	pblk->ppaf.sec_mask = (1ULL << ppaf.sect_len) - 1;
>> -	pblk->ppaf.pln_mask = ((1ULL << ppaf.pln_len) - 1) <<
>> -							pblk->ppaf.pln_offset;
>> -	pblk->ppaf.ch_mask = ((1ULL << ppaf.ch_len) - 1) <<
>> -							pblk->ppaf.ch_offset;
>> -	pblk->ppaf.lun_mask = ((1ULL << ppaf.lun_len) - 1) <<
>> -							pblk->ppaf.lun_offset;
>> -	pblk->ppaf.pg_mask = ((1ULL << ppaf.pg_len) - 1) <<
>> -							pblk->ppaf.pg_offset;
>> -	pblk->ppaf.blk_mask = ((1ULL << ppaf.blk_len) - 1) <<
>> -							pblk->ppaf.blk_offset;
>> +	dst->blk_len = src->blk_len;
>> +	dst->pg_len = src->pg_len;
>> +	dst->pln_len = src->pln_len;
>> +	dst->sect_len = src->sect_len;
>>  -	pblk->ppaf_bitsize = pblk->ppaf.blk_offset + ppaf.blk_len;
>> +	dst->sect_offset = 0;
>> +	dst->pln_offset = dst->sect_len;
>> +	dst->ch_offset = dst->pln_offset + dst->pln_len;
>> +	dst->lun_offset = dst->ch_offset + dst->ch_len;
>> +	dst->pg_offset = dst->lun_offset + dst->lun_len;
>> +	dst->blk_offset = dst->pg_offset + dst->pg_len;
>> +
>> +	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
>> +	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
>> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>> +	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
>> +	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
>> +
>> +	return dst->blk_offset + src->blk_len;
>> +}
>> +
>> +static int pblk_set_ppaf(struct pblk *pblk)
>> +{
>> +	struct nvm_tgt_dev *dev = pblk->dev;
>> +	struct nvm_geo *geo = &dev->geo;
>> +	int mod;
>> +
>> +	div_u64_rem(geo->c.clba, pblk->min_write_pgs, &mod);
>> +	if (mod) {
>> +		pr_err("pblk: bad configuration of sectors/pages\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	pblk->ppaf_bitsize = pblk_set_addrf_12(geo, (void *)&pblk->ppaf);
>>    	return 0;
>>  }
>> @@ -253,8 +269,7 @@ static int pblk_core_init(struct pblk *pblk)
>>  	struct nvm_tgt_dev *dev = pblk->dev;
>>  	struct nvm_geo *geo = &dev->geo;
>>  -	pblk->pgs_in_buffer = NVM_MEM_PAGE_WRITE * geo->sec_per_pg *
>> -						geo->nr_planes * geo->all_luns;
>> +	pblk->pgs_in_buffer = geo->c.mw_cunits * geo->c.ws_opt * geo->all_luns;
>>    	if (pblk_init_global_caches(pblk))
>>  		return -ENOMEM;
>> @@ -433,7 +448,7 @@ static void *pblk_bb_get_log(struct pblk *pblk)
>>  	int i, nr_blks, blk_per_lun;
>>  	int ret;
>>  -	blk_per_lun = geo->nr_chks * geo->plane_mode;
>> +	blk_per_lun = geo->c.num_chk * geo->c.pln_mode;
>>  	nr_blks = blk_per_lun * geo->all_luns;
>>    	log = kmalloc(nr_blks, GFP_KERNEL);
>> @@ -551,18 +566,18 @@ static unsigned int calc_emeta_len(struct pblk *pblk)
>>  	/* Round to sector size so that lba_list starts on its own sector */
>>  	lm->emeta_sec[1] = DIV_ROUND_UP(
>>  			sizeof(struct line_emeta) + lm->blk_bitmap_len +
>> -			sizeof(struct wa_counters), geo->sec_size);
>> -	lm->emeta_len[1] = lm->emeta_sec[1] * geo->sec_size;
>> +			sizeof(struct wa_counters), geo->c.csecs);
>> +	lm->emeta_len[1] = lm->emeta_sec[1] * geo->c.csecs;
>>    	/* Round to sector size so that vsc_list starts on its own sector */
>>  	lm->dsec_per_line = lm->sec_per_line - lm->emeta_sec[0];
>>  	lm->emeta_sec[2] = DIV_ROUND_UP(lm->dsec_per_line * sizeof(u64),
>> -			geo->sec_size);
>> -	lm->emeta_len[2] = lm->emeta_sec[2] * geo->sec_size;
>> +			geo->c.csecs);
>> +	lm->emeta_len[2] = lm->emeta_sec[2] * geo->c.csecs;
>>    	lm->emeta_sec[3] = DIV_ROUND_UP(l_mg->nr_lines * sizeof(u32),
>> -			geo->sec_size);
>> -	lm->emeta_len[3] = lm->emeta_sec[3] * geo->sec_size;
>> +			geo->c.csecs);
>> +	lm->emeta_len[3] = lm->emeta_sec[3] * geo->c.csecs;
>>    	lm->vsc_list_len = l_mg->nr_lines * sizeof(u32);
>>  @@ -593,13 +608,13 @@ static void pblk_set_provision(struct pblk *pblk, long nr_free_blks)
>>  	 * on user capacity consider only provisioned blocks
>>  	 */
>>  	pblk->rl.total_blocks = nr_free_blks;
>> -	pblk->rl.nr_secs = nr_free_blks * geo->sec_per_chk;
>> +	pblk->rl.nr_secs = nr_free_blks * geo->c.clba;
>>    	/* Consider sectors used for metadata */
>>  	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
>> -	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
>> +	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
>>  -	pblk->capacity = (provisioned - blk_meta) * geo->sec_per_chk;
>> +	pblk->capacity = (provisioned - blk_meta) * geo->c.clba;
>>    	atomic_set(&pblk->rl.free_blocks, nr_free_blks);
>>  	atomic_set(&pblk->rl.free_user_blocks, nr_free_blks);
>> @@ -710,10 +725,10 @@ static int pblk_lines_init(struct pblk *pblk)
>>  	void *chunk_log;
>>  	unsigned int smeta_len, emeta_len;
>>  	long nr_bad_blks = 0, nr_free_blks = 0;
>> -	int bb_distance, max_write_ppas, mod;
>> +	int bb_distance, max_write_ppas;
>>  	int i, ret;
>>  -	pblk->min_write_pgs = geo->sec_per_pl * (geo->sec_size / PAGE_SIZE);
>> +	pblk->min_write_pgs = geo->c.ws_opt * (geo->c.csecs / PAGE_SIZE);
>>  	max_write_ppas = pblk->min_write_pgs * geo->all_luns;
>>  	pblk->max_write_pgs = min_t(int, max_write_ppas, NVM_MAX_VLBA);
>>  	pblk_set_sec_per_write(pblk, pblk->min_write_pgs);
>> @@ -724,19 +739,13 @@ static int pblk_lines_init(struct pblk *pblk)
>>  		return -EINVAL;
>>  	}
>>  -	div_u64_rem(geo->sec_per_chk, pblk->min_write_pgs, &mod);
>> -	if (mod) {
>> -		pr_err("pblk: bad configuration of sectors/pages\n");
>> -		return -EINVAL;
>> -	}
>> -
>> -	l_mg->nr_lines = geo->nr_chks;
>> +	l_mg->nr_lines = geo->c.num_chk;
>>  	l_mg->log_line = l_mg->data_line = NULL;
>>  	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
>>  	l_mg->nr_free_lines = 0;
>>  	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
>>  -	lm->sec_per_line = geo->sec_per_chk * geo->all_luns;
>> +	lm->sec_per_line = geo->c.clba * geo->all_luns;
>>  	lm->blk_per_line = geo->all_luns;
>>  	lm->blk_bitmap_len = BITS_TO_LONGS(geo->all_luns) * sizeof(long);
>>  	lm->sec_bitmap_len = BITS_TO_LONGS(lm->sec_per_line) * sizeof(long);
>> @@ -750,8 +759,8 @@ static int pblk_lines_init(struct pblk *pblk)
>>  	 */
>>  	i = 1;
>>  add_smeta_page:
>> -	lm->smeta_sec = i * geo->sec_per_pl;
>> -	lm->smeta_len = lm->smeta_sec * geo->sec_size;
>> +	lm->smeta_sec = i * geo->c.ws_opt;
>> +	lm->smeta_len = lm->smeta_sec * geo->c.csecs;
>>    	smeta_len = sizeof(struct line_smeta) + lm->lun_bitmap_len;
>>  	if (smeta_len > lm->smeta_len) {
>> @@ -764,8 +773,8 @@ static int pblk_lines_init(struct pblk *pblk)
>>  	 */
>>  	i = 1;
>>  add_emeta_page:
>> -	lm->emeta_sec[0] = i * geo->sec_per_pl;
>> -	lm->emeta_len[0] = lm->emeta_sec[0] * geo->sec_size;
>> +	lm->emeta_sec[0] = i * geo->c.ws_opt;
>> +	lm->emeta_len[0] = lm->emeta_sec[0] * geo->c.csecs;
>>    	emeta_len = calc_emeta_len(pblk);
>>  	if (emeta_len > lm->emeta_len[0]) {
>> @@ -778,7 +787,7 @@ static int pblk_lines_init(struct pblk *pblk)
>>  	lm->min_blk_line = 1;
>>  	if (geo->all_luns > 1)
>>  		lm->min_blk_line += DIV_ROUND_UP(lm->smeta_sec +
>> -					lm->emeta_sec[0], geo->sec_per_chk);
>> +					lm->emeta_sec[0], geo->c.clba);
>>    	if (lm->min_blk_line > lm->blk_per_line) {
>>  		pr_err("pblk: config. not supported. Min. LUN in line:%d\n",
>> @@ -802,9 +811,9 @@ static int pblk_lines_init(struct pblk *pblk)
>>  		goto fail_free_bb_template;
>>  	}
>>  -	bb_distance = (geo->all_luns) * geo->sec_per_pl;
>> +	bb_distance = (geo->all_luns) * geo->c.ws_opt;
>>  	for (i = 0; i < lm->sec_per_line; i += bb_distance)
>> -		bitmap_set(l_mg->bb_template, i, geo->sec_per_pl);
>> +		bitmap_set(l_mg->bb_template, i, geo->c.ws_opt);
>>    	INIT_LIST_HEAD(&l_mg->free_list);
>>  	INIT_LIST_HEAD(&l_mg->corrupt_list);
>> @@ -981,9 +990,9 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>>  	struct pblk *pblk;
>>  	int ret;
>>  -	if (dev->identity.dom & NVM_RSP_L2P) {
>> +	if (dev->geo.c.dom & NVM_RSP_L2P) {
>>  		pr_err("pblk: host-side L2P table not supported. (%x)\n",
>> -							dev->identity.dom);
>> +							dev->geo.c.dom);
>>  		return ERR_PTR(-EINVAL);
>>  	}
>>  @@ -1091,7 +1100,7 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>>    	blk_queue_write_cache(tqueue, true, false);
>>  -	tqueue->limits.discard_granularity = geo->sec_per_chk * geo->sec_size;
>> +	tqueue->limits.discard_granularity = geo->c.clba * geo->c.csecs;
>>  	tqueue->limits.discard_alignment = 0;
>>  	blk_queue_max_discard_sectors(tqueue, UINT_MAX >> 9);
>>  	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, tqueue);
>> diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c
>> index 2f761283f43e..ebb6bae3a3b8 100644
>> --- a/drivers/lightnvm/pblk-read.c
>> +++ b/drivers/lightnvm/pblk-read.c
>> @@ -563,7 +563,7 @@ int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq)
>>  	if (!(gc_rq->secs_to_gc))
>>  		goto out;
>>  -	data_len = (gc_rq->secs_to_gc) * geo->sec_size;
>> +	data_len = (gc_rq->secs_to_gc) * geo->c.csecs;
>>  	bio = pblk_bio_map_addr(pblk, gc_rq->data, gc_rq->secs_to_gc, data_len,
>>  						PBLK_VMALLOC_META, GFP_KERNEL);
>>  	if (IS_ERR(bio)) {
>> diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
>> index aaab9a5c17cc..1574dbbfbb1c 100644
>> --- a/drivers/lightnvm/pblk-recovery.c
>> +++ b/drivers/lightnvm/pblk-recovery.c
>> @@ -184,7 +184,7 @@ static int pblk_calc_sec_in_line(struct pblk *pblk, struct pblk_line *line)
>>  	int nr_bb = bitmap_weight(line->blk_bitmap, lm->blk_per_line);
>>    	return lm->sec_per_line - lm->smeta_sec - lm->emeta_sec[0] -
>> -				nr_bb * geo->sec_per_chk;
>> +				nr_bb * geo->c.clba;
>>  }
>>    struct pblk_recov_alloc {
>> @@ -232,7 +232,7 @@ static int pblk_recov_read_oob(struct pblk *pblk, struct pblk_line *line,
>>  	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>  	if (!rq_ppas)
>>  		rq_ppas = pblk->min_write_pgs;
>> -	rq_len = rq_ppas * geo->sec_size;
>> +	rq_len = rq_ppas * geo->c.csecs;
>>    	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>>  	if (IS_ERR(bio))
>> @@ -351,7 +351,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
>>  	if (!pad_rq)
>>  		return -ENOMEM;
>>  -	data = vzalloc(pblk->max_write_pgs * geo->sec_size);
>> +	data = vzalloc(pblk->max_write_pgs * geo->c.csecs);
>>  	if (!data) {
>>  		ret = -ENOMEM;
>>  		goto free_rq;
>> @@ -368,7 +368,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
>>  		goto fail_free_pad;
>>  	}
>>  -	rq_len = rq_ppas * geo->sec_size;
>> +	rq_len = rq_ppas * geo->c.csecs;
>>    	meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, &dma_meta_list);
>>  	if (!meta_list) {
>> @@ -509,7 +509,7 @@ static int pblk_recov_scan_all_oob(struct pblk *pblk, struct pblk_line *line,
>>  	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>  	if (!rq_ppas)
>>  		rq_ppas = pblk->min_write_pgs;
>> -	rq_len = rq_ppas * geo->sec_size;
>> +	rq_len = rq_ppas * geo->c.csecs;
>>    	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>>  	if (IS_ERR(bio))
>> @@ -640,7 +640,7 @@ static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line,
>>  	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>  	if (!rq_ppas)
>>  		rq_ppas = pblk->min_write_pgs;
>> -	rq_len = rq_ppas * geo->sec_size;
>> +	rq_len = rq_ppas * geo->c.csecs;
>>    	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>>  	if (IS_ERR(bio))
>> @@ -745,7 +745,7 @@ static int pblk_recov_l2p_from_oob(struct pblk *pblk, struct pblk_line *line)
>>  	ppa_list = (void *)(meta_list) + pblk_dma_meta_size;
>>  	dma_ppa_list = dma_meta_list + pblk_dma_meta_size;
>>  -	data = kcalloc(pblk->max_write_pgs, geo->sec_size, GFP_KERNEL);
>> +	data = kcalloc(pblk->max_write_pgs, geo->c.csecs, GFP_KERNEL);
>>  	if (!data) {
>>  		ret = -ENOMEM;
>>  		goto free_meta_list;
>> diff --git a/drivers/lightnvm/pblk-rl.c b/drivers/lightnvm/pblk-rl.c
>> index 0d457b162f23..bcab203477ec 100644
>> --- a/drivers/lightnvm/pblk-rl.c
>> +++ b/drivers/lightnvm/pblk-rl.c
>> @@ -200,7 +200,7 @@ void pblk_rl_init(struct pblk_rl *rl, int budget)
>>    	/* Consider sectors used for metadata */
>>  	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
>> -	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
>> +	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
>>    	rl->high = pblk->op_blks - blk_meta - lm->blk_per_line;
>>  	rl->high_pw = get_count_order(rl->high);
>> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
>> index d93e9b1f083a..5eb21a279361 100644
>> --- a/drivers/lightnvm/pblk-sysfs.c
>> +++ b/drivers/lightnvm/pblk-sysfs.c
>> @@ -113,26 +113,31 @@ 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;
>>  -	sz = snprintf(page, PAGE_SIZE - sz,
>> -		"g:(b:%d)blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
>> -		pblk->ppaf_bitsize,
>> -		pblk->ppaf.blk_offset, geo->ppaf.blk_len,
>> -		pblk->ppaf.pg_offset, geo->ppaf.pg_len,
>> -		pblk->ppaf.lun_offset, geo->ppaf.lun_len,
>> -		pblk->ppaf.ch_offset, geo->ppaf.ch_len,
>> -		pblk->ppaf.pln_offset, geo->ppaf.pln_len,
>> -		pblk->ppaf.sec_offset, geo->ppaf.sect_len);
>> +	ppaf = (struct nvm_addr_format_12 *)&pblk->ppaf;
>> +	geo_ppaf = (struct nvm_addr_format_12 *)&geo->c.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",
>> +			pblk->ppaf_bitsize,
>> +			ppaf->ch_offset, ppaf->ch_len,
>> +			ppaf->lun_offset, ppaf->lun_len,
>> +			ppaf->blk_offset, ppaf->blk_len,
>> +			ppaf->pg_offset, ppaf->pg_len,
>> +			ppaf->pln_offset, ppaf->pln_len,
>> +			ppaf->sect_offset, ppaf->sect_len);
>>    	sz += snprintf(page + sz, PAGE_SIZE - sz,
>> -		"d:blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
>> -		geo->ppaf.blk_offset, geo->ppaf.blk_len,
>> -		geo->ppaf.pg_offset, geo->ppaf.pg_len,
>> -		geo->ppaf.lun_offset, geo->ppaf.lun_len,
>> -		geo->ppaf.ch_offset, geo->ppaf.ch_len,
>> -		geo->ppaf.pln_offset, geo->ppaf.pln_len,
>> -		geo->ppaf.sect_offset, geo->ppaf.sect_len);
>> +		"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->sect_offset, geo_ppaf->sect_len);
>>    	return sz;
>>  }
>> @@ -288,7 +293,7 @@ static ssize_t pblk_sysfs_lines_info(struct pblk *pblk, char *page)
>>  				"blk_line:%d, sec_line:%d, sec_blk:%d\n",
>>  					lm->blk_per_line,
>>  					lm->sec_per_line,
>> -					geo->sec_per_chk);
>> +					geo->c.clba);
>>    	return sz;
>>  }
>> diff --git a/drivers/lightnvm/pblk-write.c b/drivers/lightnvm/pblk-write.c
>> index aae86ed60b98..c49b27539d5a 100644
>> --- a/drivers/lightnvm/pblk-write.c
>> +++ b/drivers/lightnvm/pblk-write.c
>> @@ -333,7 +333,7 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line)
>>  	m_ctx = nvm_rq_to_pdu(rqd);
>>  	m_ctx->private = meta_line;
>>  -	rq_len = rq_ppas * geo->sec_size;
>> +	rq_len = rq_ppas * geo->c.csecs;
>>  	data = ((void *)emeta->buf) + emeta->mem;
>>    	bio = pblk_bio_map_addr(pblk, data, rq_ppas, rq_len,
>> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
>> index 282dfc8780e8..67ffb53608f7 100644
>> --- a/drivers/lightnvm/pblk.h
>> +++ b/drivers/lightnvm/pblk.h
>> @@ -551,21 +551,6 @@ struct pblk_line_meta {
>>  	unsigned int meta_distance;	/* Distance between data and metadata */
>>  };
>>  -struct pblk_addr_format {
>> -	u64	ch_mask;
>> -	u64	lun_mask;
>> -	u64	pln_mask;
>> -	u64	blk_mask;
>> -	u64	pg_mask;
>> -	u64	sec_mask;
>> -	u8	ch_offset;
>> -	u8	lun_offset;
>> -	u8	pln_offset;
>> -	u8	blk_offset;
>> -	u8	pg_offset;
>> -	u8	sec_offset;
>> -};
>> -
>>  enum {
>>  	PBLK_STATE_RUNNING = 0,
>>  	PBLK_STATE_STOPPING = 1,
>> @@ -585,8 +570,8 @@ struct pblk {
>>  	struct pblk_line_mgmt l_mg;		/* Line management */
>>  	struct pblk_line_meta lm;		/* Line metadata */
>>  +	struct nvm_addr_format ppaf;
>>  	int ppaf_bitsize;
>> -	struct pblk_addr_format ppaf;
>>    	struct pblk_rb rwb;
>>  @@ -941,14 +926,12 @@ static inline int pblk_line_vsc(struct pblk_line *line)
>>  	return le32_to_cpu(*line->vsc);
>>  }
>>  -#define NVM_MEM_PAGE_WRITE (8)
>> -
>>  static inline int pblk_pad_distance(struct pblk *pblk)
>>  {
>>  	struct nvm_tgt_dev *dev = pblk->dev;
>>  	struct nvm_geo *geo = &dev->geo;
>>  -	return NVM_MEM_PAGE_WRITE * geo->all_luns * geo->sec_per_pl;
>> +	return geo->c.mw_cunits * geo->all_luns * geo->c.ws_opt;
>>  }
>>    static inline int pblk_ppa_to_line(struct ppa_addr p)
>> @@ -964,15 +947,17 @@ 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->ppaf;
>>  	struct ppa_addr ppa;
>>    	ppa.ppa = 0;
>>  	ppa.g.blk = line_id;
>> -	ppa.g.pg = (paddr & pblk->ppaf.pg_mask) >> pblk->ppaf.pg_offset;
>> -	ppa.g.lun = (paddr & pblk->ppaf.lun_mask) >> pblk->ppaf.lun_offset;
>> -	ppa.g.ch = (paddr & pblk->ppaf.ch_mask) >> pblk->ppaf.ch_offset;
>> -	ppa.g.pl = (paddr & pblk->ppaf.pln_mask) >> pblk->ppaf.pln_offset;
>> -	ppa.g.sec = (paddr & pblk->ppaf.sec_mask) >> pblk->ppaf.sec_offset;
>> +	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->sect_offset;
>>    	return ppa;
>>  }
>> @@ -980,13 +965,15 @@ 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->ppaf;
>>  	u64 paddr;
>>  -	paddr = (u64)p.g.pg << pblk->ppaf.pg_offset;
>> -	paddr |= (u64)p.g.lun << pblk->ppaf.lun_offset;
>> -	paddr |= (u64)p.g.ch << pblk->ppaf.ch_offset;
>> -	paddr |= (u64)p.g.pl << pblk->ppaf.pln_offset;
>> -	paddr |= (u64)p.g.sec << pblk->ppaf.sec_offset;
>> +	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->sect_offset;
>>    	return paddr;
>>  }
>> @@ -1003,18 +990,15 @@ 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 {
>> -		ppa64.g.blk = (ppa32 & pblk->ppaf.blk_mask) >>
>> -							pblk->ppaf.blk_offset;
>> -		ppa64.g.pg = (ppa32 & pblk->ppaf.pg_mask) >>
>> -							pblk->ppaf.pg_offset;
>> -		ppa64.g.lun = (ppa32 & pblk->ppaf.lun_mask) >>
>> -							pblk->ppaf.lun_offset;
>> -		ppa64.g.ch = (ppa32 & pblk->ppaf.ch_mask) >>
>> -							pblk->ppaf.ch_offset;
>> -		ppa64.g.pl = (ppa32 & pblk->ppaf.pln_mask) >>
>> -							pblk->ppaf.pln_offset;
>> -		ppa64.g.sec = (ppa32 & pblk->ppaf.sec_mask) >>
>> -							pblk->ppaf.sec_offset;
>> +		struct nvm_addr_format_12 *ppaf =
>> +				(struct nvm_addr_format_12 *)&pblk->ppaf;
>> +
>> +		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->sect_offset;
>>  	}
>>    	return ppa64;
>> @@ -1030,12 +1014,15 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
>>  		ppa32 |= ppa64.c.line;
>>  		ppa32 |= 1U << 31;
>>  	} else {
>> -		ppa32 |= ppa64.g.blk << pblk->ppaf.blk_offset;
>> -		ppa32 |= ppa64.g.pg << pblk->ppaf.pg_offset;
>> -		ppa32 |= ppa64.g.lun << pblk->ppaf.lun_offset;
>> -		ppa32 |= ppa64.g.ch << pblk->ppaf.ch_offset;
>> -		ppa32 |= ppa64.g.pl << pblk->ppaf.pln_offset;
>> -		ppa32 |= ppa64.g.sec << pblk->ppaf.sec_offset;
>> +		struct nvm_addr_format_12 *ppaf =
>> +				(struct nvm_addr_format_12 *)&pblk->ppaf;
>> +
>> +		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->sect_offset;
>>  	}
>>    	return ppa32;
>> @@ -1153,7 +1140,7 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type)
>>  	struct nvm_geo *geo = &dev->geo;
>>  	int flags;
>>  -	flags = geo->plane_mode >> 1;
>> +	flags = geo->c.pln_mode >> 1;
>>    	if (type == PBLK_WRITE)
>>  		flags |= NVM_IO_SCRAMBLE_ENABLE;
>> @@ -1174,7 +1161,7 @@ static inline int pblk_set_read_mode(struct pblk *pblk, int type)
>>    	flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
>>  	if (type == PBLK_READ_SEQUENTIAL)
>> -		flags |= geo->plane_mode >> 1;
>> +		flags |= geo->c.pln_mode >> 1;
>>    	return flags;
>>  }
>> @@ -1229,10 +1216,10 @@ static inline int pblk_boundary_ppa_checks(struct nvm_tgt_dev *tgt_dev,
>>  		if (!ppa->c.is_cached &&
>>  				ppa->g.ch < geo->nr_chnls &&
>>  				ppa->g.lun < geo->nr_luns &&
>> -				ppa->g.pl < geo->nr_planes &&
>> -				ppa->g.blk < geo->nr_chks &&
>> -				ppa->g.pg < geo->ws_per_chk &&
>> -				ppa->g.sec < geo->sec_per_pg)
>> +				ppa->g.pl < geo->c.num_pln &&
>> +				ppa->g.blk < geo->c.num_chk &&
>> +				ppa->g.pg < geo->c.num_pg &&
>> +				ppa->g.sec < geo->c.ws_min)
>>  			continue;
>>    		print_ppa(ppa, "boundary", i);
>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>> index 839c0b96466a..c81e64cc20d7 100644
>> --- a/drivers/nvme/host/lightnvm.c
>> +++ b/drivers/nvme/host/lightnvm.c
>> @@ -152,8 +152,8 @@ struct nvme_nvm_id12_addrf {
>>  	__u8			blk_len;
>>  	__u8			pg_offset;
>>  	__u8			pg_len;
>> -	__u8			sect_offset;
>> -	__u8			sect_len;
>> +	__u8			sec_offset;
>> +	__u8			sec_len;
>>  	__u8			res[4];
>>  } __packed;
>>  @@ -254,106 +254,157 @@ static inline void _nvme_nvm_check_size(void)
>>  	BUILD_BUG_ON(sizeof(struct nvme_nvm_id20) != NVME_IDENTIFY_DATA_SIZE);
>>  }
>>  -static int init_grp(struct nvm_id *nvm_id, struct nvme_nvm_id12 *id12)
>> +static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
>> +				 struct nvme_nvm_id12_addrf *src)
>> +{
>> +	dst->ch_len = src->ch_len;
>> +	dst->lun_len = src->lun_len;
>> +	dst->blk_len = src->blk_len;
>> +	dst->pg_len = src->pg_len;
>> +	dst->pln_len = src->pln_len;
>> +	dst->sect_len = src->sec_len;
>> +
>> +	dst->ch_offset = src->ch_offset;
>> +	dst->lun_offset = src->lun_offset;
>> +	dst->blk_offset = src->blk_offset;
>> +	dst->pg_offset = src->pg_offset;
>> +	dst->pln_offset = src->pln_offset;
>> +	dst->sect_offset = src->sec_offset;
>> +
>> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>> +	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
>> +	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
>> +	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
>> +	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
>> +}
>> +
>> +static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>> +			     struct nvm_dev_geo *dev_geo)
>>  {
>>  	struct nvme_nvm_id12_grp *src;
>>  	int sec_per_pg, sec_per_pl, pg_per_blk;
>>  -	if (id12->cgrps != 1)
>> +	if (id->cgrps != 1)
>>  		return -EINVAL;
>>  -	src = &id12->grp;
>> +	src = &id->grp;
>>  -	nvm_id->mtype = src->mtype;
>> -	nvm_id->fmtype = src->fmtype;
>> +	if (src->mtype != 0) {
>> +		pr_err("nvm: memory type not supported\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	/* 1.2 spec. only reports a single version id - unfold */
>> +	dev_geo->ver_id = id->ver_id;
>>  -	nvm_id->num_ch = src->num_ch;
>> -	nvm_id->num_lun = src->num_lun;
>> +	dev_geo->nr_chnls = src->num_ch;
>> +	dev_geo->nr_luns = src->num_lun;
>> +	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
>>  -	nvm_id->num_chk = le16_to_cpu(src->num_chk);
>> -	nvm_id->csecs = le16_to_cpu(src->csecs);
>> -	nvm_id->sos = le16_to_cpu(src->sos);
>> +	dev_geo->c.num_chk = le16_to_cpu(src->num_chk);
>> +	dev_geo->c.csecs = le16_to_cpu(src->csecs);
>> +	dev_geo->c.sos = le16_to_cpu(src->sos);
>>    	pg_per_blk = le16_to_cpu(src->num_pg);
>> -	sec_per_pg = le16_to_cpu(src->fpg_sz) / nvm_id->csecs;
>> +	sec_per_pg = le16_to_cpu(src->fpg_sz) / dev_geo->c.csecs;
>>  	sec_per_pl = sec_per_pg * src->num_pln;
>> -	nvm_id->clba = sec_per_pl * pg_per_blk;
>> -	nvm_id->ws_per_chk = pg_per_blk;
>> -
>> -	nvm_id->mpos = le32_to_cpu(src->mpos);
>> -	nvm_id->cpar = le16_to_cpu(src->cpar);
>> -	nvm_id->mccap = le32_to_cpu(src->mccap);
>> -
>> -	nvm_id->ws_opt = nvm_id->ws_min = sec_per_pg;
>> -	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
>> -
>> -	if (nvm_id->mpos & 0x020202) {
>> -		nvm_id->ws_seq = NVM_IO_DUAL_ACCESS;
>> -		nvm_id->ws_opt <<= 1;
>> -	} else if (nvm_id->mpos & 0x040404) {
>> -		nvm_id->ws_seq = NVM_IO_QUAD_ACCESS;
>> -		nvm_id->ws_opt <<= 2;
>> +	dev_geo->c.clba = sec_per_pl * pg_per_blk;
>> +
>> +	dev_geo->c.ws_min = sec_per_pg;
>> +	dev_geo->c.ws_opt = sec_per_pg;
>> +	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
>> +
>> +	dev_geo->c.mccap = le32_to_cpu(src->mccap);
>> +
>> +	dev_geo->c.trdt = le32_to_cpu(src->trdt);
>> +	dev_geo->c.trdm = le32_to_cpu(src->trdm);
>> +	dev_geo->c.tprt = le32_to_cpu(src->tprt);
>> +	dev_geo->c.tprm = le32_to_cpu(src->tprm);
>> +	dev_geo->c.tbet = le32_to_cpu(src->tbet);
>> +	dev_geo->c.tbem = le32_to_cpu(src->tbem);
>> +
>> +	/* 1.2 compatibility */
>> +	dev_geo->c.vmnt = id->vmnt;
>> +	dev_geo->c.cap = le32_to_cpu(id->cap);
>> +	dev_geo->c.dom = le32_to_cpu(id->dom);
>> +
>> +	dev_geo->c.mtype = src->mtype;
>> +	dev_geo->c.fmtype = src->fmtype;
>> +
>> +	dev_geo->c.cpar = le16_to_cpu(src->cpar);
>> +	dev_geo->c.mpos = le32_to_cpu(src->mpos);
>> +
>> +	dev_geo->c.pln_mode = NVM_PLANE_SINGLE;
>> +
>> +	if (dev_geo->c.mpos & 0x020202) {
>> +		dev_geo->c.pln_mode = NVM_PLANE_DOUBLE;
>> +		dev_geo->c.ws_opt <<= 1;
>> +	} else if (dev_geo->c.mpos & 0x040404) {
>> +		dev_geo->c.pln_mode = NVM_PLANE_QUAD;
>> +		dev_geo->c.ws_opt <<= 2;
>>  	}
>>  -	nvm_id->trdt = le32_to_cpu(src->trdt);
>> -	nvm_id->trdm = le32_to_cpu(src->trdm);
>> -	nvm_id->tprt = le32_to_cpu(src->tprt);
>> -	nvm_id->tprm = le32_to_cpu(src->tprm);
>> -	nvm_id->tbet = le32_to_cpu(src->tbet);
>> -	nvm_id->tbem = le32_to_cpu(src->tbem);
>> -
>> -	/* 1.2 compatibility */
>> -	nvm_id->num_pln = src->num_pln;
>> -	nvm_id->num_pg = le16_to_cpu(src->num_pg);
>> -	nvm_id->fpg_sz = le16_to_cpu(src->fpg_sz);
>> +	dev_geo->c.num_pln = src->num_pln;
>> +	dev_geo->c.num_pg = le16_to_cpu(src->num_pg);
>> +	dev_geo->c.fpg_sz = le16_to_cpu(src->fpg_sz);
>> +
>> +	nvme_nvm_set_addr_12((struct nvm_addr_format_12 *)&dev_geo->c.addrf,
>> +								&id->ppaf);
>>    	return 0;
>>  }
>>  -static int nvme_nvm_setup_12(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
>> -		struct nvme_nvm_id12 *id)
>> +static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
>> +				 struct nvme_nvm_id20_addrf *src)
>>  {
>> -	nvm_id->ver_id = id->ver_id;
>> -	nvm_id->vmnt = id->vmnt;
>> -	nvm_id->cap = le32_to_cpu(id->cap);
>> -	nvm_id->dom = le32_to_cpu(id->dom);
>> -	memcpy(&nvm_id->ppaf, &id->ppaf,
>> -					sizeof(struct nvm_addr_format));
>> -
>> -	return init_grp(nvm_id, id);
>> +	dst->ch_len = src->grp_len;
>> +	dst->lun_len = src->pu_len;
>> +	dst->chk_len = src->chk_len;
>> +	dst->sec_len = src->lba_len;
>> +
>> +	dst->sec_offset = 0;
>> +	dst->chk_offset = dst->sec_len;
>> +	dst->lun_offset = dst->chk_offset + dst->chk_len;
>> +	dst->ch_offset = dst->lun_offset + dst->lun_len;
>> +
>> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>> +	dst->chk_mask = ((1ULL << dst->chk_len) - 1) << dst->chk_offset;
>> +	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>>  }
>>  -static int nvme_nvm_setup_20(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
>> -		struct nvme_nvm_id20 *id)
>> +static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>> +			     struct nvm_dev_geo *dev_geo)
>>  {
>> -	nvm_id->ver_id = id->mjr;
>> +	dev_geo->ver_id = id->mjr;
>>  -	nvm_id->num_ch = le16_to_cpu(id->num_grp);
>> -	nvm_id->num_lun = le16_to_cpu(id->num_pu);
>> -	nvm_id->num_chk = le32_to_cpu(id->num_chk);
>> -	nvm_id->clba = le32_to_cpu(id->clba);
>> +	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
>> +	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
>> +	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
>>  -	nvm_id->ws_min = le32_to_cpu(id->ws_min);
>> -	nvm_id->ws_opt = le32_to_cpu(id->ws_opt);
>> -	nvm_id->mw_cunits = le32_to_cpu(id->mw_cunits);
>> +	dev_geo->c.num_chk = le32_to_cpu(id->num_chk);
>> +	dev_geo->c.clba = le32_to_cpu(id->clba);
>> +	dev_geo->c.csecs = -1;		/* Set by nvme identify */
>> +	dev_geo->c.sos = -1;		/* Set bu nvme identify */
>>  -	nvm_id->trdt = le32_to_cpu(id->trdt);
>> -	nvm_id->trdm = le32_to_cpu(id->trdm);
>> -	nvm_id->tprt = le32_to_cpu(id->twrt);
>> -	nvm_id->tprm = le32_to_cpu(id->twrm);
>> -	nvm_id->tbet = le32_to_cpu(id->tcrst);
>> -	nvm_id->tbem = le32_to_cpu(id->tcrsm);
>> +	dev_geo->c.ws_min = le32_to_cpu(id->ws_min);
>> +	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
>> +	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
>>  -	/* calculated values */
>> -	nvm_id->ws_per_chk = nvm_id->clba / nvm_id->ws_min;
>> +	dev_geo->c.trdt = le32_to_cpu(id->trdt);
>> +	dev_geo->c.trdm = le32_to_cpu(id->trdm);
>> +	dev_geo->c.tprt = le32_to_cpu(id->twrt);
>> +	dev_geo->c.tprm = le32_to_cpu(id->twrm);
>> +	dev_geo->c.tbet = le32_to_cpu(id->tcrst);
>> +	dev_geo->c.tbem = le32_to_cpu(id->tcrsm);
>>  -	/* 1.2 compatibility */
>> -	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
>> +	nvme_nvm_set_addr_20(&dev_geo->c.addrf, &id->lbaf);
>>    	return 0;
>>  }
>>  -static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
>> +static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>>  {
>>  	struct nvme_ns *ns = nvmdev->q->queuedata;
>>  	struct nvme_nvm_id12 *id;
>> @@ -380,18 +431,18 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
>>  	 */
>>  	switch (id->ver_id) {
>>  	case 1:
>> -		ret = nvme_nvm_setup_12(nvmdev, nvm_id, id);
>> +		ret = nvme_nvm_setup_12(id, &nvmdev->dev_geo);
>>  		break;
>>  	case 2:
>> -		ret = nvme_nvm_setup_20(nvmdev, nvm_id,
>> -				(struct nvme_nvm_id20 *)id);
>> +		ret = nvme_nvm_setup_20((struct nvme_nvm_id20 *)id,
>> +							&nvmdev->dev_geo);
>>  		break;
>>  	default:
>> -		dev_err(ns->ctrl->device,
>> -			"OCSSD revision not supported (%d)\n",
>> -			nvm_id->ver_id);
>> +		dev_err(ns->ctrl->device, "OCSSD revision not supported (%d)\n",
>> +							id->ver_id);
>>  		ret = -EINVAL;
>>  	}
>> +
>>  out:
>>  	kfree(id);
>>  	return ret;
>> @@ -401,12 +452,12 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
>>  								u8 *blks)
>>  {
>>  	struct request_queue *q = nvmdev->q;
>> -	struct nvm_geo *geo = &nvmdev->geo;
>> +	struct nvm_dev_geo *dev_geo = &nvmdev->dev_geo;
>>  	struct nvme_ns *ns = q->queuedata;
>>  	struct nvme_ctrl *ctrl = ns->ctrl;
>>  	struct nvme_nvm_command c = {};
>>  	struct nvme_nvm_bb_tbl *bb_tbl;
>> -	int nr_blks = geo->nr_chks * geo->plane_mode;
>> +	int nr_blks = dev_geo->c.num_chk * dev_geo->c.num_pln;
>>  	int tblsz = sizeof(struct nvme_nvm_bb_tbl) + nr_blks;
>>  	int ret = 0;
>>  @@ -447,7 +498,7 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
>>  		goto out;
>>  	}
>>  -	memcpy(blks, bb_tbl->blk, geo->nr_chks * geo->plane_mode);
>> +	memcpy(blks, bb_tbl->blk, dev_geo->c.num_chk * dev_geo->c.num_pln);
>>  out:
>>  	kfree(bb_tbl);
>>  	return ret;
>> @@ -815,9 +866,10 @@ int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd, unsigned long arg)
>>  void nvme_nvm_update_nvm_info(struct nvme_ns *ns)
>>  {
>>  	struct nvm_dev *ndev = ns->ndev;
>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>  -	ndev->identity.csecs = ndev->geo.sec_size = 1 << ns->lba_shift;
>> -	ndev->identity.sos = ndev->geo.oob_size = ns->ms;
>> +	dev_geo->c.csecs = 1 << ns->lba_shift;
>> +	dev_geo->c.sos = ns->ms;
>>  }
>>    int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node)
>> @@ -850,23 +902,22 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>  {
>>  	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>>  	struct nvm_dev *ndev = ns->ndev;
>> -	struct nvm_id *id;
>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>  	struct attribute *attr;
>>    	if (!ndev)
>>  		return 0;
>>  -	id = &ndev->identity;
>>  	attr = &dattr->attr;
>>    	if (strcmp(attr->name, "version") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ver_id);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>>  	} else if (strcmp(attr->name, "capabilities") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->cap);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
>>  	} else if (strcmp(attr->name, "read_typ") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdt);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>>  	} else if (strcmp(attr->name, "read_max") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdm);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdm);
>>  	} else {
>>  		return scnprintf(page,
>>  				 PAGE_SIZE,
>> @@ -875,75 +926,79 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>  	}
>>  }
>>  +static ssize_t nvm_dev_attr_show_ppaf(struct nvm_addr_format_12 *ppaf,
>> +					 char *page)
>> +{
>> +	return scnprintf(page, PAGE_SIZE,
>> +		"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
>> +				ppaf->ch_offset, ppaf->ch_len,
>> +				ppaf->lun_offset, ppaf->lun_len,
>> +				ppaf->pln_offset, ppaf->pln_len,
>> +				ppaf->blk_offset, ppaf->blk_len,
>> +				ppaf->pg_offset, ppaf->pg_len,
>> +				ppaf->sect_offset, ppaf->sect_len);
>> +}
>> +
>>  static ssize_t nvm_dev_attr_show_12(struct device *dev,
>>  		struct device_attribute *dattr, char *page)
>>  {
>>  	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>>  	struct nvm_dev *ndev = ns->ndev;
>> -	struct nvm_id *id;
>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>  	struct attribute *attr;
>>    	if (!ndev)
>>  		return 0;
>>  -	id = &ndev->identity;
>>  	attr = &dattr->attr;
>>    	if (strcmp(attr->name, "vendor_opcode") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->vmnt);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.vmnt);
>>  	} else if (strcmp(attr->name, "device_mode") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->dom);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.dom);
>>  	/* kept for compatibility */
>>  	} else if (strcmp(attr->name, "media_manager") == 0) {
>>  		return scnprintf(page, PAGE_SIZE, "%s\n", "gennvm");
>>  	} else if (strcmp(attr->name, "ppa_format") == 0) {
>> -		return scnprintf(page, PAGE_SIZE,
>> -			"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
>> -			id->ppaf.ch_offset, id->ppaf.ch_len,
>> -			id->ppaf.lun_offset, id->ppaf.lun_len,
>> -			id->ppaf.pln_offset, id->ppaf.pln_len,
>> -			id->ppaf.blk_offset, id->ppaf.blk_len,
>> -			id->ppaf.pg_offset, id->ppaf.pg_len,
>> -			id->ppaf.sect_offset, id->ppaf.sect_len);
>> +		return nvm_dev_attr_show_ppaf((void *)&dev_geo->c.addrf, page);
>>  	} else if (strcmp(attr->name, "media_type") == 0) {	/* u8 */
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->mtype);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mtype);
>>  	} else if (strcmp(attr->name, "flash_media_type") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->fmtype);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fmtype);
>>  	} else if (strcmp(attr->name, "num_channels") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
>>  	} else if (strcmp(attr->name, "num_luns") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
>>  	} else if (strcmp(attr->name, "num_planes") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pln);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pln);
>>  	} else if (strcmp(attr->name, "num_blocks") == 0) {	/* u16 */
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
>>  	} else if (strcmp(attr->name, "num_pages") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pg);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pg);
>>  	} else if (strcmp(attr->name, "page_size") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->fpg_sz);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fpg_sz);
>>  	} else if (strcmp(attr->name, "hw_sector_size") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->csecs);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.csecs);
>>  	} else if (strcmp(attr->name, "oob_sector_size") == 0) {/* u32 */
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->sos);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.sos);
>>  	} else if (strcmp(attr->name, "prog_typ") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
>>  	} else if (strcmp(attr->name, "prog_max") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
>>  	} else if (strcmp(attr->name, "erase_typ") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
>>  	} else if (strcmp(attr->name, "erase_max") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>  	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mpos);
>> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
>>  	} else if (strcmp(attr->name, "media_capabilities") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mccap);
>> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
>>  	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
>>  		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>>  	} else {
>> -		return scnprintf(page,
>> -				 PAGE_SIZE,
>> -				 "Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
>> -				 attr->name);
>> +		return scnprintf(page, PAGE_SIZE,
>> +			"Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
>> +			attr->name);
>>  	}
>>  }
>>  @@ -952,42 +1007,40 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>>  {
>>  	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>>  	struct nvm_dev *ndev = ns->ndev;
>> -	struct nvm_id *id;
>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>  	struct attribute *attr;
>>    	if (!ndev)
>>  		return 0;
>>  -	id = &ndev->identity;
>>  	attr = &dattr->attr;
>>    	if (strcmp(attr->name, "groups") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
>>  	} else if (strcmp(attr->name, "punits") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
>>  	} else if (strcmp(attr->name, "chunks") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
>>  	} else if (strcmp(attr->name, "clba") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->clba);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.clba);
>>  	} else if (strcmp(attr->name, "ws_min") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_min);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_min);
>>  	} else if (strcmp(attr->name, "ws_opt") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_opt);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_opt);
>>  	} else if (strcmp(attr->name, "mw_cunits") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->mw_cunits);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mw_cunits);
>>  	} else if (strcmp(attr->name, "write_typ") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
>>  	} else if (strcmp(attr->name, "write_max") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
>>  	} else if (strcmp(attr->name, "reset_typ") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
>>  	} else if (strcmp(attr->name, "reset_max") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>  	} else {
>> -		return scnprintf(page,
>> -				 PAGE_SIZE,
>> -				 "Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
>> -				 attr->name);
>> +		return scnprintf(page, PAGE_SIZE,
>> +			"Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
>> +			attr->name);
>>  	}
>>  }
>>  @@ -1106,10 +1159,13 @@ static const struct attribute_group nvm_dev_attr_group_20 = {
>>    int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>>  {
>> -	if (!ns->ndev)
>> +	struct nvm_dev *ndev = ns->ndev;
>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>> +
>> +	if (!ndev)
>>  		return -EINVAL;
>>  -	switch (ns->ndev->identity.ver_id) {
>> +	switch (dev_geo->ver_id) {
>>  	case 1:
>>  		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
>>  					&nvm_dev_attr_group_12);
>> @@ -1123,7 +1179,10 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>>    void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
>>  {
>> -	switch (ns->ndev->identity.ver_id) {
>> +	struct nvm_dev *ndev = ns->ndev;
>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>> +
>> +	switch (dev_geo->ver_id) {
>>  	case 1:
>>  		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
>>  					&nvm_dev_attr_group_12);
>> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
>> index e55b10573c99..18e3751b1632 100644
>> --- a/include/linux/lightnvm.h
>> +++ b/include/linux/lightnvm.h
>> @@ -50,7 +50,7 @@ struct nvm_id;
>>  struct nvm_dev;
>>  struct nvm_tgt_dev;
>>  -typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *);
>> +typedef int (nvm_id_fn)(struct nvm_dev *);
>>  typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, u8 *);
>>  typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct ppa_addr *, int, int);
>>  typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
>> @@ -152,62 +152,107 @@ struct nvm_id_lp_tbl {
>>  	struct nvm_id_lp_mlc mlc;
>>  };
>>  -struct nvm_addr_format {
>> -	u8	ch_offset;
>> +struct nvm_addr_format_12 {
>>  	u8	ch_len;
>> -	u8	lun_offset;
>>  	u8	lun_len;
>> -	u8	pln_offset;
>> +	u8	blk_len;
>> +	u8	pg_len;
>>  	u8	pln_len;
>> +	u8	sect_len;
>> +
>> +	u8	ch_offset;
>> +	u8	lun_offset;
>>  	u8	blk_offset;
>> -	u8	blk_len;
>>  	u8	pg_offset;
>> -	u8	pg_len;
>> +	u8	pln_offset;
>>  	u8	sect_offset;
>> -	u8	sect_len;
>> +
>> +	u64	ch_mask;
>> +	u64	lun_mask;
>> +	u64	blk_mask;
>> +	u64	pg_mask;
>> +	u64	pln_mask;
>> +	u64	sec_mask;
>> +};
>> +
>> +struct nvm_addr_format {
>> +	u8	ch_len;
>> +	u8	lun_len;
>> +	u8	chk_len;
>> +	u8	sec_len;
>> +	u8	rsv_len[2];
>> +
>> +	u8	ch_offset;
>> +	u8	lun_offset;
>> +	u8	chk_offset;
>> +	u8	sec_offset;
>> +	u8	rsv_off[2];
>> +
>> +	u64	ch_mask;
>> +	u64	lun_mask;
>> +	u64	chk_mask;
>> +	u64	sec_mask;
>> +	u64	rsv_mask[2];
>>  };
>>  -struct nvm_id {
>> -	u8	ver_id;
>> +/* Device common geometry */
>> +struct nvm_common_geo {
>> +	/* chunk geometry */
>> +	u32	num_chk;	/* chunks per lun */
>> +	u32	clba;		/* sectors per chunk */
>> +	u16	csecs;		/* sector size */
>> +	u16	sos;		/* out-of-band area size */
>> +
>> +	/* device write constrains */
>> +	u32	ws_min;		/* minimum write size */
>> +	u32	ws_opt;		/* optimal write size */
>> +	u32	mw_cunits;	/* distance required for successful read */
>> +
>> +	/* device capabilities */
>> +	u32	mccap;
>> +
>> +	/* device timings */
>> +	u32	trdt;		/* Avg. Tread (ns) */
>> +	u32	trdm;		/* Max Tread (ns) */
>> +	u32	tprt;		/* Avg. Tprog (ns) */
>> +	u32	tprm;		/* Max Tprog (ns) */
>> +	u32	tbet;		/* Avg. Terase (ns) */
>> +	u32	tbem;		/* Max Terase (ns) */
>> +
>> +	/* generic address format */
>> +	struct nvm_addr_format addrf;
>> +
>> +	/* 1.2 compatibility */
>>  	u8	vmnt;
>>  	u32	cap;
>>  	u32	dom;
>>  -	struct	nvm_addr_format ppaf;
>> -
>> -	u8	num_ch;
>> -	u8	num_lun;
>> -	u16	num_chk;
>> -	u16	clba;
>> -	u16	csecs;
>> -	u16	sos;
>> -
>> -	u32	ws_min;
>> -	u32	ws_opt;
>> -	u32	mw_cunits;
>> -
>> -	u32	trdt;
>> -	u32	trdm;
>> -	u32	tprt;
>> -	u32	tprm;
>> -	u32	tbet;
>> -	u32	tbem;
>> -	u32	mpos;
>> -	u32	mccap;
>> -	u16	cpar;
>> -
>> -	/* calculated values */
>> -	u16	ws_seq;
>> -	u16	ws_per_chk;
>> -
>> -	/* 1.2 compatibility */
>>  	u8	mtype;
>>  	u8	fmtype;
>>  +	u16	cpar;
>> +	u32	mpos;
>> +
>>  	u8	num_pln;
>> +	u8	pln_mode;
>>  	u16	num_pg;
>>  	u16	fpg_sz;
>> -} __packed;
>> +};
>> +
>> +/* Device identified geometry */
>> +struct nvm_dev_geo {
>> +	/* device reported version */
>> +	u8	ver_id;
>> +
>> +	/* full device geometry */
>> +	u16	nr_chnls;
>> +	u16	nr_luns;
>> +
>> +	/* calculated values */
>> +	u16	all_luns;
>> +
>> +	struct nvm_common_geo c;
>> +};
>>    struct nvm_target {
>>  	struct list_head list;
>> @@ -274,36 +319,22 @@ enum {
>>  	NVM_BLK_ST_BAD =	0x8,	/* Bad block */
>>  };
>>  -
>> -/* Device generic information */
>> +/* Instance geometry */
>>  struct nvm_geo {
>> -	/* generic geometry */
>> +	/* instance specific geometry */
>>  	int nr_chnls;
>> -	int all_luns; /* across channels */
>> -	int nr_luns; /* per channel */
>> -	int nr_chks; /* per lun */
>> -
>> -	int sec_size;
>> -	int oob_size;
>> -	int mccap;
>> -
>> -	int sec_per_chk;
>> -	int sec_per_lun;
>> -
>> -	int ws_min;
>> -	int ws_opt;
>> -	int ws_seq;
>> -	int ws_per_chk;
>> +	int nr_luns;		/* per channel */
>>    	int op;
>>  -	struct nvm_addr_format ppaf;
>> +	/* common geometry */
>> +	struct nvm_common_geo c;
>>  -	/* Legacy 1.2 specific geometry */
>> -	int plane_mode; /* drive device in single, double or quad mode */
>> -	int nr_planes;
>> -	int sec_per_pg; /* only sectors for a single page */
>> -	int sec_per_pl; /* all sectors across planes */
>> +	/* calculated values */
>> +	int all_luns;		/* across channels */
>> +	int all_chunks;		/* across channels */
>> +
>> +	sector_t total_secs;	/* across channels */
>>  };
>>    /* sub-device structure */
>> @@ -314,9 +345,6 @@ struct nvm_tgt_dev {
>>  	/* Base ppas for target LUNs */
>>  	struct ppa_addr *luns;
>>  -	sector_t total_secs;
>> -
>> -	struct nvm_id identity;
>>  	struct request_queue *q;
>>    	struct nvm_dev *parent;
>> @@ -329,15 +357,11 @@ struct nvm_dev {
>>  	struct list_head devices;
>>    	/* Device information */
>> -	struct nvm_geo geo;
>> -
>> -	unsigned long total_secs;
>> +	struct nvm_dev_geo dev_geo;
>>    	unsigned long *lun_map;
>>  	void *dma_pool;
>>  -	struct nvm_id identity;
>> -
>>  	/* Backend device */
>>  	struct request_queue *q;
>>  	char name[DISK_NAME_LEN];
>> @@ -357,14 +381,16 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
>>  						  struct ppa_addr r)
>>  {
>>  	struct nvm_geo *geo = &tgt_dev->geo;
>> +	struct nvm_addr_format_12 *ppaf =
>> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>>  	struct ppa_addr l;
>>  -	l.ppa = ((u64)r.g.blk) << geo->ppaf.blk_offset;
>> -	l.ppa |= ((u64)r.g.pg) << geo->ppaf.pg_offset;
>> -	l.ppa |= ((u64)r.g.sec) << geo->ppaf.sect_offset;
>> -	l.ppa |= ((u64)r.g.pl) << geo->ppaf.pln_offset;
>> -	l.ppa |= ((u64)r.g.lun) << geo->ppaf.lun_offset;
>> -	l.ppa |= ((u64)r.g.ch) << geo->ppaf.ch_offset;
>> +	l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
>> +	l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
>> +	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
>> +	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
>> +	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
>> +	l.ppa |= ((u64)r.g.sec) << ppaf->sect_offset;
>>    	return l;
>>  }
>> @@ -373,24 +399,18 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
>>  						  struct ppa_addr r)
>>  {
>>  	struct nvm_geo *geo = &tgt_dev->geo;
>> +	struct nvm_addr_format_12 *ppaf =
>> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>>  	struct ppa_addr l;
>>    	l.ppa = 0;
>> -	/*
>> -	 * (r.ppa << X offset) & X len bitmask. X eq. blk, pg, etc.
>> -	 */
>> -	l.g.blk = (r.ppa >> geo->ppaf.blk_offset) &
>> -					(((1 << geo->ppaf.blk_len) - 1));
>> -	l.g.pg |= (r.ppa >> geo->ppaf.pg_offset) &
>> -					(((1 << geo->ppaf.pg_len) - 1));
>> -	l.g.sec |= (r.ppa >> geo->ppaf.sect_offset) &
>> -					(((1 << geo->ppaf.sect_len) - 1));
>> -	l.g.pl |= (r.ppa >> geo->ppaf.pln_offset) &
>> -					(((1 << geo->ppaf.pln_len) - 1));
>> -	l.g.lun |= (r.ppa >> geo->ppaf.lun_offset) &
>> -					(((1 << geo->ppaf.lun_len) - 1));
>> -	l.g.ch |= (r.ppa >> geo->ppaf.ch_offset) &
>> -					(((1 << geo->ppaf.ch_len) - 1));
>> +
>> +	l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
>> +	l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
>> +	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
>> +	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
>> +	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
>> +	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sect_offset;
>>    	return l;
>>  }
> 
> Thanks for the patch. I appreciate the work, but it is not the way I
> want the 2.0 representation to go. The 2.0 variables should stay in
> the nvm_geo data structure, and then if any 1.2 variables are on the
> side, they can be in a substructure.

I don't understand. Everything is in nvm_geo, with the only different
that there is nvm_common_geo, which contains the shared geometry between
all instances. As mentioned before, if only having nvm_geo, then we are
truncating the structure for each instance with different channel/lun
values, which is very from a target perspective (the target can access
the underlying device's values, which is _very_ error prone). This
structure represents all 2.0 variables as they are.I can move all 1.2
variables to a sub structure if that helps.

If this is not it, can you explain in detail what the problem is? In
pblk, I don't want to deal with a device-centric structure and variables
spread out across what was identity and nvm_geo, I want a single
structure that contains everything, which is the motivation for this
patch.

Javier

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: Message signed with OpenPGP
URL: <http://lists.infradead.org/pipermail/linux-nvme/attachments/20180222/63ba02a6/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 08/20] lightnvm: complete geo structure with maxoc*
  2018-02-21  9:26   ` Javier González
@ 2018-02-22  7:45     ` Matias Bjørling
  -1 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:45 UTC (permalink / raw)
  To: Javier González
  Cc: linux-block, linux-kernel, linux-nvme, Javier González

On 02/21/2018 10:26 AM, Javier González wrote:
> Complete the generic geometry structure with the maxoc and maxocpu
> felds, present in the 2.0 spec.
> 
> Signed-off-by: Javier González <javier@cnexlabs.com>
> ---
>   drivers/nvme/host/lightnvm.c | 4 ++++
>   include/linux/lightnvm.h     | 2 ++
>   2 files changed, 6 insertions(+)
> 
> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
> index cca32da05316..9c1f8225c4e1 100644
> --- a/drivers/nvme/host/lightnvm.c
> +++ b/drivers/nvme/host/lightnvm.c
> @@ -318,6 +318,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>   	dev_geo->c.ws_min = sec_per_pg;
>   	dev_geo->c.ws_opt = sec_per_pg;
>   	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
> +	dev_geo->c.maxoc = dev_geo->all_luns;	/* default to 1 chunk per LUN */
> +	dev_geo->c.maxocpu = 1;			/* default to 1 chunk per LUN */

One can't assume that it is 1 open chunk per lun. If you need this for 
specific hardware, make a quirk for it.

>   
>   	dev_geo->c.mccap = le32_to_cpu(src->mccap);
>   
> @@ -405,6 +407,8 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>   	dev_geo->c.ws_min = le32_to_cpu(id->ws_min);
>   	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
>   	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
> +	dev_geo->c.maxoc = le32_to_cpu(id->maxoc);
> +	dev_geo->c.maxocpu = le32_to_cpu(id->maxocpu);
>   
>   	dev_geo->c.mccap = le32_to_cpu(id->mccap);
>   
> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
> index ccc5faa63cb7..e1c4292ea33d 100644
> --- a/include/linux/lightnvm.h
> +++ b/include/linux/lightnvm.h
> @@ -215,6 +215,8 @@ struct nvm_common_geo {
>   	u32	ws_min;		/* minimum write size */
>   	u32	ws_opt;		/* optimal write size */
>   	u32	mw_cunits;	/* distance required for successful read */
> +	u32	maxoc;		/* maximum open chunks */
> +	u32	maxocpu;	/* maximum open chunks per parallel unit */
>   
>   	/* device capabilities */
>   	u32	mccap;
> 

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 08/20] lightnvm: complete geo structure with maxoc*
@ 2018-02-22  7:45     ` Matias Bjørling
  0 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:45 UTC (permalink / raw)


On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
> Complete the generic geometry structure with the maxoc and maxocpu
> felds, present in the 2.0 spec.
> 
> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
> ---
>   drivers/nvme/host/lightnvm.c | 4 ++++
>   include/linux/lightnvm.h     | 2 ++
>   2 files changed, 6 insertions(+)
> 
> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
> index cca32da05316..9c1f8225c4e1 100644
> --- a/drivers/nvme/host/lightnvm.c
> +++ b/drivers/nvme/host/lightnvm.c
> @@ -318,6 +318,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>   	dev_geo->c.ws_min = sec_per_pg;
>   	dev_geo->c.ws_opt = sec_per_pg;
>   	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
> +	dev_geo->c.maxoc = dev_geo->all_luns;	/* default to 1 chunk per LUN */
> +	dev_geo->c.maxocpu = 1;			/* default to 1 chunk per LUN */

One can't assume that it is 1 open chunk per lun. If you need this for 
specific hardware, make a quirk for it.

>   
>   	dev_geo->c.mccap = le32_to_cpu(src->mccap);
>   
> @@ -405,6 +407,8 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>   	dev_geo->c.ws_min = le32_to_cpu(id->ws_min);
>   	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
>   	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
> +	dev_geo->c.maxoc = le32_to_cpu(id->maxoc);
> +	dev_geo->c.maxocpu = le32_to_cpu(id->maxocpu);
>   
>   	dev_geo->c.mccap = le32_to_cpu(id->mccap);
>   
> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
> index ccc5faa63cb7..e1c4292ea33d 100644
> --- a/include/linux/lightnvm.h
> +++ b/include/linux/lightnvm.h
> @@ -215,6 +215,8 @@ struct nvm_common_geo {
>   	u32	ws_min;		/* minimum write size */
>   	u32	ws_opt;		/* optimal write size */
>   	u32	mw_cunits;	/* distance required for successful read */
> +	u32	maxoc;		/* maximum open chunks */
> +	u32	maxocpu;	/* maximum open chunks per parallel unit */
>   
>   	/* device capabilities */
>   	u32	mccap;
> 

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 09/20] lightnvm: use generic identify structure
  2018-02-21  9:26   ` Javier González
@ 2018-02-22  7:47     ` Matias Bjørling
  -1 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:47 UTC (permalink / raw)
  To: Javier González
  Cc: linux-block, linux-kernel, linux-nvme, Javier González

On 02/21/2018 10:26 AM, Javier González wrote:
> Create a generic identify structure to collect the identify information
> before knowing the spec. version. This forces different version paths to
> cast the structure to their spec structure, thus making the code less
> error prone and more maintainable.
> 
> Signed-off-by: Javier González <javier@cnexlabs.com>
> ---
>   drivers/nvme/host/lightnvm.c | 32 ++++++++++++++++++++------------
>   1 file changed, 20 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
> index 9c1f8225c4e1..70dc4740f0d3 100644
> --- a/drivers/nvme/host/lightnvm.c
> +++ b/drivers/nvme/host/lightnvm.c
> @@ -170,6 +170,12 @@ struct nvme_nvm_id12 {
>   	__u8			resv2[2880];
>   } __packed;
>   
> +/* Generic identification structure */
> +struct nvme_nvm_id {
> +	__u8			ver_id;
> +	__u8			resv[4095];
> +} __packed;
> +
>   struct nvme_nvm_bb_tbl {
>   	__u8	tblid[4];
>   	__le16	verid;
> @@ -279,9 +285,10 @@ static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
>   	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>   }
>   
> -static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
> +static int nvme_nvm_setup_12(struct nvme_nvm_id *gen_id,
>   			     struct nvm_dev_geo *dev_geo)
>   {
> +	struct nvme_nvm_id12 *id = (struct nvme_nvm_id12 *)gen_id;
>   	struct nvme_nvm_id12_grp *src;
>   	int sec_per_pg, sec_per_pl, pg_per_blk;
>   
> @@ -380,9 +387,11 @@ static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
>   	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>   }
>   
> -static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
> +static int nvme_nvm_setup_20(struct nvme_nvm_id *gen_id,
>   			     struct nvm_dev_geo *dev_geo)
>   {
> +	struct nvme_nvm_id20 *id = (struct nvme_nvm_id20 *)gen_id;
> +
>   	dev_geo->major_ver_id = id->mjr;
>   	dev_geo->minor_ver_id = id->mnr;
>   
> @@ -427,19 +436,19 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>   static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>   {
>   	struct nvme_ns *ns = nvmdev->q->queuedata;
> -	struct nvme_nvm_id12 *id;
> +	struct nvme_nvm_id *nvme_nvm_id;
>   	struct nvme_nvm_command c = {};
>   	int ret;
>   
>   	c.identity.opcode = nvme_nvm_admin_identity;
>   	c.identity.nsid = cpu_to_le32(ns->head->ns_id);
>   
> -	id = kmalloc(sizeof(struct nvme_nvm_id12), GFP_KERNEL);
> -	if (!id)
> +	nvme_nvm_id = kmalloc(sizeof(struct nvme_nvm_id), GFP_KERNEL);
> +	if (!nvme_nvm_id)
>   		return -ENOMEM;
>   
>   	ret = nvme_submit_sync_cmd(ns->ctrl->admin_q, (struct nvme_command *)&c,
> -				id, sizeof(struct nvme_nvm_id12));
> +				nvme_nvm_id, sizeof(struct nvme_nvm_id));
>   	if (ret) {
>   		ret = -EIO;
>   		goto out;
> @@ -449,22 +458,21 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>   	 * The 1.2 and 2.0 specifications share the first byte in their geometry
>   	 * command to make it possible to know what version a device implements.
>   	 */
> -	switch (id->ver_id) {
> +	switch (nvme_nvm_id->ver_id) {
>   	case 1:
> -		ret = nvme_nvm_setup_12(id, &nvmdev->dev_geo);
> +		ret = nvme_nvm_setup_12(nvme_nvm_id, &nvmdev->dev_geo);
>   		break;
>   	case 2:
> -		ret = nvme_nvm_setup_20((struct nvme_nvm_id20 *)id,
> -							&nvmdev->dev_geo);
> +		ret = nvme_nvm_setup_20(nvme_nvm_id, &nvmdev->dev_geo);
>   		break;
>   	default:
>   		dev_err(ns->ctrl->device, "OCSSD revision not supported (%d)\n",
> -							id->ver_id);
> +							nvme_nvm_id->ver_id);
>   		ret = -EINVAL;
>   	}
>   
>   out:
> -	kfree(id);
> +	kfree(nvme_nvm_id);
>   	return ret;
>   }
>   
> 

Thanks for another way to represent it. I want to keep the original 
path. If we are going that down road, then one should maybe look into 
unifying the "three" data structures, and have the version as the base 
property and the others in each their sub data structure.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 09/20] lightnvm: use generic identify structure
@ 2018-02-22  7:47     ` Matias Bjørling
  0 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:47 UTC (permalink / raw)


On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
> Create a generic identify structure to collect the identify information
> before knowing the spec. version. This forces different version paths to
> cast the structure to their spec structure, thus making the code less
> error prone and more maintainable.
> 
> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
> ---
>   drivers/nvme/host/lightnvm.c | 32 ++++++++++++++++++++------------
>   1 file changed, 20 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
> index 9c1f8225c4e1..70dc4740f0d3 100644
> --- a/drivers/nvme/host/lightnvm.c
> +++ b/drivers/nvme/host/lightnvm.c
> @@ -170,6 +170,12 @@ struct nvme_nvm_id12 {
>   	__u8			resv2[2880];
>   } __packed;
>   
> +/* Generic identification structure */
> +struct nvme_nvm_id {
> +	__u8			ver_id;
> +	__u8			resv[4095];
> +} __packed;
> +
>   struct nvme_nvm_bb_tbl {
>   	__u8	tblid[4];
>   	__le16	verid;
> @@ -279,9 +285,10 @@ static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
>   	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>   }
>   
> -static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
> +static int nvme_nvm_setup_12(struct nvme_nvm_id *gen_id,
>   			     struct nvm_dev_geo *dev_geo)
>   {
> +	struct nvme_nvm_id12 *id = (struct nvme_nvm_id12 *)gen_id;
>   	struct nvme_nvm_id12_grp *src;
>   	int sec_per_pg, sec_per_pl, pg_per_blk;
>   
> @@ -380,9 +387,11 @@ static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
>   	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>   }
>   
> -static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
> +static int nvme_nvm_setup_20(struct nvme_nvm_id *gen_id,
>   			     struct nvm_dev_geo *dev_geo)
>   {
> +	struct nvme_nvm_id20 *id = (struct nvme_nvm_id20 *)gen_id;
> +
>   	dev_geo->major_ver_id = id->mjr;
>   	dev_geo->minor_ver_id = id->mnr;
>   
> @@ -427,19 +436,19 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>   static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>   {
>   	struct nvme_ns *ns = nvmdev->q->queuedata;
> -	struct nvme_nvm_id12 *id;
> +	struct nvme_nvm_id *nvme_nvm_id;
>   	struct nvme_nvm_command c = {};
>   	int ret;
>   
>   	c.identity.opcode = nvme_nvm_admin_identity;
>   	c.identity.nsid = cpu_to_le32(ns->head->ns_id);
>   
> -	id = kmalloc(sizeof(struct nvme_nvm_id12), GFP_KERNEL);
> -	if (!id)
> +	nvme_nvm_id = kmalloc(sizeof(struct nvme_nvm_id), GFP_KERNEL);
> +	if (!nvme_nvm_id)
>   		return -ENOMEM;
>   
>   	ret = nvme_submit_sync_cmd(ns->ctrl->admin_q, (struct nvme_command *)&c,
> -				id, sizeof(struct nvme_nvm_id12));
> +				nvme_nvm_id, sizeof(struct nvme_nvm_id));
>   	if (ret) {
>   		ret = -EIO;
>   		goto out;
> @@ -449,22 +458,21 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>   	 * The 1.2 and 2.0 specifications share the first byte in their geometry
>   	 * command to make it possible to know what version a device implements.
>   	 */
> -	switch (id->ver_id) {
> +	switch (nvme_nvm_id->ver_id) {
>   	case 1:
> -		ret = nvme_nvm_setup_12(id, &nvmdev->dev_geo);
> +		ret = nvme_nvm_setup_12(nvme_nvm_id, &nvmdev->dev_geo);
>   		break;
>   	case 2:
> -		ret = nvme_nvm_setup_20((struct nvme_nvm_id20 *)id,
> -							&nvmdev->dev_geo);
> +		ret = nvme_nvm_setup_20(nvme_nvm_id, &nvmdev->dev_geo);
>   		break;
>   	default:
>   		dev_err(ns->ctrl->device, "OCSSD revision not supported (%d)\n",
> -							id->ver_id);
> +							nvme_nvm_id->ver_id);
>   		ret = -EINVAL;
>   	}
>   
>   out:
> -	kfree(id);
> +	kfree(nvme_nvm_id);
>   	return ret;
>   }
>   
> 

Thanks for another way to represent it. I want to keep the original 
path. If we are going that down road, then one should maybe look into 
unifying the "three" data structures, and have the version as the base 
property and the others in each their sub data structure.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 03/20] lightnvm: fix capabilities for 2.0 sysfs
  2018-02-22  7:28     ` Matias Bjørling
@ 2018-02-22  7:47       ` Javier Gonzalez
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier Gonzalez @ 2018-02-22  7:47 UTC (permalink / raw)
  To: Matias Bjørling; +Cc: linux-block, linux-kernel, linux-nvme

[-- Attachment #1: Type: text/plain, Size: 3918 bytes --]

> On 22 Feb 2018, at 08.28, Matias Bjørling <mb@lightnvm.io> wrote:
> 
> On 02/21/2018 10:26 AM, Javier González wrote:
>> Both 1.2 and 2.0 specs define a field for media and controller
>> capabilities. Also, 1.2 defines a separate field dedicated to device
>> capabilities.
>> In 2.0 sysfs, this values have been mixed. Revert them to the right
>> value.
>> Signed-off-by: Javier González <javier@cnexlabs.com>
>> ---
>>  drivers/nvme/host/lightnvm.c | 18 +++++++++---------
>>  1 file changed, 9 insertions(+), 9 deletions(-)
>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>> index 969bb874850c..598abba66f52 100644
>> --- a/drivers/nvme/host/lightnvm.c
>> +++ b/drivers/nvme/host/lightnvm.c
>> @@ -914,8 +914,8 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>    	if (strcmp(attr->name, "version") == 0) {
>>  		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>> -	} else if (strcmp(attr->name, "capabilities") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
>> +	} else if (strcmp(attr->name, "media_capabilities") == 0) {
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
>>  	} else if (strcmp(attr->name, "read_typ") == 0) {
>>  		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>>  	} else if (strcmp(attr->name, "read_max") == 0) {
>> @@ -993,8 +993,8 @@ static ssize_t nvm_dev_attr_show_12(struct device *dev,
>>  		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>  	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
>>  		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
>> -	} else if (strcmp(attr->name, "media_capabilities") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
>> +	} else if (strcmp(attr->name, "capabilities") == 0) {
>> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.cap);
>>  	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
>>  		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>>  	} else {
>> @@ -1055,7 +1055,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>>    /* general attributes */
>>  static NVM_DEV_ATTR_RO(version);
>> -static NVM_DEV_ATTR_RO(capabilities);
>> +static NVM_DEV_ATTR_RO(media_capabilities);
>>    static NVM_DEV_ATTR_RO(read_typ);
>>  static NVM_DEV_ATTR_RO(read_max);
>> @@ -1080,12 +1080,12 @@ static NVM_DEV_ATTR_12_RO(prog_max);
>>  static NVM_DEV_ATTR_12_RO(erase_typ);
>>  static NVM_DEV_ATTR_12_RO(erase_max);
>>  static NVM_DEV_ATTR_12_RO(multiplane_modes);
>> -static NVM_DEV_ATTR_12_RO(media_capabilities);
>> +static NVM_DEV_ATTR_12_RO(capabilities);
>>  static NVM_DEV_ATTR_12_RO(max_phys_secs);
>>    static struct attribute *nvm_dev_attrs_12[] = {
>>  	&dev_attr_version.attr,
>> -	&dev_attr_capabilities.attr,
>> +	&dev_attr_media_capabilities.attr,
>>    	&dev_attr_vendor_opcode.attr,
>>  	&dev_attr_device_mode.attr,
>> @@ -1108,7 +1108,7 @@ static struct attribute *nvm_dev_attrs_12[] = {
>>  	&dev_attr_erase_typ.attr,
>>  	&dev_attr_erase_max.attr,
>>  	&dev_attr_multiplane_modes.attr,
>> -	&dev_attr_media_capabilities.attr,
>> +	&dev_attr_capabilities.attr,
>>  	&dev_attr_max_phys_secs.attr,
>>    	NULL,
>> @@ -1134,7 +1134,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
>>    static struct attribute *nvm_dev_attrs_20[] = {
>>  	&dev_attr_version.attr,
>> -	&dev_attr_capabilities.attr,
>> +	&dev_attr_media_capabilities.attr,
>>    	&dev_attr_groups.attr,
>>  	&dev_attr_punits.attr,
> 
> With the mccap changes, it should make sense to keep the capabilities
> as is.

The change adds mccap, but sysfs points to cap, which is wrong. This
patch is needed. Otherwise, we change the name of mccap to cap, which
is _very_ confusing to people familiar to both specs. We can change
the name of mccap to cap in a future spec revision.

Javier

[-- Attachment #2: Message signed with OpenPGP --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 03/20] lightnvm: fix capabilities for 2.0 sysfs
@ 2018-02-22  7:47       ` Javier Gonzalez
  0 siblings, 0 replies; 99+ messages in thread
From: Javier Gonzalez @ 2018-02-22  7:47 UTC (permalink / raw)


> On 22 Feb 2018,@08.28, Matias Bj?rling <mb@lightnvm.io> wrote:
> 
> On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
>> Both 1.2 and 2.0 specs define a field for media and controller
>> capabilities. Also, 1.2 defines a separate field dedicated to device
>> capabilities.
>> In 2.0 sysfs, this values have been mixed. Revert them to the right
>> value.
>> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
>> ---
>>  drivers/nvme/host/lightnvm.c | 18 +++++++++---------
>>  1 file changed, 9 insertions(+), 9 deletions(-)
>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>> index 969bb874850c..598abba66f52 100644
>> --- a/drivers/nvme/host/lightnvm.c
>> +++ b/drivers/nvme/host/lightnvm.c
>> @@ -914,8 +914,8 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>    	if (strcmp(attr->name, "version") == 0) {
>>  		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>> -	} else if (strcmp(attr->name, "capabilities") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
>> +	} else if (strcmp(attr->name, "media_capabilities") == 0) {
>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
>>  	} else if (strcmp(attr->name, "read_typ") == 0) {
>>  		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>>  	} else if (strcmp(attr->name, "read_max") == 0) {
>> @@ -993,8 +993,8 @@ static ssize_t nvm_dev_attr_show_12(struct device *dev,
>>  		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>  	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
>>  		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
>> -	} else if (strcmp(attr->name, "media_capabilities") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
>> +	} else if (strcmp(attr->name, "capabilities") == 0) {
>> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.cap);
>>  	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
>>  		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>>  	} else {
>> @@ -1055,7 +1055,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>>    /* general attributes */
>>  static NVM_DEV_ATTR_RO(version);
>> -static NVM_DEV_ATTR_RO(capabilities);
>> +static NVM_DEV_ATTR_RO(media_capabilities);
>>    static NVM_DEV_ATTR_RO(read_typ);
>>  static NVM_DEV_ATTR_RO(read_max);
>> @@ -1080,12 +1080,12 @@ static NVM_DEV_ATTR_12_RO(prog_max);
>>  static NVM_DEV_ATTR_12_RO(erase_typ);
>>  static NVM_DEV_ATTR_12_RO(erase_max);
>>  static NVM_DEV_ATTR_12_RO(multiplane_modes);
>> -static NVM_DEV_ATTR_12_RO(media_capabilities);
>> +static NVM_DEV_ATTR_12_RO(capabilities);
>>  static NVM_DEV_ATTR_12_RO(max_phys_secs);
>>    static struct attribute *nvm_dev_attrs_12[] = {
>>  	&dev_attr_version.attr,
>> -	&dev_attr_capabilities.attr,
>> +	&dev_attr_media_capabilities.attr,
>>    	&dev_attr_vendor_opcode.attr,
>>  	&dev_attr_device_mode.attr,
>> @@ -1108,7 +1108,7 @@ static struct attribute *nvm_dev_attrs_12[] = {
>>  	&dev_attr_erase_typ.attr,
>>  	&dev_attr_erase_max.attr,
>>  	&dev_attr_multiplane_modes.attr,
>> -	&dev_attr_media_capabilities.attr,
>> +	&dev_attr_capabilities.attr,
>>  	&dev_attr_max_phys_secs.attr,
>>    	NULL,
>> @@ -1134,7 +1134,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
>>    static struct attribute *nvm_dev_attrs_20[] = {
>>  	&dev_attr_version.attr,
>> -	&dev_attr_capabilities.attr,
>> +	&dev_attr_media_capabilities.attr,
>>    	&dev_attr_groups.attr,
>>  	&dev_attr_punits.attr,
> 
> With the mccap changes, it should make sense to keep the capabilities
> as is.

The change adds mccap, but sysfs points to cap, which is wrong. This
patch is needed. Otherwise, we change the name of mccap to cap, which
is _very_ confusing to people familiar to both specs. We can change
the name of mccap to cap in a future spec revision.

Javier
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: Message signed with OpenPGP
URL: <http://lists.infradead.org/pipermail/linux-nvme/attachments/20180222/28c81c76/attachment.sig>

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 10/20] lightnvm: pblk: rename ppaf* to addrf*
  2018-02-21  9:26   ` Javier González
  (?)
@ 2018-02-22  7:47     ` Matias Bjørling
  -1 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:47 UTC (permalink / raw)
  To: Javier González
  Cc: linux-block, Javier González, linux-kernel, linux-nvme

T24gMDIvMjEvMjAxOCAxMDoyNiBBTSwgSmF2aWVyIEdvbnrDoWxleiB3cm90ZToKPiBJbiBwcmVw
YXJhdGlvbiBmb3IgMi4wIHN1cHBvcnQgaW4gcGJsaywgcmVuYW1lIHZhcmlhYmxlcyByZWZlcnJp
bmcgdG8KPiB0aGUgYWRkcmVzcyBmb3JtYXQgdG8gYWRkcmYgYW5kIHJlc2VydmUgcHBhZiBmb3Ig
dGhlIDEuMiBwYXRoLgo+IAo+IFNpZ25lZC1vZmYtYnk6IEphdmllciBHb256w6FsZXogPGphdmll
ckBjbmV4bGFicy5jb20+Cj4gLS0tCj4gICBkcml2ZXJzL2xpZ2h0bnZtL3BibGstaW5pdC5jICB8
ICA4ICsrKystLS0tCj4gICBkcml2ZXJzL2xpZ2h0bnZtL3BibGstc3lzZnMuYyB8ICA0ICsrLS0K
PiAgIGRyaXZlcnMvbGlnaHRudm0vcGJsay5oICAgICAgIHwgMTYgKysrKysrKystLS0tLS0tLQo+
ICAgMyBmaWxlcyBjaGFuZ2VkLCAxNCBpbnNlcnRpb25zKCspLCAxNCBkZWxldGlvbnMoLSkKPiAK
PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9saWdodG52bS9wYmxrLWluaXQuYyBiL2RyaXZlcnMvbGln
aHRudm0vcGJsay1pbml0LmMKPiBpbmRleCA2YmY1MWVmOGY1MTYuLjU2YjRhZmMyN2FkZCAxMDA2
NDQKPiAtLS0gYS9kcml2ZXJzL2xpZ2h0bnZtL3BibGstaW5pdC5jCj4gKysrIGIvZHJpdmVycy9s
aWdodG52bS9wYmxrLWluaXQuYwo+IEBAIC04MCw3ICs4MCw3IEBAIHN0YXRpYyBzaXplX3QgcGJs
a190cmFuc19tYXBfc2l6ZShzdHJ1Y3QgcGJsayAqcGJsaykKPiAgIHsKPiAgIAlpbnQgZW50cnlf
c2l6ZSA9IDg7Cj4gICAKPiAtCWlmIChwYmxrLT5wcGFmX2JpdHNpemUgPCAzMikKPiArCWlmIChw
YmxrLT5hZGRyZl9sZW4gPCAzMikKPiAgIAkJZW50cnlfc2l6ZSA9IDQ7Cj4gICAKPiAgIAlyZXR1
cm4gZW50cnlfc2l6ZSAqIHBibGstPnJsLm5yX3NlY3M7Cj4gQEAgLTE5OCw3ICsxOTgsNyBAQCBz
dGF0aWMgaW50IHBibGtfc2V0X2FkZHJmXzEyKHN0cnVjdCBudm1fZ2VvICpnZW8sCj4gICAJcmV0
dXJuIGRzdC0+YmxrX29mZnNldCArIHNyYy0+YmxrX2xlbjsKPiAgIH0KPiAgIAo+IC1zdGF0aWMg
aW50IHBibGtfc2V0X3BwYWYoc3RydWN0IHBibGsgKnBibGspCj4gK3N0YXRpYyBpbnQgcGJsa19z
ZXRfYWRkcmYoc3RydWN0IHBibGsgKnBibGspCj4gICB7Cj4gICAJc3RydWN0IG52bV90Z3RfZGV2
ICpkZXYgPSBwYmxrLT5kZXY7Cj4gICAJc3RydWN0IG52bV9nZW8gKmdlbyA9ICZkZXYtPmdlbzsK
PiBAQCAtMjEwLDcgKzIxMCw3IEBAIHN0YXRpYyBpbnQgcGJsa19zZXRfcHBhZihzdHJ1Y3QgcGJs
ayAqcGJsaykKPiAgIAkJcmV0dXJuIC1FSU5WQUw7Cj4gICAJfQo+ICAgCj4gLQlwYmxrLT5wcGFm
X2JpdHNpemUgPSBwYmxrX3NldF9hZGRyZl8xMihnZW8sICh2b2lkICopJnBibGstPnBwYWYpOwo+
ICsJcGJsay0+YWRkcmZfbGVuID0gcGJsa19zZXRfYWRkcmZfMTIoZ2VvLCAodm9pZCAqKSZwYmxr
LT5hZGRyZik7Cj4gICAKPiAgIAlyZXR1cm4gMDsKPiAgIH0KPiBAQCAtMzE5LDcgKzMxOSw3IEBA
IHN0YXRpYyBpbnQgcGJsa19jb3JlX2luaXQoc3RydWN0IHBibGsgKnBibGspCj4gICAJaWYgKCFw
YmxrLT5yX2VuZF93cSkKPiAgIAkJZ290byBmcmVlX2JiX3dxOwo+ICAgCj4gLQlpZiAocGJsa19z
ZXRfcHBhZihwYmxrKSkKPiArCWlmIChwYmxrX3NldF9hZGRyZihwYmxrKSkKPiAgIAkJZ290byBm
cmVlX3JfZW5kX3dxOwo+ICAgCj4gICAJaWYgKHBibGtfcndiX2luaXQocGJsaykpCj4gZGlmZiAt
LWdpdCBhL2RyaXZlcnMvbGlnaHRudm0vcGJsay1zeXNmcy5jIGIvZHJpdmVycy9saWdodG52bS9w
YmxrLXN5c2ZzLmMKPiBpbmRleCA4MTI4OGFhOTE2MmEuLmQzYjUwNzQxYjY5MSAxMDA2NDQKPiAt
LS0gYS9kcml2ZXJzL2xpZ2h0bnZtL3BibGstc3lzZnMuYwo+ICsrKyBiL2RyaXZlcnMvbGlnaHRu
dm0vcGJsay1zeXNmcy5jCj4gQEAgLTExNywxMiArMTE3LDEyIEBAIHN0YXRpYyBzc2l6ZV90IHBi
bGtfc3lzZnNfcHBhZihzdHJ1Y3QgcGJsayAqcGJsaywgY2hhciAqcGFnZSkKPiAgIAlzdHJ1Y3Qg
bnZtX2FkZHJfZm9ybWF0XzEyICpnZW9fcHBhZjsKPiAgIAlzc2l6ZV90IHN6ID0gMDsKPiAgIAo+
IC0JcHBhZiA9IChzdHJ1Y3QgbnZtX2FkZHJfZm9ybWF0XzEyICopJnBibGstPnBwYWY7Cj4gKwlw
cGFmID0gKHN0cnVjdCBudm1fYWRkcl9mb3JtYXRfMTIgKikmcGJsay0+YWRkcmY7Cj4gICAJZ2Vv
X3BwYWYgPSAoc3RydWN0IG52bV9hZGRyX2Zvcm1hdF8xMiAqKSZnZW8tPmMuYWRkcmY7Cj4gICAK
PiAgIAlzeiA9IHNucHJpbnRmKHBhZ2UsIFBBR0VfU0laRSwKPiAgIAkJInBibGs6KHM6JWQpY2g6
JWQvJWQsbHVuOiVkLyVkLGJsazolZC8lZCxwZzolZC8lZCxwbDolZC8lZCxzZWM6JWQvJWRcbiIs
Cj4gLQkJCXBibGstPnBwYWZfYml0c2l6ZSwKPiArCQkJcGJsay0+YWRkcmZfbGVuLAo+ICAgCQkJ
cHBhZi0+Y2hfb2Zmc2V0LCBwcGFmLT5jaF9sZW4sCj4gICAJCQlwcGFmLT5sdW5fb2Zmc2V0LCBw
cGFmLT5sdW5fbGVuLAo+ICAgCQkJcHBhZi0+YmxrX29mZnNldCwgcHBhZi0+YmxrX2xlbiwKPiBk
aWZmIC0tZ2l0IGEvZHJpdmVycy9saWdodG52bS9wYmxrLmggYi9kcml2ZXJzL2xpZ2h0bnZtL3Bi
bGsuaAo+IGluZGV4IDRmN2EzNjU0MzZmMS4uNDZiMjlhNDkyZjc0IDEwMDY0NAo+IC0tLSBhL2Ry
aXZlcnMvbGlnaHRudm0vcGJsay5oCj4gKysrIGIvZHJpdmVycy9saWdodG52bS9wYmxrLmgKPiBA
QCAtNTcwLDggKzU3MCw4IEBAIHN0cnVjdCBwYmxrIHsKPiAgIAlzdHJ1Y3QgcGJsa19saW5lX21n
bXQgbF9tZzsJCS8qIExpbmUgbWFuYWdlbWVudCAqLwo+ICAgCXN0cnVjdCBwYmxrX2xpbmVfbWV0
YSBsbTsJCS8qIExpbmUgbWV0YWRhdGEgKi8KPiAgIAo+IC0Jc3RydWN0IG52bV9hZGRyX2Zvcm1h
dCBwcGFmOwo+IC0JaW50IHBwYWZfYml0c2l6ZTsKPiArCXN0cnVjdCBudm1fYWRkcl9mb3JtYXQg
YWRkcmY7Cj4gKwlpbnQgYWRkcmZfbGVuOwo+ICAgCj4gICAJc3RydWN0IHBibGtfcmIgcndiOwo+
ICAgCj4gQEAgLTk0OCw3ICs5NDgsNyBAQCBzdGF0aWMgaW5saW5lIHN0cnVjdCBwcGFfYWRkciBh
ZGRyX3RvX2dlbl9wcGEoc3RydWN0IHBibGsgKnBibGssIHU2NCBwYWRkciwKPiAgIAkJCQkJICAg
ICAgdTY0IGxpbmVfaWQpCj4gICB7Cj4gICAJc3RydWN0IG52bV9hZGRyX2Zvcm1hdF8xMiAqcHBh
ZiA9Cj4gLQkJCQkoc3RydWN0IG52bV9hZGRyX2Zvcm1hdF8xMiAqKSZwYmxrLT5wcGFmOwo+ICsJ
CQkJKHN0cnVjdCBudm1fYWRkcl9mb3JtYXRfMTIgKikmcGJsay0+YWRkcmY7Cj4gICAJc3RydWN0
IHBwYV9hZGRyIHBwYTsKPiAgIAo+ICAgCXBwYS5wcGEgPSAwOwo+IEBAIC05NjYsNyArOTY2LDcg
QEAgc3RhdGljIGlubGluZSB1NjQgcGJsa19kZXZfcHBhX3RvX2xpbmVfYWRkcihzdHJ1Y3QgcGJs
ayAqcGJsaywKPiAgIAkJCQkJCQlzdHJ1Y3QgcHBhX2FkZHIgcCkKPiAgIHsKPiAgIAlzdHJ1Y3Qg
bnZtX2FkZHJfZm9ybWF0XzEyICpwcGFmID0KPiAtCQkJCShzdHJ1Y3QgbnZtX2FkZHJfZm9ybWF0
XzEyICopJnBibGstPnBwYWY7Cj4gKwkJCQkoc3RydWN0IG52bV9hZGRyX2Zvcm1hdF8xMiAqKSZw
YmxrLT5hZGRyZjsKPiAgIAl1NjQgcGFkZHI7Cj4gICAKPiAgIAlwYWRkciA9ICh1NjQpcC5nLmNo
IDw8IHBwYWYtPmNoX29mZnNldDsKPiBAQCAtOTkxLDcgKzk5MSw3IEBAIHN0YXRpYyBpbmxpbmUg
c3RydWN0IHBwYV9hZGRyIHBibGtfcHBhMzJfdG9fcHBhNjQoc3RydWN0IHBibGsgKnBibGssIHUz
MiBwcGEzMikKPiAgIAkJcHBhNjQuYy5pc19jYWNoZWQgPSAxOwo+ICAgCX0gZWxzZSB7Cj4gICAJ
CXN0cnVjdCBudm1fYWRkcl9mb3JtYXRfMTIgKnBwYWYgPQo+IC0JCQkJKHN0cnVjdCBudm1fYWRk
cl9mb3JtYXRfMTIgKikmcGJsay0+cHBhZjsKPiArCQkJCShzdHJ1Y3QgbnZtX2FkZHJfZm9ybWF0
XzEyICopJnBibGstPmFkZHJmOwo+ICAgCj4gICAJCXBwYTY0LmcuY2ggPSAocHBhMzIgJiBwcGFm
LT5jaF9tYXNrKSA+PiBwcGFmLT5jaF9vZmZzZXQ7Cj4gICAJCXBwYTY0LmcubHVuID0gKHBwYTMy
ICYgcHBhZi0+bHVuX21hc2spID4+IHBwYWYtPmx1bl9vZmZzZXQ7Cj4gQEAgLTEwMTUsNyArMTAx
NSw3IEBAIHN0YXRpYyBpbmxpbmUgdTMyIHBibGtfcHBhNjRfdG9fcHBhMzIoc3RydWN0IHBibGsg
KnBibGssIHN0cnVjdCBwcGFfYWRkciBwcGE2NCkKPiAgIAkJcHBhMzIgfD0gMVUgPDwgMzE7Cj4g
ICAJfSBlbHNlIHsKPiAgIAkJc3RydWN0IG52bV9hZGRyX2Zvcm1hdF8xMiAqcHBhZiA9Cj4gLQkJ
CQkoc3RydWN0IG52bV9hZGRyX2Zvcm1hdF8xMiAqKSZwYmxrLT5wcGFmOwo+ICsJCQkJKHN0cnVj
dCBudm1fYWRkcl9mb3JtYXRfMTIgKikmcGJsay0+YWRkcmY7Cj4gICAKPiAgIAkJcHBhMzIgfD0g
cHBhNjQuZy5jaCA8PCBwcGFmLT5jaF9vZmZzZXQ7Cj4gICAJCXBwYTMyIHw9IHBwYTY0LmcubHVu
IDw8IHBwYWYtPmx1bl9vZmZzZXQ7Cj4gQEAgLTEwMzMsNyArMTAzMyw3IEBAIHN0YXRpYyBpbmxp
bmUgc3RydWN0IHBwYV9hZGRyIHBibGtfdHJhbnNfbWFwX2dldChzdHJ1Y3QgcGJsayAqcGJsaywK
PiAgIHsKPiAgIAlzdHJ1Y3QgcHBhX2FkZHIgcHBhOwo+ICAgCj4gLQlpZiAocGJsay0+cHBhZl9i
aXRzaXplIDwgMzIpIHsKPiArCWlmIChwYmxrLT5hZGRyZl9sZW4gPCAzMikgewo+ICAgCQl1MzIg
Km1hcCA9ICh1MzIgKilwYmxrLT50cmFuc19tYXA7Cj4gICAKPiAgIAkJcHBhID0gcGJsa19wcGEz
Ml90b19wcGE2NChwYmxrLCBtYXBbbGJhXSk7Cj4gQEAgLTEwNDksNyArMTA0OSw3IEBAIHN0YXRp
YyBpbmxpbmUgc3RydWN0IHBwYV9hZGRyIHBibGtfdHJhbnNfbWFwX2dldChzdHJ1Y3QgcGJsayAq
cGJsaywKPiAgIHN0YXRpYyBpbmxpbmUgdm9pZCBwYmxrX3RyYW5zX21hcF9zZXQoc3RydWN0IHBi
bGsgKnBibGssIHNlY3Rvcl90IGxiYSwKPiAgIAkJCQkJCXN0cnVjdCBwcGFfYWRkciBwcGEpCj4g
ICB7Cj4gLQlpZiAocGJsay0+cHBhZl9iaXRzaXplIDwgMzIpIHsKPiArCWlmIChwYmxrLT5hZGRy
Zl9sZW4gPCAzMikgewo+ICAgCQl1MzIgKm1hcCA9ICh1MzIgKilwYmxrLT50cmFuc19tYXA7Cj4g
ICAKPiAgIAkJbWFwW2xiYV0gPSBwYmxrX3BwYTY0X3RvX3BwYTMyKHBibGssIHBwYSk7Cj4gCgpM
b29rcyBnb29kLiBJJ2xsIHBpY2sgdXAgd2hlbiByZWJhc2VkLgoKX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX18KTGludXgtbnZtZSBtYWlsaW5nIGxpc3QKTGlu
dXgtbnZtZUBsaXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21h
aWxtYW4vbGlzdGluZm8vbGludXgtbnZtZQo=

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 10/20] lightnvm: pblk: rename ppaf* to addrf*
@ 2018-02-22  7:47     ` Matias Bjørling
  0 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:47 UTC (permalink / raw)
  To: Javier González
  Cc: linux-block, linux-kernel, linux-nvme, Javier González

On 02/21/2018 10:26 AM, Javier González wrote:
> In preparation for 2.0 support in pblk, rename variables referring to
> the address format to addrf and reserve ppaf for the 1.2 path.
> 
> Signed-off-by: Javier González <javier@cnexlabs.com>
> ---
>   drivers/lightnvm/pblk-init.c  |  8 ++++----
>   drivers/lightnvm/pblk-sysfs.c |  4 ++--
>   drivers/lightnvm/pblk.h       | 16 ++++++++--------
>   3 files changed, 14 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
> index 6bf51ef8f516..56b4afc27add 100644
> --- a/drivers/lightnvm/pblk-init.c
> +++ b/drivers/lightnvm/pblk-init.c
> @@ -80,7 +80,7 @@ static size_t pblk_trans_map_size(struct pblk *pblk)
>   {
>   	int entry_size = 8;
>   
> -	if (pblk->ppaf_bitsize < 32)
> +	if (pblk->addrf_len < 32)
>   		entry_size = 4;
>   
>   	return entry_size * pblk->rl.nr_secs;
> @@ -198,7 +198,7 @@ static int pblk_set_addrf_12(struct nvm_geo *geo,
>   	return dst->blk_offset + src->blk_len;
>   }
>   
> -static int pblk_set_ppaf(struct pblk *pblk)
> +static int pblk_set_addrf(struct pblk *pblk)
>   {
>   	struct nvm_tgt_dev *dev = pblk->dev;
>   	struct nvm_geo *geo = &dev->geo;
> @@ -210,7 +210,7 @@ static int pblk_set_ppaf(struct pblk *pblk)
>   		return -EINVAL;
>   	}
>   
> -	pblk->ppaf_bitsize = pblk_set_addrf_12(geo, (void *)&pblk->ppaf);
> +	pblk->addrf_len = pblk_set_addrf_12(geo, (void *)&pblk->addrf);
>   
>   	return 0;
>   }
> @@ -319,7 +319,7 @@ static int pblk_core_init(struct pblk *pblk)
>   	if (!pblk->r_end_wq)
>   		goto free_bb_wq;
>   
> -	if (pblk_set_ppaf(pblk))
> +	if (pblk_set_addrf(pblk))
>   		goto free_r_end_wq;
>   
>   	if (pblk_rwb_init(pblk))
> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
> index 81288aa9162a..d3b50741b691 100644
> --- a/drivers/lightnvm/pblk-sysfs.c
> +++ b/drivers/lightnvm/pblk-sysfs.c
> @@ -117,12 +117,12 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
>   	struct nvm_addr_format_12 *geo_ppaf;
>   	ssize_t sz = 0;
>   
> -	ppaf = (struct nvm_addr_format_12 *)&pblk->ppaf;
> +	ppaf = (struct nvm_addr_format_12 *)&pblk->addrf;
>   	geo_ppaf = (struct nvm_addr_format_12 *)&geo->c.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",
> -			pblk->ppaf_bitsize,
> +			pblk->addrf_len,
>   			ppaf->ch_offset, ppaf->ch_len,
>   			ppaf->lun_offset, ppaf->lun_len,
>   			ppaf->blk_offset, ppaf->blk_len,
> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
> index 4f7a365436f1..46b29a492f74 100644
> --- a/drivers/lightnvm/pblk.h
> +++ b/drivers/lightnvm/pblk.h
> @@ -570,8 +570,8 @@ struct pblk {
>   	struct pblk_line_mgmt l_mg;		/* Line management */
>   	struct pblk_line_meta lm;		/* Line metadata */
>   
> -	struct nvm_addr_format ppaf;
> -	int ppaf_bitsize;
> +	struct nvm_addr_format addrf;
> +	int addrf_len;
>   
>   	struct pblk_rb rwb;
>   
> @@ -948,7 +948,7 @@ 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->ppaf;
> +				(struct nvm_addr_format_12 *)&pblk->addrf;
>   	struct ppa_addr ppa;
>   
>   	ppa.ppa = 0;
> @@ -966,7 +966,7 @@ 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->ppaf;
> +				(struct nvm_addr_format_12 *)&pblk->addrf;
>   	u64 paddr;
>   
>   	paddr = (u64)p.g.ch << ppaf->ch_offset;
> @@ -991,7 +991,7 @@ static inline struct ppa_addr pblk_ppa32_to_ppa64(struct pblk *pblk, u32 ppa32)
>   		ppa64.c.is_cached = 1;
>   	} else {
>   		struct nvm_addr_format_12 *ppaf =
> -				(struct nvm_addr_format_12 *)&pblk->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;
> @@ -1015,7 +1015,7 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
>   		ppa32 |= 1U << 31;
>   	} else {
>   		struct nvm_addr_format_12 *ppaf =
> -				(struct nvm_addr_format_12 *)&pblk->ppaf;
> +				(struct nvm_addr_format_12 *)&pblk->addrf;
>   
>   		ppa32 |= ppa64.g.ch << ppaf->ch_offset;
>   		ppa32 |= ppa64.g.lun << ppaf->lun_offset;
> @@ -1033,7 +1033,7 @@ static inline struct ppa_addr pblk_trans_map_get(struct pblk *pblk,
>   {
>   	struct ppa_addr ppa;
>   
> -	if (pblk->ppaf_bitsize < 32) {
> +	if (pblk->addrf_len < 32) {
>   		u32 *map = (u32 *)pblk->trans_map;
>   
>   		ppa = pblk_ppa32_to_ppa64(pblk, map[lba]);
> @@ -1049,7 +1049,7 @@ static inline struct ppa_addr pblk_trans_map_get(struct pblk *pblk,
>   static inline void pblk_trans_map_set(struct pblk *pblk, sector_t lba,
>   						struct ppa_addr ppa)
>   {
> -	if (pblk->ppaf_bitsize < 32) {
> +	if (pblk->addrf_len < 32) {
>   		u32 *map = (u32 *)pblk->trans_map;
>   
>   		map[lba] = pblk_ppa64_to_ppa32(pblk, ppa);
> 

Looks good. I'll pick up when rebased.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 10/20] lightnvm: pblk: rename ppaf* to addrf*
@ 2018-02-22  7:47     ` Matias Bjørling
  0 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:47 UTC (permalink / raw)


On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
> In preparation for 2.0 support in pblk, rename variables referring to
> the address format to addrf and reserve ppaf for the 1.2 path.
> 
> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
> ---
>   drivers/lightnvm/pblk-init.c  |  8 ++++----
>   drivers/lightnvm/pblk-sysfs.c |  4 ++--
>   drivers/lightnvm/pblk.h       | 16 ++++++++--------
>   3 files changed, 14 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
> index 6bf51ef8f516..56b4afc27add 100644
> --- a/drivers/lightnvm/pblk-init.c
> +++ b/drivers/lightnvm/pblk-init.c
> @@ -80,7 +80,7 @@ static size_t pblk_trans_map_size(struct pblk *pblk)
>   {
>   	int entry_size = 8;
>   
> -	if (pblk->ppaf_bitsize < 32)
> +	if (pblk->addrf_len < 32)
>   		entry_size = 4;
>   
>   	return entry_size * pblk->rl.nr_secs;
> @@ -198,7 +198,7 @@ static int pblk_set_addrf_12(struct nvm_geo *geo,
>   	return dst->blk_offset + src->blk_len;
>   }
>   
> -static int pblk_set_ppaf(struct pblk *pblk)
> +static int pblk_set_addrf(struct pblk *pblk)
>   {
>   	struct nvm_tgt_dev *dev = pblk->dev;
>   	struct nvm_geo *geo = &dev->geo;
> @@ -210,7 +210,7 @@ static int pblk_set_ppaf(struct pblk *pblk)
>   		return -EINVAL;
>   	}
>   
> -	pblk->ppaf_bitsize = pblk_set_addrf_12(geo, (void *)&pblk->ppaf);
> +	pblk->addrf_len = pblk_set_addrf_12(geo, (void *)&pblk->addrf);
>   
>   	return 0;
>   }
> @@ -319,7 +319,7 @@ static int pblk_core_init(struct pblk *pblk)
>   	if (!pblk->r_end_wq)
>   		goto free_bb_wq;
>   
> -	if (pblk_set_ppaf(pblk))
> +	if (pblk_set_addrf(pblk))
>   		goto free_r_end_wq;
>   
>   	if (pblk_rwb_init(pblk))
> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
> index 81288aa9162a..d3b50741b691 100644
> --- a/drivers/lightnvm/pblk-sysfs.c
> +++ b/drivers/lightnvm/pblk-sysfs.c
> @@ -117,12 +117,12 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
>   	struct nvm_addr_format_12 *geo_ppaf;
>   	ssize_t sz = 0;
>   
> -	ppaf = (struct nvm_addr_format_12 *)&pblk->ppaf;
> +	ppaf = (struct nvm_addr_format_12 *)&pblk->addrf;
>   	geo_ppaf = (struct nvm_addr_format_12 *)&geo->c.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",
> -			pblk->ppaf_bitsize,
> +			pblk->addrf_len,
>   			ppaf->ch_offset, ppaf->ch_len,
>   			ppaf->lun_offset, ppaf->lun_len,
>   			ppaf->blk_offset, ppaf->blk_len,
> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
> index 4f7a365436f1..46b29a492f74 100644
> --- a/drivers/lightnvm/pblk.h
> +++ b/drivers/lightnvm/pblk.h
> @@ -570,8 +570,8 @@ struct pblk {
>   	struct pblk_line_mgmt l_mg;		/* Line management */
>   	struct pblk_line_meta lm;		/* Line metadata */
>   
> -	struct nvm_addr_format ppaf;
> -	int ppaf_bitsize;
> +	struct nvm_addr_format addrf;
> +	int addrf_len;
>   
>   	struct pblk_rb rwb;
>   
> @@ -948,7 +948,7 @@ 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->ppaf;
> +				(struct nvm_addr_format_12 *)&pblk->addrf;
>   	struct ppa_addr ppa;
>   
>   	ppa.ppa = 0;
> @@ -966,7 +966,7 @@ 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->ppaf;
> +				(struct nvm_addr_format_12 *)&pblk->addrf;
>   	u64 paddr;
>   
>   	paddr = (u64)p.g.ch << ppaf->ch_offset;
> @@ -991,7 +991,7 @@ static inline struct ppa_addr pblk_ppa32_to_ppa64(struct pblk *pblk, u32 ppa32)
>   		ppa64.c.is_cached = 1;
>   	} else {
>   		struct nvm_addr_format_12 *ppaf =
> -				(struct nvm_addr_format_12 *)&pblk->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;
> @@ -1015,7 +1015,7 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
>   		ppa32 |= 1U << 31;
>   	} else {
>   		struct nvm_addr_format_12 *ppaf =
> -				(struct nvm_addr_format_12 *)&pblk->ppaf;
> +				(struct nvm_addr_format_12 *)&pblk->addrf;
>   
>   		ppa32 |= ppa64.g.ch << ppaf->ch_offset;
>   		ppa32 |= ppa64.g.lun << ppaf->lun_offset;
> @@ -1033,7 +1033,7 @@ static inline struct ppa_addr pblk_trans_map_get(struct pblk *pblk,
>   {
>   	struct ppa_addr ppa;
>   
> -	if (pblk->ppaf_bitsize < 32) {
> +	if (pblk->addrf_len < 32) {
>   		u32 *map = (u32 *)pblk->trans_map;
>   
>   		ppa = pblk_ppa32_to_ppa64(pblk, map[lba]);
> @@ -1049,7 +1049,7 @@ static inline struct ppa_addr pblk_trans_map_get(struct pblk *pblk,
>   static inline void pblk_trans_map_set(struct pblk *pblk, sector_t lba,
>   						struct ppa_addr ppa)
>   {
> -	if (pblk->ppaf_bitsize < 32) {
> +	if (pblk->addrf_len < 32) {
>   		u32 *map = (u32 *)pblk->trans_map;
>   
>   		map[lba] = pblk_ppa64_to_ppa32(pblk, ppa);
> 

Looks good. I'll pick up when rebased.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 11/20] lightnvm: pblk: check for supported version
  2018-02-21  9:26   ` Javier González
@ 2018-02-22  7:48     ` Matias Bjørling
  -1 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:48 UTC (permalink / raw)
  To: Javier González
  Cc: linux-block, linux-kernel, linux-nvme, Javier González

On 02/21/2018 10:26 AM, Javier González wrote:
> At this point, only 1.2 spec is supported, thus check for it. Also,
> since device-side L2P is only supported in the 1.2 spec, make sure to
> only check its value under 1.2.
> 
> Signed-off-by: Javier González <javier@cnexlabs.com>
> ---
>   drivers/lightnvm/pblk-init.c | 10 ++++++++--
>   1 file changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
> index 56b4afc27add..ec39800eea42 100644
> --- a/drivers/lightnvm/pblk-init.c
> +++ b/drivers/lightnvm/pblk-init.c
> @@ -990,9 +990,15 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>   	struct pblk *pblk;
>   	int ret;
>   
> -	if (dev->geo.c.dom & NVM_RSP_L2P) {
> +	if (geo->c.version != NVM_OCSSD_SPEC_12) {
> +		pr_err("pblk: OCSSD version not supported (%u)\n",
> +							geo->c.version);
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	if (geo->c.version == NVM_OCSSD_SPEC_12 && geo->c.dom & NVM_RSP_L2P) {
>   		pr_err("pblk: host-side L2P table not supported. (%x)\n",
> -							dev->geo.c.dom);
> +							geo->c.dom);
>   		return ERR_PTR(-EINVAL);
>   	}
>   
> 

Looks good to me. I'll pick up when rebased.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 11/20] lightnvm: pblk: check for supported version
@ 2018-02-22  7:48     ` Matias Bjørling
  0 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  7:48 UTC (permalink / raw)


On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
> At this point, only 1.2 spec is supported, thus check for it. Also,
> since device-side L2P is only supported in the 1.2 spec, make sure to
> only check its value under 1.2.
> 
> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
> ---
>   drivers/lightnvm/pblk-init.c | 10 ++++++++--
>   1 file changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
> index 56b4afc27add..ec39800eea42 100644
> --- a/drivers/lightnvm/pblk-init.c
> +++ b/drivers/lightnvm/pblk-init.c
> @@ -990,9 +990,15 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>   	struct pblk *pblk;
>   	int ret;
>   
> -	if (dev->geo.c.dom & NVM_RSP_L2P) {
> +	if (geo->c.version != NVM_OCSSD_SPEC_12) {
> +		pr_err("pblk: OCSSD version not supported (%u)\n",
> +							geo->c.version);
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	if (geo->c.version == NVM_OCSSD_SPEC_12 && geo->c.dom & NVM_RSP_L2P) {
>   		pr_err("pblk: host-side L2P table not supported. (%x)\n",
> -							dev->geo.c.dom);
> +							geo->c.dom);
>   		return ERR_PTR(-EINVAL);
>   	}
>   
> 

Looks good to me. I'll pick up when rebased.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 09/20] lightnvm: use generic identify structure
  2018-02-22  7:47     ` Matias Bjørling
@ 2018-02-22  7:49       ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-22  7:49 UTC (permalink / raw)
  To: Matias Bjørling; +Cc: linux-block, linux-kernel, linux-nvme

[-- Attachment #1: Type: text/plain, Size: 4262 bytes --]

> On 22 Feb 2018, at 08.47, Matias Bjørling <mb@lightnvm.io> wrote:
> 
> On 02/21/2018 10:26 AM, Javier González wrote:
>> Create a generic identify structure to collect the identify information
>> before knowing the spec. version. This forces different version paths to
>> cast the structure to their spec structure, thus making the code less
>> error prone and more maintainable.
>> Signed-off-by: Javier González <javier@cnexlabs.com>
>> ---
>>  drivers/nvme/host/lightnvm.c | 32 ++++++++++++++++++++------------
>>  1 file changed, 20 insertions(+), 12 deletions(-)
>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>> index 9c1f8225c4e1..70dc4740f0d3 100644
>> --- a/drivers/nvme/host/lightnvm.c
>> +++ b/drivers/nvme/host/lightnvm.c
>> @@ -170,6 +170,12 @@ struct nvme_nvm_id12 {
>>  	__u8			resv2[2880];
>>  } __packed;
>>  +/* Generic identification structure */
>> +struct nvme_nvm_id {
>> +	__u8			ver_id;
>> +	__u8			resv[4095];
>> +} __packed;
>> +
>>  struct nvme_nvm_bb_tbl {
>>  	__u8	tblid[4];
>>  	__le16	verid;
>> @@ -279,9 +285,10 @@ static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
>>  	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>>  }
>>  -static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>> +static int nvme_nvm_setup_12(struct nvme_nvm_id *gen_id,
>>  			     struct nvm_dev_geo *dev_geo)
>>  {
>> +	struct nvme_nvm_id12 *id = (struct nvme_nvm_id12 *)gen_id;
>>  	struct nvme_nvm_id12_grp *src;
>>  	int sec_per_pg, sec_per_pl, pg_per_blk;
>>  @@ -380,9 +387,11 @@ static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
>>  	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>>  }
>>  -static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>> +static int nvme_nvm_setup_20(struct nvme_nvm_id *gen_id,
>>  			     struct nvm_dev_geo *dev_geo)
>>  {
>> +	struct nvme_nvm_id20 *id = (struct nvme_nvm_id20 *)gen_id;
>> +
>>  	dev_geo->major_ver_id = id->mjr;
>>  	dev_geo->minor_ver_id = id->mnr;
>>  @@ -427,19 +436,19 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>>  static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>>  {
>>  	struct nvme_ns *ns = nvmdev->q->queuedata;
>> -	struct nvme_nvm_id12 *id;
>> +	struct nvme_nvm_id *nvme_nvm_id;
>>  	struct nvme_nvm_command c = {};
>>  	int ret;
>>    	c.identity.opcode = nvme_nvm_admin_identity;
>>  	c.identity.nsid = cpu_to_le32(ns->head->ns_id);
>>  -	id = kmalloc(sizeof(struct nvme_nvm_id12), GFP_KERNEL);
>> -	if (!id)
>> +	nvme_nvm_id = kmalloc(sizeof(struct nvme_nvm_id), GFP_KERNEL);
>> +	if (!nvme_nvm_id)
>>  		return -ENOMEM;
>>    	ret = nvme_submit_sync_cmd(ns->ctrl->admin_q, (struct nvme_command *)&c,
>> -				id, sizeof(struct nvme_nvm_id12));
>> +				nvme_nvm_id, sizeof(struct nvme_nvm_id));
>>  	if (ret) {
>>  		ret = -EIO;
>>  		goto out;
>> @@ -449,22 +458,21 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>>  	 * The 1.2 and 2.0 specifications share the first byte in their geometry
>>  	 * command to make it possible to know what version a device implements.
>>  	 */
>> -	switch (id->ver_id) {
>> +	switch (nvme_nvm_id->ver_id) {
>>  	case 1:
>> -		ret = nvme_nvm_setup_12(id, &nvmdev->dev_geo);
>> +		ret = nvme_nvm_setup_12(nvme_nvm_id, &nvmdev->dev_geo);
>>  		break;
>>  	case 2:
>> -		ret = nvme_nvm_setup_20((struct nvme_nvm_id20 *)id,
>> -							&nvmdev->dev_geo);
>> +		ret = nvme_nvm_setup_20(nvme_nvm_id, &nvmdev->dev_geo);
>>  		break;
>>  	default:
>>  		dev_err(ns->ctrl->device, "OCSSD revision not supported (%d)\n",
>> -							id->ver_id);
>> +							nvme_nvm_id->ver_id);
>>  		ret = -EINVAL;
>>  	}
>>    out:
>> -	kfree(id);
>> +	kfree(nvme_nvm_id);
>>  	return ret;
>>  }
>> 
> 
> Thanks for another way to represent it. I want to keep the original
> path. If we are going that down road, then one should maybe look into
> unifying the "three" data structures, and have the version as the base
> property and the others in each their sub data structure.

That's what this structure aims to do, since the version is shared. But
you call if you want to cast unrelated structures back an forth. I'll
revert it...

Javier

[-- Attachment #2: Message signed with OpenPGP --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 09/20] lightnvm: use generic identify structure
@ 2018-02-22  7:49       ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-22  7:49 UTC (permalink / raw)


> On 22 Feb 2018,@08.47, Matias Bj?rling <mb@lightnvm.io> wrote:
> 
> On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
>> Create a generic identify structure to collect the identify information
>> before knowing the spec. version. This forces different version paths to
>> cast the structure to their spec structure, thus making the code less
>> error prone and more maintainable.
>> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
>> ---
>>  drivers/nvme/host/lightnvm.c | 32 ++++++++++++++++++++------------
>>  1 file changed, 20 insertions(+), 12 deletions(-)
>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>> index 9c1f8225c4e1..70dc4740f0d3 100644
>> --- a/drivers/nvme/host/lightnvm.c
>> +++ b/drivers/nvme/host/lightnvm.c
>> @@ -170,6 +170,12 @@ struct nvme_nvm_id12 {
>>  	__u8			resv2[2880];
>>  } __packed;
>>  +/* Generic identification structure */
>> +struct nvme_nvm_id {
>> +	__u8			ver_id;
>> +	__u8			resv[4095];
>> +} __packed;
>> +
>>  struct nvme_nvm_bb_tbl {
>>  	__u8	tblid[4];
>>  	__le16	verid;
>> @@ -279,9 +285,10 @@ static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
>>  	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>>  }
>>  -static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>> +static int nvme_nvm_setup_12(struct nvme_nvm_id *gen_id,
>>  			     struct nvm_dev_geo *dev_geo)
>>  {
>> +	struct nvme_nvm_id12 *id = (struct nvme_nvm_id12 *)gen_id;
>>  	struct nvme_nvm_id12_grp *src;
>>  	int sec_per_pg, sec_per_pl, pg_per_blk;
>>  @@ -380,9 +387,11 @@ static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
>>  	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>>  }
>>  -static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>> +static int nvme_nvm_setup_20(struct nvme_nvm_id *gen_id,
>>  			     struct nvm_dev_geo *dev_geo)
>>  {
>> +	struct nvme_nvm_id20 *id = (struct nvme_nvm_id20 *)gen_id;
>> +
>>  	dev_geo->major_ver_id = id->mjr;
>>  	dev_geo->minor_ver_id = id->mnr;
>>  @@ -427,19 +436,19 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>>  static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>>  {
>>  	struct nvme_ns *ns = nvmdev->q->queuedata;
>> -	struct nvme_nvm_id12 *id;
>> +	struct nvme_nvm_id *nvme_nvm_id;
>>  	struct nvme_nvm_command c = {};
>>  	int ret;
>>    	c.identity.opcode = nvme_nvm_admin_identity;
>>  	c.identity.nsid = cpu_to_le32(ns->head->ns_id);
>>  -	id = kmalloc(sizeof(struct nvme_nvm_id12), GFP_KERNEL);
>> -	if (!id)
>> +	nvme_nvm_id = kmalloc(sizeof(struct nvme_nvm_id), GFP_KERNEL);
>> +	if (!nvme_nvm_id)
>>  		return -ENOMEM;
>>    	ret = nvme_submit_sync_cmd(ns->ctrl->admin_q, (struct nvme_command *)&c,
>> -				id, sizeof(struct nvme_nvm_id12));
>> +				nvme_nvm_id, sizeof(struct nvme_nvm_id));
>>  	if (ret) {
>>  		ret = -EIO;
>>  		goto out;
>> @@ -449,22 +458,21 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>>  	 * The 1.2 and 2.0 specifications share the first byte in their geometry
>>  	 * command to make it possible to know what version a device implements.
>>  	 */
>> -	switch (id->ver_id) {
>> +	switch (nvme_nvm_id->ver_id) {
>>  	case 1:
>> -		ret = nvme_nvm_setup_12(id, &nvmdev->dev_geo);
>> +		ret = nvme_nvm_setup_12(nvme_nvm_id, &nvmdev->dev_geo);
>>  		break;
>>  	case 2:
>> -		ret = nvme_nvm_setup_20((struct nvme_nvm_id20 *)id,
>> -							&nvmdev->dev_geo);
>> +		ret = nvme_nvm_setup_20(nvme_nvm_id, &nvmdev->dev_geo);
>>  		break;
>>  	default:
>>  		dev_err(ns->ctrl->device, "OCSSD revision not supported (%d)\n",
>> -							id->ver_id);
>> +							nvme_nvm_id->ver_id);
>>  		ret = -EINVAL;
>>  	}
>>    out:
>> -	kfree(id);
>> +	kfree(nvme_nvm_id);
>>  	return ret;
>>  }
>> 
> 
> Thanks for another way to represent it. I want to keep the original
> path. If we are going that down road, then one should maybe look into
> unifying the "three" data structures, and have the version as the base
> property and the others in each their sub data structure.

That's what this structure aims to do, since the version is shared. But
you call if you want to cast unrelated structures back an forth. I'll
revert it...

Javier
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: Message signed with OpenPGP
URL: <http://lists.infradead.org/pipermail/linux-nvme/attachments/20180222/ef438cb5/attachment.sig>

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 04/20] lightnvm: add minor version to generic geometry
  2018-02-22  7:34     ` Matias Bjørling
@ 2018-02-22  7:53       ` Javier González
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-22  7:53 UTC (permalink / raw)
  To: Matias Bjørling; +Cc: linux-block, linux-kernel, linux-nvme

[-- Attachment #1: Type: text/plain, Size: 5053 bytes --]

> On 22 Feb 2018, at 08.34, Matias Bjørling <mb@lightnvm.io> wrote:
> 
> On 02/21/2018 10:26 AM, Javier González wrote:
>> Separate the version between major and minor on the generic geometry.
>> Also, add a "subversion" entry to sysfs to expose the minor version
>> without breaking user space.
>> Signed-off-by: Javier González <javier@cnexlabs.com>
>> ---
>>  drivers/lightnvm/core.c      |  4 ++--
>>  drivers/nvme/host/lightnvm.c | 25 ++++++++++++++++++++-----
>>  include/linux/lightnvm.h     |  3 ++-
>>  3 files changed, 24 insertions(+), 8 deletions(-)
>> diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
>> index 42596afdf64c..dc9ec6baff45 100644
>> --- a/drivers/lightnvm/core.c
>> +++ b/drivers/lightnvm/core.c
>> @@ -897,8 +897,8 @@ static int nvm_init(struct nvm_dev *dev)
>>  		goto err;
>>  	}
>>  -	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
>> -				dev_geo->ver_id,
>> +	pr_debug("nvm: ver:%u.%u nvm_vendor:%x\n",
>> +				dev_geo->major_ver_id, dev_geo->minor_ver_id,
>>  				dev_geo->c.vmnt);
>>    	ret = nvm_core_init(dev);
>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>> index 598abba66f52..71b4ac57a668 100644
>> --- a/drivers/nvme/host/lightnvm.c
>> +++ b/drivers/nvme/host/lightnvm.c
>> @@ -296,7 +296,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>>  	}
>>    	/* 1.2 spec. only reports a single version id - unfold */
>> -	dev_geo->ver_id = id->ver_id;
>> +	dev_geo->major_ver_id = id->ver_id;
>> +	dev_geo->minor_ver_id = 2;
>>    	dev_geo->nr_chnls = src->num_ch;
>>  	dev_geo->nr_luns = src->num_lun;
>> @@ -377,7 +378,14 @@ static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
>>  static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>>  			     struct nvm_dev_geo *dev_geo)
>>  {
>> -	dev_geo->ver_id = id->mjr;
>> +	dev_geo->major_ver_id = id->mjr;
>> +	dev_geo->minor_ver_id = id->mnr;
>> +
>> +	if (!(dev_geo->major_ver_id == 2 && dev_geo->minor_ver_id == 0)) {
>> +		pr_err("nvm: OCSSD version not supported (v%d.%d)\n",
>> +				dev_geo->major_ver_id, dev_geo->minor_ver_id);
>> +		return -EINVAL;
>> +	}
>>    	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
>>  	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
>> @@ -913,7 +921,11 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>  	attr = &dattr->attr;
>>    	if (strcmp(attr->name, "version") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n",
>> +						dev_geo->major_ver_id);
>> +	} else if (strcmp(attr->name, "subversion") == 0) {
>> +		return scnprintf(page, PAGE_SIZE, "%u\n",
>> +						dev_geo->minor_ver_id);
>>  	} else if (strcmp(attr->name, "media_capabilities") == 0) {
>>  		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
>>  	} else if (strcmp(attr->name, "read_typ") == 0) {
>> @@ -1055,6 +1067,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>>    /* general attributes */
>>  static NVM_DEV_ATTR_RO(version);
>> +static NVM_DEV_ATTR_RO(subversion);
>>  static NVM_DEV_ATTR_RO(media_capabilities);
>>    static NVM_DEV_ATTR_RO(read_typ);
>> @@ -1085,6 +1098,7 @@ static NVM_DEV_ATTR_12_RO(max_phys_secs);
>>    static struct attribute *nvm_dev_attrs_12[] = {
>>  	&dev_attr_version.attr,
>> +	&dev_attr_subversion.attr,
>>  	&dev_attr_media_capabilities.attr,
>>    	&dev_attr_vendor_opcode.attr,
>> @@ -1134,6 +1148,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
>>    static struct attribute *nvm_dev_attrs_20[] = {
>>  	&dev_attr_version.attr,
>> +	&dev_attr_subversion.attr,
>>  	&dev_attr_media_capabilities.attr,
>>    	&dev_attr_groups.attr,
>> @@ -1167,7 +1182,7 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>>  	if (!ndev)
>>  		return -EINVAL;
>>  -	switch (dev_geo->ver_id) {
>> +	switch (dev_geo->major_ver_id) {
>>  	case 1:
>>  		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
>>  					&nvm_dev_attr_group_12);
>> @@ -1184,7 +1199,7 @@ void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
>>  	struct nvm_dev *ndev = ns->ndev;
>>  	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>  -	switch (dev_geo->ver_id) {
>> +	switch (dev_geo->major_ver_id) {
>>  	case 1:
>>  		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
>>  					&nvm_dev_attr_group_12);
>> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
>> index 18e3751b1632..5af0b8837095 100644
>> --- a/include/linux/lightnvm.h
>> +++ b/include/linux/lightnvm.h
>> @@ -242,7 +242,8 @@ struct nvm_common_geo {
>>  /* Device identified geometry */
>>  struct nvm_dev_geo {
>>  	/* device reported version */
>> -	u8	ver_id;
>> +	u8	major_ver_id;
>> +	u8	minor_ver_id;
>>    	/* full device geometry */
>>  	u16	nr_chnls;
> 
> Looks fairly good to me. Did you consider putting in the major and
> minor version id into the version attribute? e.g., keep 1 as 1, and
> have version 2 be exposed as 2.0?
> 

Yes, we can do that. I'll do the changes for the next version.


[-- Attachment #2: Message signed with OpenPGP --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 04/20] lightnvm: add minor version to generic geometry
@ 2018-02-22  7:53       ` Javier González
  0 siblings, 0 replies; 99+ messages in thread
From: Javier González @ 2018-02-22  7:53 UTC (permalink / raw)


> On 22 Feb 2018,@08.34, Matias Bj?rling <mb@lightnvm.io> wrote:
> 
> On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
>> Separate the version between major and minor on the generic geometry.
>> Also, add a "subversion" entry to sysfs to expose the minor version
>> without breaking user space.
>> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
>> ---
>>  drivers/lightnvm/core.c      |  4 ++--
>>  drivers/nvme/host/lightnvm.c | 25 ++++++++++++++++++++-----
>>  include/linux/lightnvm.h     |  3 ++-
>>  3 files changed, 24 insertions(+), 8 deletions(-)
>> diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
>> index 42596afdf64c..dc9ec6baff45 100644
>> --- a/drivers/lightnvm/core.c
>> +++ b/drivers/lightnvm/core.c
>> @@ -897,8 +897,8 @@ static int nvm_init(struct nvm_dev *dev)
>>  		goto err;
>>  	}
>>  -	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
>> -				dev_geo->ver_id,
>> +	pr_debug("nvm: ver:%u.%u nvm_vendor:%x\n",
>> +				dev_geo->major_ver_id, dev_geo->minor_ver_id,
>>  				dev_geo->c.vmnt);
>>    	ret = nvm_core_init(dev);
>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>> index 598abba66f52..71b4ac57a668 100644
>> --- a/drivers/nvme/host/lightnvm.c
>> +++ b/drivers/nvme/host/lightnvm.c
>> @@ -296,7 +296,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>>  	}
>>    	/* 1.2 spec. only reports a single version id - unfold */
>> -	dev_geo->ver_id = id->ver_id;
>> +	dev_geo->major_ver_id = id->ver_id;
>> +	dev_geo->minor_ver_id = 2;
>>    	dev_geo->nr_chnls = src->num_ch;
>>  	dev_geo->nr_luns = src->num_lun;
>> @@ -377,7 +378,14 @@ static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
>>  static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>>  			     struct nvm_dev_geo *dev_geo)
>>  {
>> -	dev_geo->ver_id = id->mjr;
>> +	dev_geo->major_ver_id = id->mjr;
>> +	dev_geo->minor_ver_id = id->mnr;
>> +
>> +	if (!(dev_geo->major_ver_id == 2 && dev_geo->minor_ver_id == 0)) {
>> +		pr_err("nvm: OCSSD version not supported (v%d.%d)\n",
>> +				dev_geo->major_ver_id, dev_geo->minor_ver_id);
>> +		return -EINVAL;
>> +	}
>>    	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
>>  	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
>> @@ -913,7 +921,11 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>  	attr = &dattr->attr;
>>    	if (strcmp(attr->name, "version") == 0) {
>> -		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>> +		return scnprintf(page, PAGE_SIZE, "%u\n",
>> +						dev_geo->major_ver_id);
>> +	} else if (strcmp(attr->name, "subversion") == 0) {
>> +		return scnprintf(page, PAGE_SIZE, "%u\n",
>> +						dev_geo->minor_ver_id);
>>  	} else if (strcmp(attr->name, "media_capabilities") == 0) {
>>  		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
>>  	} else if (strcmp(attr->name, "read_typ") == 0) {
>> @@ -1055,6 +1067,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>>    /* general attributes */
>>  static NVM_DEV_ATTR_RO(version);
>> +static NVM_DEV_ATTR_RO(subversion);
>>  static NVM_DEV_ATTR_RO(media_capabilities);
>>    static NVM_DEV_ATTR_RO(read_typ);
>> @@ -1085,6 +1098,7 @@ static NVM_DEV_ATTR_12_RO(max_phys_secs);
>>    static struct attribute *nvm_dev_attrs_12[] = {
>>  	&dev_attr_version.attr,
>> +	&dev_attr_subversion.attr,
>>  	&dev_attr_media_capabilities.attr,
>>    	&dev_attr_vendor_opcode.attr,
>> @@ -1134,6 +1148,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
>>    static struct attribute *nvm_dev_attrs_20[] = {
>>  	&dev_attr_version.attr,
>> +	&dev_attr_subversion.attr,
>>  	&dev_attr_media_capabilities.attr,
>>    	&dev_attr_groups.attr,
>> @@ -1167,7 +1182,7 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>>  	if (!ndev)
>>  		return -EINVAL;
>>  -	switch (dev_geo->ver_id) {
>> +	switch (dev_geo->major_ver_id) {
>>  	case 1:
>>  		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
>>  					&nvm_dev_attr_group_12);
>> @@ -1184,7 +1199,7 @@ void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
>>  	struct nvm_dev *ndev = ns->ndev;
>>  	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>  -	switch (dev_geo->ver_id) {
>> +	switch (dev_geo->major_ver_id) {
>>  	case 1:
>>  		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
>>  					&nvm_dev_attr_group_12);
>> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
>> index 18e3751b1632..5af0b8837095 100644
>> --- a/include/linux/lightnvm.h
>> +++ b/include/linux/lightnvm.h
>> @@ -242,7 +242,8 @@ struct nvm_common_geo {
>>  /* Device identified geometry */
>>  struct nvm_dev_geo {
>>  	/* device reported version */
>> -	u8	ver_id;
>> +	u8	major_ver_id;
>> +	u8	minor_ver_id;
>>    	/* full device geometry */
>>  	u16	nr_chnls;
> 
> Looks fairly good to me. Did you consider putting in the major and
> minor version id into the version attribute? e.g., keep 1 as 1, and
> have version 2 be exposed as 2.0?
> 

Yes, we can do that. I'll do the changes for the next version.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: Message signed with OpenPGP
URL: <http://lists.infradead.org/pipermail/linux-nvme/attachments/20180222/49b4ec3f/attachment.sig>

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 08/20] lightnvm: complete geo structure with maxoc*
  2018-02-22  7:45     ` Matias Bjørling
@ 2018-02-22  7:55       ` Javier Gonzalez
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier Gonzalez @ 2018-02-22  7:55 UTC (permalink / raw)
  To: Matias Bjørling; +Cc: linux-block, linux-kernel, linux-nvme

[-- Attachment #1: Type: text/plain, Size: 1232 bytes --]

> On 22 Feb 2018, at 08.45, Matias Bjørling <mb@lightnvm.io> wrote:
> 
> On 02/21/2018 10:26 AM, Javier González wrote:
>> Complete the generic geometry structure with the maxoc and maxocpu
>> felds, present in the 2.0 spec.
>> Signed-off-by: Javier González <javier@cnexlabs.com>
>> ---
>>  drivers/nvme/host/lightnvm.c | 4 ++++
>>  include/linux/lightnvm.h     | 2 ++
>>  2 files changed, 6 insertions(+)
>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>> index cca32da05316..9c1f8225c4e1 100644
>> --- a/drivers/nvme/host/lightnvm.c
>> +++ b/drivers/nvme/host/lightnvm.c
>> @@ -318,6 +318,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>>  	dev_geo->c.ws_min = sec_per_pg;
>>  	dev_geo->c.ws_opt = sec_per_pg;
>>  	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
>> +	dev_geo->c.maxoc = dev_geo->all_luns;	/* default to 1 chunk per LUN */
>> +	dev_geo->c.maxocpu = 1;			/* default to 1 chunk per LUN */
> 
> One can't assume that it is 1 open chunk per lun. If you need this for specific hardware, make a quirk for it.
> 

Which default you want for 1.2 if not specified then? I use 1 because it
has been the implicit default until now.

Javier

[-- Attachment #2: Message signed with OpenPGP --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 08/20] lightnvm: complete geo structure with maxoc*
@ 2018-02-22  7:55       ` Javier Gonzalez
  0 siblings, 0 replies; 99+ messages in thread
From: Javier Gonzalez @ 2018-02-22  7:55 UTC (permalink / raw)


> On 22 Feb 2018,@08.45, Matias Bj?rling <mb@lightnvm.io> wrote:
> 
> On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
>> Complete the generic geometry structure with the maxoc and maxocpu
>> felds, present in the 2.0 spec.
>> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
>> ---
>>  drivers/nvme/host/lightnvm.c | 4 ++++
>>  include/linux/lightnvm.h     | 2 ++
>>  2 files changed, 6 insertions(+)
>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>> index cca32da05316..9c1f8225c4e1 100644
>> --- a/drivers/nvme/host/lightnvm.c
>> +++ b/drivers/nvme/host/lightnvm.c
>> @@ -318,6 +318,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>>  	dev_geo->c.ws_min = sec_per_pg;
>>  	dev_geo->c.ws_opt = sec_per_pg;
>>  	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
>> +	dev_geo->c.maxoc = dev_geo->all_luns;	/* default to 1 chunk per LUN */
>> +	dev_geo->c.maxocpu = 1;			/* default to 1 chunk per LUN */
> 
> One can't assume that it is 1 open chunk per lun. If you need this for specific hardware, make a quirk for it.
> 

Which default you want for 1.2 if not specified then? I use 1 because it
has been the implicit default until now.

Javier
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: Message signed with OpenPGP
URL: <http://lists.infradead.org/pipermail/linux-nvme/attachments/20180222/9b10ae86/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 13/20] lightnvm: add support for 2.0 address format
  2018-02-21  9:26   ` Javier González
@ 2018-02-22  9:24     ` Matias Bjørling
  -1 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  9:24 UTC (permalink / raw)
  To: Javier González
  Cc: linux-block, linux-kernel, linux-nvme, Javier González

On 02/21/2018 10:26 AM, Javier González wrote:
> Add support for 2.0 address format. Also, align address bits for 1.2 and
> 2.0 to be able to operate on channel and luns without requiring a format
> conversion. Use a generic address format for this purpose.
> 
> Signed-off-by: Javier González <javier@cnexlabs.com>
> ---
>   drivers/lightnvm/core.c  |  20 ++++-----
>   include/linux/lightnvm.h | 105 ++++++++++++++++++++++++++++++++++-------------
>   2 files changed, 86 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
> index f70a907223e2..baec963b2c96 100644
> --- a/drivers/lightnvm/core.c
> +++ b/drivers/lightnvm/core.c
> @@ -196,8 +196,8 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>   
>   		for (j = 0; j < luns_in_chnl; j++) {
>   			luns[lunid].ppa = 0;
> -			luns[lunid].g.ch = i;
> -			luns[lunid++].g.lun = j;
> +			luns[lunid].a.ch = i;
> +			luns[lunid++].a.lun = j;
>   
>   			lun_offs[j] = blun;
>   			lun_roffs[j + blun] = blun;
> @@ -563,22 +563,22 @@ static void nvm_unregister_map(struct nvm_dev *dev)
>   static void nvm_map_to_dev(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
>   {
>   	struct nvm_dev_map *dev_map = tgt_dev->map;
> -	struct nvm_ch_map *ch_map = &dev_map->chnls[p->g.ch];
> -	int lun_off = ch_map->lun_offs[p->g.lun];
> +	struct nvm_ch_map *ch_map = &dev_map->chnls[p->a.ch];
> +	int lun_off = ch_map->lun_offs[p->a.lun];
>   
> -	p->g.ch += ch_map->ch_off;
> -	p->g.lun += lun_off;
> +	p->a.ch += ch_map->ch_off;
> +	p->a.lun += lun_off;
>   }
>   
>   static void nvm_map_to_tgt(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
>   {
>   	struct nvm_dev *dev = tgt_dev->parent;
>   	struct nvm_dev_map *dev_rmap = dev->rmap;
> -	struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[p->g.ch];
> -	int lun_roff = ch_rmap->lun_offs[p->g.lun];
> +	struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[p->a.ch];
> +	int lun_roff = ch_rmap->lun_offs[p->a.lun];
>   
> -	p->g.ch -= ch_rmap->ch_off;
> -	p->g.lun -= lun_roff;
> +	p->a.ch -= ch_rmap->ch_off;
> +	p->a.lun -= lun_roff;
>   }
>   
>   static void nvm_ppa_tgt_to_dev(struct nvm_tgt_dev *tgt_dev,
> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
> index e1c4292ea33d..cd310bf06051 100644
> --- a/include/linux/lightnvm.h
> +++ b/include/linux/lightnvm.h
> @@ -16,12 +16,22 @@ enum {
>   	NVM_IOTYPE_GC = 1,
>   };
>   
> -#define NVM_BLK_BITS (16)
> -#define NVM_PG_BITS  (16)
> -#define NVM_SEC_BITS (8)
> -#define NVM_PL_BITS  (8)
> -#define NVM_LUN_BITS (8)
> -#define NVM_CH_BITS  (7)
> +/* common format */
> +#define NVM_GEN_CH_BITS  (8)
> +#define NVM_GEN_LUN_BITS (8)
> +#define NVM_GEN_RESERVED (48)
> +
> +/* 1.2 format */
> +#define NVM_12_BLK_BITS (16)
> +#define NVM_12_PG_BITS  (16)
> +#define NVM_12_PL_BITS  (4)
> +#define NVM_12_SEC_BITS (4)
> +#define NVM_12_RESERVED (8)
> +
> +/* 2.0 format */
> +#define NVM_20_CHK_BITS (16)
> +#define NVM_20_SEC_BITS (24)
> +#define NVM_20_RESERVED (8)
>   
>   enum {
>   	NVM_OCSSD_SPEC_12 = 12,
> @@ -31,16 +41,33 @@ enum {
>   struct ppa_addr {
>   	/* Generic structure for all addresses */
>   	union {
> +		/* generic device format */
>   		struct {
> -			u64 blk		: NVM_BLK_BITS;
> -			u64 pg		: NVM_PG_BITS;
> -			u64 sec		: NVM_SEC_BITS;
> -			u64 pl		: NVM_PL_BITS;
> -			u64 lun		: NVM_LUN_BITS;
> -			u64 ch		: NVM_CH_BITS;
> -			u64 reserved	: 1;
> +			u64 ch		: NVM_GEN_CH_BITS;
> +			u64 lun		: NVM_GEN_LUN_BITS;
> +			u64 reserved	: NVM_GEN_RESERVED;
> +		} a;
> +
> +		/* 1.2 device format */
> +		struct {
> +			u64 ch		: NVM_GEN_CH_BITS;
> +			u64 lun		: NVM_GEN_LUN_BITS;
> +			u64 blk		: NVM_12_BLK_BITS;
> +			u64 pg		: NVM_12_PG_BITS;
> +			u64 pl		: NVM_12_PL_BITS;
> +			u64 sec		: NVM_12_SEC_BITS;
> +			u64 reserved	: NVM_12_RESERVED;
>   		} g;
>   
> +		/* 2.0 device format */
> +		struct {
> +			u64 ch		: NVM_GEN_CH_BITS;
> +			u64 lun		: NVM_GEN_LUN_BITS;
> +			u64 chk		: NVM_20_CHK_BITS;
> +			u64 sec		: NVM_20_SEC_BITS;
> +			u64 reserved	: NVM_20_RESERVED;
> +		} m;
> +
>   		struct {
>   			u64 line	: 63;
>   			u64 is_cached	: 1;
> @@ -392,16 +419,26 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
>   						  struct ppa_addr r)
>   {
>   	struct nvm_geo *geo = &tgt_dev->geo;
> -	struct nvm_addr_format_12 *ppaf =
> -				(struct nvm_addr_format_12 *)&geo->c.addrf;
>   	struct ppa_addr l;
>   
> -	l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
> -	l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
> -	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
> -	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
> -	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
> -	l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
> +	if (geo->c.version == NVM_OCSSD_SPEC_12) {
> +		struct nvm_addr_format_12 *ppaf =
> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
> +
> +		l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
> +		l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
> +		l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
> +		l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
> +		l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
> +		l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
> +	} else {
> +		struct nvm_addr_format *lbaf = &geo->c.addrf;
> +
> +		l.ppa = ((u64)r.m.ch) << lbaf->ch_offset;
> +		l.ppa |= ((u64)r.m.lun) << lbaf->lun_offset;
> +		l.ppa |= ((u64)r.m.chk) << lbaf->chk_offset;
> +		l.ppa |= ((u64)r.m.sec) << lbaf->sec_offset;
> +	}
>   
>   	return l;
>   }
> @@ -410,18 +447,28 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
>   						  struct ppa_addr r)
>   {
>   	struct nvm_geo *geo = &tgt_dev->geo;
> -	struct nvm_addr_format_12 *ppaf =
> -				(struct nvm_addr_format_12 *)&geo->c.addrf;
>   	struct ppa_addr l;
>   
>   	l.ppa = 0;
>   
> -	l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
> -	l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
> -	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
> -	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
> -	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
> -	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
> +	if (geo->c.version == NVM_OCSSD_SPEC_12) {
> +		struct nvm_addr_format_12 *ppaf =
> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
> +
> +		l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
> +		l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
> +		l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
> +		l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
> +		l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
> +		l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
> +	} else {
> +		struct nvm_addr_format *lbaf = &geo->c.addrf;
> +
> +		l.m.ch = (r.ppa & lbaf->ch_mask) >> lbaf->ch_offset;
> +		l.m.lun = (r.ppa & lbaf->lun_mask) >> lbaf->lun_offset;
> +		l.m.chk = (r.ppa & lbaf->chk_mask) >> lbaf->chk_offset;
> +		l.m.sec = (r.ppa & lbaf->sec_mask) >> lbaf->sec_offset;
> +	}
>   
>   	return l;
>   }
> 

Looks good to me.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 13/20] lightnvm: add support for 2.0 address format
@ 2018-02-22  9:24     ` Matias Bjørling
  0 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  9:24 UTC (permalink / raw)


On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
> Add support for 2.0 address format. Also, align address bits for 1.2 and
> 2.0 to be able to operate on channel and luns without requiring a format
> conversion. Use a generic address format for this purpose.
> 
> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
> ---
>   drivers/lightnvm/core.c  |  20 ++++-----
>   include/linux/lightnvm.h | 105 ++++++++++++++++++++++++++++++++++-------------
>   2 files changed, 86 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
> index f70a907223e2..baec963b2c96 100644
> --- a/drivers/lightnvm/core.c
> +++ b/drivers/lightnvm/core.c
> @@ -196,8 +196,8 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>   
>   		for (j = 0; j < luns_in_chnl; j++) {
>   			luns[lunid].ppa = 0;
> -			luns[lunid].g.ch = i;
> -			luns[lunid++].g.lun = j;
> +			luns[lunid].a.ch = i;
> +			luns[lunid++].a.lun = j;
>   
>   			lun_offs[j] = blun;
>   			lun_roffs[j + blun] = blun;
> @@ -563,22 +563,22 @@ static void nvm_unregister_map(struct nvm_dev *dev)
>   static void nvm_map_to_dev(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
>   {
>   	struct nvm_dev_map *dev_map = tgt_dev->map;
> -	struct nvm_ch_map *ch_map = &dev_map->chnls[p->g.ch];
> -	int lun_off = ch_map->lun_offs[p->g.lun];
> +	struct nvm_ch_map *ch_map = &dev_map->chnls[p->a.ch];
> +	int lun_off = ch_map->lun_offs[p->a.lun];
>   
> -	p->g.ch += ch_map->ch_off;
> -	p->g.lun += lun_off;
> +	p->a.ch += ch_map->ch_off;
> +	p->a.lun += lun_off;
>   }
>   
>   static void nvm_map_to_tgt(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
>   {
>   	struct nvm_dev *dev = tgt_dev->parent;
>   	struct nvm_dev_map *dev_rmap = dev->rmap;
> -	struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[p->g.ch];
> -	int lun_roff = ch_rmap->lun_offs[p->g.lun];
> +	struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[p->a.ch];
> +	int lun_roff = ch_rmap->lun_offs[p->a.lun];
>   
> -	p->g.ch -= ch_rmap->ch_off;
> -	p->g.lun -= lun_roff;
> +	p->a.ch -= ch_rmap->ch_off;
> +	p->a.lun -= lun_roff;
>   }
>   
>   static void nvm_ppa_tgt_to_dev(struct nvm_tgt_dev *tgt_dev,
> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
> index e1c4292ea33d..cd310bf06051 100644
> --- a/include/linux/lightnvm.h
> +++ b/include/linux/lightnvm.h
> @@ -16,12 +16,22 @@ enum {
>   	NVM_IOTYPE_GC = 1,
>   };
>   
> -#define NVM_BLK_BITS (16)
> -#define NVM_PG_BITS  (16)
> -#define NVM_SEC_BITS (8)
> -#define NVM_PL_BITS  (8)
> -#define NVM_LUN_BITS (8)
> -#define NVM_CH_BITS  (7)
> +/* common format */
> +#define NVM_GEN_CH_BITS  (8)
> +#define NVM_GEN_LUN_BITS (8)
> +#define NVM_GEN_RESERVED (48)
> +
> +/* 1.2 format */
> +#define NVM_12_BLK_BITS (16)
> +#define NVM_12_PG_BITS  (16)
> +#define NVM_12_PL_BITS  (4)
> +#define NVM_12_SEC_BITS (4)
> +#define NVM_12_RESERVED (8)
> +
> +/* 2.0 format */
> +#define NVM_20_CHK_BITS (16)
> +#define NVM_20_SEC_BITS (24)
> +#define NVM_20_RESERVED (8)
>   
>   enum {
>   	NVM_OCSSD_SPEC_12 = 12,
> @@ -31,16 +41,33 @@ enum {
>   struct ppa_addr {
>   	/* Generic structure for all addresses */
>   	union {
> +		/* generic device format */
>   		struct {
> -			u64 blk		: NVM_BLK_BITS;
> -			u64 pg		: NVM_PG_BITS;
> -			u64 sec		: NVM_SEC_BITS;
> -			u64 pl		: NVM_PL_BITS;
> -			u64 lun		: NVM_LUN_BITS;
> -			u64 ch		: NVM_CH_BITS;
> -			u64 reserved	: 1;
> +			u64 ch		: NVM_GEN_CH_BITS;
> +			u64 lun		: NVM_GEN_LUN_BITS;
> +			u64 reserved	: NVM_GEN_RESERVED;
> +		} a;
> +
> +		/* 1.2 device format */
> +		struct {
> +			u64 ch		: NVM_GEN_CH_BITS;
> +			u64 lun		: NVM_GEN_LUN_BITS;
> +			u64 blk		: NVM_12_BLK_BITS;
> +			u64 pg		: NVM_12_PG_BITS;
> +			u64 pl		: NVM_12_PL_BITS;
> +			u64 sec		: NVM_12_SEC_BITS;
> +			u64 reserved	: NVM_12_RESERVED;
>   		} g;
>   
> +		/* 2.0 device format */
> +		struct {
> +			u64 ch		: NVM_GEN_CH_BITS;
> +			u64 lun		: NVM_GEN_LUN_BITS;
> +			u64 chk		: NVM_20_CHK_BITS;
> +			u64 sec		: NVM_20_SEC_BITS;
> +			u64 reserved	: NVM_20_RESERVED;
> +		} m;
> +
>   		struct {
>   			u64 line	: 63;
>   			u64 is_cached	: 1;
> @@ -392,16 +419,26 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
>   						  struct ppa_addr r)
>   {
>   	struct nvm_geo *geo = &tgt_dev->geo;
> -	struct nvm_addr_format_12 *ppaf =
> -				(struct nvm_addr_format_12 *)&geo->c.addrf;
>   	struct ppa_addr l;
>   
> -	l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
> -	l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
> -	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
> -	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
> -	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
> -	l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
> +	if (geo->c.version == NVM_OCSSD_SPEC_12) {
> +		struct nvm_addr_format_12 *ppaf =
> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
> +
> +		l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
> +		l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
> +		l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
> +		l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
> +		l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
> +		l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
> +	} else {
> +		struct nvm_addr_format *lbaf = &geo->c.addrf;
> +
> +		l.ppa = ((u64)r.m.ch) << lbaf->ch_offset;
> +		l.ppa |= ((u64)r.m.lun) << lbaf->lun_offset;
> +		l.ppa |= ((u64)r.m.chk) << lbaf->chk_offset;
> +		l.ppa |= ((u64)r.m.sec) << lbaf->sec_offset;
> +	}
>   
>   	return l;
>   }
> @@ -410,18 +447,28 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
>   						  struct ppa_addr r)
>   {
>   	struct nvm_geo *geo = &tgt_dev->geo;
> -	struct nvm_addr_format_12 *ppaf =
> -				(struct nvm_addr_format_12 *)&geo->c.addrf;
>   	struct ppa_addr l;
>   
>   	l.ppa = 0;
>   
> -	l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
> -	l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
> -	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
> -	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
> -	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
> -	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
> +	if (geo->c.version == NVM_OCSSD_SPEC_12) {
> +		struct nvm_addr_format_12 *ppaf =
> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
> +
> +		l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
> +		l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
> +		l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
> +		l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
> +		l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
> +		l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
> +	} else {
> +		struct nvm_addr_format *lbaf = &geo->c.addrf;
> +
> +		l.m.ch = (r.ppa & lbaf->ch_mask) >> lbaf->ch_offset;
> +		l.m.lun = (r.ppa & lbaf->lun_mask) >> lbaf->lun_offset;
> +		l.m.chk = (r.ppa & lbaf->chk_mask) >> lbaf->chk_offset;
> +		l.m.sec = (r.ppa & lbaf->sec_mask) >> lbaf->sec_offset;
> +	}
>   
>   	return l;
>   }
> 

Looks good to me.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 03/20] lightnvm: fix capabilities for 2.0 sysfs
  2018-02-22  7:47       ` Javier Gonzalez
@ 2018-02-22  9:39         ` Matias Bjørling
  -1 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  9:39 UTC (permalink / raw)
  To: Javier Gonzalez; +Cc: linux-block, linux-kernel, linux-nvme

On 02/22/2018 08:47 AM, Javier Gonzalez wrote:
>> On 22 Feb 2018, at 08.28, Matias Bjørling <mb@lightnvm.io> wrote:
>>
>> On 02/21/2018 10:26 AM, Javier González wrote:
>>> Both 1.2 and 2.0 specs define a field for media and controller
>>> capabilities. Also, 1.2 defines a separate field dedicated to device
>>> capabilities.
>>> In 2.0 sysfs, this values have been mixed. Revert them to the right
>>> value.
>>> Signed-off-by: Javier González <javier@cnexlabs.com>
>>> ---
>>>   drivers/nvme/host/lightnvm.c | 18 +++++++++---------
>>>   1 file changed, 9 insertions(+), 9 deletions(-)
>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>> index 969bb874850c..598abba66f52 100644
>>> --- a/drivers/nvme/host/lightnvm.c
>>> +++ b/drivers/nvme/host/lightnvm.c
>>> @@ -914,8 +914,8 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>>     	if (strcmp(attr->name, "version") == 0) {
>>>   		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>>> -	} else if (strcmp(attr->name, "capabilities") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
>>> +	} else if (strcmp(attr->name, "media_capabilities") == 0) {
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
>>>   	} else if (strcmp(attr->name, "read_typ") == 0) {
>>>   		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>>>   	} else if (strcmp(attr->name, "read_max") == 0) {
>>> @@ -993,8 +993,8 @@ static ssize_t nvm_dev_attr_show_12(struct device *dev,
>>>   		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>>   	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
>>>   		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
>>> -	} else if (strcmp(attr->name, "media_capabilities") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
>>> +	} else if (strcmp(attr->name, "capabilities") == 0) {
>>> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.cap);
>>>   	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
>>>   		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>>>   	} else {
>>> @@ -1055,7 +1055,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>>>     /* general attributes */
>>>   static NVM_DEV_ATTR_RO(version);
>>> -static NVM_DEV_ATTR_RO(capabilities);
>>> +static NVM_DEV_ATTR_RO(media_capabilities);
>>>     static NVM_DEV_ATTR_RO(read_typ);
>>>   static NVM_DEV_ATTR_RO(read_max);
>>> @@ -1080,12 +1080,12 @@ static NVM_DEV_ATTR_12_RO(prog_max);
>>>   static NVM_DEV_ATTR_12_RO(erase_typ);
>>>   static NVM_DEV_ATTR_12_RO(erase_max);
>>>   static NVM_DEV_ATTR_12_RO(multiplane_modes);
>>> -static NVM_DEV_ATTR_12_RO(media_capabilities);
>>> +static NVM_DEV_ATTR_12_RO(capabilities);
>>>   static NVM_DEV_ATTR_12_RO(max_phys_secs);
>>>     static struct attribute *nvm_dev_attrs_12[] = {
>>>   	&dev_attr_version.attr,
>>> -	&dev_attr_capabilities.attr,
>>> +	&dev_attr_media_capabilities.attr,
>>>     	&dev_attr_vendor_opcode.attr,
>>>   	&dev_attr_device_mode.attr,
>>> @@ -1108,7 +1108,7 @@ static struct attribute *nvm_dev_attrs_12[] = {
>>>   	&dev_attr_erase_typ.attr,
>>>   	&dev_attr_erase_max.attr,
>>>   	&dev_attr_multiplane_modes.attr,
>>> -	&dev_attr_media_capabilities.attr,
>>> +	&dev_attr_capabilities.attr,
>>>   	&dev_attr_max_phys_secs.attr,
>>>     	NULL,
>>> @@ -1134,7 +1134,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
>>>     static struct attribute *nvm_dev_attrs_20[] = {
>>>   	&dev_attr_version.attr,
>>> -	&dev_attr_capabilities.attr,
>>> +	&dev_attr_media_capabilities.attr,
>>>     	&dev_attr_groups.attr,
>>>   	&dev_attr_punits.attr,
>>
>> With the mccap changes, it should make sense to keep the capabilities
>> as is.
> 
> The change adds mccap, but sysfs points to cap, which is wrong. This
> patch is needed. Otherwise, we change the name of mccap to cap, which
> is _very_ confusing to people familiar to both specs. We can change
> the name of mccap to cap in a future spec revision.
> 
> Javier
> 

Think of the sysfs capabilities as an abstract value that defines 
generic capabilities. It is not directly tied to either 1.2 or 2.0.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 03/20] lightnvm: fix capabilities for 2.0 sysfs
@ 2018-02-22  9:39         ` Matias Bjørling
  0 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  9:39 UTC (permalink / raw)


On 02/22/2018 08:47 AM, Javier Gonzalez wrote:
>> On 22 Feb 2018,@08.28, Matias Bj?rling <mb@lightnvm.io> wrote:
>>
>> On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
>>> Both 1.2 and 2.0 specs define a field for media and controller
>>> capabilities. Also, 1.2 defines a separate field dedicated to device
>>> capabilities.
>>> In 2.0 sysfs, this values have been mixed. Revert them to the right
>>> value.
>>> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
>>> ---
>>>   drivers/nvme/host/lightnvm.c | 18 +++++++++---------
>>>   1 file changed, 9 insertions(+), 9 deletions(-)
>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>> index 969bb874850c..598abba66f52 100644
>>> --- a/drivers/nvme/host/lightnvm.c
>>> +++ b/drivers/nvme/host/lightnvm.c
>>> @@ -914,8 +914,8 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>>     	if (strcmp(attr->name, "version") == 0) {
>>>   		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>>> -	} else if (strcmp(attr->name, "capabilities") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
>>> +	} else if (strcmp(attr->name, "media_capabilities") == 0) {
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
>>>   	} else if (strcmp(attr->name, "read_typ") == 0) {
>>>   		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>>>   	} else if (strcmp(attr->name, "read_max") == 0) {
>>> @@ -993,8 +993,8 @@ static ssize_t nvm_dev_attr_show_12(struct device *dev,
>>>   		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>>   	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
>>>   		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
>>> -	} else if (strcmp(attr->name, "media_capabilities") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
>>> +	} else if (strcmp(attr->name, "capabilities") == 0) {
>>> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.cap);
>>>   	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
>>>   		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>>>   	} else {
>>> @@ -1055,7 +1055,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>>>     /* general attributes */
>>>   static NVM_DEV_ATTR_RO(version);
>>> -static NVM_DEV_ATTR_RO(capabilities);
>>> +static NVM_DEV_ATTR_RO(media_capabilities);
>>>     static NVM_DEV_ATTR_RO(read_typ);
>>>   static NVM_DEV_ATTR_RO(read_max);
>>> @@ -1080,12 +1080,12 @@ static NVM_DEV_ATTR_12_RO(prog_max);
>>>   static NVM_DEV_ATTR_12_RO(erase_typ);
>>>   static NVM_DEV_ATTR_12_RO(erase_max);
>>>   static NVM_DEV_ATTR_12_RO(multiplane_modes);
>>> -static NVM_DEV_ATTR_12_RO(media_capabilities);
>>> +static NVM_DEV_ATTR_12_RO(capabilities);
>>>   static NVM_DEV_ATTR_12_RO(max_phys_secs);
>>>     static struct attribute *nvm_dev_attrs_12[] = {
>>>   	&dev_attr_version.attr,
>>> -	&dev_attr_capabilities.attr,
>>> +	&dev_attr_media_capabilities.attr,
>>>     	&dev_attr_vendor_opcode.attr,
>>>   	&dev_attr_device_mode.attr,
>>> @@ -1108,7 +1108,7 @@ static struct attribute *nvm_dev_attrs_12[] = {
>>>   	&dev_attr_erase_typ.attr,
>>>   	&dev_attr_erase_max.attr,
>>>   	&dev_attr_multiplane_modes.attr,
>>> -	&dev_attr_media_capabilities.attr,
>>> +	&dev_attr_capabilities.attr,
>>>   	&dev_attr_max_phys_secs.attr,
>>>     	NULL,
>>> @@ -1134,7 +1134,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
>>>     static struct attribute *nvm_dev_attrs_20[] = {
>>>   	&dev_attr_version.attr,
>>> -	&dev_attr_capabilities.attr,
>>> +	&dev_attr_media_capabilities.attr,
>>>     	&dev_attr_groups.attr,
>>>   	&dev_attr_punits.attr,
>>
>> With the mccap changes, it should make sense to keep the capabilities
>> as is.
> 
> The change adds mccap, but sysfs points to cap, which is wrong. This
> patch is needed. Otherwise, we change the name of mccap to cap, which
> is _very_ confusing to people familiar to both specs. We can change
> the name of mccap to cap in a future spec revision.
> 
> Javier
> 

Think of the sysfs capabilities as an abstract value that defines 
generic capabilities. It is not directly tied to either 1.2 or 2.0.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 09/20] lightnvm: use generic identify structure
  2018-02-22  7:49       ` Javier González
@ 2018-02-22  9:41         ` Matias Bjørling
  -1 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  9:41 UTC (permalink / raw)
  To: Javier González; +Cc: linux-block, linux-kernel, linux-nvme

On 02/22/2018 08:49 AM, Javier González wrote:
>> On 22 Feb 2018, at 08.47, Matias Bjørling <mb@lightnvm.io> wrote:
>>
>> On 02/21/2018 10:26 AM, Javier González wrote:
>>> Create a generic identify structure to collect the identify information
>>> before knowing the spec. version. This forces different version paths to
>>> cast the structure to their spec structure, thus making the code less
>>> error prone and more maintainable.
>>> Signed-off-by: Javier González <javier@cnexlabs.com>
>>> ---
>>>   drivers/nvme/host/lightnvm.c | 32 ++++++++++++++++++++------------
>>>   1 file changed, 20 insertions(+), 12 deletions(-)
>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>> index 9c1f8225c4e1..70dc4740f0d3 100644
>>> --- a/drivers/nvme/host/lightnvm.c
>>> +++ b/drivers/nvme/host/lightnvm.c
>>> @@ -170,6 +170,12 @@ struct nvme_nvm_id12 {
>>>   	__u8			resv2[2880];
>>>   } __packed;
>>>   +/* Generic identification structure */
>>> +struct nvme_nvm_id {
>>> +	__u8			ver_id;
>>> +	__u8			resv[4095];
>>> +} __packed;
>>> +
>>>   struct nvme_nvm_bb_tbl {
>>>   	__u8	tblid[4];
>>>   	__le16	verid;
>>> @@ -279,9 +285,10 @@ static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
>>>   	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>>>   }
>>>   -static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>>> +static int nvme_nvm_setup_12(struct nvme_nvm_id *gen_id,
>>>   			     struct nvm_dev_geo *dev_geo)
>>>   {
>>> +	struct nvme_nvm_id12 *id = (struct nvme_nvm_id12 *)gen_id;
>>>   	struct nvme_nvm_id12_grp *src;
>>>   	int sec_per_pg, sec_per_pl, pg_per_blk;
>>>   @@ -380,9 +387,11 @@ static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
>>>   	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>>>   }
>>>   -static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>>> +static int nvme_nvm_setup_20(struct nvme_nvm_id *gen_id,
>>>   			     struct nvm_dev_geo *dev_geo)
>>>   {
>>> +	struct nvme_nvm_id20 *id = (struct nvme_nvm_id20 *)gen_id;
>>> +
>>>   	dev_geo->major_ver_id = id->mjr;
>>>   	dev_geo->minor_ver_id = id->mnr;
>>>   @@ -427,19 +436,19 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>>>   static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>>>   {
>>>   	struct nvme_ns *ns = nvmdev->q->queuedata;
>>> -	struct nvme_nvm_id12 *id;
>>> +	struct nvme_nvm_id *nvme_nvm_id;
>>>   	struct nvme_nvm_command c = {};
>>>   	int ret;
>>>     	c.identity.opcode = nvme_nvm_admin_identity;
>>>   	c.identity.nsid = cpu_to_le32(ns->head->ns_id);
>>>   -	id = kmalloc(sizeof(struct nvme_nvm_id12), GFP_KERNEL);
>>> -	if (!id)
>>> +	nvme_nvm_id = kmalloc(sizeof(struct nvme_nvm_id), GFP_KERNEL);
>>> +	if (!nvme_nvm_id)
>>>   		return -ENOMEM;
>>>     	ret = nvme_submit_sync_cmd(ns->ctrl->admin_q, (struct nvme_command *)&c,
>>> -				id, sizeof(struct nvme_nvm_id12));
>>> +				nvme_nvm_id, sizeof(struct nvme_nvm_id));
>>>   	if (ret) {
>>>   		ret = -EIO;
>>>   		goto out;
>>> @@ -449,22 +458,21 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>>>   	 * The 1.2 and 2.0 specifications share the first byte in their geometry
>>>   	 * command to make it possible to know what version a device implements.
>>>   	 */
>>> -	switch (id->ver_id) {
>>> +	switch (nvme_nvm_id->ver_id) {
>>>   	case 1:
>>> -		ret = nvme_nvm_setup_12(id, &nvmdev->dev_geo);
>>> +		ret = nvme_nvm_setup_12(nvme_nvm_id, &nvmdev->dev_geo);
>>>   		break;
>>>   	case 2:
>>> -		ret = nvme_nvm_setup_20((struct nvme_nvm_id20 *)id,
>>> -							&nvmdev->dev_geo);
>>> +		ret = nvme_nvm_setup_20(nvme_nvm_id, &nvmdev->dev_geo);
>>>   		break;
>>>   	default:
>>>   		dev_err(ns->ctrl->device, "OCSSD revision not supported (%d)\n",
>>> -							id->ver_id);
>>> +							nvme_nvm_id->ver_id);
>>>   		ret = -EINVAL;
>>>   	}
>>>     out:
>>> -	kfree(id);
>>> +	kfree(nvme_nvm_id);
>>>   	return ret;
>>>   }
>>>
>>
>> Thanks for another way to represent it. I want to keep the original
>> path. If we are going that down road, then one should maybe look into
>> unifying the "three" data structures, and have the version as the base
>> property and the others in each their sub data structure.
> 
> That's what this structure aims to do, since the version is shared. But
> you call if you want to cast unrelated structures back an forth. I'll
> revert it...
> 
> Javier
> 

In that case, the patch could look like

struct nvm_id {
	__u8 ver_id;

	union {
		struct v1 {};
		struct v2 {};
	};
};

I'm good with just having the single cast instead of putting each under 
a v1/v2 variable or using nvm_id first, and then goto either v1 or v2.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 09/20] lightnvm: use generic identify structure
@ 2018-02-22  9:41         ` Matias Bjørling
  0 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  9:41 UTC (permalink / raw)


On 02/22/2018 08:49 AM, Javier Gonz?lez wrote:
>> On 22 Feb 2018,@08.47, Matias Bj?rling <mb@lightnvm.io> wrote:
>>
>> On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
>>> Create a generic identify structure to collect the identify information
>>> before knowing the spec. version. This forces different version paths to
>>> cast the structure to their spec structure, thus making the code less
>>> error prone and more maintainable.
>>> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
>>> ---
>>>   drivers/nvme/host/lightnvm.c | 32 ++++++++++++++++++++------------
>>>   1 file changed, 20 insertions(+), 12 deletions(-)
>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>> index 9c1f8225c4e1..70dc4740f0d3 100644
>>> --- a/drivers/nvme/host/lightnvm.c
>>> +++ b/drivers/nvme/host/lightnvm.c
>>> @@ -170,6 +170,12 @@ struct nvme_nvm_id12 {
>>>   	__u8			resv2[2880];
>>>   } __packed;
>>>   +/* Generic identification structure */
>>> +struct nvme_nvm_id {
>>> +	__u8			ver_id;
>>> +	__u8			resv[4095];
>>> +} __packed;
>>> +
>>>   struct nvme_nvm_bb_tbl {
>>>   	__u8	tblid[4];
>>>   	__le16	verid;
>>> @@ -279,9 +285,10 @@ static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
>>>   	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>>>   }
>>>   -static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>>> +static int nvme_nvm_setup_12(struct nvme_nvm_id *gen_id,
>>>   			     struct nvm_dev_geo *dev_geo)
>>>   {
>>> +	struct nvme_nvm_id12 *id = (struct nvme_nvm_id12 *)gen_id;
>>>   	struct nvme_nvm_id12_grp *src;
>>>   	int sec_per_pg, sec_per_pl, pg_per_blk;
>>>   @@ -380,9 +387,11 @@ static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
>>>   	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>>>   }
>>>   -static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>>> +static int nvme_nvm_setup_20(struct nvme_nvm_id *gen_id,
>>>   			     struct nvm_dev_geo *dev_geo)
>>>   {
>>> +	struct nvme_nvm_id20 *id = (struct nvme_nvm_id20 *)gen_id;
>>> +
>>>   	dev_geo->major_ver_id = id->mjr;
>>>   	dev_geo->minor_ver_id = id->mnr;
>>>   @@ -427,19 +436,19 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>>>   static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>>>   {
>>>   	struct nvme_ns *ns = nvmdev->q->queuedata;
>>> -	struct nvme_nvm_id12 *id;
>>> +	struct nvme_nvm_id *nvme_nvm_id;
>>>   	struct nvme_nvm_command c = {};
>>>   	int ret;
>>>     	c.identity.opcode = nvme_nvm_admin_identity;
>>>   	c.identity.nsid = cpu_to_le32(ns->head->ns_id);
>>>   -	id = kmalloc(sizeof(struct nvme_nvm_id12), GFP_KERNEL);
>>> -	if (!id)
>>> +	nvme_nvm_id = kmalloc(sizeof(struct nvme_nvm_id), GFP_KERNEL);
>>> +	if (!nvme_nvm_id)
>>>   		return -ENOMEM;
>>>     	ret = nvme_submit_sync_cmd(ns->ctrl->admin_q, (struct nvme_command *)&c,
>>> -				id, sizeof(struct nvme_nvm_id12));
>>> +				nvme_nvm_id, sizeof(struct nvme_nvm_id));
>>>   	if (ret) {
>>>   		ret = -EIO;
>>>   		goto out;
>>> @@ -449,22 +458,21 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>>>   	 * The 1.2 and 2.0 specifications share the first byte in their geometry
>>>   	 * command to make it possible to know what version a device implements.
>>>   	 */
>>> -	switch (id->ver_id) {
>>> +	switch (nvme_nvm_id->ver_id) {
>>>   	case 1:
>>> -		ret = nvme_nvm_setup_12(id, &nvmdev->dev_geo);
>>> +		ret = nvme_nvm_setup_12(nvme_nvm_id, &nvmdev->dev_geo);
>>>   		break;
>>>   	case 2:
>>> -		ret = nvme_nvm_setup_20((struct nvme_nvm_id20 *)id,
>>> -							&nvmdev->dev_geo);
>>> +		ret = nvme_nvm_setup_20(nvme_nvm_id, &nvmdev->dev_geo);
>>>   		break;
>>>   	default:
>>>   		dev_err(ns->ctrl->device, "OCSSD revision not supported (%d)\n",
>>> -							id->ver_id);
>>> +							nvme_nvm_id->ver_id);
>>>   		ret = -EINVAL;
>>>   	}
>>>     out:
>>> -	kfree(id);
>>> +	kfree(nvme_nvm_id);
>>>   	return ret;
>>>   }
>>>
>>
>> Thanks for another way to represent it. I want to keep the original
>> path. If we are going that down road, then one should maybe look into
>> unifying the "three" data structures, and have the version as the base
>> property and the others in each their sub data structure.
> 
> That's what this structure aims to do, since the version is shared. But
> you call if you want to cast unrelated structures back an forth. I'll
> revert it...
> 
> Javier
> 

In that case, the patch could look like

struct nvm_id {
	__u8 ver_id;

	union {
		struct v1 {};
		struct v2 {};
	};
};

I'm good with just having the single cast instead of putting each under 
a v1/v2 variable or using nvm_id first, and then goto either v1 or v2.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 08/20] lightnvm: complete geo structure with maxoc*
  2018-02-22  7:55       ` Javier Gonzalez
@ 2018-02-22  9:45         ` Matias Bjørling
  -1 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  9:45 UTC (permalink / raw)
  To: Javier Gonzalez; +Cc: linux-block, linux-kernel, linux-nvme

On 02/22/2018 08:55 AM, Javier Gonzalez wrote:
>> On 22 Feb 2018, at 08.45, Matias Bjørling <mb@lightnvm.io> wrote:
>>
>> On 02/21/2018 10:26 AM, Javier González wrote:
>>> Complete the generic geometry structure with the maxoc and maxocpu
>>> felds, present in the 2.0 spec.
>>> Signed-off-by: Javier González <javier@cnexlabs.com>
>>> ---
>>>   drivers/nvme/host/lightnvm.c | 4 ++++
>>>   include/linux/lightnvm.h     | 2 ++
>>>   2 files changed, 6 insertions(+)
>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>> index cca32da05316..9c1f8225c4e1 100644
>>> --- a/drivers/nvme/host/lightnvm.c
>>> +++ b/drivers/nvme/host/lightnvm.c
>>> @@ -318,6 +318,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>>>   	dev_geo->c.ws_min = sec_per_pg;
>>>   	dev_geo->c.ws_opt = sec_per_pg;
>>>   	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
>>> +	dev_geo->c.maxoc = dev_geo->all_luns;	/* default to 1 chunk per LUN */
>>> +	dev_geo->c.maxocpu = 1;			/* default to 1 chunk per LUN */
>>
>> One can't assume that it is 1 open chunk per lun. If you need this for specific hardware, make a quirk for it.
>>
> 
> Which default you want for 1.2 if not specified then? I use 1 because it
> has been the implicit default until now.

INT_MAX, since it then allows the maximum of open chunks. It cannot be 
assumed that other 1.2 devices is limited to a single open chunk.

> 
> Javier
> 

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 08/20] lightnvm: complete geo structure with maxoc*
@ 2018-02-22  9:45         ` Matias Bjørling
  0 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22  9:45 UTC (permalink / raw)


On 02/22/2018 08:55 AM, Javier Gonzalez wrote:
>> On 22 Feb 2018,@08.45, Matias Bj?rling <mb@lightnvm.io> wrote:
>>
>> On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
>>> Complete the generic geometry structure with the maxoc and maxocpu
>>> felds, present in the 2.0 spec.
>>> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
>>> ---
>>>   drivers/nvme/host/lightnvm.c | 4 ++++
>>>   include/linux/lightnvm.h     | 2 ++
>>>   2 files changed, 6 insertions(+)
>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>> index cca32da05316..9c1f8225c4e1 100644
>>> --- a/drivers/nvme/host/lightnvm.c
>>> +++ b/drivers/nvme/host/lightnvm.c
>>> @@ -318,6 +318,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>>>   	dev_geo->c.ws_min = sec_per_pg;
>>>   	dev_geo->c.ws_opt = sec_per_pg;
>>>   	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
>>> +	dev_geo->c.maxoc = dev_geo->all_luns;	/* default to 1 chunk per LUN */
>>> +	dev_geo->c.maxocpu = 1;			/* default to 1 chunk per LUN */
>>
>> One can't assume that it is 1 open chunk per lun. If you need this for specific hardware, make a quirk for it.
>>
> 
> Which default you want for 1.2 if not specified then? I use 1 because it
> has been the implicit default until now.

INT_MAX, since it then allows the maximum of open chunks. It cannot be 
assumed that other 1.2 devices is limited to a single open chunk.

> 
> Javier
> 

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 08/20] lightnvm: complete geo structure with maxoc*
  2018-02-22  9:45         ` Matias Bjørling
@ 2018-02-22  9:52           ` Javier Gonzalez
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier Gonzalez @ 2018-02-22  9:52 UTC (permalink / raw)
  To: Matias Bjørling; +Cc: linux-block, linux-kernel, linux-nvme

[-- Attachment #1: Type: text/plain, Size: 1874 bytes --]

> On 22 Feb 2018, at 10.45, Matias Bjørling <mb@lightnvm.io> wrote:
> 
> On 02/22/2018 08:55 AM, Javier Gonzalez wrote:
>>> On 22 Feb 2018, at 08.45, Matias Bjørling <mb@lightnvm.io> wrote:
>>> 
>>> On 02/21/2018 10:26 AM, Javier González wrote:
>>>> Complete the generic geometry structure with the maxoc and maxocpu
>>>> felds, present in the 2.0 spec.
>>>> Signed-off-by: Javier González <javier@cnexlabs.com>
>>>> ---
>>>>  drivers/nvme/host/lightnvm.c | 4 ++++
>>>>  include/linux/lightnvm.h     | 2 ++
>>>>  2 files changed, 6 insertions(+)
>>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>>> index cca32da05316..9c1f8225c4e1 100644
>>>> --- a/drivers/nvme/host/lightnvm.c
>>>> +++ b/drivers/nvme/host/lightnvm.c
>>>> @@ -318,6 +318,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>>>>  	dev_geo->c.ws_min = sec_per_pg;
>>>>  	dev_geo->c.ws_opt = sec_per_pg;
>>>>  	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
>>>> +	dev_geo->c.maxoc = dev_geo->all_luns;	/* default to 1 chunk per LUN */
>>>> +	dev_geo->c.maxocpu = 1;			/* default to 1 chunk per LUN */
>>> 
>>> One can't assume that it is 1 open chunk per lun. If you need this for specific hardware, make a quirk for it.
>> Which default you want for 1.2 if not specified then? I use 1 because it
>> has been the implicit default until now.
> 
> INT_MAX, since it then allows the maximum of open chunks. It cannot be assumed that other 1.2 devices is limited to a single open chunk.

So you want the default to be that all blocks on the device can be
opened at the same time. Interesting... I guess that such a SSD will
have a AA battery attached to it, but fine by me if that's how you want
it.

Assuming this, can we instead set it to the reported number of chunks,
since this is the hard limit anyway.

Javier

[-- Attachment #2: Message signed with OpenPGP --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 08/20] lightnvm: complete geo structure with maxoc*
@ 2018-02-22  9:52           ` Javier Gonzalez
  0 siblings, 0 replies; 99+ messages in thread
From: Javier Gonzalez @ 2018-02-22  9:52 UTC (permalink / raw)


> On 22 Feb 2018,@10.45, Matias Bj?rling <mb@lightnvm.io> wrote:
> 
> On 02/22/2018 08:55 AM, Javier Gonzalez wrote:
>>> On 22 Feb 2018,@08.45, Matias Bj?rling <mb@lightnvm.io> wrote:
>>> 
>>> On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
>>>> Complete the generic geometry structure with the maxoc and maxocpu
>>>> felds, present in the 2.0 spec.
>>>> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
>>>> ---
>>>>  drivers/nvme/host/lightnvm.c | 4 ++++
>>>>  include/linux/lightnvm.h     | 2 ++
>>>>  2 files changed, 6 insertions(+)
>>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>>> index cca32da05316..9c1f8225c4e1 100644
>>>> --- a/drivers/nvme/host/lightnvm.c
>>>> +++ b/drivers/nvme/host/lightnvm.c
>>>> @@ -318,6 +318,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>>>>  	dev_geo->c.ws_min = sec_per_pg;
>>>>  	dev_geo->c.ws_opt = sec_per_pg;
>>>>  	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
>>>> +	dev_geo->c.maxoc = dev_geo->all_luns;	/* default to 1 chunk per LUN */
>>>> +	dev_geo->c.maxocpu = 1;			/* default to 1 chunk per LUN */
>>> 
>>> One can't assume that it is 1 open chunk per lun. If you need this for specific hardware, make a quirk for it.
>> Which default you want for 1.2 if not specified then? I use 1 because it
>> has been the implicit default until now.
> 
> INT_MAX, since it then allows the maximum of open chunks. It cannot be assumed that other 1.2 devices is limited to a single open chunk.

So you want the default to be that all blocks on the device can be
opened at the same time. Interesting... I guess that such a SSD will
have a AA battery attached to it, but fine by me if that's how you want
it.

Assuming this, can we instead set it to the reported number of chunks,
since this is the hard limit anyway.

Javier
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: Message signed with OpenPGP
URL: <http://lists.infradead.org/pipermail/linux-nvme/attachments/20180222/52e0f1d8/attachment.sig>

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 08/20] lightnvm: complete geo structure with maxoc*
  2018-02-22  9:52           ` Javier Gonzalez
@ 2018-02-22 10:00             ` Matias Bjørling
  -1 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22 10:00 UTC (permalink / raw)
  To: Javier Gonzalez; +Cc: linux-block, linux-kernel, linux-nvme

On 02/22/2018 10:52 AM, Javier Gonzalez wrote:
>> On 22 Feb 2018, at 10.45, Matias Bjørling <mb@lightnvm.io> wrote:
>>
>> On 02/22/2018 08:55 AM, Javier Gonzalez wrote:
>>>> On 22 Feb 2018, at 08.45, Matias Bjørling <mb@lightnvm.io> wrote:
>>>>
>>>> On 02/21/2018 10:26 AM, Javier González wrote:
>>>>> Complete the generic geometry structure with the maxoc and maxocpu
>>>>> felds, present in the 2.0 spec.
>>>>> Signed-off-by: Javier González <javier@cnexlabs.com>
>>>>> ---
>>>>>   drivers/nvme/host/lightnvm.c | 4 ++++
>>>>>   include/linux/lightnvm.h     | 2 ++
>>>>>   2 files changed, 6 insertions(+)
>>>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>>>> index cca32da05316..9c1f8225c4e1 100644
>>>>> --- a/drivers/nvme/host/lightnvm.c
>>>>> +++ b/drivers/nvme/host/lightnvm.c
>>>>> @@ -318,6 +318,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>>>>>   	dev_geo->c.ws_min = sec_per_pg;
>>>>>   	dev_geo->c.ws_opt = sec_per_pg;
>>>>>   	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
>>>>> +	dev_geo->c.maxoc = dev_geo->all_luns;	/* default to 1 chunk per LUN */
>>>>> +	dev_geo->c.maxocpu = 1;			/* default to 1 chunk per LUN */
>>>>
>>>> One can't assume that it is 1 open chunk per lun. If you need this for specific hardware, make a quirk for it.
>>> Which default you want for 1.2 if not specified then? I use 1 because it
>>> has been the implicit default until now.
>>
>> INT_MAX, since it then allows the maximum of open chunks. It cannot be assumed that other 1.2 devices is limited to a single open chunk.
> 
> So you want the default to be that all blocks on the device can be
> opened at the same time. Interesting... I guess that such a SSD will
> have a AA battery attached to it, but fine by me if that's how you want
> it.

I feel you're a bit sarcastic here. One may think of SLC and other 
memories that does one-shot programming. In that case no caching is 
needed, and therefore power-caps can be limited on the hardware.

> 
> Assuming this, can we instead set it to the reported number of chunks,
> since this is the hard limit anyway.
> 

Works for me.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 08/20] lightnvm: complete geo structure with maxoc*
@ 2018-02-22 10:00             ` Matias Bjørling
  0 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22 10:00 UTC (permalink / raw)


On 02/22/2018 10:52 AM, Javier Gonzalez wrote:
>> On 22 Feb 2018,@10.45, Matias Bj?rling <mb@lightnvm.io> wrote:
>>
>> On 02/22/2018 08:55 AM, Javier Gonzalez wrote:
>>>> On 22 Feb 2018,@08.45, Matias Bj?rling <mb@lightnvm.io> wrote:
>>>>
>>>> On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
>>>>> Complete the generic geometry structure with the maxoc and maxocpu
>>>>> felds, present in the 2.0 spec.
>>>>> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
>>>>> ---
>>>>>   drivers/nvme/host/lightnvm.c | 4 ++++
>>>>>   include/linux/lightnvm.h     | 2 ++
>>>>>   2 files changed, 6 insertions(+)
>>>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>>>> index cca32da05316..9c1f8225c4e1 100644
>>>>> --- a/drivers/nvme/host/lightnvm.c
>>>>> +++ b/drivers/nvme/host/lightnvm.c
>>>>> @@ -318,6 +318,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>>>>>   	dev_geo->c.ws_min = sec_per_pg;
>>>>>   	dev_geo->c.ws_opt = sec_per_pg;
>>>>>   	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
>>>>> +	dev_geo->c.maxoc = dev_geo->all_luns;	/* default to 1 chunk per LUN */
>>>>> +	dev_geo->c.maxocpu = 1;			/* default to 1 chunk per LUN */
>>>>
>>>> One can't assume that it is 1 open chunk per lun. If you need this for specific hardware, make a quirk for it.
>>> Which default you want for 1.2 if not specified then? I use 1 because it
>>> has been the implicit default until now.
>>
>> INT_MAX, since it then allows the maximum of open chunks. It cannot be assumed that other 1.2 devices is limited to a single open chunk.
> 
> So you want the default to be that all blocks on the device can be
> opened at the same time. Interesting... I guess that such a SSD will
> have a AA battery attached to it, but fine by me if that's how you want
> it.

I feel you're a bit sarcastic here. One may think of SLC and other 
memories that does one-shot programming. In that case no caching is 
needed, and therefore power-caps can be limited on the hardware.

> 
> Assuming this, can we instead set it to the reported number of chunks,
> since this is the hard limit anyway.
> 

Works for me.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 08/20] lightnvm: complete geo structure with maxoc*
  2018-02-22 10:00             ` Matias Bjørling
@ 2018-02-22 10:03               ` Javier Gonzalez
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier Gonzalez @ 2018-02-22 10:03 UTC (permalink / raw)
  To: Matias Bjørling; +Cc: linux-block, linux-kernel, linux-nvme

[-- Attachment #1: Type: text/plain, Size: 2513 bytes --]


Javier

> On 22 Feb 2018, at 11.00, Matias Bjørling <mb@lightnvm.io> wrote:
> 
> On 02/22/2018 10:52 AM, Javier Gonzalez wrote:
>>> On 22 Feb 2018, at 10.45, Matias Bjørling <mb@lightnvm.io> wrote:
>>> 
>>> On 02/22/2018 08:55 AM, Javier Gonzalez wrote:
>>>>> On 22 Feb 2018, at 08.45, Matias Bjørling <mb@lightnvm.io> wrote:
>>>>> 
>>>>> On 02/21/2018 10:26 AM, Javier González wrote:
>>>>>> Complete the generic geometry structure with the maxoc and maxocpu
>>>>>> felds, present in the 2.0 spec.
>>>>>> Signed-off-by: Javier González <javier@cnexlabs.com>
>>>>>> ---
>>>>>>  drivers/nvme/host/lightnvm.c | 4 ++++
>>>>>>  include/linux/lightnvm.h     | 2 ++
>>>>>>  2 files changed, 6 insertions(+)
>>>>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>>>>> index cca32da05316..9c1f8225c4e1 100644
>>>>>> --- a/drivers/nvme/host/lightnvm.c
>>>>>> +++ b/drivers/nvme/host/lightnvm.c
>>>>>> @@ -318,6 +318,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>>>>>>  	dev_geo->c.ws_min = sec_per_pg;
>>>>>>  	dev_geo->c.ws_opt = sec_per_pg;
>>>>>>  	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
>>>>>> +	dev_geo->c.maxoc = dev_geo->all_luns;	/* default to 1 chunk per LUN */
>>>>>> +	dev_geo->c.maxocpu = 1;			/* default to 1 chunk per LUN */
>>>>> 
>>>>> One can't assume that it is 1 open chunk per lun. If you need this for specific hardware, make a quirk for it.
>>>> Which default you want for 1.2 if not specified then? I use 1 because it
>>>> has been the implicit default until now.
>>> 
>>> INT_MAX, since it then allows the maximum of open chunks. It cannot be assumed that other 1.2 devices is limited to a single open chunk.
>> So you want the default to be that all blocks on the device can be
>> opened at the same time. Interesting... I guess that such a SSD will
>> have a AA battery attached to it, but fine by me if that's how you want
>> it.
> 
> I feel you're a bit sarcastic here. One may think of SLC and other memories that does one-shot programming. In that case no caching is needed, and therefore power-caps can be limited on the hardware.

Sure. Hope people move to 2.0 then for all >SLC memories out there,
otherwise we'll see a lot of quirks coming in. Thought we wanted to be
generic.

> 
>> Assuming this, can we instead set it to the reported number of chunks,
>> since this is the hard limit anyway.
> 
> Works for me.

Cool. I'll add this to the next version.

Javier

[-- Attachment #2: Message signed with OpenPGP --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 08/20] lightnvm: complete geo structure with maxoc*
@ 2018-02-22 10:03               ` Javier Gonzalez
  0 siblings, 0 replies; 99+ messages in thread
From: Javier Gonzalez @ 2018-02-22 10:03 UTC (permalink / raw)



Javier

> On 22 Feb 2018,@11.00, Matias Bj?rling <mb@lightnvm.io> wrote:
> 
> On 02/22/2018 10:52 AM, Javier Gonzalez wrote:
>>> On 22 Feb 2018,@10.45, Matias Bj?rling <mb@lightnvm.io> wrote:
>>> 
>>> On 02/22/2018 08:55 AM, Javier Gonzalez wrote:
>>>>> On 22 Feb 2018,@08.45, Matias Bj?rling <mb@lightnvm.io> wrote:
>>>>> 
>>>>> On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
>>>>>> Complete the generic geometry structure with the maxoc and maxocpu
>>>>>> felds, present in the 2.0 spec.
>>>>>> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
>>>>>> ---
>>>>>>  drivers/nvme/host/lightnvm.c | 4 ++++
>>>>>>  include/linux/lightnvm.h     | 2 ++
>>>>>>  2 files changed, 6 insertions(+)
>>>>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>>>>> index cca32da05316..9c1f8225c4e1 100644
>>>>>> --- a/drivers/nvme/host/lightnvm.c
>>>>>> +++ b/drivers/nvme/host/lightnvm.c
>>>>>> @@ -318,6 +318,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>>>>>>  	dev_geo->c.ws_min = sec_per_pg;
>>>>>>  	dev_geo->c.ws_opt = sec_per_pg;
>>>>>>  	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
>>>>>> +	dev_geo->c.maxoc = dev_geo->all_luns;	/* default to 1 chunk per LUN */
>>>>>> +	dev_geo->c.maxocpu = 1;			/* default to 1 chunk per LUN */
>>>>> 
>>>>> One can't assume that it is 1 open chunk per lun. If you need this for specific hardware, make a quirk for it.
>>>> Which default you want for 1.2 if not specified then? I use 1 because it
>>>> has been the implicit default until now.
>>> 
>>> INT_MAX, since it then allows the maximum of open chunks. It cannot be assumed that other 1.2 devices is limited to a single open chunk.
>> So you want the default to be that all blocks on the device can be
>> opened at the same time. Interesting... I guess that such a SSD will
>> have a AA battery attached to it, but fine by me if that's how you want
>> it.
> 
> I feel you're a bit sarcastic here. One may think of SLC and other memories that does one-shot programming. In that case no caching is needed, and therefore power-caps can be limited on the hardware.

Sure. Hope people move to 2.0 then for all >SLC memories out there,
otherwise we'll see a lot of quirks coming in. Thought we wanted to be
generic.

> 
>> Assuming this, can we instead set it to the reported number of chunks,
>> since this is the hard limit anyway.
> 
> Works for me.

Cool. I'll add this to the next version.

Javier
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: Message signed with OpenPGP
URL: <http://lists.infradead.org/pipermail/linux-nvme/attachments/20180222/c888845b/attachment.sig>

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 03/20] lightnvm: fix capabilities for 2.0 sysfs
  2018-02-22  9:39         ` Matias Bjørling
  (?)
@ 2018-02-22 10:25           ` Javier Gonzalez
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier Gonzalez @ 2018-02-22 10:25 UTC (permalink / raw)
  To: Matias Bjørling; +Cc: linux-block, linux-kernel, linux-nvme

DQoNCj4gT24gMjIgRmViIDIwMTgsIGF0IDEwLjM5LCBNYXRpYXMgQmrDuHJsaW5nIDxtYkBsaWdo
dG52bS5pbz4gd3JvdGU6DQo+IA0KPiBPbiAwMi8yMi8yMDE4IDA4OjQ3IEFNLCBKYXZpZXIgR29u
emFsZXogd3JvdGU6DQo+Pj4gT24gMjIgRmViIDIwMTgsIGF0IDA4LjI4LCBNYXRpYXMgQmrDuHJs
aW5nIDxtYkBsaWdodG52bS5pbz4gd3JvdGU6DQo+Pj4gDQo+Pj4+IE9uIDAyLzIxLzIwMTggMTA6
MjYgQU0sIEphdmllciBHb256w6FsZXogd3JvdGU6DQo+Pj4+IEJvdGggMS4yIGFuZCAyLjAgc3Bl
Y3MgZGVmaW5lIGEgZmllbGQgZm9yIG1lZGlhIGFuZCBjb250cm9sbGVyDQo+Pj4+IGNhcGFiaWxp
dGllcy4gQWxzbywgMS4yIGRlZmluZXMgYSBzZXBhcmF0ZSBmaWVsZCBkZWRpY2F0ZWQgdG8gZGV2
aWNlDQo+Pj4+IGNhcGFiaWxpdGllcy4NCj4+Pj4gSW4gMi4wIHN5c2ZzLCB0aGlzIHZhbHVlcyBo
YXZlIGJlZW4gbWl4ZWQuIFJldmVydCB0aGVtIHRvIHRoZSByaWdodA0KPj4+PiB2YWx1ZS4NCj4+
Pj4gU2lnbmVkLW9mZi1ieTogSmF2aWVyIEdvbnrDoWxleiA8amF2aWVyQGNuZXhsYWJzLmNvbT4N
Cj4+Pj4gLS0tDQo+Pj4+ICBkcml2ZXJzL252bWUvaG9zdC9saWdodG52bS5jIHwgMTggKysrKysr
KysrLS0tLS0tLS0tDQo+Pj4+ICAxIGZpbGUgY2hhbmdlZCwgOSBpbnNlcnRpb25zKCspLCA5IGRl
bGV0aW9ucygtKQ0KPj4+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9udm1lL2hvc3QvbGlnaHRudm0u
YyBiL2RyaXZlcnMvbnZtZS9ob3N0L2xpZ2h0bnZtLmMNCj4+Pj4gaW5kZXggOTY5YmI4NzQ4NTBj
Li41OThhYmJhNjZmNTIgMTAwNjQ0DQo+Pj4+IC0tLSBhL2RyaXZlcnMvbnZtZS9ob3N0L2xpZ2h0
bnZtLmMNCj4+Pj4gKysrIGIvZHJpdmVycy9udm1lL2hvc3QvbGlnaHRudm0uYw0KPj4+PiBAQCAt
OTE0LDggKzkxNCw4IEBAIHN0YXRpYyBzc2l6ZV90IG52bV9kZXZfYXR0cl9zaG93KHN0cnVjdCBk
ZXZpY2UgKmRldiwNCj4+Pj4gICAgICAgIGlmIChzdHJjbXAoYXR0ci0+bmFtZSwgInZlcnNpb24i
KSA9PSAwKSB7DQo+Pj4+ICAgICAgICAgIHJldHVybiBzY25wcmludGYocGFnZSwgUEFHRV9TSVpF
LCAiJXVcbiIsIGRldl9nZW8tPnZlcl9pZCk7DQo+Pj4+IC0gICAgfSBlbHNlIGlmIChzdHJjbXAo
YXR0ci0+bmFtZSwgImNhcGFiaWxpdGllcyIpID09IDApIHsNCj4+Pj4gLSAgICAgICAgcmV0dXJu
IHNjbnByaW50ZihwYWdlLCBQQUdFX1NJWkUsICIldVxuIiwgZGV2X2dlby0+Yy5jYXApOw0KPj4+
PiArICAgIH0gZWxzZSBpZiAoc3RyY21wKGF0dHItPm5hbWUsICJtZWRpYV9jYXBhYmlsaXRpZXMi
KSA9PSAwKSB7DQo+Pj4+ICsgICAgICAgIHJldHVybiBzY25wcmludGYocGFnZSwgUEFHRV9TSVpF
LCAiJXVcbiIsIGRldl9nZW8tPmMubWNjYXApOw0KPj4+PiAgICAgIH0gZWxzZSBpZiAoc3RyY21w
KGF0dHItPm5hbWUsICJyZWFkX3R5cCIpID09IDApIHsNCj4+Pj4gICAgICAgICAgcmV0dXJuIHNj
bnByaW50ZihwYWdlLCBQQUdFX1NJWkUsICIldVxuIiwgZGV2X2dlby0+Yy50cmR0KTsNCj4+Pj4g
ICAgICB9IGVsc2UgaWYgKHN0cmNtcChhdHRyLT5uYW1lLCAicmVhZF9tYXgiKSA9PSAwKSB7DQo+
Pj4+IEBAIC05OTMsOCArOTkzLDggQEAgc3RhdGljIHNzaXplX3QgbnZtX2Rldl9hdHRyX3Nob3df
MTIoc3RydWN0IGRldmljZSAqZGV2LA0KPj4+PiAgICAgICAgICByZXR1cm4gc2NucHJpbnRmKHBh
Z2UsIFBBR0VfU0laRSwgIiV1XG4iLCBkZXZfZ2VvLT5jLnRiZW0pOw0KPj4+PiAgICAgIH0gZWxz
ZSBpZiAoc3RyY21wKGF0dHItPm5hbWUsICJtdWx0aXBsYW5lX21vZGVzIikgPT0gMCkgew0KPj4+
PiAgICAgICAgICByZXR1cm4gc2NucHJpbnRmKHBhZ2UsIFBBR0VfU0laRSwgIjB4JTA4eFxuIiwg
ZGV2X2dlby0+Yy5tcG9zKTsNCj4+Pj4gLSAgICB9IGVsc2UgaWYgKHN0cmNtcChhdHRyLT5uYW1l
LCAibWVkaWFfY2FwYWJpbGl0aWVzIikgPT0gMCkgew0KPj4+PiAtICAgICAgICByZXR1cm4gc2Nu
cHJpbnRmKHBhZ2UsIFBBR0VfU0laRSwgIjB4JTA4eFxuIiwgZGV2X2dlby0+Yy5tY2NhcCk7DQo+
Pj4+ICsgICAgfSBlbHNlIGlmIChzdHJjbXAoYXR0ci0+bmFtZSwgImNhcGFiaWxpdGllcyIpID09
IDApIHsNCj4+Pj4gKyAgICAgICAgcmV0dXJuIHNjbnByaW50ZihwYWdlLCBQQUdFX1NJWkUsICIw
eCUwOHhcbiIsIGRldl9nZW8tPmMuY2FwKTsNCj4+Pj4gICAgICB9IGVsc2UgaWYgKHN0cmNtcChh
dHRyLT5uYW1lLCAibWF4X3BoeXNfc2VjcyIpID09IDApIHsNCj4+Pj4gICAgICAgICAgcmV0dXJu
IHNjbnByaW50ZihwYWdlLCBQQUdFX1NJWkUsICIldVxuIiwgTlZNX01BWF9WTEJBKTsNCj4+Pj4g
ICAgICB9IGVsc2Ugew0KPj4+PiBAQCAtMTA1NSw3ICsxMDU1LDcgQEAgc3RhdGljIHNzaXplX3Qg
bnZtX2Rldl9hdHRyX3Nob3dfMjAoc3RydWN0IGRldmljZSAqZGV2LA0KPj4+PiAgICAvKiBnZW5l
cmFsIGF0dHJpYnV0ZXMgKi8NCj4+Pj4gIHN0YXRpYyBOVk1fREVWX0FUVFJfUk8odmVyc2lvbik7
DQo+Pj4+IC1zdGF0aWMgTlZNX0RFVl9BVFRSX1JPKGNhcGFiaWxpdGllcyk7DQo+Pj4+ICtzdGF0
aWMgTlZNX0RFVl9BVFRSX1JPKG1lZGlhX2NhcGFiaWxpdGllcyk7DQo+Pj4+ICAgIHN0YXRpYyBO
Vk1fREVWX0FUVFJfUk8ocmVhZF90eXApOw0KPj4+PiAgc3RhdGljIE5WTV9ERVZfQVRUUl9STyhy
ZWFkX21heCk7DQo+Pj4+IEBAIC0xMDgwLDEyICsxMDgwLDEyIEBAIHN0YXRpYyBOVk1fREVWX0FU
VFJfMTJfUk8ocHJvZ19tYXgpOw0KPj4+PiAgc3RhdGljIE5WTV9ERVZfQVRUUl8xMl9STyhlcmFz
ZV90eXApOw0KPj4+PiAgc3RhdGljIE5WTV9ERVZfQVRUUl8xMl9STyhlcmFzZV9tYXgpOw0KPj4+
PiAgc3RhdGljIE5WTV9ERVZfQVRUUl8xMl9STyhtdWx0aXBsYW5lX21vZGVzKTsNCj4+Pj4gLXN0
YXRpYyBOVk1fREVWX0FUVFJfMTJfUk8obWVkaWFfY2FwYWJpbGl0aWVzKTsNCj4+Pj4gK3N0YXRp
YyBOVk1fREVWX0FUVFJfMTJfUk8oY2FwYWJpbGl0aWVzKTsNCj4+Pj4gIHN0YXRpYyBOVk1fREVW
X0FUVFJfMTJfUk8obWF4X3BoeXNfc2Vjcyk7DQo+Pj4+ICAgIHN0YXRpYyBzdHJ1Y3QgYXR0cmli
dXRlICpudm1fZGV2X2F0dHJzXzEyW10gPSB7DQo+Pj4+ICAgICAgJmRldl9hdHRyX3ZlcnNpb24u
YXR0ciwNCj4+Pj4gLSAgICAmZGV2X2F0dHJfY2FwYWJpbGl0aWVzLmF0dHIsDQo+Pj4+ICsgICAg
JmRldl9hdHRyX21lZGlhX2NhcGFiaWxpdGllcy5hdHRyLA0KPj4+PiAgICAgICAgJmRldl9hdHRy
X3ZlbmRvcl9vcGNvZGUuYXR0ciwNCj4+Pj4gICAgICAmZGV2X2F0dHJfZGV2aWNlX21vZGUuYXR0
ciwNCj4+Pj4gQEAgLTExMDgsNyArMTEwOCw3IEBAIHN0YXRpYyBzdHJ1Y3QgYXR0cmlidXRlICpu
dm1fZGV2X2F0dHJzXzEyW10gPSB7DQo+Pj4+ICAgICAgJmRldl9hdHRyX2VyYXNlX3R5cC5hdHRy
LA0KPj4+PiAgICAgICZkZXZfYXR0cl9lcmFzZV9tYXguYXR0ciwNCj4+Pj4gICAgICAmZGV2X2F0
dHJfbXVsdGlwbGFuZV9tb2Rlcy5hdHRyLA0KPj4+PiAtICAgICZkZXZfYXR0cl9tZWRpYV9jYXBh
YmlsaXRpZXMuYXR0ciwNCj4+Pj4gKyAgICAmZGV2X2F0dHJfY2FwYWJpbGl0aWVzLmF0dHIsDQo+
Pj4+ICAgICAgJmRldl9hdHRyX21heF9waHlzX3NlY3MuYXR0ciwNCj4+Pj4gICAgICAgIE5VTEws
DQo+Pj4+IEBAIC0xMTM0LDcgKzExMzQsNyBAQCBzdGF0aWMgTlZNX0RFVl9BVFRSXzIwX1JPKHJl
c2V0X21heCk7DQo+Pj4+ICAgIHN0YXRpYyBzdHJ1Y3QgYXR0cmlidXRlICpudm1fZGV2X2F0dHJz
XzIwW10gPSB7DQo+Pj4+ICAgICAgJmRldl9hdHRyX3ZlcnNpb24uYXR0ciwNCj4+Pj4gLSAgICAm
ZGV2X2F0dHJfY2FwYWJpbGl0aWVzLmF0dHIsDQo+Pj4+ICsgICAgJmRldl9hdHRyX21lZGlhX2Nh
cGFiaWxpdGllcy5hdHRyLA0KPj4+PiAgICAgICAgJmRldl9hdHRyX2dyb3Vwcy5hdHRyLA0KPj4+
PiAgICAgICZkZXZfYXR0cl9wdW5pdHMuYXR0ciwNCj4+PiANCj4+PiBXaXRoIHRoZSBtY2NhcCBj
aGFuZ2VzLCBpdCBzaG91bGQgbWFrZSBzZW5zZSB0byBrZWVwIHRoZSBjYXBhYmlsaXRpZXMNCj4+
PiBhcyBpcy4NCj4+IFRoZSBjaGFuZ2UgYWRkcyBtY2NhcCwgYnV0IHN5c2ZzIHBvaW50cyB0byBj
YXAsIHdoaWNoIGlzIHdyb25nLiBUaGlzDQo+PiBwYXRjaCBpcyBuZWVkZWQuIE90aGVyd2lzZSwg
d2UgY2hhbmdlIHRoZSBuYW1lIG9mIG1jY2FwIHRvIGNhcCwgd2hpY2gNCj4+IGlzIF92ZXJ5XyBj
b25mdXNpbmcgdG8gcGVvcGxlIGZhbWlsaWFyIHRvIGJvdGggc3BlY3MuIFdlIGNhbiBjaGFuZ2UN
Cj4+IHRoZSBuYW1lIG9mIG1jY2FwIHRvIGNhcCBpbiBhIGZ1dHVyZSBzcGVjIHJldmlzaW9uLg0K
Pj4gSmF2aWVyDQo+IA0KPiBUaGluayBvZiB0aGUgc3lzZnMgY2FwYWJpbGl0aWVzIGFzIGFuIGFi
c3RyYWN0IHZhbHVlIHRoYXQgZGVmaW5lcyBnZW5lcmljIGNhcGFiaWxpdGllcy4gSXQgaXMgbm90
IGRpcmVjdGx5IHRpZWQgdG8gZWl0aGVyIDEuMiBvciAyLjAuDQoNCknigJltIHRoaW5raW5nIGFi
b3V0IHRoZSB1c2VyIGxvb2tpbmcgYXQgc3lzZnMgYW5kIGF0IHRoZSBzcGVjIGF0IHRoZSBzYW1l
IHRpbWUgLSBJIG15c2VsZiBnZXQgY29uZnVzZWQgd2hlbiBuYW1lcyBkb27igJl0IG1hdGNoLiAN
Cg0KQW55d2F5LCBJ4oCZbGwga2VlcCBpdCB0aGUgd2F5IGl0IHdhcyBhbmQgYWRkIGEgY29tbWVu
dCBmb3IgY2xhcmlmaWNhdGlvbi4gV291bGQgdGhhdCB3b3JrIGZvciB5b3U/DQoNCkphdmllciA=

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 03/20] lightnvm: fix capabilities for 2.0 sysfs
@ 2018-02-22 10:25           ` Javier Gonzalez
  0 siblings, 0 replies; 99+ messages in thread
From: Javier Gonzalez @ 2018-02-22 10:25 UTC (permalink / raw)
  To: Matias Bjørling; +Cc: linux-block, linux-kernel, linux-nvme



> On 22 Feb 2018, at 10.39, Matias Bjørling <mb@lightnvm.io> wrote:
> 
> On 02/22/2018 08:47 AM, Javier Gonzalez wrote:
>>> On 22 Feb 2018, at 08.28, Matias Bjørling <mb@lightnvm.io> wrote:
>>> 
>>>> On 02/21/2018 10:26 AM, Javier González wrote:
>>>> Both 1.2 and 2.0 specs define a field for media and controller
>>>> capabilities. Also, 1.2 defines a separate field dedicated to device
>>>> capabilities.
>>>> In 2.0 sysfs, this values have been mixed. Revert them to the right
>>>> value.
>>>> Signed-off-by: Javier González <javier@cnexlabs.com>
>>>> ---
>>>>  drivers/nvme/host/lightnvm.c | 18 +++++++++---------
>>>>  1 file changed, 9 insertions(+), 9 deletions(-)
>>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>>> index 969bb874850c..598abba66f52 100644
>>>> --- a/drivers/nvme/host/lightnvm.c
>>>> +++ b/drivers/nvme/host/lightnvm.c
>>>> @@ -914,8 +914,8 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>>>        if (strcmp(attr->name, "version") == 0) {
>>>>          return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>>>> -    } else if (strcmp(attr->name, "capabilities") == 0) {
>>>> -        return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
>>>> +    } else if (strcmp(attr->name, "media_capabilities") == 0) {
>>>> +        return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
>>>>      } else if (strcmp(attr->name, "read_typ") == 0) {
>>>>          return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>>>>      } else if (strcmp(attr->name, "read_max") == 0) {
>>>> @@ -993,8 +993,8 @@ static ssize_t nvm_dev_attr_show_12(struct device *dev,
>>>>          return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>>>      } else if (strcmp(attr->name, "multiplane_modes") == 0) {
>>>>          return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
>>>> -    } else if (strcmp(attr->name, "media_capabilities") == 0) {
>>>> -        return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
>>>> +    } else if (strcmp(attr->name, "capabilities") == 0) {
>>>> +        return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.cap);
>>>>      } else if (strcmp(attr->name, "max_phys_secs") == 0) {
>>>>          return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>>>>      } else {
>>>> @@ -1055,7 +1055,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>>>>    /* general attributes */
>>>>  static NVM_DEV_ATTR_RO(version);
>>>> -static NVM_DEV_ATTR_RO(capabilities);
>>>> +static NVM_DEV_ATTR_RO(media_capabilities);
>>>>    static NVM_DEV_ATTR_RO(read_typ);
>>>>  static NVM_DEV_ATTR_RO(read_max);
>>>> @@ -1080,12 +1080,12 @@ static NVM_DEV_ATTR_12_RO(prog_max);
>>>>  static NVM_DEV_ATTR_12_RO(erase_typ);
>>>>  static NVM_DEV_ATTR_12_RO(erase_max);
>>>>  static NVM_DEV_ATTR_12_RO(multiplane_modes);
>>>> -static NVM_DEV_ATTR_12_RO(media_capabilities);
>>>> +static NVM_DEV_ATTR_12_RO(capabilities);
>>>>  static NVM_DEV_ATTR_12_RO(max_phys_secs);
>>>>    static struct attribute *nvm_dev_attrs_12[] = {
>>>>      &dev_attr_version.attr,
>>>> -    &dev_attr_capabilities.attr,
>>>> +    &dev_attr_media_capabilities.attr,
>>>>        &dev_attr_vendor_opcode.attr,
>>>>      &dev_attr_device_mode.attr,
>>>> @@ -1108,7 +1108,7 @@ static struct attribute *nvm_dev_attrs_12[] = {
>>>>      &dev_attr_erase_typ.attr,
>>>>      &dev_attr_erase_max.attr,
>>>>      &dev_attr_multiplane_modes.attr,
>>>> -    &dev_attr_media_capabilities.attr,
>>>> +    &dev_attr_capabilities.attr,
>>>>      &dev_attr_max_phys_secs.attr,
>>>>        NULL,
>>>> @@ -1134,7 +1134,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
>>>>    static struct attribute *nvm_dev_attrs_20[] = {
>>>>      &dev_attr_version.attr,
>>>> -    &dev_attr_capabilities.attr,
>>>> +    &dev_attr_media_capabilities.attr,
>>>>        &dev_attr_groups.attr,
>>>>      &dev_attr_punits.attr,
>>> 
>>> With the mccap changes, it should make sense to keep the capabilities
>>> as is.
>> The change adds mccap, but sysfs points to cap, which is wrong. This
>> patch is needed. Otherwise, we change the name of mccap to cap, which
>> is _very_ confusing to people familiar to both specs. We can change
>> the name of mccap to cap in a future spec revision.
>> Javier
> 
> Think of the sysfs capabilities as an abstract value that defines generic capabilities. It is not directly tied to either 1.2 or 2.0.

I’m thinking about the user looking at sysfs and at the spec at the same time - I myself get confused when names don’t match. 

Anyway, I’ll keep it the way it was and add a comment for clarification. Would that work for you?

Javier 

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 03/20] lightnvm: fix capabilities for 2.0 sysfs
@ 2018-02-22 10:25           ` Javier Gonzalez
  0 siblings, 0 replies; 99+ messages in thread
From: Javier Gonzalez @ 2018-02-22 10:25 UTC (permalink / raw)




> On 22 Feb 2018,@10.39, Matias Bj?rling <mb@lightnvm.io> wrote:
> 
> On 02/22/2018 08:47 AM, Javier Gonzalez wrote:
>>> On 22 Feb 2018,@08.28, Matias Bj?rling <mb@lightnvm.io> wrote:
>>> 
>>>> On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
>>>> Both 1.2 and 2.0 specs define a field for media and controller
>>>> capabilities. Also, 1.2 defines a separate field dedicated to device
>>>> capabilities.
>>>> In 2.0 sysfs, this values have been mixed. Revert them to the right
>>>> value.
>>>> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
>>>> ---
>>>>  drivers/nvme/host/lightnvm.c | 18 +++++++++---------
>>>>  1 file changed, 9 insertions(+), 9 deletions(-)
>>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>>> index 969bb874850c..598abba66f52 100644
>>>> --- a/drivers/nvme/host/lightnvm.c
>>>> +++ b/drivers/nvme/host/lightnvm.c
>>>> @@ -914,8 +914,8 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>>>        if (strcmp(attr->name, "version") == 0) {
>>>>          return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>>>> -    } else if (strcmp(attr->name, "capabilities") == 0) {
>>>> -        return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
>>>> +    } else if (strcmp(attr->name, "media_capabilities") == 0) {
>>>> +        return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
>>>>      } else if (strcmp(attr->name, "read_typ") == 0) {
>>>>          return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>>>>      } else if (strcmp(attr->name, "read_max") == 0) {
>>>> @@ -993,8 +993,8 @@ static ssize_t nvm_dev_attr_show_12(struct device *dev,
>>>>          return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>>>      } else if (strcmp(attr->name, "multiplane_modes") == 0) {
>>>>          return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
>>>> -    } else if (strcmp(attr->name, "media_capabilities") == 0) {
>>>> -        return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
>>>> +    } else if (strcmp(attr->name, "capabilities") == 0) {
>>>> +        return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.cap);
>>>>      } else if (strcmp(attr->name, "max_phys_secs") == 0) {
>>>>          return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>>>>      } else {
>>>> @@ -1055,7 +1055,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>>>>    /* general attributes */
>>>>  static NVM_DEV_ATTR_RO(version);
>>>> -static NVM_DEV_ATTR_RO(capabilities);
>>>> +static NVM_DEV_ATTR_RO(media_capabilities);
>>>>    static NVM_DEV_ATTR_RO(read_typ);
>>>>  static NVM_DEV_ATTR_RO(read_max);
>>>> @@ -1080,12 +1080,12 @@ static NVM_DEV_ATTR_12_RO(prog_max);
>>>>  static NVM_DEV_ATTR_12_RO(erase_typ);
>>>>  static NVM_DEV_ATTR_12_RO(erase_max);
>>>>  static NVM_DEV_ATTR_12_RO(multiplane_modes);
>>>> -static NVM_DEV_ATTR_12_RO(media_capabilities);
>>>> +static NVM_DEV_ATTR_12_RO(capabilities);
>>>>  static NVM_DEV_ATTR_12_RO(max_phys_secs);
>>>>    static struct attribute *nvm_dev_attrs_12[] = {
>>>>      &dev_attr_version.attr,
>>>> -    &dev_attr_capabilities.attr,
>>>> +    &dev_attr_media_capabilities.attr,
>>>>        &dev_attr_vendor_opcode.attr,
>>>>      &dev_attr_device_mode.attr,
>>>> @@ -1108,7 +1108,7 @@ static struct attribute *nvm_dev_attrs_12[] = {
>>>>      &dev_attr_erase_typ.attr,
>>>>      &dev_attr_erase_max.attr,
>>>>      &dev_attr_multiplane_modes.attr,
>>>> -    &dev_attr_media_capabilities.attr,
>>>> +    &dev_attr_capabilities.attr,
>>>>      &dev_attr_max_phys_secs.attr,
>>>>        NULL,
>>>> @@ -1134,7 +1134,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
>>>>    static struct attribute *nvm_dev_attrs_20[] = {
>>>>      &dev_attr_version.attr,
>>>> -    &dev_attr_capabilities.attr,
>>>> +    &dev_attr_media_capabilities.attr,
>>>>        &dev_attr_groups.attr,
>>>>      &dev_attr_punits.attr,
>>> 
>>> With the mccap changes, it should make sense to keep the capabilities
>>> as is.
>> The change adds mccap, but sysfs points to cap, which is wrong. This
>> patch is needed. Otherwise, we change the name of mccap to cap, which
>> is _very_ confusing to people familiar to both specs. We can change
>> the name of mccap to cap in a future spec revision.
>> Javier
> 
> Think of the sysfs capabilities as an abstract value that defines generic capabilities. It is not directly tied to either 1.2 or 2.0.

I?m thinking about the user looking at sysfs and at the spec at the same time - I myself get confused when names don?t match. 

Anyway, I?ll keep it the way it was and add a comment for clarification. Would that work for you?

Javier 

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 03/20] lightnvm: fix capabilities for 2.0 sysfs
  2018-02-22 10:25           ` Javier Gonzalez
@ 2018-02-22 11:10             ` Matias Bjørling
  -1 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22 11:10 UTC (permalink / raw)
  To: Javier Gonzalez; +Cc: linux-block, linux-kernel, linux-nvme

On 02/22/2018 11:25 AM, Javier Gonzalez wrote:
> 
> 
>> On 22 Feb 2018, at 10.39, Matias Bjørling <mb@lightnvm.io> wrote:
>>
>> On 02/22/2018 08:47 AM, Javier Gonzalez wrote:
>>>> On 22 Feb 2018, at 08.28, Matias Bjørling <mb@lightnvm.io> wrote:
>>>>
>>>>> On 02/21/2018 10:26 AM, Javier González wrote:
>>>>> Both 1.2 and 2.0 specs define a field for media and controller
>>>>> capabilities. Also, 1.2 defines a separate field dedicated to device
>>>>> capabilities.
>>>>> In 2.0 sysfs, this values have been mixed. Revert them to the right
>>>>> value.
>>>>> Signed-off-by: Javier González <javier@cnexlabs.com>
>>>>> ---
>>>>>   drivers/nvme/host/lightnvm.c | 18 +++++++++---------
>>>>>   1 file changed, 9 insertions(+), 9 deletions(-)
>>>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>>>> index 969bb874850c..598abba66f52 100644
>>>>> --- a/drivers/nvme/host/lightnvm.c
>>>>> +++ b/drivers/nvme/host/lightnvm.c
>>>>> @@ -914,8 +914,8 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>>>>         if (strcmp(attr->name, "version") == 0) {
>>>>>           return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>>>>> -    } else if (strcmp(attr->name, "capabilities") == 0) {
>>>>> -        return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
>>>>> +    } else if (strcmp(attr->name, "media_capabilities") == 0) {
>>>>> +        return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
>>>>>       } else if (strcmp(attr->name, "read_typ") == 0) {
>>>>>           return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>>>>>       } else if (strcmp(attr->name, "read_max") == 0) {
>>>>> @@ -993,8 +993,8 @@ static ssize_t nvm_dev_attr_show_12(struct device *dev,
>>>>>           return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>>>>       } else if (strcmp(attr->name, "multiplane_modes") == 0) {
>>>>>           return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
>>>>> -    } else if (strcmp(attr->name, "media_capabilities") == 0) {
>>>>> -        return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
>>>>> +    } else if (strcmp(attr->name, "capabilities") == 0) {
>>>>> +        return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.cap);
>>>>>       } else if (strcmp(attr->name, "max_phys_secs") == 0) {
>>>>>           return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>>>>>       } else {
>>>>> @@ -1055,7 +1055,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>>>>>     /* general attributes */
>>>>>   static NVM_DEV_ATTR_RO(version);
>>>>> -static NVM_DEV_ATTR_RO(capabilities);
>>>>> +static NVM_DEV_ATTR_RO(media_capabilities);
>>>>>     static NVM_DEV_ATTR_RO(read_typ);
>>>>>   static NVM_DEV_ATTR_RO(read_max);
>>>>> @@ -1080,12 +1080,12 @@ static NVM_DEV_ATTR_12_RO(prog_max);
>>>>>   static NVM_DEV_ATTR_12_RO(erase_typ);
>>>>>   static NVM_DEV_ATTR_12_RO(erase_max);
>>>>>   static NVM_DEV_ATTR_12_RO(multiplane_modes);
>>>>> -static NVM_DEV_ATTR_12_RO(media_capabilities);
>>>>> +static NVM_DEV_ATTR_12_RO(capabilities);
>>>>>   static NVM_DEV_ATTR_12_RO(max_phys_secs);
>>>>>     static struct attribute *nvm_dev_attrs_12[] = {
>>>>>       &dev_attr_version.attr,
>>>>> -    &dev_attr_capabilities.attr,
>>>>> +    &dev_attr_media_capabilities.attr,
>>>>>         &dev_attr_vendor_opcode.attr,
>>>>>       &dev_attr_device_mode.attr,
>>>>> @@ -1108,7 +1108,7 @@ static struct attribute *nvm_dev_attrs_12[] = {
>>>>>       &dev_attr_erase_typ.attr,
>>>>>       &dev_attr_erase_max.attr,
>>>>>       &dev_attr_multiplane_modes.attr,
>>>>> -    &dev_attr_media_capabilities.attr,
>>>>> +    &dev_attr_capabilities.attr,
>>>>>       &dev_attr_max_phys_secs.attr,
>>>>>         NULL,
>>>>> @@ -1134,7 +1134,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
>>>>>     static struct attribute *nvm_dev_attrs_20[] = {
>>>>>       &dev_attr_version.attr,
>>>>> -    &dev_attr_capabilities.attr,
>>>>> +    &dev_attr_media_capabilities.attr,
>>>>>         &dev_attr_groups.attr,
>>>>>       &dev_attr_punits.attr,
>>>>
>>>> With the mccap changes, it should make sense to keep the capabilities
>>>> as is.
>>> The change adds mccap, but sysfs points to cap, which is wrong. This
>>> patch is needed. Otherwise, we change the name of mccap to cap, which
>>> is _very_ confusing to people familiar to both specs. We can change
>>> the name of mccap to cap in a future spec revision.
>>> Javier
>>
>> Think of the sysfs capabilities as an abstract value that defines generic capabilities. It is not directly tied to either 1.2 or 2.0.
> 
> I’m thinking about the user looking at sysfs and at the spec at the same time - I myself get confused when names don’t match.
> 
> Anyway, I’ll keep it the way it was and add a comment for clarification. Would that work for you?
> 

That works. One may also wait until it is going to be used, e.g., when 
vector copy is implemented. Then it's natural to revisit.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 03/20] lightnvm: fix capabilities for 2.0 sysfs
@ 2018-02-22 11:10             ` Matias Bjørling
  0 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22 11:10 UTC (permalink / raw)


On 02/22/2018 11:25 AM, Javier Gonzalez wrote:
> 
> 
>> On 22 Feb 2018,@10.39, Matias Bj?rling <mb@lightnvm.io> wrote:
>>
>> On 02/22/2018 08:47 AM, Javier Gonzalez wrote:
>>>> On 22 Feb 2018,@08.28, Matias Bj?rling <mb@lightnvm.io> wrote:
>>>>
>>>>> On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
>>>>> Both 1.2 and 2.0 specs define a field for media and controller
>>>>> capabilities. Also, 1.2 defines a separate field dedicated to device
>>>>> capabilities.
>>>>> In 2.0 sysfs, this values have been mixed. Revert them to the right
>>>>> value.
>>>>> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
>>>>> ---
>>>>>   drivers/nvme/host/lightnvm.c | 18 +++++++++---------
>>>>>   1 file changed, 9 insertions(+), 9 deletions(-)
>>>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>>>> index 969bb874850c..598abba66f52 100644
>>>>> --- a/drivers/nvme/host/lightnvm.c
>>>>> +++ b/drivers/nvme/host/lightnvm.c
>>>>> @@ -914,8 +914,8 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>>>>         if (strcmp(attr->name, "version") == 0) {
>>>>>           return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>>>>> -    } else if (strcmp(attr->name, "capabilities") == 0) {
>>>>> -        return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
>>>>> +    } else if (strcmp(attr->name, "media_capabilities") == 0) {
>>>>> +        return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
>>>>>       } else if (strcmp(attr->name, "read_typ") == 0) {
>>>>>           return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>>>>>       } else if (strcmp(attr->name, "read_max") == 0) {
>>>>> @@ -993,8 +993,8 @@ static ssize_t nvm_dev_attr_show_12(struct device *dev,
>>>>>           return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>>>>       } else if (strcmp(attr->name, "multiplane_modes") == 0) {
>>>>>           return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
>>>>> -    } else if (strcmp(attr->name, "media_capabilities") == 0) {
>>>>> -        return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
>>>>> +    } else if (strcmp(attr->name, "capabilities") == 0) {
>>>>> +        return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.cap);
>>>>>       } else if (strcmp(attr->name, "max_phys_secs") == 0) {
>>>>>           return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>>>>>       } else {
>>>>> @@ -1055,7 +1055,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>>>>>     /* general attributes */
>>>>>   static NVM_DEV_ATTR_RO(version);
>>>>> -static NVM_DEV_ATTR_RO(capabilities);
>>>>> +static NVM_DEV_ATTR_RO(media_capabilities);
>>>>>     static NVM_DEV_ATTR_RO(read_typ);
>>>>>   static NVM_DEV_ATTR_RO(read_max);
>>>>> @@ -1080,12 +1080,12 @@ static NVM_DEV_ATTR_12_RO(prog_max);
>>>>>   static NVM_DEV_ATTR_12_RO(erase_typ);
>>>>>   static NVM_DEV_ATTR_12_RO(erase_max);
>>>>>   static NVM_DEV_ATTR_12_RO(multiplane_modes);
>>>>> -static NVM_DEV_ATTR_12_RO(media_capabilities);
>>>>> +static NVM_DEV_ATTR_12_RO(capabilities);
>>>>>   static NVM_DEV_ATTR_12_RO(max_phys_secs);
>>>>>     static struct attribute *nvm_dev_attrs_12[] = {
>>>>>       &dev_attr_version.attr,
>>>>> -    &dev_attr_capabilities.attr,
>>>>> +    &dev_attr_media_capabilities.attr,
>>>>>         &dev_attr_vendor_opcode.attr,
>>>>>       &dev_attr_device_mode.attr,
>>>>> @@ -1108,7 +1108,7 @@ static struct attribute *nvm_dev_attrs_12[] = {
>>>>>       &dev_attr_erase_typ.attr,
>>>>>       &dev_attr_erase_max.attr,
>>>>>       &dev_attr_multiplane_modes.attr,
>>>>> -    &dev_attr_media_capabilities.attr,
>>>>> +    &dev_attr_capabilities.attr,
>>>>>       &dev_attr_max_phys_secs.attr,
>>>>>         NULL,
>>>>> @@ -1134,7 +1134,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
>>>>>     static struct attribute *nvm_dev_attrs_20[] = {
>>>>>       &dev_attr_version.attr,
>>>>> -    &dev_attr_capabilities.attr,
>>>>> +    &dev_attr_media_capabilities.attr,
>>>>>         &dev_attr_groups.attr,
>>>>>       &dev_attr_punits.attr,
>>>>
>>>> With the mccap changes, it should make sense to keep the capabilities
>>>> as is.
>>> The change adds mccap, but sysfs points to cap, which is wrong. This
>>> patch is needed. Otherwise, we change the name of mccap to cap, which
>>> is _very_ confusing to people familiar to both specs. We can change
>>> the name of mccap to cap in a future spec revision.
>>> Javier
>>
>> Think of the sysfs capabilities as an abstract value that defines generic capabilities. It is not directly tied to either 1.2 or 2.0.
> 
> I?m thinking about the user looking at sysfs and at the spec at the same time - I myself get confused when names don?t match.
> 
> Anyway, I?ll keep it the way it was and add a comment for clarification. Would that work for you?
> 

That works. One may also wait until it is going to be used, e.g., when 
vector copy is implemented. Then it's natural to revisit.

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 03/20] lightnvm: fix capabilities for 2.0 sysfs
  2018-02-22 11:10             ` Matias Bjørling
@ 2018-02-22 11:12               ` Javier Gonzalez
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier Gonzalez @ 2018-02-22 11:12 UTC (permalink / raw)
  To: Matias Bjørling; +Cc: linux-block, linux-kernel, linux-nvme

[-- Attachment #1: Type: text/plain, Size: 5218 bytes --]

> On 22 Feb 2018, at 12.10, Matias Bjørling <mb@lightnvm.io> wrote:
> 
> On 02/22/2018 11:25 AM, Javier Gonzalez wrote:
>>> On 22 Feb 2018, at 10.39, Matias Bjørling <mb@lightnvm.io> wrote:
>>> 
>>> On 02/22/2018 08:47 AM, Javier Gonzalez wrote:
>>>>> On 22 Feb 2018, at 08.28, Matias Bjørling <mb@lightnvm.io> wrote:
>>>>> 
>>>>>> On 02/21/2018 10:26 AM, Javier González wrote:
>>>>>> Both 1.2 and 2.0 specs define a field for media and controller
>>>>>> capabilities. Also, 1.2 defines a separate field dedicated to device
>>>>>> capabilities.
>>>>>> In 2.0 sysfs, this values have been mixed. Revert them to the right
>>>>>> value.
>>>>>> Signed-off-by: Javier González <javier@cnexlabs.com>
>>>>>> ---
>>>>>>  drivers/nvme/host/lightnvm.c | 18 +++++++++---------
>>>>>>  1 file changed, 9 insertions(+), 9 deletions(-)
>>>>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>>>>> index 969bb874850c..598abba66f52 100644
>>>>>> --- a/drivers/nvme/host/lightnvm.c
>>>>>> +++ b/drivers/nvme/host/lightnvm.c
>>>>>> @@ -914,8 +914,8 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>>>>>        if (strcmp(attr->name, "version") == 0) {
>>>>>>          return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>>>>>> -    } else if (strcmp(attr->name, "capabilities") == 0) {
>>>>>> -        return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
>>>>>> +    } else if (strcmp(attr->name, "media_capabilities") == 0) {
>>>>>> +        return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
>>>>>>      } else if (strcmp(attr->name, "read_typ") == 0) {
>>>>>>          return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>>>>>>      } else if (strcmp(attr->name, "read_max") == 0) {
>>>>>> @@ -993,8 +993,8 @@ static ssize_t nvm_dev_attr_show_12(struct device *dev,
>>>>>>          return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>>>>>      } else if (strcmp(attr->name, "multiplane_modes") == 0) {
>>>>>>          return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
>>>>>> -    } else if (strcmp(attr->name, "media_capabilities") == 0) {
>>>>>> -        return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
>>>>>> +    } else if (strcmp(attr->name, "capabilities") == 0) {
>>>>>> +        return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.cap);
>>>>>>      } else if (strcmp(attr->name, "max_phys_secs") == 0) {
>>>>>>          return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>>>>>>      } else {
>>>>>> @@ -1055,7 +1055,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>>>>>>    /* general attributes */
>>>>>>  static NVM_DEV_ATTR_RO(version);
>>>>>> -static NVM_DEV_ATTR_RO(capabilities);
>>>>>> +static NVM_DEV_ATTR_RO(media_capabilities);
>>>>>>    static NVM_DEV_ATTR_RO(read_typ);
>>>>>>  static NVM_DEV_ATTR_RO(read_max);
>>>>>> @@ -1080,12 +1080,12 @@ static NVM_DEV_ATTR_12_RO(prog_max);
>>>>>>  static NVM_DEV_ATTR_12_RO(erase_typ);
>>>>>>  static NVM_DEV_ATTR_12_RO(erase_max);
>>>>>>  static NVM_DEV_ATTR_12_RO(multiplane_modes);
>>>>>> -static NVM_DEV_ATTR_12_RO(media_capabilities);
>>>>>> +static NVM_DEV_ATTR_12_RO(capabilities);
>>>>>>  static NVM_DEV_ATTR_12_RO(max_phys_secs);
>>>>>>    static struct attribute *nvm_dev_attrs_12[] = {
>>>>>>      &dev_attr_version.attr,
>>>>>> -    &dev_attr_capabilities.attr,
>>>>>> +    &dev_attr_media_capabilities.attr,
>>>>>>        &dev_attr_vendor_opcode.attr,
>>>>>>      &dev_attr_device_mode.attr,
>>>>>> @@ -1108,7 +1108,7 @@ static struct attribute *nvm_dev_attrs_12[] = {
>>>>>>      &dev_attr_erase_typ.attr,
>>>>>>      &dev_attr_erase_max.attr,
>>>>>>      &dev_attr_multiplane_modes.attr,
>>>>>> -    &dev_attr_media_capabilities.attr,
>>>>>> +    &dev_attr_capabilities.attr,
>>>>>>      &dev_attr_max_phys_secs.attr,
>>>>>>        NULL,
>>>>>> @@ -1134,7 +1134,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
>>>>>>    static struct attribute *nvm_dev_attrs_20[] = {
>>>>>>      &dev_attr_version.attr,
>>>>>> -    &dev_attr_capabilities.attr,
>>>>>> +    &dev_attr_media_capabilities.attr,
>>>>>>        &dev_attr_groups.attr,
>>>>>>      &dev_attr_punits.attr,
>>>>> 
>>>>> With the mccap changes, it should make sense to keep the capabilities
>>>>> as is.
>>>> The change adds mccap, but sysfs points to cap, which is wrong. This
>>>> patch is needed. Otherwise, we change the name of mccap to cap, which
>>>> is _very_ confusing to people familiar to both specs. We can change
>>>> the name of mccap to cap in a future spec revision.
>>>> Javier
>>> 
>>> Think of the sysfs capabilities as an abstract value that defines generic capabilities. It is not directly tied to either 1.2 or 2.0.
>> I’m thinking about the user looking at sysfs and at the spec at the same time - I myself get confused when names don’t match.
>> Anyway, I’ll keep it the way it was and add a comment for clarification. Would that work for you?
> 
> That works. One may also wait until it is going to be used, e.g., when
> vector copy is implemented. Then it's natural to revisit.

Ok. Let's do that then. I'll drop the 2 patches then.

Javier

[-- Attachment #2: Message signed with OpenPGP --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 03/20] lightnvm: fix capabilities for 2.0 sysfs
@ 2018-02-22 11:12               ` Javier Gonzalez
  0 siblings, 0 replies; 99+ messages in thread
From: Javier Gonzalez @ 2018-02-22 11:12 UTC (permalink / raw)


> On 22 Feb 2018,@12.10, Matias Bj?rling <mb@lightnvm.io> wrote:
> 
> On 02/22/2018 11:25 AM, Javier Gonzalez wrote:
>>> On 22 Feb 2018,@10.39, Matias Bj?rling <mb@lightnvm.io> wrote:
>>> 
>>> On 02/22/2018 08:47 AM, Javier Gonzalez wrote:
>>>>> On 22 Feb 2018,@08.28, Matias Bj?rling <mb@lightnvm.io> wrote:
>>>>> 
>>>>>> On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
>>>>>> Both 1.2 and 2.0 specs define a field for media and controller
>>>>>> capabilities. Also, 1.2 defines a separate field dedicated to device
>>>>>> capabilities.
>>>>>> In 2.0 sysfs, this values have been mixed. Revert them to the right
>>>>>> value.
>>>>>> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
>>>>>> ---
>>>>>>  drivers/nvme/host/lightnvm.c | 18 +++++++++---------
>>>>>>  1 file changed, 9 insertions(+), 9 deletions(-)
>>>>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>>>>> index 969bb874850c..598abba66f52 100644
>>>>>> --- a/drivers/nvme/host/lightnvm.c
>>>>>> +++ b/drivers/nvme/host/lightnvm.c
>>>>>> @@ -914,8 +914,8 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>>>>>        if (strcmp(attr->name, "version") == 0) {
>>>>>>          return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>>>>>> -    } else if (strcmp(attr->name, "capabilities") == 0) {
>>>>>> -        return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
>>>>>> +    } else if (strcmp(attr->name, "media_capabilities") == 0) {
>>>>>> +        return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mccap);
>>>>>>      } else if (strcmp(attr->name, "read_typ") == 0) {
>>>>>>          return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>>>>>>      } else if (strcmp(attr->name, "read_max") == 0) {
>>>>>> @@ -993,8 +993,8 @@ static ssize_t nvm_dev_attr_show_12(struct device *dev,
>>>>>>          return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>>>>>      } else if (strcmp(attr->name, "multiplane_modes") == 0) {
>>>>>>          return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
>>>>>> -    } else if (strcmp(attr->name, "media_capabilities") == 0) {
>>>>>> -        return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
>>>>>> +    } else if (strcmp(attr->name, "capabilities") == 0) {
>>>>>> +        return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.cap);
>>>>>>      } else if (strcmp(attr->name, "max_phys_secs") == 0) {
>>>>>>          return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>>>>>>      } else {
>>>>>> @@ -1055,7 +1055,7 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>>>>>>    /* general attributes */
>>>>>>  static NVM_DEV_ATTR_RO(version);
>>>>>> -static NVM_DEV_ATTR_RO(capabilities);
>>>>>> +static NVM_DEV_ATTR_RO(media_capabilities);
>>>>>>    static NVM_DEV_ATTR_RO(read_typ);
>>>>>>  static NVM_DEV_ATTR_RO(read_max);
>>>>>> @@ -1080,12 +1080,12 @@ static NVM_DEV_ATTR_12_RO(prog_max);
>>>>>>  static NVM_DEV_ATTR_12_RO(erase_typ);
>>>>>>  static NVM_DEV_ATTR_12_RO(erase_max);
>>>>>>  static NVM_DEV_ATTR_12_RO(multiplane_modes);
>>>>>> -static NVM_DEV_ATTR_12_RO(media_capabilities);
>>>>>> +static NVM_DEV_ATTR_12_RO(capabilities);
>>>>>>  static NVM_DEV_ATTR_12_RO(max_phys_secs);
>>>>>>    static struct attribute *nvm_dev_attrs_12[] = {
>>>>>>      &dev_attr_version.attr,
>>>>>> -    &dev_attr_capabilities.attr,
>>>>>> +    &dev_attr_media_capabilities.attr,
>>>>>>        &dev_attr_vendor_opcode.attr,
>>>>>>      &dev_attr_device_mode.attr,
>>>>>> @@ -1108,7 +1108,7 @@ static struct attribute *nvm_dev_attrs_12[] = {
>>>>>>      &dev_attr_erase_typ.attr,
>>>>>>      &dev_attr_erase_max.attr,
>>>>>>      &dev_attr_multiplane_modes.attr,
>>>>>> -    &dev_attr_media_capabilities.attr,
>>>>>> +    &dev_attr_capabilities.attr,
>>>>>>      &dev_attr_max_phys_secs.attr,
>>>>>>        NULL,
>>>>>> @@ -1134,7 +1134,7 @@ static NVM_DEV_ATTR_20_RO(reset_max);
>>>>>>    static struct attribute *nvm_dev_attrs_20[] = {
>>>>>>      &dev_attr_version.attr,
>>>>>> -    &dev_attr_capabilities.attr,
>>>>>> +    &dev_attr_media_capabilities.attr,
>>>>>>        &dev_attr_groups.attr,
>>>>>>      &dev_attr_punits.attr,
>>>>> 
>>>>> With the mccap changes, it should make sense to keep the capabilities
>>>>> as is.
>>>> The change adds mccap, but sysfs points to cap, which is wrong. This
>>>> patch is needed. Otherwise, we change the name of mccap to cap, which
>>>> is _very_ confusing to people familiar to both specs. We can change
>>>> the name of mccap to cap in a future spec revision.
>>>> Javier
>>> 
>>> Think of the sysfs capabilities as an abstract value that defines generic capabilities. It is not directly tied to either 1.2 or 2.0.
>> I?m thinking about the user looking at sysfs and at the spec at the same time - I myself get confused when names don?t match.
>> Anyway, I?ll keep it the way it was and add a comment for clarification. Would that work for you?
> 
> That works. One may also wait until it is going to be used, e.g., when
> vector copy is implemented. Then it's natural to revisit.

Ok. Let's do that then. I'll drop the 2 patches then.

Javier
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: Message signed with OpenPGP
URL: <http://lists.infradead.org/pipermail/linux-nvme/attachments/20180222/baf7e8b4/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 01/20] lightnvm: simplify geometry structure.
  2018-02-22  7:44       ` Javier Gonzalez
@ 2018-02-22 12:22         ` Matias Bjørling
  -1 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22 12:22 UTC (permalink / raw)
  To: Javier Gonzalez; +Cc: linux-block, linux-kernel, linux-nvme

On 02/22/2018 08:44 AM, Javier Gonzalez wrote:
> 
>> On 22 Feb 2018, at 08.25, Matias Bjørling <mb@lightnvm.io> wrote:
>>
>> On 02/21/2018 10:26 AM, Javier González wrote:
>>> Currently, the device geometry is stored redundantly in the nvm_id and
>>> nvm_geo structures at a device level. Moreover, when instantiating
>>> targets on a specific number of LUNs, these structures are replicated
>>> and manually modified to fit the instance channel and LUN partitioning.
>>> Instead, create a generic geometry around two base structures:
>>> nvm_dev_geo, which describes the geometry of the whole device and
>>> nvm_geo, which describes the geometry of the instance. Since these share
>>> a big part of the geometry, create a nvm_common_geo structure that keeps
>>> the static geoometry values that are shared across instances.
>>> As we introduce support for 2.0, these structures allow to abstract
>>> spec. specific values and present a common geometry to targets.
>>> Signed-off-by: Javier González <javier@cnexlabs.com>
>>> ---
>>>   drivers/lightnvm/core.c          | 137 +++++++---------
>>>   drivers/lightnvm/pblk-core.c     |  16 +-
>>>   drivers/lightnvm/pblk-gc.c       |   2 +-
>>>   drivers/lightnvm/pblk-init.c     | 123 +++++++-------
>>>   drivers/lightnvm/pblk-read.c     |   2 +-
>>>   drivers/lightnvm/pblk-recovery.c |  14 +-
>>>   drivers/lightnvm/pblk-rl.c       |   2 +-
>>>   drivers/lightnvm/pblk-sysfs.c    |  39 +++--
>>>   drivers/lightnvm/pblk-write.c    |   2 +-
>>>   drivers/lightnvm/pblk.h          |  93 +++++------
>>>   drivers/nvme/host/lightnvm.c     | 339 +++++++++++++++++++++++----------------
>>>   include/linux/lightnvm.h         | 204 ++++++++++++-----------
>>>   12 files changed, 514 insertions(+), 459 deletions(-)
>>> diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
>>> index 689c97b97775..42596afdf64c 100644
>>> --- a/drivers/lightnvm/core.c
>>> +++ b/drivers/lightnvm/core.c
>>> @@ -111,6 +111,7 @@ static void nvm_release_luns_err(struct nvm_dev *dev, int lun_begin,
>>>   static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
>>>   {
>>>   	struct nvm_dev *dev = tgt_dev->parent;
>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>   	struct nvm_dev_map *dev_map = tgt_dev->map;
>>>   	int i, j;
>>>   @@ -122,7 +123,7 @@ static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
>>>   		if (clear) {
>>>   			for (j = 0; j < ch_map->nr_luns; j++) {
>>>   				int lun = j + lun_offs[j];
>>> -				int lunid = (ch * dev->geo.nr_luns) + lun;
>>> +				int lunid = (ch * dev_geo->nr_luns) + lun;
>>>     				WARN_ON(!test_and_clear_bit(lunid,
>>>   							dev->lun_map));
>>> @@ -143,19 +144,20 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>>>   					      u16 lun_begin, u16 lun_end,
>>>   					      u16 op)
>>>   {
>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>   	struct nvm_tgt_dev *tgt_dev = NULL;
>>>   	struct nvm_dev_map *dev_rmap = dev->rmap;
>>>   	struct nvm_dev_map *dev_map;
>>>   	struct ppa_addr *luns;
>>>   	int nr_luns = lun_end - lun_begin + 1;
>>>   	int luns_left = nr_luns;
>>> -	int nr_chnls = nr_luns / dev->geo.nr_luns;
>>> -	int nr_chnls_mod = nr_luns % dev->geo.nr_luns;
>>> -	int bch = lun_begin / dev->geo.nr_luns;
>>> -	int blun = lun_begin % dev->geo.nr_luns;
>>> +	int nr_chnls = nr_luns / dev_geo->nr_luns;
>>> +	int nr_chnls_mod = nr_luns % dev_geo->nr_luns;
>>> +	int bch = lun_begin / dev_geo->nr_luns;
>>> +	int blun = lun_begin % dev_geo->nr_luns;
>>>   	int lunid = 0;
>>>   	int lun_balanced = 1;
>>> -	int prev_nr_luns;
>>> +	int sec_per_lun, prev_nr_luns;
>>>   	int i, j;
>>>     	nr_chnls = (nr_chnls_mod == 0) ? nr_chnls : nr_chnls + 1;
>>> @@ -173,15 +175,15 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>>>   	if (!luns)
>>>   		goto err_luns;
>>>   -	prev_nr_luns = (luns_left > dev->geo.nr_luns) ?
>>> -					dev->geo.nr_luns : luns_left;
>>> +	prev_nr_luns = (luns_left > dev_geo->nr_luns) ?
>>> +					dev_geo->nr_luns : luns_left;
>>>   	for (i = 0; i < nr_chnls; i++) {
>>>   		struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[i + bch];
>>>   		int *lun_roffs = ch_rmap->lun_offs;
>>>   		struct nvm_ch_map *ch_map = &dev_map->chnls[i];
>>>   		int *lun_offs;
>>> -		int luns_in_chnl = (luns_left > dev->geo.nr_luns) ?
>>> -					dev->geo.nr_luns : luns_left;
>>> +		int luns_in_chnl = (luns_left > dev_geo->nr_luns) ?
>>> +					dev_geo->nr_luns : luns_left;
>>>     		if (lun_balanced && prev_nr_luns != luns_in_chnl)
>>>   			lun_balanced = 0;
>>> @@ -215,18 +217,22 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>>>   	if (!tgt_dev)
>>>   		goto err_ch;
>>>   -	memcpy(&tgt_dev->geo, &dev->geo, sizeof(struct nvm_geo));
>>>   	/* Target device only owns a portion of the physical device */
>>>   	tgt_dev->geo.nr_chnls = nr_chnls;
>>> -	tgt_dev->geo.all_luns = nr_luns;
>>>   	tgt_dev->geo.nr_luns = (lun_balanced) ? prev_nr_luns : -1;
>>> +	tgt_dev->geo.all_luns = nr_luns;
>>> +	tgt_dev->geo.all_chunks = nr_luns * dev_geo->c.num_chk;
>>> +
>>>   	tgt_dev->geo.op = op;
>>> -	tgt_dev->total_secs = nr_luns * tgt_dev->geo.sec_per_lun;
>>> +
>>> +	sec_per_lun = dev_geo->c.clba * dev_geo->c.num_chk;
>>> +	tgt_dev->geo.total_secs = nr_luns * sec_per_lun;
>>> +
>>> +	tgt_dev->geo.c = dev_geo->c;
>>> +
>>>   	tgt_dev->q = dev->q;
>>>   	tgt_dev->map = dev_map;
>>>   	tgt_dev->luns = luns;
>>> -	memcpy(&tgt_dev->identity, &dev->identity, sizeof(struct nvm_id));
>>> -
>>>   	tgt_dev->parent = dev;
>>>     	return tgt_dev;
>>> @@ -268,12 +274,12 @@ static struct nvm_tgt_type *nvm_find_target_type(const char *name)
>>>   	return tt;
>>>   }
>>>   -static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
>>> +static int nvm_config_check_luns(struct nvm_dev_geo *dev_geo, int lun_begin,
>>>   				 int lun_end)
>>>   {
>>> -	if (lun_begin > lun_end || lun_end >= geo->all_luns) {
>>> +	if (lun_begin > lun_end || lun_end >= dev_geo->all_luns) {
>>>   		pr_err("nvm: lun out of bound (%u:%u > %u)\n",
>>> -			lun_begin, lun_end, geo->all_luns - 1);
>>> +			lun_begin, lun_end, dev_geo->all_luns - 1);
>>>   		return -EINVAL;
>>>   	}
>>>   @@ -283,24 +289,24 @@ static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
>>>   static int __nvm_config_simple(struct nvm_dev *dev,
>>>   			       struct nvm_ioctl_create_simple *s)
>>>   {
>>> -	struct nvm_geo *geo = &dev->geo;
>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>     	if (s->lun_begin == -1 && s->lun_end == -1) {
>>>   		s->lun_begin = 0;
>>> -		s->lun_end = geo->all_luns - 1;
>>> +		s->lun_end = dev_geo->all_luns - 1;
>>>   	}
>>>   -	return nvm_config_check_luns(geo, s->lun_begin, s->lun_end);
>>> +	return nvm_config_check_luns(dev_geo, s->lun_begin, s->lun_end);
>>>   }
>>>     static int __nvm_config_extended(struct nvm_dev *dev,
>>>   				 struct nvm_ioctl_create_extended *e)
>>>   {
>>> -	struct nvm_geo *geo = &dev->geo;
>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>     	if (e->lun_begin == 0xFFFF && e->lun_end == 0xFFFF) {
>>>   		e->lun_begin = 0;
>>> -		e->lun_end = dev->geo.all_luns - 1;
>>> +		e->lun_end = dev_geo->all_luns - 1;
>>>   	}
>>>     	/* op not set falls into target's default */
>>> @@ -313,7 +319,7 @@ static int __nvm_config_extended(struct nvm_dev *dev,
>>>   		return -EINVAL;
>>>   	}
>>>   -	return nvm_config_check_luns(geo, e->lun_begin, e->lun_end);
>>> +	return nvm_config_check_luns(dev_geo, e->lun_begin, e->lun_end);
>>>   }
>>>     static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
>>> @@ -408,7 +414,7 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
>>>   	tqueue->queuedata = targetdata;
>>>     	blk_queue_max_hw_sectors(tqueue,
>>> -			(dev->geo.sec_size >> 9) * NVM_MAX_VLBA);
>>> +			(dev->dev_geo.c.csecs >> 9) * NVM_MAX_VLBA);
>>>     	set_capacity(tdisk, tt->capacity(targetdata));
>>>   	add_disk(tdisk);
>>> @@ -497,6 +503,7 @@ static int nvm_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove)
>>>     static int nvm_register_map(struct nvm_dev *dev)
>>>   {
>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>   	struct nvm_dev_map *rmap;
>>>   	int i, j;
>>>   @@ -504,15 +511,15 @@ static int nvm_register_map(struct nvm_dev *dev)
>>>   	if (!rmap)
>>>   		goto err_rmap;
>>>   -	rmap->chnls = kcalloc(dev->geo.nr_chnls, sizeof(struct nvm_ch_map),
>>> +	rmap->chnls = kcalloc(dev_geo->nr_chnls, sizeof(struct nvm_ch_map),
>>>   								GFP_KERNEL);
>>>   	if (!rmap->chnls)
>>>   		goto err_chnls;
>>>   -	for (i = 0; i < dev->geo.nr_chnls; i++) {
>>> +	for (i = 0; i < dev_geo->nr_chnls; i++) {
>>>   		struct nvm_ch_map *ch_rmap;
>>>   		int *lun_roffs;
>>> -		int luns_in_chnl = dev->geo.nr_luns;
>>> +		int luns_in_chnl = dev_geo->nr_luns;
>>>     		ch_rmap = &rmap->chnls[i];
>>>   @@ -543,10 +550,11 @@ static int nvm_register_map(struct nvm_dev *dev)
>>>     static void nvm_unregister_map(struct nvm_dev *dev)
>>>   {
>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>   	struct nvm_dev_map *rmap = dev->rmap;
>>>   	int i;
>>>   -	for (i = 0; i < dev->geo.nr_chnls; i++)
>>> +	for (i = 0; i < dev_geo->nr_chnls; i++)
>>>   		kfree(rmap->chnls[i].lun_offs);
>>>     	kfree(rmap->chnls);
>>> @@ -675,7 +683,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
>>>   	int i, plane_cnt, pl_idx;
>>>   	struct ppa_addr ppa;
>>>   -	if (geo->plane_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
>>> +	if (geo->c.pln_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
>>>   		rqd->nr_ppas = nr_ppas;
>>>   		rqd->ppa_addr = ppas[0];
>>>   @@ -689,7 +697,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
>>>   		return -ENOMEM;
>>>   	}
>>>   -	plane_cnt = geo->plane_mode;
>>> +	plane_cnt = geo->c.pln_mode;
>>>   	rqd->nr_ppas *= plane_cnt;
>>>     	for (i = 0; i < nr_ppas; i++) {
>>> @@ -804,18 +812,18 @@ EXPORT_SYMBOL(nvm_end_io);
>>>    */
>>>   int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
>>>   {
>>> -	struct nvm_geo *geo = &dev->geo;
>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>   	int blk, offset, pl, blktype;
>>>   -	if (nr_blks != geo->nr_chks * geo->plane_mode)
>>> +	if (nr_blks != dev_geo->c.num_chk * dev_geo->c.pln_mode)
>>>   		return -EINVAL;
>>>   -	for (blk = 0; blk < geo->nr_chks; blk++) {
>>> -		offset = blk * geo->plane_mode;
>>> +	for (blk = 0; blk < dev_geo->c.num_chk; blk++) {
>>> +		offset = blk * dev_geo->c.pln_mode;
>>>   		blktype = blks[offset];
>>>     		/* Bad blocks on any planes take precedence over other types */
>>> -		for (pl = 0; pl < geo->plane_mode; pl++) {
>>> +		for (pl = 0; pl < dev_geo->c.pln_mode; pl++) {
>>>   			if (blks[offset + pl] &
>>>   					(NVM_BLK_T_BAD|NVM_BLK_T_GRWN_BAD)) {
>>>   				blktype = blks[offset + pl];
>>> @@ -826,7 +834,7 @@ int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
>>>   		blks[blk] = blktype;
>>>   	}
>>>   -	return geo->nr_chks;
>>> +	return dev_geo->c.num_chk;
>>>   }
>>>   EXPORT_SYMBOL(nvm_bb_tbl_fold);
>>>   @@ -843,41 +851,10 @@ EXPORT_SYMBOL(nvm_get_tgt_bb_tbl);
>>>     static int nvm_core_init(struct nvm_dev *dev)
>>>   {
>>> -	struct nvm_id *id = &dev->identity;
>>> -	struct nvm_geo *geo = &dev->geo;
>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>   	int ret;
>>>   -	memcpy(&geo->ppaf, &id->ppaf, sizeof(struct nvm_addr_format));
>>> -
>>> -	if (id->mtype != 0) {
>>> -		pr_err("nvm: memory type not supported\n");
>>> -		return -EINVAL;
>>> -	}
>>> -
>>> -	/* Whole device values */
>>> -	geo->nr_chnls = id->num_ch;
>>> -	geo->nr_luns = id->num_lun;
>>> -
>>> -	/* Generic device geometry values */
>>> -	geo->ws_min = id->ws_min;
>>> -	geo->ws_opt = id->ws_opt;
>>> -	geo->ws_seq = id->ws_seq;
>>> -	geo->ws_per_chk = id->ws_per_chk;
>>> -	geo->nr_chks = id->num_chk;
>>> -	geo->mccap = id->mccap;
>>> -
>>> -	geo->sec_per_chk = id->clba;
>>> -	geo->sec_per_lun = geo->sec_per_chk * geo->nr_chks;
>>> -	geo->all_luns = geo->nr_luns * geo->nr_chnls;
>>> -
>>> -	/* 1.2 spec device geometry values */
>>> -	geo->plane_mode = 1 << geo->ws_seq;
>>> -	geo->nr_planes = geo->ws_opt / geo->ws_min;
>>> -	geo->sec_per_pg = geo->ws_min;
>>> -	geo->sec_per_pl = geo->sec_per_pg * geo->nr_planes;
>>> -
>>> -	dev->total_secs = geo->all_luns * geo->sec_per_lun;
>>> -	dev->lun_map = kcalloc(BITS_TO_LONGS(geo->all_luns),
>>> +	dev->lun_map = kcalloc(BITS_TO_LONGS(dev_geo->all_luns),
>>>   					sizeof(unsigned long), GFP_KERNEL);
>>>   	if (!dev->lun_map)
>>>   		return -ENOMEM;
>>> @@ -912,19 +889,17 @@ static void nvm_free(struct nvm_dev *dev)
>>>     static int nvm_init(struct nvm_dev *dev)
>>>   {
>>> -	struct nvm_geo *geo = &dev->geo;
>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>   	int ret = -EINVAL;
>>>   -	if (dev->ops->identity(dev, &dev->identity)) {
>>> +	if (dev->ops->identity(dev)) {
>>>   		pr_err("nvm: device could not be identified\n");
>>>   		goto err;
>>>   	}
>>>   -	if (dev->identity.ver_id != 1 && dev->identity.ver_id != 2) {
>>> -		pr_err("nvm: device ver_id %d not supported by kernel.\n",
>>> -				dev->identity.ver_id);
>>> -		goto err;
>>> -	}
>>> +	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
>>> +				dev_geo->ver_id,
>>> +				dev_geo->c.vmnt);
>>>     	ret = nvm_core_init(dev);
>>>   	if (ret) {
>>> @@ -932,10 +907,10 @@ static int nvm_init(struct nvm_dev *dev)
>>>   		goto err;
>>>   	}
>>>   -	pr_info("nvm: registered %s [%u/%u/%u/%u/%u/%u]\n",
>>> -			dev->name, geo->sec_per_pg, geo->nr_planes,
>>> -			geo->ws_per_chk, geo->nr_chks,
>>> -			geo->all_luns, geo->nr_chnls);
>>> +	pr_info("nvm: registered %s [%u/%u/%u/%u/%u]\n",
>>> +			dev->name, dev_geo->c.ws_min, dev_geo->c.ws_opt,
>>> +			dev_geo->c.num_chk, dev_geo->all_luns,
>>> +			dev_geo->nr_chnls);
>>>   	return 0;
>>>   err:
>>>   	pr_err("nvm: failed to initialize nvm\n");
>>> diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
>>> index 22e61cd4f801..519af8b9eab7 100644
>>> --- a/drivers/lightnvm/pblk-core.c
>>> +++ b/drivers/lightnvm/pblk-core.c
>>> @@ -613,7 +613,7 @@ static int pblk_line_submit_emeta_io(struct pblk *pblk, struct pblk_line *line,
>>>   	memset(&rqd, 0, sizeof(struct nvm_rq));
>>>     	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>> -	rq_len = rq_ppas * geo->sec_size;
>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>     	bio = pblk_bio_map_addr(pblk, emeta_buf, rq_ppas, rq_len,
>>>   					l_mg->emeta_alloc_type, GFP_KERNEL);
>>> @@ -722,7 +722,7 @@ u64 pblk_line_smeta_start(struct pblk *pblk, struct pblk_line *line)
>>>   	if (bit >= lm->blk_per_line)
>>>   		return -1;
>>>   -	return bit * geo->sec_per_pl;
>>> +	return bit * geo->c.ws_opt;
>>>   }
>>>     static int pblk_line_submit_smeta_io(struct pblk *pblk, struct pblk_line *line,
>>> @@ -1035,19 +1035,19 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>>>   	/* Capture bad block information on line mapping bitmaps */
>>>   	while ((bit = find_next_bit(line->blk_bitmap, lm->blk_per_line,
>>>   					bit + 1)) < lm->blk_per_line) {
>>> -		off = bit * geo->sec_per_pl;
>>> +		off = bit * geo->c.ws_opt;
>>>   		bitmap_shift_left(l_mg->bb_aux, l_mg->bb_template, off,
>>>   							lm->sec_per_line);
>>>   		bitmap_or(line->map_bitmap, line->map_bitmap, l_mg->bb_aux,
>>>   							lm->sec_per_line);
>>> -		line->sec_in_line -= geo->sec_per_chk;
>>> +		line->sec_in_line -= geo->c.clba;
>>>   		if (bit >= lm->emeta_bb)
>>>   			nr_bb++;
>>>   	}
>>>     	/* Mark smeta metadata sectors as bad sectors */
>>>   	bit = find_first_zero_bit(line->blk_bitmap, lm->blk_per_line);
>>> -	off = bit * geo->sec_per_pl;
>>> +	off = bit * geo->c.ws_opt;
>>>   	bitmap_set(line->map_bitmap, off, lm->smeta_sec);
>>>   	line->sec_in_line -= lm->smeta_sec;
>>>   	line->smeta_ssec = off;
>>> @@ -1066,10 +1066,10 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>>>   	emeta_secs = lm->emeta_sec[0];
>>>   	off = lm->sec_per_line;
>>>   	while (emeta_secs) {
>>> -		off -= geo->sec_per_pl;
>>> +		off -= geo->c.ws_opt;
>>>   		if (!test_bit(off, line->invalid_bitmap)) {
>>> -			bitmap_set(line->invalid_bitmap, off, geo->sec_per_pl);
>>> -			emeta_secs -= geo->sec_per_pl;
>>> +			bitmap_set(line->invalid_bitmap, off, geo->c.ws_opt);
>>> +			emeta_secs -= geo->c.ws_opt;
>>>   		}
>>>   	}
>>>   diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c
>>> index 320f99af99e9..16afea3f5541 100644
>>> --- a/drivers/lightnvm/pblk-gc.c
>>> +++ b/drivers/lightnvm/pblk-gc.c
>>> @@ -88,7 +88,7 @@ static void pblk_gc_line_ws(struct work_struct *work)
>>>     	up(&gc->gc_sem);
>>>   -	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->sec_size);
>>> +	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->c.csecs);
>>>   	if (!gc_rq->data) {
>>>   		pr_err("pblk: could not GC line:%d (%d/%d)\n",
>>>   					line->id, *line->vsc, gc_rq->nr_secs);
>>> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
>>> index 5261702e9ff7..95ecb0ec736b 100644
>>> --- a/drivers/lightnvm/pblk-init.c
>>> +++ b/drivers/lightnvm/pblk-init.c
>>> @@ -146,7 +146,7 @@ static int pblk_rwb_init(struct pblk *pblk)
>>>   		return -ENOMEM;
>>>     	power_size = get_count_order(nr_entries);
>>> -	power_seg_sz = get_count_order(geo->sec_size);
>>> +	power_seg_sz = get_count_order(geo->c.csecs);
>>>     	return pblk_rb_init(&pblk->rwb, entries, power_size, power_seg_sz);
>>>   }
>>> @@ -154,11 +154,11 @@ static int pblk_rwb_init(struct pblk *pblk)
>>>   /* Minimum pages needed within a lun */
>>>   #define ADDR_POOL_SIZE 64
>>>   -static int pblk_set_ppaf(struct pblk *pblk)
>>> +static int pblk_set_addrf_12(struct nvm_geo *geo,
>>> +			     struct nvm_addr_format_12 *dst)
>>>   {
>>> -	struct nvm_tgt_dev *dev = pblk->dev;
>>> -	struct nvm_geo *geo = &dev->geo;
>>> -	struct nvm_addr_format ppaf = geo->ppaf;
>>> +	struct nvm_addr_format_12 *src =
>>> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>>>   	int power_len;
>>>     	/* Re-calculate channel and lun format to adapt to configuration */
>>> @@ -167,34 +167,50 @@ static int pblk_set_ppaf(struct pblk *pblk)
>>>   		pr_err("pblk: supports only power-of-two channel config.\n");
>>>   		return -EINVAL;
>>>   	}
>>> -	ppaf.ch_len = power_len;
>>> +	dst->ch_len = power_len;
>>>     	power_len = get_count_order(geo->nr_luns);
>>>   	if (1 << power_len != geo->nr_luns) {
>>>   		pr_err("pblk: supports only power-of-two LUN config.\n");
>>>   		return -EINVAL;
>>>   	}
>>> -	ppaf.lun_len = power_len;
>>> +	dst->lun_len = power_len;
>>>   -	pblk->ppaf.sec_offset = 0;
>>> -	pblk->ppaf.pln_offset = ppaf.sect_len;
>>> -	pblk->ppaf.ch_offset = pblk->ppaf.pln_offset + ppaf.pln_len;
>>> -	pblk->ppaf.lun_offset = pblk->ppaf.ch_offset + ppaf.ch_len;
>>> -	pblk->ppaf.pg_offset = pblk->ppaf.lun_offset + ppaf.lun_len;
>>> -	pblk->ppaf.blk_offset = pblk->ppaf.pg_offset + ppaf.pg_len;
>>> -	pblk->ppaf.sec_mask = (1ULL << ppaf.sect_len) - 1;
>>> -	pblk->ppaf.pln_mask = ((1ULL << ppaf.pln_len) - 1) <<
>>> -							pblk->ppaf.pln_offset;
>>> -	pblk->ppaf.ch_mask = ((1ULL << ppaf.ch_len) - 1) <<
>>> -							pblk->ppaf.ch_offset;
>>> -	pblk->ppaf.lun_mask = ((1ULL << ppaf.lun_len) - 1) <<
>>> -							pblk->ppaf.lun_offset;
>>> -	pblk->ppaf.pg_mask = ((1ULL << ppaf.pg_len) - 1) <<
>>> -							pblk->ppaf.pg_offset;
>>> -	pblk->ppaf.blk_mask = ((1ULL << ppaf.blk_len) - 1) <<
>>> -							pblk->ppaf.blk_offset;
>>> +	dst->blk_len = src->blk_len;
>>> +	dst->pg_len = src->pg_len;
>>> +	dst->pln_len = src->pln_len;
>>> +	dst->sect_len = src->sect_len;
>>>   -	pblk->ppaf_bitsize = pblk->ppaf.blk_offset + ppaf.blk_len;
>>> +	dst->sect_offset = 0;
>>> +	dst->pln_offset = dst->sect_len;
>>> +	dst->ch_offset = dst->pln_offset + dst->pln_len;
>>> +	dst->lun_offset = dst->ch_offset + dst->ch_len;
>>> +	dst->pg_offset = dst->lun_offset + dst->lun_len;
>>> +	dst->blk_offset = dst->pg_offset + dst->pg_len;
>>> +
>>> +	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
>>> +	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
>>> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>>> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>>> +	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
>>> +	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
>>> +
>>> +	return dst->blk_offset + src->blk_len;
>>> +}
>>> +
>>> +static int pblk_set_ppaf(struct pblk *pblk)
>>> +{
>>> +	struct nvm_tgt_dev *dev = pblk->dev;
>>> +	struct nvm_geo *geo = &dev->geo;
>>> +	int mod;
>>> +
>>> +	div_u64_rem(geo->c.clba, pblk->min_write_pgs, &mod);
>>> +	if (mod) {
>>> +		pr_err("pblk: bad configuration of sectors/pages\n");
>>> +		return -EINVAL;
>>> +	}
>>> +
>>> +	pblk->ppaf_bitsize = pblk_set_addrf_12(geo, (void *)&pblk->ppaf);
>>>     	return 0;
>>>   }
>>> @@ -253,8 +269,7 @@ static int pblk_core_init(struct pblk *pblk)
>>>   	struct nvm_tgt_dev *dev = pblk->dev;
>>>   	struct nvm_geo *geo = &dev->geo;
>>>   -	pblk->pgs_in_buffer = NVM_MEM_PAGE_WRITE * geo->sec_per_pg *
>>> -						geo->nr_planes * geo->all_luns;
>>> +	pblk->pgs_in_buffer = geo->c.mw_cunits * geo->c.ws_opt * geo->all_luns;
>>>     	if (pblk_init_global_caches(pblk))
>>>   		return -ENOMEM;
>>> @@ -433,7 +448,7 @@ static void *pblk_bb_get_log(struct pblk *pblk)
>>>   	int i, nr_blks, blk_per_lun;
>>>   	int ret;
>>>   -	blk_per_lun = geo->nr_chks * geo->plane_mode;
>>> +	blk_per_lun = geo->c.num_chk * geo->c.pln_mode;
>>>   	nr_blks = blk_per_lun * geo->all_luns;
>>>     	log = kmalloc(nr_blks, GFP_KERNEL);
>>> @@ -551,18 +566,18 @@ static unsigned int calc_emeta_len(struct pblk *pblk)
>>>   	/* Round to sector size so that lba_list starts on its own sector */
>>>   	lm->emeta_sec[1] = DIV_ROUND_UP(
>>>   			sizeof(struct line_emeta) + lm->blk_bitmap_len +
>>> -			sizeof(struct wa_counters), geo->sec_size);
>>> -	lm->emeta_len[1] = lm->emeta_sec[1] * geo->sec_size;
>>> +			sizeof(struct wa_counters), geo->c.csecs);
>>> +	lm->emeta_len[1] = lm->emeta_sec[1] * geo->c.csecs;
>>>     	/* Round to sector size so that vsc_list starts on its own sector */
>>>   	lm->dsec_per_line = lm->sec_per_line - lm->emeta_sec[0];
>>>   	lm->emeta_sec[2] = DIV_ROUND_UP(lm->dsec_per_line * sizeof(u64),
>>> -			geo->sec_size);
>>> -	lm->emeta_len[2] = lm->emeta_sec[2] * geo->sec_size;
>>> +			geo->c.csecs);
>>> +	lm->emeta_len[2] = lm->emeta_sec[2] * geo->c.csecs;
>>>     	lm->emeta_sec[3] = DIV_ROUND_UP(l_mg->nr_lines * sizeof(u32),
>>> -			geo->sec_size);
>>> -	lm->emeta_len[3] = lm->emeta_sec[3] * geo->sec_size;
>>> +			geo->c.csecs);
>>> +	lm->emeta_len[3] = lm->emeta_sec[3] * geo->c.csecs;
>>>     	lm->vsc_list_len = l_mg->nr_lines * sizeof(u32);
>>>   @@ -593,13 +608,13 @@ static void pblk_set_provision(struct pblk *pblk, long nr_free_blks)
>>>   	 * on user capacity consider only provisioned blocks
>>>   	 */
>>>   	pblk->rl.total_blocks = nr_free_blks;
>>> -	pblk->rl.nr_secs = nr_free_blks * geo->sec_per_chk;
>>> +	pblk->rl.nr_secs = nr_free_blks * geo->c.clba;
>>>     	/* Consider sectors used for metadata */
>>>   	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
>>> -	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
>>> +	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
>>>   -	pblk->capacity = (provisioned - blk_meta) * geo->sec_per_chk;
>>> +	pblk->capacity = (provisioned - blk_meta) * geo->c.clba;
>>>     	atomic_set(&pblk->rl.free_blocks, nr_free_blks);
>>>   	atomic_set(&pblk->rl.free_user_blocks, nr_free_blks);
>>> @@ -710,10 +725,10 @@ static int pblk_lines_init(struct pblk *pblk)
>>>   	void *chunk_log;
>>>   	unsigned int smeta_len, emeta_len;
>>>   	long nr_bad_blks = 0, nr_free_blks = 0;
>>> -	int bb_distance, max_write_ppas, mod;
>>> +	int bb_distance, max_write_ppas;
>>>   	int i, ret;
>>>   -	pblk->min_write_pgs = geo->sec_per_pl * (geo->sec_size / PAGE_SIZE);
>>> +	pblk->min_write_pgs = geo->c.ws_opt * (geo->c.csecs / PAGE_SIZE);
>>>   	max_write_ppas = pblk->min_write_pgs * geo->all_luns;
>>>   	pblk->max_write_pgs = min_t(int, max_write_ppas, NVM_MAX_VLBA);
>>>   	pblk_set_sec_per_write(pblk, pblk->min_write_pgs);
>>> @@ -724,19 +739,13 @@ static int pblk_lines_init(struct pblk *pblk)
>>>   		return -EINVAL;
>>>   	}
>>>   -	div_u64_rem(geo->sec_per_chk, pblk->min_write_pgs, &mod);
>>> -	if (mod) {
>>> -		pr_err("pblk: bad configuration of sectors/pages\n");
>>> -		return -EINVAL;
>>> -	}
>>> -
>>> -	l_mg->nr_lines = geo->nr_chks;
>>> +	l_mg->nr_lines = geo->c.num_chk;
>>>   	l_mg->log_line = l_mg->data_line = NULL;
>>>   	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
>>>   	l_mg->nr_free_lines = 0;
>>>   	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
>>>   -	lm->sec_per_line = geo->sec_per_chk * geo->all_luns;
>>> +	lm->sec_per_line = geo->c.clba * geo->all_luns;
>>>   	lm->blk_per_line = geo->all_luns;
>>>   	lm->blk_bitmap_len = BITS_TO_LONGS(geo->all_luns) * sizeof(long);
>>>   	lm->sec_bitmap_len = BITS_TO_LONGS(lm->sec_per_line) * sizeof(long);
>>> @@ -750,8 +759,8 @@ static int pblk_lines_init(struct pblk *pblk)
>>>   	 */
>>>   	i = 1;
>>>   add_smeta_page:
>>> -	lm->smeta_sec = i * geo->sec_per_pl;
>>> -	lm->smeta_len = lm->smeta_sec * geo->sec_size;
>>> +	lm->smeta_sec = i * geo->c.ws_opt;
>>> +	lm->smeta_len = lm->smeta_sec * geo->c.csecs;
>>>     	smeta_len = sizeof(struct line_smeta) + lm->lun_bitmap_len;
>>>   	if (smeta_len > lm->smeta_len) {
>>> @@ -764,8 +773,8 @@ static int pblk_lines_init(struct pblk *pblk)
>>>   	 */
>>>   	i = 1;
>>>   add_emeta_page:
>>> -	lm->emeta_sec[0] = i * geo->sec_per_pl;
>>> -	lm->emeta_len[0] = lm->emeta_sec[0] * geo->sec_size;
>>> +	lm->emeta_sec[0] = i * geo->c.ws_opt;
>>> +	lm->emeta_len[0] = lm->emeta_sec[0] * geo->c.csecs;
>>>     	emeta_len = calc_emeta_len(pblk);
>>>   	if (emeta_len > lm->emeta_len[0]) {
>>> @@ -778,7 +787,7 @@ static int pblk_lines_init(struct pblk *pblk)
>>>   	lm->min_blk_line = 1;
>>>   	if (geo->all_luns > 1)
>>>   		lm->min_blk_line += DIV_ROUND_UP(lm->smeta_sec +
>>> -					lm->emeta_sec[0], geo->sec_per_chk);
>>> +					lm->emeta_sec[0], geo->c.clba);
>>>     	if (lm->min_blk_line > lm->blk_per_line) {
>>>   		pr_err("pblk: config. not supported. Min. LUN in line:%d\n",
>>> @@ -802,9 +811,9 @@ static int pblk_lines_init(struct pblk *pblk)
>>>   		goto fail_free_bb_template;
>>>   	}
>>>   -	bb_distance = (geo->all_luns) * geo->sec_per_pl;
>>> +	bb_distance = (geo->all_luns) * geo->c.ws_opt;
>>>   	for (i = 0; i < lm->sec_per_line; i += bb_distance)
>>> -		bitmap_set(l_mg->bb_template, i, geo->sec_per_pl);
>>> +		bitmap_set(l_mg->bb_template, i, geo->c.ws_opt);
>>>     	INIT_LIST_HEAD(&l_mg->free_list);
>>>   	INIT_LIST_HEAD(&l_mg->corrupt_list);
>>> @@ -981,9 +990,9 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>>>   	struct pblk *pblk;
>>>   	int ret;
>>>   -	if (dev->identity.dom & NVM_RSP_L2P) {
>>> +	if (dev->geo.c.dom & NVM_RSP_L2P) {
>>>   		pr_err("pblk: host-side L2P table not supported. (%x)\n",
>>> -							dev->identity.dom);
>>> +							dev->geo.c.dom);
>>>   		return ERR_PTR(-EINVAL);
>>>   	}
>>>   @@ -1091,7 +1100,7 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>>>     	blk_queue_write_cache(tqueue, true, false);
>>>   -	tqueue->limits.discard_granularity = geo->sec_per_chk * geo->sec_size;
>>> +	tqueue->limits.discard_granularity = geo->c.clba * geo->c.csecs;
>>>   	tqueue->limits.discard_alignment = 0;
>>>   	blk_queue_max_discard_sectors(tqueue, UINT_MAX >> 9);
>>>   	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, tqueue);
>>> diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c
>>> index 2f761283f43e..ebb6bae3a3b8 100644
>>> --- a/drivers/lightnvm/pblk-read.c
>>> +++ b/drivers/lightnvm/pblk-read.c
>>> @@ -563,7 +563,7 @@ int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq)
>>>   	if (!(gc_rq->secs_to_gc))
>>>   		goto out;
>>>   -	data_len = (gc_rq->secs_to_gc) * geo->sec_size;
>>> +	data_len = (gc_rq->secs_to_gc) * geo->c.csecs;
>>>   	bio = pblk_bio_map_addr(pblk, gc_rq->data, gc_rq->secs_to_gc, data_len,
>>>   						PBLK_VMALLOC_META, GFP_KERNEL);
>>>   	if (IS_ERR(bio)) {
>>> diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
>>> index aaab9a5c17cc..1574dbbfbb1c 100644
>>> --- a/drivers/lightnvm/pblk-recovery.c
>>> +++ b/drivers/lightnvm/pblk-recovery.c
>>> @@ -184,7 +184,7 @@ static int pblk_calc_sec_in_line(struct pblk *pblk, struct pblk_line *line)
>>>   	int nr_bb = bitmap_weight(line->blk_bitmap, lm->blk_per_line);
>>>     	return lm->sec_per_line - lm->smeta_sec - lm->emeta_sec[0] -
>>> -				nr_bb * geo->sec_per_chk;
>>> +				nr_bb * geo->c.clba;
>>>   }
>>>     struct pblk_recov_alloc {
>>> @@ -232,7 +232,7 @@ static int pblk_recov_read_oob(struct pblk *pblk, struct pblk_line *line,
>>>   	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>>   	if (!rq_ppas)
>>>   		rq_ppas = pblk->min_write_pgs;
>>> -	rq_len = rq_ppas * geo->sec_size;
>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>     	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>>>   	if (IS_ERR(bio))
>>> @@ -351,7 +351,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
>>>   	if (!pad_rq)
>>>   		return -ENOMEM;
>>>   -	data = vzalloc(pblk->max_write_pgs * geo->sec_size);
>>> +	data = vzalloc(pblk->max_write_pgs * geo->c.csecs);
>>>   	if (!data) {
>>>   		ret = -ENOMEM;
>>>   		goto free_rq;
>>> @@ -368,7 +368,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
>>>   		goto fail_free_pad;
>>>   	}
>>>   -	rq_len = rq_ppas * geo->sec_size;
>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>     	meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, &dma_meta_list);
>>>   	if (!meta_list) {
>>> @@ -509,7 +509,7 @@ static int pblk_recov_scan_all_oob(struct pblk *pblk, struct pblk_line *line,
>>>   	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>>   	if (!rq_ppas)
>>>   		rq_ppas = pblk->min_write_pgs;
>>> -	rq_len = rq_ppas * geo->sec_size;
>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>     	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>>>   	if (IS_ERR(bio))
>>> @@ -640,7 +640,7 @@ static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line,
>>>   	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>>   	if (!rq_ppas)
>>>   		rq_ppas = pblk->min_write_pgs;
>>> -	rq_len = rq_ppas * geo->sec_size;
>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>     	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>>>   	if (IS_ERR(bio))
>>> @@ -745,7 +745,7 @@ static int pblk_recov_l2p_from_oob(struct pblk *pblk, struct pblk_line *line)
>>>   	ppa_list = (void *)(meta_list) + pblk_dma_meta_size;
>>>   	dma_ppa_list = dma_meta_list + pblk_dma_meta_size;
>>>   -	data = kcalloc(pblk->max_write_pgs, geo->sec_size, GFP_KERNEL);
>>> +	data = kcalloc(pblk->max_write_pgs, geo->c.csecs, GFP_KERNEL);
>>>   	if (!data) {
>>>   		ret = -ENOMEM;
>>>   		goto free_meta_list;
>>> diff --git a/drivers/lightnvm/pblk-rl.c b/drivers/lightnvm/pblk-rl.c
>>> index 0d457b162f23..bcab203477ec 100644
>>> --- a/drivers/lightnvm/pblk-rl.c
>>> +++ b/drivers/lightnvm/pblk-rl.c
>>> @@ -200,7 +200,7 @@ void pblk_rl_init(struct pblk_rl *rl, int budget)
>>>     	/* Consider sectors used for metadata */
>>>   	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
>>> -	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
>>> +	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
>>>     	rl->high = pblk->op_blks - blk_meta - lm->blk_per_line;
>>>   	rl->high_pw = get_count_order(rl->high);
>>> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
>>> index d93e9b1f083a..5eb21a279361 100644
>>> --- a/drivers/lightnvm/pblk-sysfs.c
>>> +++ b/drivers/lightnvm/pblk-sysfs.c
>>> @@ -113,26 +113,31 @@ 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;
>>>   -	sz = snprintf(page, PAGE_SIZE - sz,
>>> -		"g:(b:%d)blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
>>> -		pblk->ppaf_bitsize,
>>> -		pblk->ppaf.blk_offset, geo->ppaf.blk_len,
>>> -		pblk->ppaf.pg_offset, geo->ppaf.pg_len,
>>> -		pblk->ppaf.lun_offset, geo->ppaf.lun_len,
>>> -		pblk->ppaf.ch_offset, geo->ppaf.ch_len,
>>> -		pblk->ppaf.pln_offset, geo->ppaf.pln_len,
>>> -		pblk->ppaf.sec_offset, geo->ppaf.sect_len);
>>> +	ppaf = (struct nvm_addr_format_12 *)&pblk->ppaf;
>>> +	geo_ppaf = (struct nvm_addr_format_12 *)&geo->c.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",
>>> +			pblk->ppaf_bitsize,
>>> +			ppaf->ch_offset, ppaf->ch_len,
>>> +			ppaf->lun_offset, ppaf->lun_len,
>>> +			ppaf->blk_offset, ppaf->blk_len,
>>> +			ppaf->pg_offset, ppaf->pg_len,
>>> +			ppaf->pln_offset, ppaf->pln_len,
>>> +			ppaf->sect_offset, ppaf->sect_len);
>>>     	sz += snprintf(page + sz, PAGE_SIZE - sz,
>>> -		"d:blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
>>> -		geo->ppaf.blk_offset, geo->ppaf.blk_len,
>>> -		geo->ppaf.pg_offset, geo->ppaf.pg_len,
>>> -		geo->ppaf.lun_offset, geo->ppaf.lun_len,
>>> -		geo->ppaf.ch_offset, geo->ppaf.ch_len,
>>> -		geo->ppaf.pln_offset, geo->ppaf.pln_len,
>>> -		geo->ppaf.sect_offset, geo->ppaf.sect_len);
>>> +		"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->sect_offset, geo_ppaf->sect_len);
>>>     	return sz;
>>>   }
>>> @@ -288,7 +293,7 @@ static ssize_t pblk_sysfs_lines_info(struct pblk *pblk, char *page)
>>>   				"blk_line:%d, sec_line:%d, sec_blk:%d\n",
>>>   					lm->blk_per_line,
>>>   					lm->sec_per_line,
>>> -					geo->sec_per_chk);
>>> +					geo->c.clba);
>>>     	return sz;
>>>   }
>>> diff --git a/drivers/lightnvm/pblk-write.c b/drivers/lightnvm/pblk-write.c
>>> index aae86ed60b98..c49b27539d5a 100644
>>> --- a/drivers/lightnvm/pblk-write.c
>>> +++ b/drivers/lightnvm/pblk-write.c
>>> @@ -333,7 +333,7 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line)
>>>   	m_ctx = nvm_rq_to_pdu(rqd);
>>>   	m_ctx->private = meta_line;
>>>   -	rq_len = rq_ppas * geo->sec_size;
>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>   	data = ((void *)emeta->buf) + emeta->mem;
>>>     	bio = pblk_bio_map_addr(pblk, data, rq_ppas, rq_len,
>>> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
>>> index 282dfc8780e8..67ffb53608f7 100644
>>> --- a/drivers/lightnvm/pblk.h
>>> +++ b/drivers/lightnvm/pblk.h
>>> @@ -551,21 +551,6 @@ struct pblk_line_meta {
>>>   	unsigned int meta_distance;	/* Distance between data and metadata */
>>>   };
>>>   -struct pblk_addr_format {
>>> -	u64	ch_mask;
>>> -	u64	lun_mask;
>>> -	u64	pln_mask;
>>> -	u64	blk_mask;
>>> -	u64	pg_mask;
>>> -	u64	sec_mask;
>>> -	u8	ch_offset;
>>> -	u8	lun_offset;
>>> -	u8	pln_offset;
>>> -	u8	blk_offset;
>>> -	u8	pg_offset;
>>> -	u8	sec_offset;
>>> -};
>>> -
>>>   enum {
>>>   	PBLK_STATE_RUNNING = 0,
>>>   	PBLK_STATE_STOPPING = 1,
>>> @@ -585,8 +570,8 @@ struct pblk {
>>>   	struct pblk_line_mgmt l_mg;		/* Line management */
>>>   	struct pblk_line_meta lm;		/* Line metadata */
>>>   +	struct nvm_addr_format ppaf;
>>>   	int ppaf_bitsize;
>>> -	struct pblk_addr_format ppaf;
>>>     	struct pblk_rb rwb;
>>>   @@ -941,14 +926,12 @@ static inline int pblk_line_vsc(struct pblk_line *line)
>>>   	return le32_to_cpu(*line->vsc);
>>>   }
>>>   -#define NVM_MEM_PAGE_WRITE (8)
>>> -
>>>   static inline int pblk_pad_distance(struct pblk *pblk)
>>>   {
>>>   	struct nvm_tgt_dev *dev = pblk->dev;
>>>   	struct nvm_geo *geo = &dev->geo;
>>>   -	return NVM_MEM_PAGE_WRITE * geo->all_luns * geo->sec_per_pl;
>>> +	return geo->c.mw_cunits * geo->all_luns * geo->c.ws_opt;
>>>   }
>>>     static inline int pblk_ppa_to_line(struct ppa_addr p)
>>> @@ -964,15 +947,17 @@ 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->ppaf;
>>>   	struct ppa_addr ppa;
>>>     	ppa.ppa = 0;
>>>   	ppa.g.blk = line_id;
>>> -	ppa.g.pg = (paddr & pblk->ppaf.pg_mask) >> pblk->ppaf.pg_offset;
>>> -	ppa.g.lun = (paddr & pblk->ppaf.lun_mask) >> pblk->ppaf.lun_offset;
>>> -	ppa.g.ch = (paddr & pblk->ppaf.ch_mask) >> pblk->ppaf.ch_offset;
>>> -	ppa.g.pl = (paddr & pblk->ppaf.pln_mask) >> pblk->ppaf.pln_offset;
>>> -	ppa.g.sec = (paddr & pblk->ppaf.sec_mask) >> pblk->ppaf.sec_offset;
>>> +	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->sect_offset;
>>>     	return ppa;
>>>   }
>>> @@ -980,13 +965,15 @@ 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->ppaf;
>>>   	u64 paddr;
>>>   -	paddr = (u64)p.g.pg << pblk->ppaf.pg_offset;
>>> -	paddr |= (u64)p.g.lun << pblk->ppaf.lun_offset;
>>> -	paddr |= (u64)p.g.ch << pblk->ppaf.ch_offset;
>>> -	paddr |= (u64)p.g.pl << pblk->ppaf.pln_offset;
>>> -	paddr |= (u64)p.g.sec << pblk->ppaf.sec_offset;
>>> +	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->sect_offset;
>>>     	return paddr;
>>>   }
>>> @@ -1003,18 +990,15 @@ 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 {
>>> -		ppa64.g.blk = (ppa32 & pblk->ppaf.blk_mask) >>
>>> -							pblk->ppaf.blk_offset;
>>> -		ppa64.g.pg = (ppa32 & pblk->ppaf.pg_mask) >>
>>> -							pblk->ppaf.pg_offset;
>>> -		ppa64.g.lun = (ppa32 & pblk->ppaf.lun_mask) >>
>>> -							pblk->ppaf.lun_offset;
>>> -		ppa64.g.ch = (ppa32 & pblk->ppaf.ch_mask) >>
>>> -							pblk->ppaf.ch_offset;
>>> -		ppa64.g.pl = (ppa32 & pblk->ppaf.pln_mask) >>
>>> -							pblk->ppaf.pln_offset;
>>> -		ppa64.g.sec = (ppa32 & pblk->ppaf.sec_mask) >>
>>> -							pblk->ppaf.sec_offset;
>>> +		struct nvm_addr_format_12 *ppaf =
>>> +				(struct nvm_addr_format_12 *)&pblk->ppaf;
>>> +
>>> +		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->sect_offset;
>>>   	}
>>>     	return ppa64;
>>> @@ -1030,12 +1014,15 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
>>>   		ppa32 |= ppa64.c.line;
>>>   		ppa32 |= 1U << 31;
>>>   	} else {
>>> -		ppa32 |= ppa64.g.blk << pblk->ppaf.blk_offset;
>>> -		ppa32 |= ppa64.g.pg << pblk->ppaf.pg_offset;
>>> -		ppa32 |= ppa64.g.lun << pblk->ppaf.lun_offset;
>>> -		ppa32 |= ppa64.g.ch << pblk->ppaf.ch_offset;
>>> -		ppa32 |= ppa64.g.pl << pblk->ppaf.pln_offset;
>>> -		ppa32 |= ppa64.g.sec << pblk->ppaf.sec_offset;
>>> +		struct nvm_addr_format_12 *ppaf =
>>> +				(struct nvm_addr_format_12 *)&pblk->ppaf;
>>> +
>>> +		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->sect_offset;
>>>   	}
>>>     	return ppa32;
>>> @@ -1153,7 +1140,7 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type)
>>>   	struct nvm_geo *geo = &dev->geo;
>>>   	int flags;
>>>   -	flags = geo->plane_mode >> 1;
>>> +	flags = geo->c.pln_mode >> 1;
>>>     	if (type == PBLK_WRITE)
>>>   		flags |= NVM_IO_SCRAMBLE_ENABLE;
>>> @@ -1174,7 +1161,7 @@ static inline int pblk_set_read_mode(struct pblk *pblk, int type)
>>>     	flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
>>>   	if (type == PBLK_READ_SEQUENTIAL)
>>> -		flags |= geo->plane_mode >> 1;
>>> +		flags |= geo->c.pln_mode >> 1;
>>>     	return flags;
>>>   }
>>> @@ -1229,10 +1216,10 @@ static inline int pblk_boundary_ppa_checks(struct nvm_tgt_dev *tgt_dev,
>>>   		if (!ppa->c.is_cached &&
>>>   				ppa->g.ch < geo->nr_chnls &&
>>>   				ppa->g.lun < geo->nr_luns &&
>>> -				ppa->g.pl < geo->nr_planes &&
>>> -				ppa->g.blk < geo->nr_chks &&
>>> -				ppa->g.pg < geo->ws_per_chk &&
>>> -				ppa->g.sec < geo->sec_per_pg)
>>> +				ppa->g.pl < geo->c.num_pln &&
>>> +				ppa->g.blk < geo->c.num_chk &&
>>> +				ppa->g.pg < geo->c.num_pg &&
>>> +				ppa->g.sec < geo->c.ws_min)
>>>   			continue;
>>>     		print_ppa(ppa, "boundary", i);
>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>> index 839c0b96466a..c81e64cc20d7 100644
>>> --- a/drivers/nvme/host/lightnvm.c
>>> +++ b/drivers/nvme/host/lightnvm.c
>>> @@ -152,8 +152,8 @@ struct nvme_nvm_id12_addrf {
>>>   	__u8			blk_len;
>>>   	__u8			pg_offset;
>>>   	__u8			pg_len;
>>> -	__u8			sect_offset;
>>> -	__u8			sect_len;
>>> +	__u8			sec_offset;
>>> +	__u8			sec_len;
>>>   	__u8			res[4];
>>>   } __packed;
>>>   @@ -254,106 +254,157 @@ static inline void _nvme_nvm_check_size(void)
>>>   	BUILD_BUG_ON(sizeof(struct nvme_nvm_id20) != NVME_IDENTIFY_DATA_SIZE);
>>>   }
>>>   -static int init_grp(struct nvm_id *nvm_id, struct nvme_nvm_id12 *id12)
>>> +static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
>>> +				 struct nvme_nvm_id12_addrf *src)
>>> +{
>>> +	dst->ch_len = src->ch_len;
>>> +	dst->lun_len = src->lun_len;
>>> +	dst->blk_len = src->blk_len;
>>> +	dst->pg_len = src->pg_len;
>>> +	dst->pln_len = src->pln_len;
>>> +	dst->sect_len = src->sec_len;
>>> +
>>> +	dst->ch_offset = src->ch_offset;
>>> +	dst->lun_offset = src->lun_offset;
>>> +	dst->blk_offset = src->blk_offset;
>>> +	dst->pg_offset = src->pg_offset;
>>> +	dst->pln_offset = src->pln_offset;
>>> +	dst->sect_offset = src->sec_offset;
>>> +
>>> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>>> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>>> +	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
>>> +	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
>>> +	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
>>> +	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
>>> +}
>>> +
>>> +static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>>> +			     struct nvm_dev_geo *dev_geo)
>>>   {
>>>   	struct nvme_nvm_id12_grp *src;
>>>   	int sec_per_pg, sec_per_pl, pg_per_blk;
>>>   -	if (id12->cgrps != 1)
>>> +	if (id->cgrps != 1)
>>>   		return -EINVAL;
>>>   -	src = &id12->grp;
>>> +	src = &id->grp;
>>>   -	nvm_id->mtype = src->mtype;
>>> -	nvm_id->fmtype = src->fmtype;
>>> +	if (src->mtype != 0) {
>>> +		pr_err("nvm: memory type not supported\n");
>>> +		return -EINVAL;
>>> +	}
>>> +
>>> +	/* 1.2 spec. only reports a single version id - unfold */
>>> +	dev_geo->ver_id = id->ver_id;
>>>   -	nvm_id->num_ch = src->num_ch;
>>> -	nvm_id->num_lun = src->num_lun;
>>> +	dev_geo->nr_chnls = src->num_ch;
>>> +	dev_geo->nr_luns = src->num_lun;
>>> +	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
>>>   -	nvm_id->num_chk = le16_to_cpu(src->num_chk);
>>> -	nvm_id->csecs = le16_to_cpu(src->csecs);
>>> -	nvm_id->sos = le16_to_cpu(src->sos);
>>> +	dev_geo->c.num_chk = le16_to_cpu(src->num_chk);
>>> +	dev_geo->c.csecs = le16_to_cpu(src->csecs);
>>> +	dev_geo->c.sos = le16_to_cpu(src->sos);
>>>     	pg_per_blk = le16_to_cpu(src->num_pg);
>>> -	sec_per_pg = le16_to_cpu(src->fpg_sz) / nvm_id->csecs;
>>> +	sec_per_pg = le16_to_cpu(src->fpg_sz) / dev_geo->c.csecs;
>>>   	sec_per_pl = sec_per_pg * src->num_pln;
>>> -	nvm_id->clba = sec_per_pl * pg_per_blk;
>>> -	nvm_id->ws_per_chk = pg_per_blk;
>>> -
>>> -	nvm_id->mpos = le32_to_cpu(src->mpos);
>>> -	nvm_id->cpar = le16_to_cpu(src->cpar);
>>> -	nvm_id->mccap = le32_to_cpu(src->mccap);
>>> -
>>> -	nvm_id->ws_opt = nvm_id->ws_min = sec_per_pg;
>>> -	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
>>> -
>>> -	if (nvm_id->mpos & 0x020202) {
>>> -		nvm_id->ws_seq = NVM_IO_DUAL_ACCESS;
>>> -		nvm_id->ws_opt <<= 1;
>>> -	} else if (nvm_id->mpos & 0x040404) {
>>> -		nvm_id->ws_seq = NVM_IO_QUAD_ACCESS;
>>> -		nvm_id->ws_opt <<= 2;
>>> +	dev_geo->c.clba = sec_per_pl * pg_per_blk;
>>> +
>>> +	dev_geo->c.ws_min = sec_per_pg;
>>> +	dev_geo->c.ws_opt = sec_per_pg;
>>> +	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
>>> +
>>> +	dev_geo->c.mccap = le32_to_cpu(src->mccap);
>>> +
>>> +	dev_geo->c.trdt = le32_to_cpu(src->trdt);
>>> +	dev_geo->c.trdm = le32_to_cpu(src->trdm);
>>> +	dev_geo->c.tprt = le32_to_cpu(src->tprt);
>>> +	dev_geo->c.tprm = le32_to_cpu(src->tprm);
>>> +	dev_geo->c.tbet = le32_to_cpu(src->tbet);
>>> +	dev_geo->c.tbem = le32_to_cpu(src->tbem);
>>> +
>>> +	/* 1.2 compatibility */
>>> +	dev_geo->c.vmnt = id->vmnt;
>>> +	dev_geo->c.cap = le32_to_cpu(id->cap);
>>> +	dev_geo->c.dom = le32_to_cpu(id->dom);
>>> +
>>> +	dev_geo->c.mtype = src->mtype;
>>> +	dev_geo->c.fmtype = src->fmtype;
>>> +
>>> +	dev_geo->c.cpar = le16_to_cpu(src->cpar);
>>> +	dev_geo->c.mpos = le32_to_cpu(src->mpos);
>>> +
>>> +	dev_geo->c.pln_mode = NVM_PLANE_SINGLE;
>>> +
>>> +	if (dev_geo->c.mpos & 0x020202) {
>>> +		dev_geo->c.pln_mode = NVM_PLANE_DOUBLE;
>>> +		dev_geo->c.ws_opt <<= 1;
>>> +	} else if (dev_geo->c.mpos & 0x040404) {
>>> +		dev_geo->c.pln_mode = NVM_PLANE_QUAD;
>>> +		dev_geo->c.ws_opt <<= 2;
>>>   	}
>>>   -	nvm_id->trdt = le32_to_cpu(src->trdt);
>>> -	nvm_id->trdm = le32_to_cpu(src->trdm);
>>> -	nvm_id->tprt = le32_to_cpu(src->tprt);
>>> -	nvm_id->tprm = le32_to_cpu(src->tprm);
>>> -	nvm_id->tbet = le32_to_cpu(src->tbet);
>>> -	nvm_id->tbem = le32_to_cpu(src->tbem);
>>> -
>>> -	/* 1.2 compatibility */
>>> -	nvm_id->num_pln = src->num_pln;
>>> -	nvm_id->num_pg = le16_to_cpu(src->num_pg);
>>> -	nvm_id->fpg_sz = le16_to_cpu(src->fpg_sz);
>>> +	dev_geo->c.num_pln = src->num_pln;
>>> +	dev_geo->c.num_pg = le16_to_cpu(src->num_pg);
>>> +	dev_geo->c.fpg_sz = le16_to_cpu(src->fpg_sz);
>>> +
>>> +	nvme_nvm_set_addr_12((struct nvm_addr_format_12 *)&dev_geo->c.addrf,
>>> +								&id->ppaf);
>>>     	return 0;
>>>   }
>>>   -static int nvme_nvm_setup_12(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
>>> -		struct nvme_nvm_id12 *id)
>>> +static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
>>> +				 struct nvme_nvm_id20_addrf *src)
>>>   {
>>> -	nvm_id->ver_id = id->ver_id;
>>> -	nvm_id->vmnt = id->vmnt;
>>> -	nvm_id->cap = le32_to_cpu(id->cap);
>>> -	nvm_id->dom = le32_to_cpu(id->dom);
>>> -	memcpy(&nvm_id->ppaf, &id->ppaf,
>>> -					sizeof(struct nvm_addr_format));
>>> -
>>> -	return init_grp(nvm_id, id);
>>> +	dst->ch_len = src->grp_len;
>>> +	dst->lun_len = src->pu_len;
>>> +	dst->chk_len = src->chk_len;
>>> +	dst->sec_len = src->lba_len;
>>> +
>>> +	dst->sec_offset = 0;
>>> +	dst->chk_offset = dst->sec_len;
>>> +	dst->lun_offset = dst->chk_offset + dst->chk_len;
>>> +	dst->ch_offset = dst->lun_offset + dst->lun_len;
>>> +
>>> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>>> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>>> +	dst->chk_mask = ((1ULL << dst->chk_len) - 1) << dst->chk_offset;
>>> +	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>>>   }
>>>   -static int nvme_nvm_setup_20(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
>>> -		struct nvme_nvm_id20 *id)
>>> +static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>>> +			     struct nvm_dev_geo *dev_geo)
>>>   {
>>> -	nvm_id->ver_id = id->mjr;
>>> +	dev_geo->ver_id = id->mjr;
>>>   -	nvm_id->num_ch = le16_to_cpu(id->num_grp);
>>> -	nvm_id->num_lun = le16_to_cpu(id->num_pu);
>>> -	nvm_id->num_chk = le32_to_cpu(id->num_chk);
>>> -	nvm_id->clba = le32_to_cpu(id->clba);
>>> +	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
>>> +	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
>>> +	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
>>>   -	nvm_id->ws_min = le32_to_cpu(id->ws_min);
>>> -	nvm_id->ws_opt = le32_to_cpu(id->ws_opt);
>>> -	nvm_id->mw_cunits = le32_to_cpu(id->mw_cunits);
>>> +	dev_geo->c.num_chk = le32_to_cpu(id->num_chk);
>>> +	dev_geo->c.clba = le32_to_cpu(id->clba);
>>> +	dev_geo->c.csecs = -1;		/* Set by nvme identify */
>>> +	dev_geo->c.sos = -1;		/* Set bu nvme identify */
>>>   -	nvm_id->trdt = le32_to_cpu(id->trdt);
>>> -	nvm_id->trdm = le32_to_cpu(id->trdm);
>>> -	nvm_id->tprt = le32_to_cpu(id->twrt);
>>> -	nvm_id->tprm = le32_to_cpu(id->twrm);
>>> -	nvm_id->tbet = le32_to_cpu(id->tcrst);
>>> -	nvm_id->tbem = le32_to_cpu(id->tcrsm);
>>> +	dev_geo->c.ws_min = le32_to_cpu(id->ws_min);
>>> +	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
>>> +	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
>>>   -	/* calculated values */
>>> -	nvm_id->ws_per_chk = nvm_id->clba / nvm_id->ws_min;
>>> +	dev_geo->c.trdt = le32_to_cpu(id->trdt);
>>> +	dev_geo->c.trdm = le32_to_cpu(id->trdm);
>>> +	dev_geo->c.tprt = le32_to_cpu(id->twrt);
>>> +	dev_geo->c.tprm = le32_to_cpu(id->twrm);
>>> +	dev_geo->c.tbet = le32_to_cpu(id->tcrst);
>>> +	dev_geo->c.tbem = le32_to_cpu(id->tcrsm);
>>>   -	/* 1.2 compatibility */
>>> -	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
>>> +	nvme_nvm_set_addr_20(&dev_geo->c.addrf, &id->lbaf);
>>>     	return 0;
>>>   }
>>>   -static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
>>> +static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>>>   {
>>>   	struct nvme_ns *ns = nvmdev->q->queuedata;
>>>   	struct nvme_nvm_id12 *id;
>>> @@ -380,18 +431,18 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
>>>   	 */
>>>   	switch (id->ver_id) {
>>>   	case 1:
>>> -		ret = nvme_nvm_setup_12(nvmdev, nvm_id, id);
>>> +		ret = nvme_nvm_setup_12(id, &nvmdev->dev_geo);
>>>   		break;
>>>   	case 2:
>>> -		ret = nvme_nvm_setup_20(nvmdev, nvm_id,
>>> -				(struct nvme_nvm_id20 *)id);
>>> +		ret = nvme_nvm_setup_20((struct nvme_nvm_id20 *)id,
>>> +							&nvmdev->dev_geo);
>>>   		break;
>>>   	default:
>>> -		dev_err(ns->ctrl->device,
>>> -			"OCSSD revision not supported (%d)\n",
>>> -			nvm_id->ver_id);
>>> +		dev_err(ns->ctrl->device, "OCSSD revision not supported (%d)\n",
>>> +							id->ver_id);
>>>   		ret = -EINVAL;
>>>   	}
>>> +
>>>   out:
>>>   	kfree(id);
>>>   	return ret;
>>> @@ -401,12 +452,12 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
>>>   								u8 *blks)
>>>   {
>>>   	struct request_queue *q = nvmdev->q;
>>> -	struct nvm_geo *geo = &nvmdev->geo;
>>> +	struct nvm_dev_geo *dev_geo = &nvmdev->dev_geo;
>>>   	struct nvme_ns *ns = q->queuedata;
>>>   	struct nvme_ctrl *ctrl = ns->ctrl;
>>>   	struct nvme_nvm_command c = {};
>>>   	struct nvme_nvm_bb_tbl *bb_tbl;
>>> -	int nr_blks = geo->nr_chks * geo->plane_mode;
>>> +	int nr_blks = dev_geo->c.num_chk * dev_geo->c.num_pln;
>>>   	int tblsz = sizeof(struct nvme_nvm_bb_tbl) + nr_blks;
>>>   	int ret = 0;
>>>   @@ -447,7 +498,7 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
>>>   		goto out;
>>>   	}
>>>   -	memcpy(blks, bb_tbl->blk, geo->nr_chks * geo->plane_mode);
>>> +	memcpy(blks, bb_tbl->blk, dev_geo->c.num_chk * dev_geo->c.num_pln);
>>>   out:
>>>   	kfree(bb_tbl);
>>>   	return ret;
>>> @@ -815,9 +866,10 @@ int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd, unsigned long arg)
>>>   void nvme_nvm_update_nvm_info(struct nvme_ns *ns)
>>>   {
>>>   	struct nvm_dev *ndev = ns->ndev;
>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>   -	ndev->identity.csecs = ndev->geo.sec_size = 1 << ns->lba_shift;
>>> -	ndev->identity.sos = ndev->geo.oob_size = ns->ms;
>>> +	dev_geo->c.csecs = 1 << ns->lba_shift;
>>> +	dev_geo->c.sos = ns->ms;
>>>   }
>>>     int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node)
>>> @@ -850,23 +902,22 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>>   {
>>>   	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>>>   	struct nvm_dev *ndev = ns->ndev;
>>> -	struct nvm_id *id;
>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>   	struct attribute *attr;
>>>     	if (!ndev)
>>>   		return 0;
>>>   -	id = &ndev->identity;
>>>   	attr = &dattr->attr;
>>>     	if (strcmp(attr->name, "version") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ver_id);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>>>   	} else if (strcmp(attr->name, "capabilities") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->cap);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
>>>   	} else if (strcmp(attr->name, "read_typ") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdt);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>>>   	} else if (strcmp(attr->name, "read_max") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdm);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdm);
>>>   	} else {
>>>   		return scnprintf(page,
>>>   				 PAGE_SIZE,
>>> @@ -875,75 +926,79 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>>   	}
>>>   }
>>>   +static ssize_t nvm_dev_attr_show_ppaf(struct nvm_addr_format_12 *ppaf,
>>> +					 char *page)
>>> +{
>>> +	return scnprintf(page, PAGE_SIZE,
>>> +		"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
>>> +				ppaf->ch_offset, ppaf->ch_len,
>>> +				ppaf->lun_offset, ppaf->lun_len,
>>> +				ppaf->pln_offset, ppaf->pln_len,
>>> +				ppaf->blk_offset, ppaf->blk_len,
>>> +				ppaf->pg_offset, ppaf->pg_len,
>>> +				ppaf->sect_offset, ppaf->sect_len);
>>> +}
>>> +
>>>   static ssize_t nvm_dev_attr_show_12(struct device *dev,
>>>   		struct device_attribute *dattr, char *page)
>>>   {
>>>   	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>>>   	struct nvm_dev *ndev = ns->ndev;
>>> -	struct nvm_id *id;
>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>   	struct attribute *attr;
>>>     	if (!ndev)
>>>   		return 0;
>>>   -	id = &ndev->identity;
>>>   	attr = &dattr->attr;
>>>     	if (strcmp(attr->name, "vendor_opcode") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->vmnt);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.vmnt);
>>>   	} else if (strcmp(attr->name, "device_mode") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->dom);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.dom);
>>>   	/* kept for compatibility */
>>>   	} else if (strcmp(attr->name, "media_manager") == 0) {
>>>   		return scnprintf(page, PAGE_SIZE, "%s\n", "gennvm");
>>>   	} else if (strcmp(attr->name, "ppa_format") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE,
>>> -			"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
>>> -			id->ppaf.ch_offset, id->ppaf.ch_len,
>>> -			id->ppaf.lun_offset, id->ppaf.lun_len,
>>> -			id->ppaf.pln_offset, id->ppaf.pln_len,
>>> -			id->ppaf.blk_offset, id->ppaf.blk_len,
>>> -			id->ppaf.pg_offset, id->ppaf.pg_len,
>>> -			id->ppaf.sect_offset, id->ppaf.sect_len);
>>> +		return nvm_dev_attr_show_ppaf((void *)&dev_geo->c.addrf, page);
>>>   	} else if (strcmp(attr->name, "media_type") == 0) {	/* u8 */
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->mtype);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mtype);
>>>   	} else if (strcmp(attr->name, "flash_media_type") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->fmtype);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fmtype);
>>>   	} else if (strcmp(attr->name, "num_channels") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
>>>   	} else if (strcmp(attr->name, "num_luns") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
>>>   	} else if (strcmp(attr->name, "num_planes") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pln);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pln);
>>>   	} else if (strcmp(attr->name, "num_blocks") == 0) {	/* u16 */
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
>>>   	} else if (strcmp(attr->name, "num_pages") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pg);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pg);
>>>   	} else if (strcmp(attr->name, "page_size") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->fpg_sz);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fpg_sz);
>>>   	} else if (strcmp(attr->name, "hw_sector_size") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->csecs);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.csecs);
>>>   	} else if (strcmp(attr->name, "oob_sector_size") == 0) {/* u32 */
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->sos);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.sos);
>>>   	} else if (strcmp(attr->name, "prog_typ") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
>>>   	} else if (strcmp(attr->name, "prog_max") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
>>>   	} else if (strcmp(attr->name, "erase_typ") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
>>>   	} else if (strcmp(attr->name, "erase_max") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>>   	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mpos);
>>> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
>>>   	} else if (strcmp(attr->name, "media_capabilities") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mccap);
>>> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
>>>   	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
>>>   		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>>>   	} else {
>>> -		return scnprintf(page,
>>> -				 PAGE_SIZE,
>>> -				 "Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
>>> -				 attr->name);
>>> +		return scnprintf(page, PAGE_SIZE,
>>> +			"Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
>>> +			attr->name);
>>>   	}
>>>   }
>>>   @@ -952,42 +1007,40 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>>>   {
>>>   	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>>>   	struct nvm_dev *ndev = ns->ndev;
>>> -	struct nvm_id *id;
>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>   	struct attribute *attr;
>>>     	if (!ndev)
>>>   		return 0;
>>>   -	id = &ndev->identity;
>>>   	attr = &dattr->attr;
>>>     	if (strcmp(attr->name, "groups") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
>>>   	} else if (strcmp(attr->name, "punits") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
>>>   	} else if (strcmp(attr->name, "chunks") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
>>>   	} else if (strcmp(attr->name, "clba") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->clba);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.clba);
>>>   	} else if (strcmp(attr->name, "ws_min") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_min);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_min);
>>>   	} else if (strcmp(attr->name, "ws_opt") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_opt);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_opt);
>>>   	} else if (strcmp(attr->name, "mw_cunits") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->mw_cunits);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mw_cunits);
>>>   	} else if (strcmp(attr->name, "write_typ") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
>>>   	} else if (strcmp(attr->name, "write_max") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
>>>   	} else if (strcmp(attr->name, "reset_typ") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
>>>   	} else if (strcmp(attr->name, "reset_max") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>>   	} else {
>>> -		return scnprintf(page,
>>> -				 PAGE_SIZE,
>>> -				 "Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
>>> -				 attr->name);
>>> +		return scnprintf(page, PAGE_SIZE,
>>> +			"Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
>>> +			attr->name);
>>>   	}
>>>   }
>>>   @@ -1106,10 +1159,13 @@ static const struct attribute_group nvm_dev_attr_group_20 = {
>>>     int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>>>   {
>>> -	if (!ns->ndev)
>>> +	struct nvm_dev *ndev = ns->ndev;
>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>> +
>>> +	if (!ndev)
>>>   		return -EINVAL;
>>>   -	switch (ns->ndev->identity.ver_id) {
>>> +	switch (dev_geo->ver_id) {
>>>   	case 1:
>>>   		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
>>>   					&nvm_dev_attr_group_12);
>>> @@ -1123,7 +1179,10 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>>>     void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
>>>   {
>>> -	switch (ns->ndev->identity.ver_id) {
>>> +	struct nvm_dev *ndev = ns->ndev;
>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>> +
>>> +	switch (dev_geo->ver_id) {
>>>   	case 1:
>>>   		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
>>>   					&nvm_dev_attr_group_12);
>>> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
>>> index e55b10573c99..18e3751b1632 100644
>>> --- a/include/linux/lightnvm.h
>>> +++ b/include/linux/lightnvm.h
>>> @@ -50,7 +50,7 @@ struct nvm_id;
>>>   struct nvm_dev;
>>>   struct nvm_tgt_dev;
>>>   -typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *);
>>> +typedef int (nvm_id_fn)(struct nvm_dev *);
>>>   typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, u8 *);
>>>   typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct ppa_addr *, int, int);
>>>   typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
>>> @@ -152,62 +152,107 @@ struct nvm_id_lp_tbl {
>>>   	struct nvm_id_lp_mlc mlc;
>>>   };
>>>   -struct nvm_addr_format {
>>> -	u8	ch_offset;
>>> +struct nvm_addr_format_12 {
>>>   	u8	ch_len;
>>> -	u8	lun_offset;
>>>   	u8	lun_len;
>>> -	u8	pln_offset;
>>> +	u8	blk_len;
>>> +	u8	pg_len;
>>>   	u8	pln_len;
>>> +	u8	sect_len;
>>> +
>>> +	u8	ch_offset;
>>> +	u8	lun_offset;
>>>   	u8	blk_offset;
>>> -	u8	blk_len;
>>>   	u8	pg_offset;
>>> -	u8	pg_len;
>>> +	u8	pln_offset;
>>>   	u8	sect_offset;
>>> -	u8	sect_len;
>>> +
>>> +	u64	ch_mask;
>>> +	u64	lun_mask;
>>> +	u64	blk_mask;
>>> +	u64	pg_mask;
>>> +	u64	pln_mask;
>>> +	u64	sec_mask;
>>> +};
>>> +
>>> +struct nvm_addr_format {
>>> +	u8	ch_len;
>>> +	u8	lun_len;
>>> +	u8	chk_len;
>>> +	u8	sec_len;
>>> +	u8	rsv_len[2];
>>> +
>>> +	u8	ch_offset;
>>> +	u8	lun_offset;
>>> +	u8	chk_offset;
>>> +	u8	sec_offset;
>>> +	u8	rsv_off[2];
>>> +
>>> +	u64	ch_mask;
>>> +	u64	lun_mask;
>>> +	u64	chk_mask;
>>> +	u64	sec_mask;
>>> +	u64	rsv_mask[2];
>>>   };
>>>   -struct nvm_id {
>>> -	u8	ver_id;
>>> +/* Device common geometry */
>>> +struct nvm_common_geo {
>>> +	/* chunk geometry */
>>> +	u32	num_chk;	/* chunks per lun */
>>> +	u32	clba;		/* sectors per chunk */
>>> +	u16	csecs;		/* sector size */
>>> +	u16	sos;		/* out-of-band area size */
>>> +
>>> +	/* device write constrains */
>>> +	u32	ws_min;		/* minimum write size */
>>> +	u32	ws_opt;		/* optimal write size */
>>> +	u32	mw_cunits;	/* distance required for successful read */
>>> +
>>> +	/* device capabilities */
>>> +	u32	mccap;
>>> +
>>> +	/* device timings */
>>> +	u32	trdt;		/* Avg. Tread (ns) */
>>> +	u32	trdm;		/* Max Tread (ns) */
>>> +	u32	tprt;		/* Avg. Tprog (ns) */
>>> +	u32	tprm;		/* Max Tprog (ns) */
>>> +	u32	tbet;		/* Avg. Terase (ns) */
>>> +	u32	tbem;		/* Max Terase (ns) */
>>> +
>>> +	/* generic address format */
>>> +	struct nvm_addr_format addrf;
>>> +
>>> +	/* 1.2 compatibility */
>>>   	u8	vmnt;
>>>   	u32	cap;
>>>   	u32	dom;
>>>   -	struct	nvm_addr_format ppaf;
>>> -
>>> -	u8	num_ch;
>>> -	u8	num_lun;
>>> -	u16	num_chk;
>>> -	u16	clba;
>>> -	u16	csecs;
>>> -	u16	sos;
>>> -
>>> -	u32	ws_min;
>>> -	u32	ws_opt;
>>> -	u32	mw_cunits;
>>> -
>>> -	u32	trdt;
>>> -	u32	trdm;
>>> -	u32	tprt;
>>> -	u32	tprm;
>>> -	u32	tbet;
>>> -	u32	tbem;
>>> -	u32	mpos;
>>> -	u32	mccap;
>>> -	u16	cpar;
>>> -
>>> -	/* calculated values */
>>> -	u16	ws_seq;
>>> -	u16	ws_per_chk;
>>> -
>>> -	/* 1.2 compatibility */
>>>   	u8	mtype;
>>>   	u8	fmtype;
>>>   +	u16	cpar;
>>> +	u32	mpos;
>>> +
>>>   	u8	num_pln;
>>> +	u8	pln_mode;
>>>   	u16	num_pg;
>>>   	u16	fpg_sz;
>>> -} __packed;
>>> +};
>>> +
>>> +/* Device identified geometry */
>>> +struct nvm_dev_geo {
>>> +	/* device reported version */
>>> +	u8	ver_id;
>>> +
>>> +	/* full device geometry */
>>> +	u16	nr_chnls;
>>> +	u16	nr_luns;
>>> +
>>> +	/* calculated values */
>>> +	u16	all_luns;
>>> +
>>> +	struct nvm_common_geo c;
>>> +};
>>>     struct nvm_target {
>>>   	struct list_head list;
>>> @@ -274,36 +319,22 @@ enum {
>>>   	NVM_BLK_ST_BAD =	0x8,	/* Bad block */
>>>   };
>>>   -
>>> -/* Device generic information */
>>> +/* Instance geometry */
>>>   struct nvm_geo {
>>> -	/* generic geometry */
>>> +	/* instance specific geometry */
>>>   	int nr_chnls;
>>> -	int all_luns; /* across channels */
>>> -	int nr_luns; /* per channel */
>>> -	int nr_chks; /* per lun */
>>> -
>>> -	int sec_size;
>>> -	int oob_size;
>>> -	int mccap;
>>> -
>>> -	int sec_per_chk;
>>> -	int sec_per_lun;
>>> -
>>> -	int ws_min;
>>> -	int ws_opt;
>>> -	int ws_seq;
>>> -	int ws_per_chk;
>>> +	int nr_luns;		/* per channel */
>>>     	int op;
>>>   -	struct nvm_addr_format ppaf;
>>> +	/* common geometry */
>>> +	struct nvm_common_geo c;
>>>   -	/* Legacy 1.2 specific geometry */
>>> -	int plane_mode; /* drive device in single, double or quad mode */
>>> -	int nr_planes;
>>> -	int sec_per_pg; /* only sectors for a single page */
>>> -	int sec_per_pl; /* all sectors across planes */
>>> +	/* calculated values */
>>> +	int all_luns;		/* across channels */
>>> +	int all_chunks;		/* across channels */
>>> +
>>> +	sector_t total_secs;	/* across channels */
>>>   };
>>>     /* sub-device structure */
>>> @@ -314,9 +345,6 @@ struct nvm_tgt_dev {
>>>   	/* Base ppas for target LUNs */
>>>   	struct ppa_addr *luns;
>>>   -	sector_t total_secs;
>>> -
>>> -	struct nvm_id identity;
>>>   	struct request_queue *q;
>>>     	struct nvm_dev *parent;
>>> @@ -329,15 +357,11 @@ struct nvm_dev {
>>>   	struct list_head devices;
>>>     	/* Device information */
>>> -	struct nvm_geo geo;
>>> -
>>> -	unsigned long total_secs;
>>> +	struct nvm_dev_geo dev_geo;
>>>     	unsigned long *lun_map;
>>>   	void *dma_pool;
>>>   -	struct nvm_id identity;
>>> -
>>>   	/* Backend device */
>>>   	struct request_queue *q;
>>>   	char name[DISK_NAME_LEN];
>>> @@ -357,14 +381,16 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
>>>   						  struct ppa_addr r)
>>>   {
>>>   	struct nvm_geo *geo = &tgt_dev->geo;
>>> +	struct nvm_addr_format_12 *ppaf =
>>> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>>>   	struct ppa_addr l;
>>>   -	l.ppa = ((u64)r.g.blk) << geo->ppaf.blk_offset;
>>> -	l.ppa |= ((u64)r.g.pg) << geo->ppaf.pg_offset;
>>> -	l.ppa |= ((u64)r.g.sec) << geo->ppaf.sect_offset;
>>> -	l.ppa |= ((u64)r.g.pl) << geo->ppaf.pln_offset;
>>> -	l.ppa |= ((u64)r.g.lun) << geo->ppaf.lun_offset;
>>> -	l.ppa |= ((u64)r.g.ch) << geo->ppaf.ch_offset;
>>> +	l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
>>> +	l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
>>> +	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
>>> +	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
>>> +	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
>>> +	l.ppa |= ((u64)r.g.sec) << ppaf->sect_offset;
>>>     	return l;
>>>   }
>>> @@ -373,24 +399,18 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
>>>   						  struct ppa_addr r)
>>>   {
>>>   	struct nvm_geo *geo = &tgt_dev->geo;
>>> +	struct nvm_addr_format_12 *ppaf =
>>> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>>>   	struct ppa_addr l;
>>>     	l.ppa = 0;
>>> -	/*
>>> -	 * (r.ppa << X offset) & X len bitmask. X eq. blk, pg, etc.
>>> -	 */
>>> -	l.g.blk = (r.ppa >> geo->ppaf.blk_offset) &
>>> -					(((1 << geo->ppaf.blk_len) - 1));
>>> -	l.g.pg |= (r.ppa >> geo->ppaf.pg_offset) &
>>> -					(((1 << geo->ppaf.pg_len) - 1));
>>> -	l.g.sec |= (r.ppa >> geo->ppaf.sect_offset) &
>>> -					(((1 << geo->ppaf.sect_len) - 1));
>>> -	l.g.pl |= (r.ppa >> geo->ppaf.pln_offset) &
>>> -					(((1 << geo->ppaf.pln_len) - 1));
>>> -	l.g.lun |= (r.ppa >> geo->ppaf.lun_offset) &
>>> -					(((1 << geo->ppaf.lun_len) - 1));
>>> -	l.g.ch |= (r.ppa >> geo->ppaf.ch_offset) &
>>> -					(((1 << geo->ppaf.ch_len) - 1));
>>> +
>>> +	l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
>>> +	l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
>>> +	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
>>> +	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
>>> +	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
>>> +	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sect_offset;
>>>     	return l;
>>>   }
>>
>> Thanks for the patch. I appreciate the work, but it is not the way I
>> want the 2.0 representation to go. The 2.0 variables should stay in
>> the nvm_geo data structure, and then if any 1.2 variables are on the
>> side, they can be in a substructure.
> 
> I don't understand. Everything is in nvm_geo, with the only different
> that there is nvm_common_geo, which contains the shared geometry between
> all instances. As mentioned before, if only having nvm_geo, then we are
> truncating the structure for each instance with different channel/lun
> values, which is very from a target perspective (the target can access
> the underlying device's values, which is _very_ error prone). This
> structure represents all 2.0 variables as they are.I can move all 1.2
> variables to a sub structure if that helps.

Let me try to see if I can clarify. From my understanding,the patch is 
doing three things,

1. Replace dev->identify and use a generic data structure
2. Introduced nvm_dev_geo to represent both intance and device channels 
and luns.
3. Move pblk addressing logic into core

Could these be split up? maybe 1 and 3 go together, and the address 
format go by itself. Maybe not. I'm fine if you say that they should 
stay together.

For 1 and 3, Instead of making the nvm_dev_geo the base structure, the 
code should continue to use nvm_geo (don't move the variables into 
nvm_geo_common and similar data struct. The nvm_dev->nvm_dev_geo is not 
pretty, the code already has a reference that the nvm_dev_geo is in the 
nvm_dev data structure.

When the code needs the instance specific channels and luns, put them in 
another data structure (than nvm_dev_geo), and maintain the relationship 
there.

> 
> If this is not it, can you explain in detail what the problem is? In
> pblk, I don't want to deal with a device-centric structure and variables
> spread out across what was identity and nvm_geo, I want a single
> structure that contains everything, which is the motivation for this
> patch.
> 

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 01/20] lightnvm: simplify geometry structure.
@ 2018-02-22 12:22         ` Matias Bjørling
  0 siblings, 0 replies; 99+ messages in thread
From: Matias Bjørling @ 2018-02-22 12:22 UTC (permalink / raw)


On 02/22/2018 08:44 AM, Javier Gonzalez wrote:
> 
>> On 22 Feb 2018,@08.25, Matias Bj?rling <mb@lightnvm.io> wrote:
>>
>> On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
>>> Currently, the device geometry is stored redundantly in the nvm_id and
>>> nvm_geo structures at a device level. Moreover, when instantiating
>>> targets on a specific number of LUNs, these structures are replicated
>>> and manually modified to fit the instance channel and LUN partitioning.
>>> Instead, create a generic geometry around two base structures:
>>> nvm_dev_geo, which describes the geometry of the whole device and
>>> nvm_geo, which describes the geometry of the instance. Since these share
>>> a big part of the geometry, create a nvm_common_geo structure that keeps
>>> the static geoometry values that are shared across instances.
>>> As we introduce support for 2.0, these structures allow to abstract
>>> spec. specific values and present a common geometry to targets.
>>> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
>>> ---
>>>   drivers/lightnvm/core.c          | 137 +++++++---------
>>>   drivers/lightnvm/pblk-core.c     |  16 +-
>>>   drivers/lightnvm/pblk-gc.c       |   2 +-
>>>   drivers/lightnvm/pblk-init.c     | 123 +++++++-------
>>>   drivers/lightnvm/pblk-read.c     |   2 +-
>>>   drivers/lightnvm/pblk-recovery.c |  14 +-
>>>   drivers/lightnvm/pblk-rl.c       |   2 +-
>>>   drivers/lightnvm/pblk-sysfs.c    |  39 +++--
>>>   drivers/lightnvm/pblk-write.c    |   2 +-
>>>   drivers/lightnvm/pblk.h          |  93 +++++------
>>>   drivers/nvme/host/lightnvm.c     | 339 +++++++++++++++++++++++----------------
>>>   include/linux/lightnvm.h         | 204 ++++++++++++-----------
>>>   12 files changed, 514 insertions(+), 459 deletions(-)
>>> diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
>>> index 689c97b97775..42596afdf64c 100644
>>> --- a/drivers/lightnvm/core.c
>>> +++ b/drivers/lightnvm/core.c
>>> @@ -111,6 +111,7 @@ static void nvm_release_luns_err(struct nvm_dev *dev, int lun_begin,
>>>   static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
>>>   {
>>>   	struct nvm_dev *dev = tgt_dev->parent;
>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>   	struct nvm_dev_map *dev_map = tgt_dev->map;
>>>   	int i, j;
>>>   @@ -122,7 +123,7 @@ static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
>>>   		if (clear) {
>>>   			for (j = 0; j < ch_map->nr_luns; j++) {
>>>   				int lun = j + lun_offs[j];
>>> -				int lunid = (ch * dev->geo.nr_luns) + lun;
>>> +				int lunid = (ch * dev_geo->nr_luns) + lun;
>>>     				WARN_ON(!test_and_clear_bit(lunid,
>>>   							dev->lun_map));
>>> @@ -143,19 +144,20 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>>>   					      u16 lun_begin, u16 lun_end,
>>>   					      u16 op)
>>>   {
>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>   	struct nvm_tgt_dev *tgt_dev = NULL;
>>>   	struct nvm_dev_map *dev_rmap = dev->rmap;
>>>   	struct nvm_dev_map *dev_map;
>>>   	struct ppa_addr *luns;
>>>   	int nr_luns = lun_end - lun_begin + 1;
>>>   	int luns_left = nr_luns;
>>> -	int nr_chnls = nr_luns / dev->geo.nr_luns;
>>> -	int nr_chnls_mod = nr_luns % dev->geo.nr_luns;
>>> -	int bch = lun_begin / dev->geo.nr_luns;
>>> -	int blun = lun_begin % dev->geo.nr_luns;
>>> +	int nr_chnls = nr_luns / dev_geo->nr_luns;
>>> +	int nr_chnls_mod = nr_luns % dev_geo->nr_luns;
>>> +	int bch = lun_begin / dev_geo->nr_luns;
>>> +	int blun = lun_begin % dev_geo->nr_luns;
>>>   	int lunid = 0;
>>>   	int lun_balanced = 1;
>>> -	int prev_nr_luns;
>>> +	int sec_per_lun, prev_nr_luns;
>>>   	int i, j;
>>>     	nr_chnls = (nr_chnls_mod == 0) ? nr_chnls : nr_chnls + 1;
>>> @@ -173,15 +175,15 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>>>   	if (!luns)
>>>   		goto err_luns;
>>>   -	prev_nr_luns = (luns_left > dev->geo.nr_luns) ?
>>> -					dev->geo.nr_luns : luns_left;
>>> +	prev_nr_luns = (luns_left > dev_geo->nr_luns) ?
>>> +					dev_geo->nr_luns : luns_left;
>>>   	for (i = 0; i < nr_chnls; i++) {
>>>   		struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[i + bch];
>>>   		int *lun_roffs = ch_rmap->lun_offs;
>>>   		struct nvm_ch_map *ch_map = &dev_map->chnls[i];
>>>   		int *lun_offs;
>>> -		int luns_in_chnl = (luns_left > dev->geo.nr_luns) ?
>>> -					dev->geo.nr_luns : luns_left;
>>> +		int luns_in_chnl = (luns_left > dev_geo->nr_luns) ?
>>> +					dev_geo->nr_luns : luns_left;
>>>     		if (lun_balanced && prev_nr_luns != luns_in_chnl)
>>>   			lun_balanced = 0;
>>> @@ -215,18 +217,22 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>>>   	if (!tgt_dev)
>>>   		goto err_ch;
>>>   -	memcpy(&tgt_dev->geo, &dev->geo, sizeof(struct nvm_geo));
>>>   	/* Target device only owns a portion of the physical device */
>>>   	tgt_dev->geo.nr_chnls = nr_chnls;
>>> -	tgt_dev->geo.all_luns = nr_luns;
>>>   	tgt_dev->geo.nr_luns = (lun_balanced) ? prev_nr_luns : -1;
>>> +	tgt_dev->geo.all_luns = nr_luns;
>>> +	tgt_dev->geo.all_chunks = nr_luns * dev_geo->c.num_chk;
>>> +
>>>   	tgt_dev->geo.op = op;
>>> -	tgt_dev->total_secs = nr_luns * tgt_dev->geo.sec_per_lun;
>>> +
>>> +	sec_per_lun = dev_geo->c.clba * dev_geo->c.num_chk;
>>> +	tgt_dev->geo.total_secs = nr_luns * sec_per_lun;
>>> +
>>> +	tgt_dev->geo.c = dev_geo->c;
>>> +
>>>   	tgt_dev->q = dev->q;
>>>   	tgt_dev->map = dev_map;
>>>   	tgt_dev->luns = luns;
>>> -	memcpy(&tgt_dev->identity, &dev->identity, sizeof(struct nvm_id));
>>> -
>>>   	tgt_dev->parent = dev;
>>>     	return tgt_dev;
>>> @@ -268,12 +274,12 @@ static struct nvm_tgt_type *nvm_find_target_type(const char *name)
>>>   	return tt;
>>>   }
>>>   -static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
>>> +static int nvm_config_check_luns(struct nvm_dev_geo *dev_geo, int lun_begin,
>>>   				 int lun_end)
>>>   {
>>> -	if (lun_begin > lun_end || lun_end >= geo->all_luns) {
>>> +	if (lun_begin > lun_end || lun_end >= dev_geo->all_luns) {
>>>   		pr_err("nvm: lun out of bound (%u:%u > %u)\n",
>>> -			lun_begin, lun_end, geo->all_luns - 1);
>>> +			lun_begin, lun_end, dev_geo->all_luns - 1);
>>>   		return -EINVAL;
>>>   	}
>>>   @@ -283,24 +289,24 @@ static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
>>>   static int __nvm_config_simple(struct nvm_dev *dev,
>>>   			       struct nvm_ioctl_create_simple *s)
>>>   {
>>> -	struct nvm_geo *geo = &dev->geo;
>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>     	if (s->lun_begin == -1 && s->lun_end == -1) {
>>>   		s->lun_begin = 0;
>>> -		s->lun_end = geo->all_luns - 1;
>>> +		s->lun_end = dev_geo->all_luns - 1;
>>>   	}
>>>   -	return nvm_config_check_luns(geo, s->lun_begin, s->lun_end);
>>> +	return nvm_config_check_luns(dev_geo, s->lun_begin, s->lun_end);
>>>   }
>>>     static int __nvm_config_extended(struct nvm_dev *dev,
>>>   				 struct nvm_ioctl_create_extended *e)
>>>   {
>>> -	struct nvm_geo *geo = &dev->geo;
>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>     	if (e->lun_begin == 0xFFFF && e->lun_end == 0xFFFF) {
>>>   		e->lun_begin = 0;
>>> -		e->lun_end = dev->geo.all_luns - 1;
>>> +		e->lun_end = dev_geo->all_luns - 1;
>>>   	}
>>>     	/* op not set falls into target's default */
>>> @@ -313,7 +319,7 @@ static int __nvm_config_extended(struct nvm_dev *dev,
>>>   		return -EINVAL;
>>>   	}
>>>   -	return nvm_config_check_luns(geo, e->lun_begin, e->lun_end);
>>> +	return nvm_config_check_luns(dev_geo, e->lun_begin, e->lun_end);
>>>   }
>>>     static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
>>> @@ -408,7 +414,7 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
>>>   	tqueue->queuedata = targetdata;
>>>     	blk_queue_max_hw_sectors(tqueue,
>>> -			(dev->geo.sec_size >> 9) * NVM_MAX_VLBA);
>>> +			(dev->dev_geo.c.csecs >> 9) * NVM_MAX_VLBA);
>>>     	set_capacity(tdisk, tt->capacity(targetdata));
>>>   	add_disk(tdisk);
>>> @@ -497,6 +503,7 @@ static int nvm_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove)
>>>     static int nvm_register_map(struct nvm_dev *dev)
>>>   {
>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>   	struct nvm_dev_map *rmap;
>>>   	int i, j;
>>>   @@ -504,15 +511,15 @@ static int nvm_register_map(struct nvm_dev *dev)
>>>   	if (!rmap)
>>>   		goto err_rmap;
>>>   -	rmap->chnls = kcalloc(dev->geo.nr_chnls, sizeof(struct nvm_ch_map),
>>> +	rmap->chnls = kcalloc(dev_geo->nr_chnls, sizeof(struct nvm_ch_map),
>>>   								GFP_KERNEL);
>>>   	if (!rmap->chnls)
>>>   		goto err_chnls;
>>>   -	for (i = 0; i < dev->geo.nr_chnls; i++) {
>>> +	for (i = 0; i < dev_geo->nr_chnls; i++) {
>>>   		struct nvm_ch_map *ch_rmap;
>>>   		int *lun_roffs;
>>> -		int luns_in_chnl = dev->geo.nr_luns;
>>> +		int luns_in_chnl = dev_geo->nr_luns;
>>>     		ch_rmap = &rmap->chnls[i];
>>>   @@ -543,10 +550,11 @@ static int nvm_register_map(struct nvm_dev *dev)
>>>     static void nvm_unregister_map(struct nvm_dev *dev)
>>>   {
>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>   	struct nvm_dev_map *rmap = dev->rmap;
>>>   	int i;
>>>   -	for (i = 0; i < dev->geo.nr_chnls; i++)
>>> +	for (i = 0; i < dev_geo->nr_chnls; i++)
>>>   		kfree(rmap->chnls[i].lun_offs);
>>>     	kfree(rmap->chnls);
>>> @@ -675,7 +683,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
>>>   	int i, plane_cnt, pl_idx;
>>>   	struct ppa_addr ppa;
>>>   -	if (geo->plane_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
>>> +	if (geo->c.pln_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
>>>   		rqd->nr_ppas = nr_ppas;
>>>   		rqd->ppa_addr = ppas[0];
>>>   @@ -689,7 +697,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
>>>   		return -ENOMEM;
>>>   	}
>>>   -	plane_cnt = geo->plane_mode;
>>> +	plane_cnt = geo->c.pln_mode;
>>>   	rqd->nr_ppas *= plane_cnt;
>>>     	for (i = 0; i < nr_ppas; i++) {
>>> @@ -804,18 +812,18 @@ EXPORT_SYMBOL(nvm_end_io);
>>>    */
>>>   int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
>>>   {
>>> -	struct nvm_geo *geo = &dev->geo;
>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>   	int blk, offset, pl, blktype;
>>>   -	if (nr_blks != geo->nr_chks * geo->plane_mode)
>>> +	if (nr_blks != dev_geo->c.num_chk * dev_geo->c.pln_mode)
>>>   		return -EINVAL;
>>>   -	for (blk = 0; blk < geo->nr_chks; blk++) {
>>> -		offset = blk * geo->plane_mode;
>>> +	for (blk = 0; blk < dev_geo->c.num_chk; blk++) {
>>> +		offset = blk * dev_geo->c.pln_mode;
>>>   		blktype = blks[offset];
>>>     		/* Bad blocks on any planes take precedence over other types */
>>> -		for (pl = 0; pl < geo->plane_mode; pl++) {
>>> +		for (pl = 0; pl < dev_geo->c.pln_mode; pl++) {
>>>   			if (blks[offset + pl] &
>>>   					(NVM_BLK_T_BAD|NVM_BLK_T_GRWN_BAD)) {
>>>   				blktype = blks[offset + pl];
>>> @@ -826,7 +834,7 @@ int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
>>>   		blks[blk] = blktype;
>>>   	}
>>>   -	return geo->nr_chks;
>>> +	return dev_geo->c.num_chk;
>>>   }
>>>   EXPORT_SYMBOL(nvm_bb_tbl_fold);
>>>   @@ -843,41 +851,10 @@ EXPORT_SYMBOL(nvm_get_tgt_bb_tbl);
>>>     static int nvm_core_init(struct nvm_dev *dev)
>>>   {
>>> -	struct nvm_id *id = &dev->identity;
>>> -	struct nvm_geo *geo = &dev->geo;
>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>   	int ret;
>>>   -	memcpy(&geo->ppaf, &id->ppaf, sizeof(struct nvm_addr_format));
>>> -
>>> -	if (id->mtype != 0) {
>>> -		pr_err("nvm: memory type not supported\n");
>>> -		return -EINVAL;
>>> -	}
>>> -
>>> -	/* Whole device values */
>>> -	geo->nr_chnls = id->num_ch;
>>> -	geo->nr_luns = id->num_lun;
>>> -
>>> -	/* Generic device geometry values */
>>> -	geo->ws_min = id->ws_min;
>>> -	geo->ws_opt = id->ws_opt;
>>> -	geo->ws_seq = id->ws_seq;
>>> -	geo->ws_per_chk = id->ws_per_chk;
>>> -	geo->nr_chks = id->num_chk;
>>> -	geo->mccap = id->mccap;
>>> -
>>> -	geo->sec_per_chk = id->clba;
>>> -	geo->sec_per_lun = geo->sec_per_chk * geo->nr_chks;
>>> -	geo->all_luns = geo->nr_luns * geo->nr_chnls;
>>> -
>>> -	/* 1.2 spec device geometry values */
>>> -	geo->plane_mode = 1 << geo->ws_seq;
>>> -	geo->nr_planes = geo->ws_opt / geo->ws_min;
>>> -	geo->sec_per_pg = geo->ws_min;
>>> -	geo->sec_per_pl = geo->sec_per_pg * geo->nr_planes;
>>> -
>>> -	dev->total_secs = geo->all_luns * geo->sec_per_lun;
>>> -	dev->lun_map = kcalloc(BITS_TO_LONGS(geo->all_luns),
>>> +	dev->lun_map = kcalloc(BITS_TO_LONGS(dev_geo->all_luns),
>>>   					sizeof(unsigned long), GFP_KERNEL);
>>>   	if (!dev->lun_map)
>>>   		return -ENOMEM;
>>> @@ -912,19 +889,17 @@ static void nvm_free(struct nvm_dev *dev)
>>>     static int nvm_init(struct nvm_dev *dev)
>>>   {
>>> -	struct nvm_geo *geo = &dev->geo;
>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>   	int ret = -EINVAL;
>>>   -	if (dev->ops->identity(dev, &dev->identity)) {
>>> +	if (dev->ops->identity(dev)) {
>>>   		pr_err("nvm: device could not be identified\n");
>>>   		goto err;
>>>   	}
>>>   -	if (dev->identity.ver_id != 1 && dev->identity.ver_id != 2) {
>>> -		pr_err("nvm: device ver_id %d not supported by kernel.\n",
>>> -				dev->identity.ver_id);
>>> -		goto err;
>>> -	}
>>> +	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
>>> +				dev_geo->ver_id,
>>> +				dev_geo->c.vmnt);
>>>     	ret = nvm_core_init(dev);
>>>   	if (ret) {
>>> @@ -932,10 +907,10 @@ static int nvm_init(struct nvm_dev *dev)
>>>   		goto err;
>>>   	}
>>>   -	pr_info("nvm: registered %s [%u/%u/%u/%u/%u/%u]\n",
>>> -			dev->name, geo->sec_per_pg, geo->nr_planes,
>>> -			geo->ws_per_chk, geo->nr_chks,
>>> -			geo->all_luns, geo->nr_chnls);
>>> +	pr_info("nvm: registered %s [%u/%u/%u/%u/%u]\n",
>>> +			dev->name, dev_geo->c.ws_min, dev_geo->c.ws_opt,
>>> +			dev_geo->c.num_chk, dev_geo->all_luns,
>>> +			dev_geo->nr_chnls);
>>>   	return 0;
>>>   err:
>>>   	pr_err("nvm: failed to initialize nvm\n");
>>> diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
>>> index 22e61cd4f801..519af8b9eab7 100644
>>> --- a/drivers/lightnvm/pblk-core.c
>>> +++ b/drivers/lightnvm/pblk-core.c
>>> @@ -613,7 +613,7 @@ static int pblk_line_submit_emeta_io(struct pblk *pblk, struct pblk_line *line,
>>>   	memset(&rqd, 0, sizeof(struct nvm_rq));
>>>     	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>> -	rq_len = rq_ppas * geo->sec_size;
>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>     	bio = pblk_bio_map_addr(pblk, emeta_buf, rq_ppas, rq_len,
>>>   					l_mg->emeta_alloc_type, GFP_KERNEL);
>>> @@ -722,7 +722,7 @@ u64 pblk_line_smeta_start(struct pblk *pblk, struct pblk_line *line)
>>>   	if (bit >= lm->blk_per_line)
>>>   		return -1;
>>>   -	return bit * geo->sec_per_pl;
>>> +	return bit * geo->c.ws_opt;
>>>   }
>>>     static int pblk_line_submit_smeta_io(struct pblk *pblk, struct pblk_line *line,
>>> @@ -1035,19 +1035,19 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>>>   	/* Capture bad block information on line mapping bitmaps */
>>>   	while ((bit = find_next_bit(line->blk_bitmap, lm->blk_per_line,
>>>   					bit + 1)) < lm->blk_per_line) {
>>> -		off = bit * geo->sec_per_pl;
>>> +		off = bit * geo->c.ws_opt;
>>>   		bitmap_shift_left(l_mg->bb_aux, l_mg->bb_template, off,
>>>   							lm->sec_per_line);
>>>   		bitmap_or(line->map_bitmap, line->map_bitmap, l_mg->bb_aux,
>>>   							lm->sec_per_line);
>>> -		line->sec_in_line -= geo->sec_per_chk;
>>> +		line->sec_in_line -= geo->c.clba;
>>>   		if (bit >= lm->emeta_bb)
>>>   			nr_bb++;
>>>   	}
>>>     	/* Mark smeta metadata sectors as bad sectors */
>>>   	bit = find_first_zero_bit(line->blk_bitmap, lm->blk_per_line);
>>> -	off = bit * geo->sec_per_pl;
>>> +	off = bit * geo->c.ws_opt;
>>>   	bitmap_set(line->map_bitmap, off, lm->smeta_sec);
>>>   	line->sec_in_line -= lm->smeta_sec;
>>>   	line->smeta_ssec = off;
>>> @@ -1066,10 +1066,10 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>>>   	emeta_secs = lm->emeta_sec[0];
>>>   	off = lm->sec_per_line;
>>>   	while (emeta_secs) {
>>> -		off -= geo->sec_per_pl;
>>> +		off -= geo->c.ws_opt;
>>>   		if (!test_bit(off, line->invalid_bitmap)) {
>>> -			bitmap_set(line->invalid_bitmap, off, geo->sec_per_pl);
>>> -			emeta_secs -= geo->sec_per_pl;
>>> +			bitmap_set(line->invalid_bitmap, off, geo->c.ws_opt);
>>> +			emeta_secs -= geo->c.ws_opt;
>>>   		}
>>>   	}
>>>   diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c
>>> index 320f99af99e9..16afea3f5541 100644
>>> --- a/drivers/lightnvm/pblk-gc.c
>>> +++ b/drivers/lightnvm/pblk-gc.c
>>> @@ -88,7 +88,7 @@ static void pblk_gc_line_ws(struct work_struct *work)
>>>     	up(&gc->gc_sem);
>>>   -	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->sec_size);
>>> +	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->c.csecs);
>>>   	if (!gc_rq->data) {
>>>   		pr_err("pblk: could not GC line:%d (%d/%d)\n",
>>>   					line->id, *line->vsc, gc_rq->nr_secs);
>>> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
>>> index 5261702e9ff7..95ecb0ec736b 100644
>>> --- a/drivers/lightnvm/pblk-init.c
>>> +++ b/drivers/lightnvm/pblk-init.c
>>> @@ -146,7 +146,7 @@ static int pblk_rwb_init(struct pblk *pblk)
>>>   		return -ENOMEM;
>>>     	power_size = get_count_order(nr_entries);
>>> -	power_seg_sz = get_count_order(geo->sec_size);
>>> +	power_seg_sz = get_count_order(geo->c.csecs);
>>>     	return pblk_rb_init(&pblk->rwb, entries, power_size, power_seg_sz);
>>>   }
>>> @@ -154,11 +154,11 @@ static int pblk_rwb_init(struct pblk *pblk)
>>>   /* Minimum pages needed within a lun */
>>>   #define ADDR_POOL_SIZE 64
>>>   -static int pblk_set_ppaf(struct pblk *pblk)
>>> +static int pblk_set_addrf_12(struct nvm_geo *geo,
>>> +			     struct nvm_addr_format_12 *dst)
>>>   {
>>> -	struct nvm_tgt_dev *dev = pblk->dev;
>>> -	struct nvm_geo *geo = &dev->geo;
>>> -	struct nvm_addr_format ppaf = geo->ppaf;
>>> +	struct nvm_addr_format_12 *src =
>>> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>>>   	int power_len;
>>>     	/* Re-calculate channel and lun format to adapt to configuration */
>>> @@ -167,34 +167,50 @@ static int pblk_set_ppaf(struct pblk *pblk)
>>>   		pr_err("pblk: supports only power-of-two channel config.\n");
>>>   		return -EINVAL;
>>>   	}
>>> -	ppaf.ch_len = power_len;
>>> +	dst->ch_len = power_len;
>>>     	power_len = get_count_order(geo->nr_luns);
>>>   	if (1 << power_len != geo->nr_luns) {
>>>   		pr_err("pblk: supports only power-of-two LUN config.\n");
>>>   		return -EINVAL;
>>>   	}
>>> -	ppaf.lun_len = power_len;
>>> +	dst->lun_len = power_len;
>>>   -	pblk->ppaf.sec_offset = 0;
>>> -	pblk->ppaf.pln_offset = ppaf.sect_len;
>>> -	pblk->ppaf.ch_offset = pblk->ppaf.pln_offset + ppaf.pln_len;
>>> -	pblk->ppaf.lun_offset = pblk->ppaf.ch_offset + ppaf.ch_len;
>>> -	pblk->ppaf.pg_offset = pblk->ppaf.lun_offset + ppaf.lun_len;
>>> -	pblk->ppaf.blk_offset = pblk->ppaf.pg_offset + ppaf.pg_len;
>>> -	pblk->ppaf.sec_mask = (1ULL << ppaf.sect_len) - 1;
>>> -	pblk->ppaf.pln_mask = ((1ULL << ppaf.pln_len) - 1) <<
>>> -							pblk->ppaf.pln_offset;
>>> -	pblk->ppaf.ch_mask = ((1ULL << ppaf.ch_len) - 1) <<
>>> -							pblk->ppaf.ch_offset;
>>> -	pblk->ppaf.lun_mask = ((1ULL << ppaf.lun_len) - 1) <<
>>> -							pblk->ppaf.lun_offset;
>>> -	pblk->ppaf.pg_mask = ((1ULL << ppaf.pg_len) - 1) <<
>>> -							pblk->ppaf.pg_offset;
>>> -	pblk->ppaf.blk_mask = ((1ULL << ppaf.blk_len) - 1) <<
>>> -							pblk->ppaf.blk_offset;
>>> +	dst->blk_len = src->blk_len;
>>> +	dst->pg_len = src->pg_len;
>>> +	dst->pln_len = src->pln_len;
>>> +	dst->sect_len = src->sect_len;
>>>   -	pblk->ppaf_bitsize = pblk->ppaf.blk_offset + ppaf.blk_len;
>>> +	dst->sect_offset = 0;
>>> +	dst->pln_offset = dst->sect_len;
>>> +	dst->ch_offset = dst->pln_offset + dst->pln_len;
>>> +	dst->lun_offset = dst->ch_offset + dst->ch_len;
>>> +	dst->pg_offset = dst->lun_offset + dst->lun_len;
>>> +	dst->blk_offset = dst->pg_offset + dst->pg_len;
>>> +
>>> +	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
>>> +	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
>>> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>>> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>>> +	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
>>> +	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
>>> +
>>> +	return dst->blk_offset + src->blk_len;
>>> +}
>>> +
>>> +static int pblk_set_ppaf(struct pblk *pblk)
>>> +{
>>> +	struct nvm_tgt_dev *dev = pblk->dev;
>>> +	struct nvm_geo *geo = &dev->geo;
>>> +	int mod;
>>> +
>>> +	div_u64_rem(geo->c.clba, pblk->min_write_pgs, &mod);
>>> +	if (mod) {
>>> +		pr_err("pblk: bad configuration of sectors/pages\n");
>>> +		return -EINVAL;
>>> +	}
>>> +
>>> +	pblk->ppaf_bitsize = pblk_set_addrf_12(geo, (void *)&pblk->ppaf);
>>>     	return 0;
>>>   }
>>> @@ -253,8 +269,7 @@ static int pblk_core_init(struct pblk *pblk)
>>>   	struct nvm_tgt_dev *dev = pblk->dev;
>>>   	struct nvm_geo *geo = &dev->geo;
>>>   -	pblk->pgs_in_buffer = NVM_MEM_PAGE_WRITE * geo->sec_per_pg *
>>> -						geo->nr_planes * geo->all_luns;
>>> +	pblk->pgs_in_buffer = geo->c.mw_cunits * geo->c.ws_opt * geo->all_luns;
>>>     	if (pblk_init_global_caches(pblk))
>>>   		return -ENOMEM;
>>> @@ -433,7 +448,7 @@ static void *pblk_bb_get_log(struct pblk *pblk)
>>>   	int i, nr_blks, blk_per_lun;
>>>   	int ret;
>>>   -	blk_per_lun = geo->nr_chks * geo->plane_mode;
>>> +	blk_per_lun = geo->c.num_chk * geo->c.pln_mode;
>>>   	nr_blks = blk_per_lun * geo->all_luns;
>>>     	log = kmalloc(nr_blks, GFP_KERNEL);
>>> @@ -551,18 +566,18 @@ static unsigned int calc_emeta_len(struct pblk *pblk)
>>>   	/* Round to sector size so that lba_list starts on its own sector */
>>>   	lm->emeta_sec[1] = DIV_ROUND_UP(
>>>   			sizeof(struct line_emeta) + lm->blk_bitmap_len +
>>> -			sizeof(struct wa_counters), geo->sec_size);
>>> -	lm->emeta_len[1] = lm->emeta_sec[1] * geo->sec_size;
>>> +			sizeof(struct wa_counters), geo->c.csecs);
>>> +	lm->emeta_len[1] = lm->emeta_sec[1] * geo->c.csecs;
>>>     	/* Round to sector size so that vsc_list starts on its own sector */
>>>   	lm->dsec_per_line = lm->sec_per_line - lm->emeta_sec[0];
>>>   	lm->emeta_sec[2] = DIV_ROUND_UP(lm->dsec_per_line * sizeof(u64),
>>> -			geo->sec_size);
>>> -	lm->emeta_len[2] = lm->emeta_sec[2] * geo->sec_size;
>>> +			geo->c.csecs);
>>> +	lm->emeta_len[2] = lm->emeta_sec[2] * geo->c.csecs;
>>>     	lm->emeta_sec[3] = DIV_ROUND_UP(l_mg->nr_lines * sizeof(u32),
>>> -			geo->sec_size);
>>> -	lm->emeta_len[3] = lm->emeta_sec[3] * geo->sec_size;
>>> +			geo->c.csecs);
>>> +	lm->emeta_len[3] = lm->emeta_sec[3] * geo->c.csecs;
>>>     	lm->vsc_list_len = l_mg->nr_lines * sizeof(u32);
>>>   @@ -593,13 +608,13 @@ static void pblk_set_provision(struct pblk *pblk, long nr_free_blks)
>>>   	 * on user capacity consider only provisioned blocks
>>>   	 */
>>>   	pblk->rl.total_blocks = nr_free_blks;
>>> -	pblk->rl.nr_secs = nr_free_blks * geo->sec_per_chk;
>>> +	pblk->rl.nr_secs = nr_free_blks * geo->c.clba;
>>>     	/* Consider sectors used for metadata */
>>>   	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
>>> -	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
>>> +	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
>>>   -	pblk->capacity = (provisioned - blk_meta) * geo->sec_per_chk;
>>> +	pblk->capacity = (provisioned - blk_meta) * geo->c.clba;
>>>     	atomic_set(&pblk->rl.free_blocks, nr_free_blks);
>>>   	atomic_set(&pblk->rl.free_user_blocks, nr_free_blks);
>>> @@ -710,10 +725,10 @@ static int pblk_lines_init(struct pblk *pblk)
>>>   	void *chunk_log;
>>>   	unsigned int smeta_len, emeta_len;
>>>   	long nr_bad_blks = 0, nr_free_blks = 0;
>>> -	int bb_distance, max_write_ppas, mod;
>>> +	int bb_distance, max_write_ppas;
>>>   	int i, ret;
>>>   -	pblk->min_write_pgs = geo->sec_per_pl * (geo->sec_size / PAGE_SIZE);
>>> +	pblk->min_write_pgs = geo->c.ws_opt * (geo->c.csecs / PAGE_SIZE);
>>>   	max_write_ppas = pblk->min_write_pgs * geo->all_luns;
>>>   	pblk->max_write_pgs = min_t(int, max_write_ppas, NVM_MAX_VLBA);
>>>   	pblk_set_sec_per_write(pblk, pblk->min_write_pgs);
>>> @@ -724,19 +739,13 @@ static int pblk_lines_init(struct pblk *pblk)
>>>   		return -EINVAL;
>>>   	}
>>>   -	div_u64_rem(geo->sec_per_chk, pblk->min_write_pgs, &mod);
>>> -	if (mod) {
>>> -		pr_err("pblk: bad configuration of sectors/pages\n");
>>> -		return -EINVAL;
>>> -	}
>>> -
>>> -	l_mg->nr_lines = geo->nr_chks;
>>> +	l_mg->nr_lines = geo->c.num_chk;
>>>   	l_mg->log_line = l_mg->data_line = NULL;
>>>   	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
>>>   	l_mg->nr_free_lines = 0;
>>>   	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
>>>   -	lm->sec_per_line = geo->sec_per_chk * geo->all_luns;
>>> +	lm->sec_per_line = geo->c.clba * geo->all_luns;
>>>   	lm->blk_per_line = geo->all_luns;
>>>   	lm->blk_bitmap_len = BITS_TO_LONGS(geo->all_luns) * sizeof(long);
>>>   	lm->sec_bitmap_len = BITS_TO_LONGS(lm->sec_per_line) * sizeof(long);
>>> @@ -750,8 +759,8 @@ static int pblk_lines_init(struct pblk *pblk)
>>>   	 */
>>>   	i = 1;
>>>   add_smeta_page:
>>> -	lm->smeta_sec = i * geo->sec_per_pl;
>>> -	lm->smeta_len = lm->smeta_sec * geo->sec_size;
>>> +	lm->smeta_sec = i * geo->c.ws_opt;
>>> +	lm->smeta_len = lm->smeta_sec * geo->c.csecs;
>>>     	smeta_len = sizeof(struct line_smeta) + lm->lun_bitmap_len;
>>>   	if (smeta_len > lm->smeta_len) {
>>> @@ -764,8 +773,8 @@ static int pblk_lines_init(struct pblk *pblk)
>>>   	 */
>>>   	i = 1;
>>>   add_emeta_page:
>>> -	lm->emeta_sec[0] = i * geo->sec_per_pl;
>>> -	lm->emeta_len[0] = lm->emeta_sec[0] * geo->sec_size;
>>> +	lm->emeta_sec[0] = i * geo->c.ws_opt;
>>> +	lm->emeta_len[0] = lm->emeta_sec[0] * geo->c.csecs;
>>>     	emeta_len = calc_emeta_len(pblk);
>>>   	if (emeta_len > lm->emeta_len[0]) {
>>> @@ -778,7 +787,7 @@ static int pblk_lines_init(struct pblk *pblk)
>>>   	lm->min_blk_line = 1;
>>>   	if (geo->all_luns > 1)
>>>   		lm->min_blk_line += DIV_ROUND_UP(lm->smeta_sec +
>>> -					lm->emeta_sec[0], geo->sec_per_chk);
>>> +					lm->emeta_sec[0], geo->c.clba);
>>>     	if (lm->min_blk_line > lm->blk_per_line) {
>>>   		pr_err("pblk: config. not supported. Min. LUN in line:%d\n",
>>> @@ -802,9 +811,9 @@ static int pblk_lines_init(struct pblk *pblk)
>>>   		goto fail_free_bb_template;
>>>   	}
>>>   -	bb_distance = (geo->all_luns) * geo->sec_per_pl;
>>> +	bb_distance = (geo->all_luns) * geo->c.ws_opt;
>>>   	for (i = 0; i < lm->sec_per_line; i += bb_distance)
>>> -		bitmap_set(l_mg->bb_template, i, geo->sec_per_pl);
>>> +		bitmap_set(l_mg->bb_template, i, geo->c.ws_opt);
>>>     	INIT_LIST_HEAD(&l_mg->free_list);
>>>   	INIT_LIST_HEAD(&l_mg->corrupt_list);
>>> @@ -981,9 +990,9 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>>>   	struct pblk *pblk;
>>>   	int ret;
>>>   -	if (dev->identity.dom & NVM_RSP_L2P) {
>>> +	if (dev->geo.c.dom & NVM_RSP_L2P) {
>>>   		pr_err("pblk: host-side L2P table not supported. (%x)\n",
>>> -							dev->identity.dom);
>>> +							dev->geo.c.dom);
>>>   		return ERR_PTR(-EINVAL);
>>>   	}
>>>   @@ -1091,7 +1100,7 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>>>     	blk_queue_write_cache(tqueue, true, false);
>>>   -	tqueue->limits.discard_granularity = geo->sec_per_chk * geo->sec_size;
>>> +	tqueue->limits.discard_granularity = geo->c.clba * geo->c.csecs;
>>>   	tqueue->limits.discard_alignment = 0;
>>>   	blk_queue_max_discard_sectors(tqueue, UINT_MAX >> 9);
>>>   	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, tqueue);
>>> diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c
>>> index 2f761283f43e..ebb6bae3a3b8 100644
>>> --- a/drivers/lightnvm/pblk-read.c
>>> +++ b/drivers/lightnvm/pblk-read.c
>>> @@ -563,7 +563,7 @@ int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq)
>>>   	if (!(gc_rq->secs_to_gc))
>>>   		goto out;
>>>   -	data_len = (gc_rq->secs_to_gc) * geo->sec_size;
>>> +	data_len = (gc_rq->secs_to_gc) * geo->c.csecs;
>>>   	bio = pblk_bio_map_addr(pblk, gc_rq->data, gc_rq->secs_to_gc, data_len,
>>>   						PBLK_VMALLOC_META, GFP_KERNEL);
>>>   	if (IS_ERR(bio)) {
>>> diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
>>> index aaab9a5c17cc..1574dbbfbb1c 100644
>>> --- a/drivers/lightnvm/pblk-recovery.c
>>> +++ b/drivers/lightnvm/pblk-recovery.c
>>> @@ -184,7 +184,7 @@ static int pblk_calc_sec_in_line(struct pblk *pblk, struct pblk_line *line)
>>>   	int nr_bb = bitmap_weight(line->blk_bitmap, lm->blk_per_line);
>>>     	return lm->sec_per_line - lm->smeta_sec - lm->emeta_sec[0] -
>>> -				nr_bb * geo->sec_per_chk;
>>> +				nr_bb * geo->c.clba;
>>>   }
>>>     struct pblk_recov_alloc {
>>> @@ -232,7 +232,7 @@ static int pblk_recov_read_oob(struct pblk *pblk, struct pblk_line *line,
>>>   	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>>   	if (!rq_ppas)
>>>   		rq_ppas = pblk->min_write_pgs;
>>> -	rq_len = rq_ppas * geo->sec_size;
>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>     	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>>>   	if (IS_ERR(bio))
>>> @@ -351,7 +351,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
>>>   	if (!pad_rq)
>>>   		return -ENOMEM;
>>>   -	data = vzalloc(pblk->max_write_pgs * geo->sec_size);
>>> +	data = vzalloc(pblk->max_write_pgs * geo->c.csecs);
>>>   	if (!data) {
>>>   		ret = -ENOMEM;
>>>   		goto free_rq;
>>> @@ -368,7 +368,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
>>>   		goto fail_free_pad;
>>>   	}
>>>   -	rq_len = rq_ppas * geo->sec_size;
>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>     	meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, &dma_meta_list);
>>>   	if (!meta_list) {
>>> @@ -509,7 +509,7 @@ static int pblk_recov_scan_all_oob(struct pblk *pblk, struct pblk_line *line,
>>>   	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>>   	if (!rq_ppas)
>>>   		rq_ppas = pblk->min_write_pgs;
>>> -	rq_len = rq_ppas * geo->sec_size;
>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>     	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>>>   	if (IS_ERR(bio))
>>> @@ -640,7 +640,7 @@ static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line,
>>>   	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>>   	if (!rq_ppas)
>>>   		rq_ppas = pblk->min_write_pgs;
>>> -	rq_len = rq_ppas * geo->sec_size;
>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>     	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>>>   	if (IS_ERR(bio))
>>> @@ -745,7 +745,7 @@ static int pblk_recov_l2p_from_oob(struct pblk *pblk, struct pblk_line *line)
>>>   	ppa_list = (void *)(meta_list) + pblk_dma_meta_size;
>>>   	dma_ppa_list = dma_meta_list + pblk_dma_meta_size;
>>>   -	data = kcalloc(pblk->max_write_pgs, geo->sec_size, GFP_KERNEL);
>>> +	data = kcalloc(pblk->max_write_pgs, geo->c.csecs, GFP_KERNEL);
>>>   	if (!data) {
>>>   		ret = -ENOMEM;
>>>   		goto free_meta_list;
>>> diff --git a/drivers/lightnvm/pblk-rl.c b/drivers/lightnvm/pblk-rl.c
>>> index 0d457b162f23..bcab203477ec 100644
>>> --- a/drivers/lightnvm/pblk-rl.c
>>> +++ b/drivers/lightnvm/pblk-rl.c
>>> @@ -200,7 +200,7 @@ void pblk_rl_init(struct pblk_rl *rl, int budget)
>>>     	/* Consider sectors used for metadata */
>>>   	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
>>> -	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
>>> +	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
>>>     	rl->high = pblk->op_blks - blk_meta - lm->blk_per_line;
>>>   	rl->high_pw = get_count_order(rl->high);
>>> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
>>> index d93e9b1f083a..5eb21a279361 100644
>>> --- a/drivers/lightnvm/pblk-sysfs.c
>>> +++ b/drivers/lightnvm/pblk-sysfs.c
>>> @@ -113,26 +113,31 @@ 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;
>>>   -	sz = snprintf(page, PAGE_SIZE - sz,
>>> -		"g:(b:%d)blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
>>> -		pblk->ppaf_bitsize,
>>> -		pblk->ppaf.blk_offset, geo->ppaf.blk_len,
>>> -		pblk->ppaf.pg_offset, geo->ppaf.pg_len,
>>> -		pblk->ppaf.lun_offset, geo->ppaf.lun_len,
>>> -		pblk->ppaf.ch_offset, geo->ppaf.ch_len,
>>> -		pblk->ppaf.pln_offset, geo->ppaf.pln_len,
>>> -		pblk->ppaf.sec_offset, geo->ppaf.sect_len);
>>> +	ppaf = (struct nvm_addr_format_12 *)&pblk->ppaf;
>>> +	geo_ppaf = (struct nvm_addr_format_12 *)&geo->c.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",
>>> +			pblk->ppaf_bitsize,
>>> +			ppaf->ch_offset, ppaf->ch_len,
>>> +			ppaf->lun_offset, ppaf->lun_len,
>>> +			ppaf->blk_offset, ppaf->blk_len,
>>> +			ppaf->pg_offset, ppaf->pg_len,
>>> +			ppaf->pln_offset, ppaf->pln_len,
>>> +			ppaf->sect_offset, ppaf->sect_len);
>>>     	sz += snprintf(page + sz, PAGE_SIZE - sz,
>>> -		"d:blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
>>> -		geo->ppaf.blk_offset, geo->ppaf.blk_len,
>>> -		geo->ppaf.pg_offset, geo->ppaf.pg_len,
>>> -		geo->ppaf.lun_offset, geo->ppaf.lun_len,
>>> -		geo->ppaf.ch_offset, geo->ppaf.ch_len,
>>> -		geo->ppaf.pln_offset, geo->ppaf.pln_len,
>>> -		geo->ppaf.sect_offset, geo->ppaf.sect_len);
>>> +		"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->sect_offset, geo_ppaf->sect_len);
>>>     	return sz;
>>>   }
>>> @@ -288,7 +293,7 @@ static ssize_t pblk_sysfs_lines_info(struct pblk *pblk, char *page)
>>>   				"blk_line:%d, sec_line:%d, sec_blk:%d\n",
>>>   					lm->blk_per_line,
>>>   					lm->sec_per_line,
>>> -					geo->sec_per_chk);
>>> +					geo->c.clba);
>>>     	return sz;
>>>   }
>>> diff --git a/drivers/lightnvm/pblk-write.c b/drivers/lightnvm/pblk-write.c
>>> index aae86ed60b98..c49b27539d5a 100644
>>> --- a/drivers/lightnvm/pblk-write.c
>>> +++ b/drivers/lightnvm/pblk-write.c
>>> @@ -333,7 +333,7 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line)
>>>   	m_ctx = nvm_rq_to_pdu(rqd);
>>>   	m_ctx->private = meta_line;
>>>   -	rq_len = rq_ppas * geo->sec_size;
>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>   	data = ((void *)emeta->buf) + emeta->mem;
>>>     	bio = pblk_bio_map_addr(pblk, data, rq_ppas, rq_len,
>>> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
>>> index 282dfc8780e8..67ffb53608f7 100644
>>> --- a/drivers/lightnvm/pblk.h
>>> +++ b/drivers/lightnvm/pblk.h
>>> @@ -551,21 +551,6 @@ struct pblk_line_meta {
>>>   	unsigned int meta_distance;	/* Distance between data and metadata */
>>>   };
>>>   -struct pblk_addr_format {
>>> -	u64	ch_mask;
>>> -	u64	lun_mask;
>>> -	u64	pln_mask;
>>> -	u64	blk_mask;
>>> -	u64	pg_mask;
>>> -	u64	sec_mask;
>>> -	u8	ch_offset;
>>> -	u8	lun_offset;
>>> -	u8	pln_offset;
>>> -	u8	blk_offset;
>>> -	u8	pg_offset;
>>> -	u8	sec_offset;
>>> -};
>>> -
>>>   enum {
>>>   	PBLK_STATE_RUNNING = 0,
>>>   	PBLK_STATE_STOPPING = 1,
>>> @@ -585,8 +570,8 @@ struct pblk {
>>>   	struct pblk_line_mgmt l_mg;		/* Line management */
>>>   	struct pblk_line_meta lm;		/* Line metadata */
>>>   +	struct nvm_addr_format ppaf;
>>>   	int ppaf_bitsize;
>>> -	struct pblk_addr_format ppaf;
>>>     	struct pblk_rb rwb;
>>>   @@ -941,14 +926,12 @@ static inline int pblk_line_vsc(struct pblk_line *line)
>>>   	return le32_to_cpu(*line->vsc);
>>>   }
>>>   -#define NVM_MEM_PAGE_WRITE (8)
>>> -
>>>   static inline int pblk_pad_distance(struct pblk *pblk)
>>>   {
>>>   	struct nvm_tgt_dev *dev = pblk->dev;
>>>   	struct nvm_geo *geo = &dev->geo;
>>>   -	return NVM_MEM_PAGE_WRITE * geo->all_luns * geo->sec_per_pl;
>>> +	return geo->c.mw_cunits * geo->all_luns * geo->c.ws_opt;
>>>   }
>>>     static inline int pblk_ppa_to_line(struct ppa_addr p)
>>> @@ -964,15 +947,17 @@ 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->ppaf;
>>>   	struct ppa_addr ppa;
>>>     	ppa.ppa = 0;
>>>   	ppa.g.blk = line_id;
>>> -	ppa.g.pg = (paddr & pblk->ppaf.pg_mask) >> pblk->ppaf.pg_offset;
>>> -	ppa.g.lun = (paddr & pblk->ppaf.lun_mask) >> pblk->ppaf.lun_offset;
>>> -	ppa.g.ch = (paddr & pblk->ppaf.ch_mask) >> pblk->ppaf.ch_offset;
>>> -	ppa.g.pl = (paddr & pblk->ppaf.pln_mask) >> pblk->ppaf.pln_offset;
>>> -	ppa.g.sec = (paddr & pblk->ppaf.sec_mask) >> pblk->ppaf.sec_offset;
>>> +	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->sect_offset;
>>>     	return ppa;
>>>   }
>>> @@ -980,13 +965,15 @@ 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->ppaf;
>>>   	u64 paddr;
>>>   -	paddr = (u64)p.g.pg << pblk->ppaf.pg_offset;
>>> -	paddr |= (u64)p.g.lun << pblk->ppaf.lun_offset;
>>> -	paddr |= (u64)p.g.ch << pblk->ppaf.ch_offset;
>>> -	paddr |= (u64)p.g.pl << pblk->ppaf.pln_offset;
>>> -	paddr |= (u64)p.g.sec << pblk->ppaf.sec_offset;
>>> +	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->sect_offset;
>>>     	return paddr;
>>>   }
>>> @@ -1003,18 +990,15 @@ 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 {
>>> -		ppa64.g.blk = (ppa32 & pblk->ppaf.blk_mask) >>
>>> -							pblk->ppaf.blk_offset;
>>> -		ppa64.g.pg = (ppa32 & pblk->ppaf.pg_mask) >>
>>> -							pblk->ppaf.pg_offset;
>>> -		ppa64.g.lun = (ppa32 & pblk->ppaf.lun_mask) >>
>>> -							pblk->ppaf.lun_offset;
>>> -		ppa64.g.ch = (ppa32 & pblk->ppaf.ch_mask) >>
>>> -							pblk->ppaf.ch_offset;
>>> -		ppa64.g.pl = (ppa32 & pblk->ppaf.pln_mask) >>
>>> -							pblk->ppaf.pln_offset;
>>> -		ppa64.g.sec = (ppa32 & pblk->ppaf.sec_mask) >>
>>> -							pblk->ppaf.sec_offset;
>>> +		struct nvm_addr_format_12 *ppaf =
>>> +				(struct nvm_addr_format_12 *)&pblk->ppaf;
>>> +
>>> +		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->sect_offset;
>>>   	}
>>>     	return ppa64;
>>> @@ -1030,12 +1014,15 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
>>>   		ppa32 |= ppa64.c.line;
>>>   		ppa32 |= 1U << 31;
>>>   	} else {
>>> -		ppa32 |= ppa64.g.blk << pblk->ppaf.blk_offset;
>>> -		ppa32 |= ppa64.g.pg << pblk->ppaf.pg_offset;
>>> -		ppa32 |= ppa64.g.lun << pblk->ppaf.lun_offset;
>>> -		ppa32 |= ppa64.g.ch << pblk->ppaf.ch_offset;
>>> -		ppa32 |= ppa64.g.pl << pblk->ppaf.pln_offset;
>>> -		ppa32 |= ppa64.g.sec << pblk->ppaf.sec_offset;
>>> +		struct nvm_addr_format_12 *ppaf =
>>> +				(struct nvm_addr_format_12 *)&pblk->ppaf;
>>> +
>>> +		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->sect_offset;
>>>   	}
>>>     	return ppa32;
>>> @@ -1153,7 +1140,7 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type)
>>>   	struct nvm_geo *geo = &dev->geo;
>>>   	int flags;
>>>   -	flags = geo->plane_mode >> 1;
>>> +	flags = geo->c.pln_mode >> 1;
>>>     	if (type == PBLK_WRITE)
>>>   		flags |= NVM_IO_SCRAMBLE_ENABLE;
>>> @@ -1174,7 +1161,7 @@ static inline int pblk_set_read_mode(struct pblk *pblk, int type)
>>>     	flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
>>>   	if (type == PBLK_READ_SEQUENTIAL)
>>> -		flags |= geo->plane_mode >> 1;
>>> +		flags |= geo->c.pln_mode >> 1;
>>>     	return flags;
>>>   }
>>> @@ -1229,10 +1216,10 @@ static inline int pblk_boundary_ppa_checks(struct nvm_tgt_dev *tgt_dev,
>>>   		if (!ppa->c.is_cached &&
>>>   				ppa->g.ch < geo->nr_chnls &&
>>>   				ppa->g.lun < geo->nr_luns &&
>>> -				ppa->g.pl < geo->nr_planes &&
>>> -				ppa->g.blk < geo->nr_chks &&
>>> -				ppa->g.pg < geo->ws_per_chk &&
>>> -				ppa->g.sec < geo->sec_per_pg)
>>> +				ppa->g.pl < geo->c.num_pln &&
>>> +				ppa->g.blk < geo->c.num_chk &&
>>> +				ppa->g.pg < geo->c.num_pg &&
>>> +				ppa->g.sec < geo->c.ws_min)
>>>   			continue;
>>>     		print_ppa(ppa, "boundary", i);
>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>> index 839c0b96466a..c81e64cc20d7 100644
>>> --- a/drivers/nvme/host/lightnvm.c
>>> +++ b/drivers/nvme/host/lightnvm.c
>>> @@ -152,8 +152,8 @@ struct nvme_nvm_id12_addrf {
>>>   	__u8			blk_len;
>>>   	__u8			pg_offset;
>>>   	__u8			pg_len;
>>> -	__u8			sect_offset;
>>> -	__u8			sect_len;
>>> +	__u8			sec_offset;
>>> +	__u8			sec_len;
>>>   	__u8			res[4];
>>>   } __packed;
>>>   @@ -254,106 +254,157 @@ static inline void _nvme_nvm_check_size(void)
>>>   	BUILD_BUG_ON(sizeof(struct nvme_nvm_id20) != NVME_IDENTIFY_DATA_SIZE);
>>>   }
>>>   -static int init_grp(struct nvm_id *nvm_id, struct nvme_nvm_id12 *id12)
>>> +static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
>>> +				 struct nvme_nvm_id12_addrf *src)
>>> +{
>>> +	dst->ch_len = src->ch_len;
>>> +	dst->lun_len = src->lun_len;
>>> +	dst->blk_len = src->blk_len;
>>> +	dst->pg_len = src->pg_len;
>>> +	dst->pln_len = src->pln_len;
>>> +	dst->sect_len = src->sec_len;
>>> +
>>> +	dst->ch_offset = src->ch_offset;
>>> +	dst->lun_offset = src->lun_offset;
>>> +	dst->blk_offset = src->blk_offset;
>>> +	dst->pg_offset = src->pg_offset;
>>> +	dst->pln_offset = src->pln_offset;
>>> +	dst->sect_offset = src->sec_offset;
>>> +
>>> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>>> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>>> +	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
>>> +	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
>>> +	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
>>> +	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
>>> +}
>>> +
>>> +static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>>> +			     struct nvm_dev_geo *dev_geo)
>>>   {
>>>   	struct nvme_nvm_id12_grp *src;
>>>   	int sec_per_pg, sec_per_pl, pg_per_blk;
>>>   -	if (id12->cgrps != 1)
>>> +	if (id->cgrps != 1)
>>>   		return -EINVAL;
>>>   -	src = &id12->grp;
>>> +	src = &id->grp;
>>>   -	nvm_id->mtype = src->mtype;
>>> -	nvm_id->fmtype = src->fmtype;
>>> +	if (src->mtype != 0) {
>>> +		pr_err("nvm: memory type not supported\n");
>>> +		return -EINVAL;
>>> +	}
>>> +
>>> +	/* 1.2 spec. only reports a single version id - unfold */
>>> +	dev_geo->ver_id = id->ver_id;
>>>   -	nvm_id->num_ch = src->num_ch;
>>> -	nvm_id->num_lun = src->num_lun;
>>> +	dev_geo->nr_chnls = src->num_ch;
>>> +	dev_geo->nr_luns = src->num_lun;
>>> +	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
>>>   -	nvm_id->num_chk = le16_to_cpu(src->num_chk);
>>> -	nvm_id->csecs = le16_to_cpu(src->csecs);
>>> -	nvm_id->sos = le16_to_cpu(src->sos);
>>> +	dev_geo->c.num_chk = le16_to_cpu(src->num_chk);
>>> +	dev_geo->c.csecs = le16_to_cpu(src->csecs);
>>> +	dev_geo->c.sos = le16_to_cpu(src->sos);
>>>     	pg_per_blk = le16_to_cpu(src->num_pg);
>>> -	sec_per_pg = le16_to_cpu(src->fpg_sz) / nvm_id->csecs;
>>> +	sec_per_pg = le16_to_cpu(src->fpg_sz) / dev_geo->c.csecs;
>>>   	sec_per_pl = sec_per_pg * src->num_pln;
>>> -	nvm_id->clba = sec_per_pl * pg_per_blk;
>>> -	nvm_id->ws_per_chk = pg_per_blk;
>>> -
>>> -	nvm_id->mpos = le32_to_cpu(src->mpos);
>>> -	nvm_id->cpar = le16_to_cpu(src->cpar);
>>> -	nvm_id->mccap = le32_to_cpu(src->mccap);
>>> -
>>> -	nvm_id->ws_opt = nvm_id->ws_min = sec_per_pg;
>>> -	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
>>> -
>>> -	if (nvm_id->mpos & 0x020202) {
>>> -		nvm_id->ws_seq = NVM_IO_DUAL_ACCESS;
>>> -		nvm_id->ws_opt <<= 1;
>>> -	} else if (nvm_id->mpos & 0x040404) {
>>> -		nvm_id->ws_seq = NVM_IO_QUAD_ACCESS;
>>> -		nvm_id->ws_opt <<= 2;
>>> +	dev_geo->c.clba = sec_per_pl * pg_per_blk;
>>> +
>>> +	dev_geo->c.ws_min = sec_per_pg;
>>> +	dev_geo->c.ws_opt = sec_per_pg;
>>> +	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
>>> +
>>> +	dev_geo->c.mccap = le32_to_cpu(src->mccap);
>>> +
>>> +	dev_geo->c.trdt = le32_to_cpu(src->trdt);
>>> +	dev_geo->c.trdm = le32_to_cpu(src->trdm);
>>> +	dev_geo->c.tprt = le32_to_cpu(src->tprt);
>>> +	dev_geo->c.tprm = le32_to_cpu(src->tprm);
>>> +	dev_geo->c.tbet = le32_to_cpu(src->tbet);
>>> +	dev_geo->c.tbem = le32_to_cpu(src->tbem);
>>> +
>>> +	/* 1.2 compatibility */
>>> +	dev_geo->c.vmnt = id->vmnt;
>>> +	dev_geo->c.cap = le32_to_cpu(id->cap);
>>> +	dev_geo->c.dom = le32_to_cpu(id->dom);
>>> +
>>> +	dev_geo->c.mtype = src->mtype;
>>> +	dev_geo->c.fmtype = src->fmtype;
>>> +
>>> +	dev_geo->c.cpar = le16_to_cpu(src->cpar);
>>> +	dev_geo->c.mpos = le32_to_cpu(src->mpos);
>>> +
>>> +	dev_geo->c.pln_mode = NVM_PLANE_SINGLE;
>>> +
>>> +	if (dev_geo->c.mpos & 0x020202) {
>>> +		dev_geo->c.pln_mode = NVM_PLANE_DOUBLE;
>>> +		dev_geo->c.ws_opt <<= 1;
>>> +	} else if (dev_geo->c.mpos & 0x040404) {
>>> +		dev_geo->c.pln_mode = NVM_PLANE_QUAD;
>>> +		dev_geo->c.ws_opt <<= 2;
>>>   	}
>>>   -	nvm_id->trdt = le32_to_cpu(src->trdt);
>>> -	nvm_id->trdm = le32_to_cpu(src->trdm);
>>> -	nvm_id->tprt = le32_to_cpu(src->tprt);
>>> -	nvm_id->tprm = le32_to_cpu(src->tprm);
>>> -	nvm_id->tbet = le32_to_cpu(src->tbet);
>>> -	nvm_id->tbem = le32_to_cpu(src->tbem);
>>> -
>>> -	/* 1.2 compatibility */
>>> -	nvm_id->num_pln = src->num_pln;
>>> -	nvm_id->num_pg = le16_to_cpu(src->num_pg);
>>> -	nvm_id->fpg_sz = le16_to_cpu(src->fpg_sz);
>>> +	dev_geo->c.num_pln = src->num_pln;
>>> +	dev_geo->c.num_pg = le16_to_cpu(src->num_pg);
>>> +	dev_geo->c.fpg_sz = le16_to_cpu(src->fpg_sz);
>>> +
>>> +	nvme_nvm_set_addr_12((struct nvm_addr_format_12 *)&dev_geo->c.addrf,
>>> +								&id->ppaf);
>>>     	return 0;
>>>   }
>>>   -static int nvme_nvm_setup_12(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
>>> -		struct nvme_nvm_id12 *id)
>>> +static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
>>> +				 struct nvme_nvm_id20_addrf *src)
>>>   {
>>> -	nvm_id->ver_id = id->ver_id;
>>> -	nvm_id->vmnt = id->vmnt;
>>> -	nvm_id->cap = le32_to_cpu(id->cap);
>>> -	nvm_id->dom = le32_to_cpu(id->dom);
>>> -	memcpy(&nvm_id->ppaf, &id->ppaf,
>>> -					sizeof(struct nvm_addr_format));
>>> -
>>> -	return init_grp(nvm_id, id);
>>> +	dst->ch_len = src->grp_len;
>>> +	dst->lun_len = src->pu_len;
>>> +	dst->chk_len = src->chk_len;
>>> +	dst->sec_len = src->lba_len;
>>> +
>>> +	dst->sec_offset = 0;
>>> +	dst->chk_offset = dst->sec_len;
>>> +	dst->lun_offset = dst->chk_offset + dst->chk_len;
>>> +	dst->ch_offset = dst->lun_offset + dst->lun_len;
>>> +
>>> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>>> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>>> +	dst->chk_mask = ((1ULL << dst->chk_len) - 1) << dst->chk_offset;
>>> +	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>>>   }
>>>   -static int nvme_nvm_setup_20(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
>>> -		struct nvme_nvm_id20 *id)
>>> +static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>>> +			     struct nvm_dev_geo *dev_geo)
>>>   {
>>> -	nvm_id->ver_id = id->mjr;
>>> +	dev_geo->ver_id = id->mjr;
>>>   -	nvm_id->num_ch = le16_to_cpu(id->num_grp);
>>> -	nvm_id->num_lun = le16_to_cpu(id->num_pu);
>>> -	nvm_id->num_chk = le32_to_cpu(id->num_chk);
>>> -	nvm_id->clba = le32_to_cpu(id->clba);
>>> +	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
>>> +	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
>>> +	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
>>>   -	nvm_id->ws_min = le32_to_cpu(id->ws_min);
>>> -	nvm_id->ws_opt = le32_to_cpu(id->ws_opt);
>>> -	nvm_id->mw_cunits = le32_to_cpu(id->mw_cunits);
>>> +	dev_geo->c.num_chk = le32_to_cpu(id->num_chk);
>>> +	dev_geo->c.clba = le32_to_cpu(id->clba);
>>> +	dev_geo->c.csecs = -1;		/* Set by nvme identify */
>>> +	dev_geo->c.sos = -1;		/* Set bu nvme identify */
>>>   -	nvm_id->trdt = le32_to_cpu(id->trdt);
>>> -	nvm_id->trdm = le32_to_cpu(id->trdm);
>>> -	nvm_id->tprt = le32_to_cpu(id->twrt);
>>> -	nvm_id->tprm = le32_to_cpu(id->twrm);
>>> -	nvm_id->tbet = le32_to_cpu(id->tcrst);
>>> -	nvm_id->tbem = le32_to_cpu(id->tcrsm);
>>> +	dev_geo->c.ws_min = le32_to_cpu(id->ws_min);
>>> +	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
>>> +	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
>>>   -	/* calculated values */
>>> -	nvm_id->ws_per_chk = nvm_id->clba / nvm_id->ws_min;
>>> +	dev_geo->c.trdt = le32_to_cpu(id->trdt);
>>> +	dev_geo->c.trdm = le32_to_cpu(id->trdm);
>>> +	dev_geo->c.tprt = le32_to_cpu(id->twrt);
>>> +	dev_geo->c.tprm = le32_to_cpu(id->twrm);
>>> +	dev_geo->c.tbet = le32_to_cpu(id->tcrst);
>>> +	dev_geo->c.tbem = le32_to_cpu(id->tcrsm);
>>>   -	/* 1.2 compatibility */
>>> -	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
>>> +	nvme_nvm_set_addr_20(&dev_geo->c.addrf, &id->lbaf);
>>>     	return 0;
>>>   }
>>>   -static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
>>> +static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>>>   {
>>>   	struct nvme_ns *ns = nvmdev->q->queuedata;
>>>   	struct nvme_nvm_id12 *id;
>>> @@ -380,18 +431,18 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
>>>   	 */
>>>   	switch (id->ver_id) {
>>>   	case 1:
>>> -		ret = nvme_nvm_setup_12(nvmdev, nvm_id, id);
>>> +		ret = nvme_nvm_setup_12(id, &nvmdev->dev_geo);
>>>   		break;
>>>   	case 2:
>>> -		ret = nvme_nvm_setup_20(nvmdev, nvm_id,
>>> -				(struct nvme_nvm_id20 *)id);
>>> +		ret = nvme_nvm_setup_20((struct nvme_nvm_id20 *)id,
>>> +							&nvmdev->dev_geo);
>>>   		break;
>>>   	default:
>>> -		dev_err(ns->ctrl->device,
>>> -			"OCSSD revision not supported (%d)\n",
>>> -			nvm_id->ver_id);
>>> +		dev_err(ns->ctrl->device, "OCSSD revision not supported (%d)\n",
>>> +							id->ver_id);
>>>   		ret = -EINVAL;
>>>   	}
>>> +
>>>   out:
>>>   	kfree(id);
>>>   	return ret;
>>> @@ -401,12 +452,12 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
>>>   								u8 *blks)
>>>   {
>>>   	struct request_queue *q = nvmdev->q;
>>> -	struct nvm_geo *geo = &nvmdev->geo;
>>> +	struct nvm_dev_geo *dev_geo = &nvmdev->dev_geo;
>>>   	struct nvme_ns *ns = q->queuedata;
>>>   	struct nvme_ctrl *ctrl = ns->ctrl;
>>>   	struct nvme_nvm_command c = {};
>>>   	struct nvme_nvm_bb_tbl *bb_tbl;
>>> -	int nr_blks = geo->nr_chks * geo->plane_mode;
>>> +	int nr_blks = dev_geo->c.num_chk * dev_geo->c.num_pln;
>>>   	int tblsz = sizeof(struct nvme_nvm_bb_tbl) + nr_blks;
>>>   	int ret = 0;
>>>   @@ -447,7 +498,7 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
>>>   		goto out;
>>>   	}
>>>   -	memcpy(blks, bb_tbl->blk, geo->nr_chks * geo->plane_mode);
>>> +	memcpy(blks, bb_tbl->blk, dev_geo->c.num_chk * dev_geo->c.num_pln);
>>>   out:
>>>   	kfree(bb_tbl);
>>>   	return ret;
>>> @@ -815,9 +866,10 @@ int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd, unsigned long arg)
>>>   void nvme_nvm_update_nvm_info(struct nvme_ns *ns)
>>>   {
>>>   	struct nvm_dev *ndev = ns->ndev;
>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>   -	ndev->identity.csecs = ndev->geo.sec_size = 1 << ns->lba_shift;
>>> -	ndev->identity.sos = ndev->geo.oob_size = ns->ms;
>>> +	dev_geo->c.csecs = 1 << ns->lba_shift;
>>> +	dev_geo->c.sos = ns->ms;
>>>   }
>>>     int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node)
>>> @@ -850,23 +902,22 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>>   {
>>>   	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>>>   	struct nvm_dev *ndev = ns->ndev;
>>> -	struct nvm_id *id;
>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>   	struct attribute *attr;
>>>     	if (!ndev)
>>>   		return 0;
>>>   -	id = &ndev->identity;
>>>   	attr = &dattr->attr;
>>>     	if (strcmp(attr->name, "version") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ver_id);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>>>   	} else if (strcmp(attr->name, "capabilities") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->cap);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
>>>   	} else if (strcmp(attr->name, "read_typ") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdt);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>>>   	} else if (strcmp(attr->name, "read_max") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdm);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdm);
>>>   	} else {
>>>   		return scnprintf(page,
>>>   				 PAGE_SIZE,
>>> @@ -875,75 +926,79 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>>   	}
>>>   }
>>>   +static ssize_t nvm_dev_attr_show_ppaf(struct nvm_addr_format_12 *ppaf,
>>> +					 char *page)
>>> +{
>>> +	return scnprintf(page, PAGE_SIZE,
>>> +		"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
>>> +				ppaf->ch_offset, ppaf->ch_len,
>>> +				ppaf->lun_offset, ppaf->lun_len,
>>> +				ppaf->pln_offset, ppaf->pln_len,
>>> +				ppaf->blk_offset, ppaf->blk_len,
>>> +				ppaf->pg_offset, ppaf->pg_len,
>>> +				ppaf->sect_offset, ppaf->sect_len);
>>> +}
>>> +
>>>   static ssize_t nvm_dev_attr_show_12(struct device *dev,
>>>   		struct device_attribute *dattr, char *page)
>>>   {
>>>   	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>>>   	struct nvm_dev *ndev = ns->ndev;
>>> -	struct nvm_id *id;
>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>   	struct attribute *attr;
>>>     	if (!ndev)
>>>   		return 0;
>>>   -	id = &ndev->identity;
>>>   	attr = &dattr->attr;
>>>     	if (strcmp(attr->name, "vendor_opcode") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->vmnt);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.vmnt);
>>>   	} else if (strcmp(attr->name, "device_mode") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->dom);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.dom);
>>>   	/* kept for compatibility */
>>>   	} else if (strcmp(attr->name, "media_manager") == 0) {
>>>   		return scnprintf(page, PAGE_SIZE, "%s\n", "gennvm");
>>>   	} else if (strcmp(attr->name, "ppa_format") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE,
>>> -			"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
>>> -			id->ppaf.ch_offset, id->ppaf.ch_len,
>>> -			id->ppaf.lun_offset, id->ppaf.lun_len,
>>> -			id->ppaf.pln_offset, id->ppaf.pln_len,
>>> -			id->ppaf.blk_offset, id->ppaf.blk_len,
>>> -			id->ppaf.pg_offset, id->ppaf.pg_len,
>>> -			id->ppaf.sect_offset, id->ppaf.sect_len);
>>> +		return nvm_dev_attr_show_ppaf((void *)&dev_geo->c.addrf, page);
>>>   	} else if (strcmp(attr->name, "media_type") == 0) {	/* u8 */
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->mtype);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mtype);
>>>   	} else if (strcmp(attr->name, "flash_media_type") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->fmtype);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fmtype);
>>>   	} else if (strcmp(attr->name, "num_channels") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
>>>   	} else if (strcmp(attr->name, "num_luns") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
>>>   	} else if (strcmp(attr->name, "num_planes") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pln);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pln);
>>>   	} else if (strcmp(attr->name, "num_blocks") == 0) {	/* u16 */
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
>>>   	} else if (strcmp(attr->name, "num_pages") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pg);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pg);
>>>   	} else if (strcmp(attr->name, "page_size") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->fpg_sz);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fpg_sz);
>>>   	} else if (strcmp(attr->name, "hw_sector_size") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->csecs);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.csecs);
>>>   	} else if (strcmp(attr->name, "oob_sector_size") == 0) {/* u32 */
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->sos);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.sos);
>>>   	} else if (strcmp(attr->name, "prog_typ") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
>>>   	} else if (strcmp(attr->name, "prog_max") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
>>>   	} else if (strcmp(attr->name, "erase_typ") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
>>>   	} else if (strcmp(attr->name, "erase_max") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>>   	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mpos);
>>> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
>>>   	} else if (strcmp(attr->name, "media_capabilities") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mccap);
>>> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
>>>   	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
>>>   		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>>>   	} else {
>>> -		return scnprintf(page,
>>> -				 PAGE_SIZE,
>>> -				 "Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
>>> -				 attr->name);
>>> +		return scnprintf(page, PAGE_SIZE,
>>> +			"Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
>>> +			attr->name);
>>>   	}
>>>   }
>>>   @@ -952,42 +1007,40 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>>>   {
>>>   	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>>>   	struct nvm_dev *ndev = ns->ndev;
>>> -	struct nvm_id *id;
>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>   	struct attribute *attr;
>>>     	if (!ndev)
>>>   		return 0;
>>>   -	id = &ndev->identity;
>>>   	attr = &dattr->attr;
>>>     	if (strcmp(attr->name, "groups") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
>>>   	} else if (strcmp(attr->name, "punits") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
>>>   	} else if (strcmp(attr->name, "chunks") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
>>>   	} else if (strcmp(attr->name, "clba") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->clba);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.clba);
>>>   	} else if (strcmp(attr->name, "ws_min") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_min);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_min);
>>>   	} else if (strcmp(attr->name, "ws_opt") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_opt);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_opt);
>>>   	} else if (strcmp(attr->name, "mw_cunits") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->mw_cunits);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mw_cunits);
>>>   	} else if (strcmp(attr->name, "write_typ") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
>>>   	} else if (strcmp(attr->name, "write_max") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
>>>   	} else if (strcmp(attr->name, "reset_typ") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
>>>   	} else if (strcmp(attr->name, "reset_max") == 0) {
>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>>   	} else {
>>> -		return scnprintf(page,
>>> -				 PAGE_SIZE,
>>> -				 "Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
>>> -				 attr->name);
>>> +		return scnprintf(page, PAGE_SIZE,
>>> +			"Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
>>> +			attr->name);
>>>   	}
>>>   }
>>>   @@ -1106,10 +1159,13 @@ static const struct attribute_group nvm_dev_attr_group_20 = {
>>>     int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>>>   {
>>> -	if (!ns->ndev)
>>> +	struct nvm_dev *ndev = ns->ndev;
>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>> +
>>> +	if (!ndev)
>>>   		return -EINVAL;
>>>   -	switch (ns->ndev->identity.ver_id) {
>>> +	switch (dev_geo->ver_id) {
>>>   	case 1:
>>>   		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
>>>   					&nvm_dev_attr_group_12);
>>> @@ -1123,7 +1179,10 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>>>     void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
>>>   {
>>> -	switch (ns->ndev->identity.ver_id) {
>>> +	struct nvm_dev *ndev = ns->ndev;
>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>> +
>>> +	switch (dev_geo->ver_id) {
>>>   	case 1:
>>>   		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
>>>   					&nvm_dev_attr_group_12);
>>> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
>>> index e55b10573c99..18e3751b1632 100644
>>> --- a/include/linux/lightnvm.h
>>> +++ b/include/linux/lightnvm.h
>>> @@ -50,7 +50,7 @@ struct nvm_id;
>>>   struct nvm_dev;
>>>   struct nvm_tgt_dev;
>>>   -typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *);
>>> +typedef int (nvm_id_fn)(struct nvm_dev *);
>>>   typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, u8 *);
>>>   typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct ppa_addr *, int, int);
>>>   typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
>>> @@ -152,62 +152,107 @@ struct nvm_id_lp_tbl {
>>>   	struct nvm_id_lp_mlc mlc;
>>>   };
>>>   -struct nvm_addr_format {
>>> -	u8	ch_offset;
>>> +struct nvm_addr_format_12 {
>>>   	u8	ch_len;
>>> -	u8	lun_offset;
>>>   	u8	lun_len;
>>> -	u8	pln_offset;
>>> +	u8	blk_len;
>>> +	u8	pg_len;
>>>   	u8	pln_len;
>>> +	u8	sect_len;
>>> +
>>> +	u8	ch_offset;
>>> +	u8	lun_offset;
>>>   	u8	blk_offset;
>>> -	u8	blk_len;
>>>   	u8	pg_offset;
>>> -	u8	pg_len;
>>> +	u8	pln_offset;
>>>   	u8	sect_offset;
>>> -	u8	sect_len;
>>> +
>>> +	u64	ch_mask;
>>> +	u64	lun_mask;
>>> +	u64	blk_mask;
>>> +	u64	pg_mask;
>>> +	u64	pln_mask;
>>> +	u64	sec_mask;
>>> +};
>>> +
>>> +struct nvm_addr_format {
>>> +	u8	ch_len;
>>> +	u8	lun_len;
>>> +	u8	chk_len;
>>> +	u8	sec_len;
>>> +	u8	rsv_len[2];
>>> +
>>> +	u8	ch_offset;
>>> +	u8	lun_offset;
>>> +	u8	chk_offset;
>>> +	u8	sec_offset;
>>> +	u8	rsv_off[2];
>>> +
>>> +	u64	ch_mask;
>>> +	u64	lun_mask;
>>> +	u64	chk_mask;
>>> +	u64	sec_mask;
>>> +	u64	rsv_mask[2];
>>>   };
>>>   -struct nvm_id {
>>> -	u8	ver_id;
>>> +/* Device common geometry */
>>> +struct nvm_common_geo {
>>> +	/* chunk geometry */
>>> +	u32	num_chk;	/* chunks per lun */
>>> +	u32	clba;		/* sectors per chunk */
>>> +	u16	csecs;		/* sector size */
>>> +	u16	sos;		/* out-of-band area size */
>>> +
>>> +	/* device write constrains */
>>> +	u32	ws_min;		/* minimum write size */
>>> +	u32	ws_opt;		/* optimal write size */
>>> +	u32	mw_cunits;	/* distance required for successful read */
>>> +
>>> +	/* device capabilities */
>>> +	u32	mccap;
>>> +
>>> +	/* device timings */
>>> +	u32	trdt;		/* Avg. Tread (ns) */
>>> +	u32	trdm;		/* Max Tread (ns) */
>>> +	u32	tprt;		/* Avg. Tprog (ns) */
>>> +	u32	tprm;		/* Max Tprog (ns) */
>>> +	u32	tbet;		/* Avg. Terase (ns) */
>>> +	u32	tbem;		/* Max Terase (ns) */
>>> +
>>> +	/* generic address format */
>>> +	struct nvm_addr_format addrf;
>>> +
>>> +	/* 1.2 compatibility */
>>>   	u8	vmnt;
>>>   	u32	cap;
>>>   	u32	dom;
>>>   -	struct	nvm_addr_format ppaf;
>>> -
>>> -	u8	num_ch;
>>> -	u8	num_lun;
>>> -	u16	num_chk;
>>> -	u16	clba;
>>> -	u16	csecs;
>>> -	u16	sos;
>>> -
>>> -	u32	ws_min;
>>> -	u32	ws_opt;
>>> -	u32	mw_cunits;
>>> -
>>> -	u32	trdt;
>>> -	u32	trdm;
>>> -	u32	tprt;
>>> -	u32	tprm;
>>> -	u32	tbet;
>>> -	u32	tbem;
>>> -	u32	mpos;
>>> -	u32	mccap;
>>> -	u16	cpar;
>>> -
>>> -	/* calculated values */
>>> -	u16	ws_seq;
>>> -	u16	ws_per_chk;
>>> -
>>> -	/* 1.2 compatibility */
>>>   	u8	mtype;
>>>   	u8	fmtype;
>>>   +	u16	cpar;
>>> +	u32	mpos;
>>> +
>>>   	u8	num_pln;
>>> +	u8	pln_mode;
>>>   	u16	num_pg;
>>>   	u16	fpg_sz;
>>> -} __packed;
>>> +};
>>> +
>>> +/* Device identified geometry */
>>> +struct nvm_dev_geo {
>>> +	/* device reported version */
>>> +	u8	ver_id;
>>> +
>>> +	/* full device geometry */
>>> +	u16	nr_chnls;
>>> +	u16	nr_luns;
>>> +
>>> +	/* calculated values */
>>> +	u16	all_luns;
>>> +
>>> +	struct nvm_common_geo c;
>>> +};
>>>     struct nvm_target {
>>>   	struct list_head list;
>>> @@ -274,36 +319,22 @@ enum {
>>>   	NVM_BLK_ST_BAD =	0x8,	/* Bad block */
>>>   };
>>>   -
>>> -/* Device generic information */
>>> +/* Instance geometry */
>>>   struct nvm_geo {
>>> -	/* generic geometry */
>>> +	/* instance specific geometry */
>>>   	int nr_chnls;
>>> -	int all_luns; /* across channels */
>>> -	int nr_luns; /* per channel */
>>> -	int nr_chks; /* per lun */
>>> -
>>> -	int sec_size;
>>> -	int oob_size;
>>> -	int mccap;
>>> -
>>> -	int sec_per_chk;
>>> -	int sec_per_lun;
>>> -
>>> -	int ws_min;
>>> -	int ws_opt;
>>> -	int ws_seq;
>>> -	int ws_per_chk;
>>> +	int nr_luns;		/* per channel */
>>>     	int op;
>>>   -	struct nvm_addr_format ppaf;
>>> +	/* common geometry */
>>> +	struct nvm_common_geo c;
>>>   -	/* Legacy 1.2 specific geometry */
>>> -	int plane_mode; /* drive device in single, double or quad mode */
>>> -	int nr_planes;
>>> -	int sec_per_pg; /* only sectors for a single page */
>>> -	int sec_per_pl; /* all sectors across planes */
>>> +	/* calculated values */
>>> +	int all_luns;		/* across channels */
>>> +	int all_chunks;		/* across channels */
>>> +
>>> +	sector_t total_secs;	/* across channels */
>>>   };
>>>     /* sub-device structure */
>>> @@ -314,9 +345,6 @@ struct nvm_tgt_dev {
>>>   	/* Base ppas for target LUNs */
>>>   	struct ppa_addr *luns;
>>>   -	sector_t total_secs;
>>> -
>>> -	struct nvm_id identity;
>>>   	struct request_queue *q;
>>>     	struct nvm_dev *parent;
>>> @@ -329,15 +357,11 @@ struct nvm_dev {
>>>   	struct list_head devices;
>>>     	/* Device information */
>>> -	struct nvm_geo geo;
>>> -
>>> -	unsigned long total_secs;
>>> +	struct nvm_dev_geo dev_geo;
>>>     	unsigned long *lun_map;
>>>   	void *dma_pool;
>>>   -	struct nvm_id identity;
>>> -
>>>   	/* Backend device */
>>>   	struct request_queue *q;
>>>   	char name[DISK_NAME_LEN];
>>> @@ -357,14 +381,16 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
>>>   						  struct ppa_addr r)
>>>   {
>>>   	struct nvm_geo *geo = &tgt_dev->geo;
>>> +	struct nvm_addr_format_12 *ppaf =
>>> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>>>   	struct ppa_addr l;
>>>   -	l.ppa = ((u64)r.g.blk) << geo->ppaf.blk_offset;
>>> -	l.ppa |= ((u64)r.g.pg) << geo->ppaf.pg_offset;
>>> -	l.ppa |= ((u64)r.g.sec) << geo->ppaf.sect_offset;
>>> -	l.ppa |= ((u64)r.g.pl) << geo->ppaf.pln_offset;
>>> -	l.ppa |= ((u64)r.g.lun) << geo->ppaf.lun_offset;
>>> -	l.ppa |= ((u64)r.g.ch) << geo->ppaf.ch_offset;
>>> +	l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
>>> +	l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
>>> +	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
>>> +	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
>>> +	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
>>> +	l.ppa |= ((u64)r.g.sec) << ppaf->sect_offset;
>>>     	return l;
>>>   }
>>> @@ -373,24 +399,18 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
>>>   						  struct ppa_addr r)
>>>   {
>>>   	struct nvm_geo *geo = &tgt_dev->geo;
>>> +	struct nvm_addr_format_12 *ppaf =
>>> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>>>   	struct ppa_addr l;
>>>     	l.ppa = 0;
>>> -	/*
>>> -	 * (r.ppa << X offset) & X len bitmask. X eq. blk, pg, etc.
>>> -	 */
>>> -	l.g.blk = (r.ppa >> geo->ppaf.blk_offset) &
>>> -					(((1 << geo->ppaf.blk_len) - 1));
>>> -	l.g.pg |= (r.ppa >> geo->ppaf.pg_offset) &
>>> -					(((1 << geo->ppaf.pg_len) - 1));
>>> -	l.g.sec |= (r.ppa >> geo->ppaf.sect_offset) &
>>> -					(((1 << geo->ppaf.sect_len) - 1));
>>> -	l.g.pl |= (r.ppa >> geo->ppaf.pln_offset) &
>>> -					(((1 << geo->ppaf.pln_len) - 1));
>>> -	l.g.lun |= (r.ppa >> geo->ppaf.lun_offset) &
>>> -					(((1 << geo->ppaf.lun_len) - 1));
>>> -	l.g.ch |= (r.ppa >> geo->ppaf.ch_offset) &
>>> -					(((1 << geo->ppaf.ch_len) - 1));
>>> +
>>> +	l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
>>> +	l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
>>> +	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
>>> +	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
>>> +	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
>>> +	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sect_offset;
>>>     	return l;
>>>   }
>>
>> Thanks for the patch. I appreciate the work, but it is not the way I
>> want the 2.0 representation to go. The 2.0 variables should stay in
>> the nvm_geo data structure, and then if any 1.2 variables are on the
>> side, they can be in a substructure.
> 
> I don't understand. Everything is in nvm_geo, with the only different
> that there is nvm_common_geo, which contains the shared geometry between
> all instances. As mentioned before, if only having nvm_geo, then we are
> truncating the structure for each instance with different channel/lun
> values, which is very from a target perspective (the target can access
> the underlying device's values, which is _very_ error prone). This
> structure represents all 2.0 variables as they are.I can move all 1.2
> variables to a sub structure if that helps.

Let me try to see if I can clarify. From my understanding,the patch is 
doing three things,

1. Replace dev->identify and use a generic data structure
2. Introduced nvm_dev_geo to represent both intance and device channels 
and luns.
3. Move pblk addressing logic into core

Could these be split up? maybe 1 and 3 go together, and the address 
format go by itself. Maybe not. I'm fine if you say that they should 
stay together.

For 1 and 3, Instead of making the nvm_dev_geo the base structure, the 
code should continue to use nvm_geo (don't move the variables into 
nvm_geo_common and similar data struct. The nvm_dev->nvm_dev_geo is not 
pretty, the code already has a reference that the nvm_dev_geo is in the 
nvm_dev data structure.

When the code needs the instance specific channels and luns, put them in 
another data structure (than nvm_dev_geo), and maintain the relationship 
there.

> 
> If this is not it, can you explain in detail what the problem is? In
> pblk, I don't want to deal with a device-centric structure and variables
> spread out across what was identity and nvm_geo, I want a single
> structure that contains everything, which is the motivation for this
> patch.
> 

^ permalink raw reply	[flat|nested] 99+ messages in thread

* Re: [PATCH 01/20] lightnvm: simplify geometry structure.
  2018-02-22 12:22         ` Matias Bjørling
@ 2018-02-22 14:13           ` Javier Gonzalez
  -1 siblings, 0 replies; 99+ messages in thread
From: Javier Gonzalez @ 2018-02-22 14:13 UTC (permalink / raw)
  To: Matias Bjørling; +Cc: linux-block, linux-kernel, linux-nvme

[-- Attachment #1: Type: text/plain, Size: 75667 bytes --]

> On 22 Feb 2018, at 13.22, Matias Bjørling <mb@lightnvm.io> wrote:
> 
> On 02/22/2018 08:44 AM, Javier Gonzalez wrote:
>>> On 22 Feb 2018, at 08.25, Matias Bjørling <mb@lightnvm.io> wrote:
>>> 
>>> On 02/21/2018 10:26 AM, Javier González wrote:
>>>> Currently, the device geometry is stored redundantly in the nvm_id and
>>>> nvm_geo structures at a device level. Moreover, when instantiating
>>>> targets on a specific number of LUNs, these structures are replicated
>>>> and manually modified to fit the instance channel and LUN partitioning.
>>>> Instead, create a generic geometry around two base structures:
>>>> nvm_dev_geo, which describes the geometry of the whole device and
>>>> nvm_geo, which describes the geometry of the instance. Since these share
>>>> a big part of the geometry, create a nvm_common_geo structure that keeps
>>>> the static geoometry values that are shared across instances.
>>>> As we introduce support for 2.0, these structures allow to abstract
>>>> spec. specific values and present a common geometry to targets.
>>>> Signed-off-by: Javier González <javier@cnexlabs.com>
>>>> ---
>>>>  drivers/lightnvm/core.c          | 137 +++++++---------
>>>>  drivers/lightnvm/pblk-core.c     |  16 +-
>>>>  drivers/lightnvm/pblk-gc.c       |   2 +-
>>>>  drivers/lightnvm/pblk-init.c     | 123 +++++++-------
>>>>  drivers/lightnvm/pblk-read.c     |   2 +-
>>>>  drivers/lightnvm/pblk-recovery.c |  14 +-
>>>>  drivers/lightnvm/pblk-rl.c       |   2 +-
>>>>  drivers/lightnvm/pblk-sysfs.c    |  39 +++--
>>>>  drivers/lightnvm/pblk-write.c    |   2 +-
>>>>  drivers/lightnvm/pblk.h          |  93 +++++------
>>>>  drivers/nvme/host/lightnvm.c     | 339 +++++++++++++++++++++++----------------
>>>>  include/linux/lightnvm.h         | 204 ++++++++++++-----------
>>>>  12 files changed, 514 insertions(+), 459 deletions(-)
>>>> diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
>>>> index 689c97b97775..42596afdf64c 100644
>>>> --- a/drivers/lightnvm/core.c
>>>> +++ b/drivers/lightnvm/core.c
>>>> @@ -111,6 +111,7 @@ static void nvm_release_luns_err(struct nvm_dev *dev, int lun_begin,
>>>>  static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
>>>>  {
>>>>  	struct nvm_dev *dev = tgt_dev->parent;
>>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>>  	struct nvm_dev_map *dev_map = tgt_dev->map;
>>>>  	int i, j;
>>>>  @@ -122,7 +123,7 @@ static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
>>>>  		if (clear) {
>>>>  			for (j = 0; j < ch_map->nr_luns; j++) {
>>>>  				int lun = j + lun_offs[j];
>>>> -				int lunid = (ch * dev->geo.nr_luns) + lun;
>>>> +				int lunid = (ch * dev_geo->nr_luns) + lun;
>>>>    				WARN_ON(!test_and_clear_bit(lunid,
>>>>  							dev->lun_map));
>>>> @@ -143,19 +144,20 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>>>>  					      u16 lun_begin, u16 lun_end,
>>>>  					      u16 op)
>>>>  {
>>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>>  	struct nvm_tgt_dev *tgt_dev = NULL;
>>>>  	struct nvm_dev_map *dev_rmap = dev->rmap;
>>>>  	struct nvm_dev_map *dev_map;
>>>>  	struct ppa_addr *luns;
>>>>  	int nr_luns = lun_end - lun_begin + 1;
>>>>  	int luns_left = nr_luns;
>>>> -	int nr_chnls = nr_luns / dev->geo.nr_luns;
>>>> -	int nr_chnls_mod = nr_luns % dev->geo.nr_luns;
>>>> -	int bch = lun_begin / dev->geo.nr_luns;
>>>> -	int blun = lun_begin % dev->geo.nr_luns;
>>>> +	int nr_chnls = nr_luns / dev_geo->nr_luns;
>>>> +	int nr_chnls_mod = nr_luns % dev_geo->nr_luns;
>>>> +	int bch = lun_begin / dev_geo->nr_luns;
>>>> +	int blun = lun_begin % dev_geo->nr_luns;
>>>>  	int lunid = 0;
>>>>  	int lun_balanced = 1;
>>>> -	int prev_nr_luns;
>>>> +	int sec_per_lun, prev_nr_luns;
>>>>  	int i, j;
>>>>    	nr_chnls = (nr_chnls_mod == 0) ? nr_chnls : nr_chnls + 1;
>>>> @@ -173,15 +175,15 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>>>>  	if (!luns)
>>>>  		goto err_luns;
>>>>  -	prev_nr_luns = (luns_left > dev->geo.nr_luns) ?
>>>> -					dev->geo.nr_luns : luns_left;
>>>> +	prev_nr_luns = (luns_left > dev_geo->nr_luns) ?
>>>> +					dev_geo->nr_luns : luns_left;
>>>>  	for (i = 0; i < nr_chnls; i++) {
>>>>  		struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[i + bch];
>>>>  		int *lun_roffs = ch_rmap->lun_offs;
>>>>  		struct nvm_ch_map *ch_map = &dev_map->chnls[i];
>>>>  		int *lun_offs;
>>>> -		int luns_in_chnl = (luns_left > dev->geo.nr_luns) ?
>>>> -					dev->geo.nr_luns : luns_left;
>>>> +		int luns_in_chnl = (luns_left > dev_geo->nr_luns) ?
>>>> +					dev_geo->nr_luns : luns_left;
>>>>    		if (lun_balanced && prev_nr_luns != luns_in_chnl)
>>>>  			lun_balanced = 0;
>>>> @@ -215,18 +217,22 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>>>>  	if (!tgt_dev)
>>>>  		goto err_ch;
>>>>  -	memcpy(&tgt_dev->geo, &dev->geo, sizeof(struct nvm_geo));
>>>>  	/* Target device only owns a portion of the physical device */
>>>>  	tgt_dev->geo.nr_chnls = nr_chnls;
>>>> -	tgt_dev->geo.all_luns = nr_luns;
>>>>  	tgt_dev->geo.nr_luns = (lun_balanced) ? prev_nr_luns : -1;
>>>> +	tgt_dev->geo.all_luns = nr_luns;
>>>> +	tgt_dev->geo.all_chunks = nr_luns * dev_geo->c.num_chk;
>>>> +
>>>>  	tgt_dev->geo.op = op;
>>>> -	tgt_dev->total_secs = nr_luns * tgt_dev->geo.sec_per_lun;
>>>> +
>>>> +	sec_per_lun = dev_geo->c.clba * dev_geo->c.num_chk;
>>>> +	tgt_dev->geo.total_secs = nr_luns * sec_per_lun;
>>>> +
>>>> +	tgt_dev->geo.c = dev_geo->c;
>>>> +
>>>>  	tgt_dev->q = dev->q;
>>>>  	tgt_dev->map = dev_map;
>>>>  	tgt_dev->luns = luns;
>>>> -	memcpy(&tgt_dev->identity, &dev->identity, sizeof(struct nvm_id));
>>>> -
>>>>  	tgt_dev->parent = dev;
>>>>    	return tgt_dev;
>>>> @@ -268,12 +274,12 @@ static struct nvm_tgt_type *nvm_find_target_type(const char *name)
>>>>  	return tt;
>>>>  }
>>>>  -static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
>>>> +static int nvm_config_check_luns(struct nvm_dev_geo *dev_geo, int lun_begin,
>>>>  				 int lun_end)
>>>>  {
>>>> -	if (lun_begin > lun_end || lun_end >= geo->all_luns) {
>>>> +	if (lun_begin > lun_end || lun_end >= dev_geo->all_luns) {
>>>>  		pr_err("nvm: lun out of bound (%u:%u > %u)\n",
>>>> -			lun_begin, lun_end, geo->all_luns - 1);
>>>> +			lun_begin, lun_end, dev_geo->all_luns - 1);
>>>>  		return -EINVAL;
>>>>  	}
>>>>  @@ -283,24 +289,24 @@ static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
>>>>  static int __nvm_config_simple(struct nvm_dev *dev,
>>>>  			       struct nvm_ioctl_create_simple *s)
>>>>  {
>>>> -	struct nvm_geo *geo = &dev->geo;
>>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>>    	if (s->lun_begin == -1 && s->lun_end == -1) {
>>>>  		s->lun_begin = 0;
>>>> -		s->lun_end = geo->all_luns - 1;
>>>> +		s->lun_end = dev_geo->all_luns - 1;
>>>>  	}
>>>>  -	return nvm_config_check_luns(geo, s->lun_begin, s->lun_end);
>>>> +	return nvm_config_check_luns(dev_geo, s->lun_begin, s->lun_end);
>>>>  }
>>>>    static int __nvm_config_extended(struct nvm_dev *dev,
>>>>  				 struct nvm_ioctl_create_extended *e)
>>>>  {
>>>> -	struct nvm_geo *geo = &dev->geo;
>>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>>    	if (e->lun_begin == 0xFFFF && e->lun_end == 0xFFFF) {
>>>>  		e->lun_begin = 0;
>>>> -		e->lun_end = dev->geo.all_luns - 1;
>>>> +		e->lun_end = dev_geo->all_luns - 1;
>>>>  	}
>>>>    	/* op not set falls into target's default */
>>>> @@ -313,7 +319,7 @@ static int __nvm_config_extended(struct nvm_dev *dev,
>>>>  		return -EINVAL;
>>>>  	}
>>>>  -	return nvm_config_check_luns(geo, e->lun_begin, e->lun_end);
>>>> +	return nvm_config_check_luns(dev_geo, e->lun_begin, e->lun_end);
>>>>  }
>>>>    static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
>>>> @@ -408,7 +414,7 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
>>>>  	tqueue->queuedata = targetdata;
>>>>    	blk_queue_max_hw_sectors(tqueue,
>>>> -			(dev->geo.sec_size >> 9) * NVM_MAX_VLBA);
>>>> +			(dev->dev_geo.c.csecs >> 9) * NVM_MAX_VLBA);
>>>>    	set_capacity(tdisk, tt->capacity(targetdata));
>>>>  	add_disk(tdisk);
>>>> @@ -497,6 +503,7 @@ static int nvm_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove)
>>>>    static int nvm_register_map(struct nvm_dev *dev)
>>>>  {
>>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>>  	struct nvm_dev_map *rmap;
>>>>  	int i, j;
>>>>  @@ -504,15 +511,15 @@ static int nvm_register_map(struct nvm_dev *dev)
>>>>  	if (!rmap)
>>>>  		goto err_rmap;
>>>>  -	rmap->chnls = kcalloc(dev->geo.nr_chnls, sizeof(struct nvm_ch_map),
>>>> +	rmap->chnls = kcalloc(dev_geo->nr_chnls, sizeof(struct nvm_ch_map),
>>>>  								GFP_KERNEL);
>>>>  	if (!rmap->chnls)
>>>>  		goto err_chnls;
>>>>  -	for (i = 0; i < dev->geo.nr_chnls; i++) {
>>>> +	for (i = 0; i < dev_geo->nr_chnls; i++) {
>>>>  		struct nvm_ch_map *ch_rmap;
>>>>  		int *lun_roffs;
>>>> -		int luns_in_chnl = dev->geo.nr_luns;
>>>> +		int luns_in_chnl = dev_geo->nr_luns;
>>>>    		ch_rmap = &rmap->chnls[i];
>>>>  @@ -543,10 +550,11 @@ static int nvm_register_map(struct nvm_dev *dev)
>>>>    static void nvm_unregister_map(struct nvm_dev *dev)
>>>>  {
>>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>>  	struct nvm_dev_map *rmap = dev->rmap;
>>>>  	int i;
>>>>  -	for (i = 0; i < dev->geo.nr_chnls; i++)
>>>> +	for (i = 0; i < dev_geo->nr_chnls; i++)
>>>>  		kfree(rmap->chnls[i].lun_offs);
>>>>    	kfree(rmap->chnls);
>>>> @@ -675,7 +683,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
>>>>  	int i, plane_cnt, pl_idx;
>>>>  	struct ppa_addr ppa;
>>>>  -	if (geo->plane_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
>>>> +	if (geo->c.pln_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
>>>>  		rqd->nr_ppas = nr_ppas;
>>>>  		rqd->ppa_addr = ppas[0];
>>>>  @@ -689,7 +697,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
>>>>  		return -ENOMEM;
>>>>  	}
>>>>  -	plane_cnt = geo->plane_mode;
>>>> +	plane_cnt = geo->c.pln_mode;
>>>>  	rqd->nr_ppas *= plane_cnt;
>>>>    	for (i = 0; i < nr_ppas; i++) {
>>>> @@ -804,18 +812,18 @@ EXPORT_SYMBOL(nvm_end_io);
>>>>   */
>>>>  int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
>>>>  {
>>>> -	struct nvm_geo *geo = &dev->geo;
>>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>>  	int blk, offset, pl, blktype;
>>>>  -	if (nr_blks != geo->nr_chks * geo->plane_mode)
>>>> +	if (nr_blks != dev_geo->c.num_chk * dev_geo->c.pln_mode)
>>>>  		return -EINVAL;
>>>>  -	for (blk = 0; blk < geo->nr_chks; blk++) {
>>>> -		offset = blk * geo->plane_mode;
>>>> +	for (blk = 0; blk < dev_geo->c.num_chk; blk++) {
>>>> +		offset = blk * dev_geo->c.pln_mode;
>>>>  		blktype = blks[offset];
>>>>    		/* Bad blocks on any planes take precedence over other types */
>>>> -		for (pl = 0; pl < geo->plane_mode; pl++) {
>>>> +		for (pl = 0; pl < dev_geo->c.pln_mode; pl++) {
>>>>  			if (blks[offset + pl] &
>>>>  					(NVM_BLK_T_BAD|NVM_BLK_T_GRWN_BAD)) {
>>>>  				blktype = blks[offset + pl];
>>>> @@ -826,7 +834,7 @@ int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
>>>>  		blks[blk] = blktype;
>>>>  	}
>>>>  -	return geo->nr_chks;
>>>> +	return dev_geo->c.num_chk;
>>>>  }
>>>>  EXPORT_SYMBOL(nvm_bb_tbl_fold);
>>>>  @@ -843,41 +851,10 @@ EXPORT_SYMBOL(nvm_get_tgt_bb_tbl);
>>>>    static int nvm_core_init(struct nvm_dev *dev)
>>>>  {
>>>> -	struct nvm_id *id = &dev->identity;
>>>> -	struct nvm_geo *geo = &dev->geo;
>>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>>  	int ret;
>>>>  -	memcpy(&geo->ppaf, &id->ppaf, sizeof(struct nvm_addr_format));
>>>> -
>>>> -	if (id->mtype != 0) {
>>>> -		pr_err("nvm: memory type not supported\n");
>>>> -		return -EINVAL;
>>>> -	}
>>>> -
>>>> -	/* Whole device values */
>>>> -	geo->nr_chnls = id->num_ch;
>>>> -	geo->nr_luns = id->num_lun;
>>>> -
>>>> -	/* Generic device geometry values */
>>>> -	geo->ws_min = id->ws_min;
>>>> -	geo->ws_opt = id->ws_opt;
>>>> -	geo->ws_seq = id->ws_seq;
>>>> -	geo->ws_per_chk = id->ws_per_chk;
>>>> -	geo->nr_chks = id->num_chk;
>>>> -	geo->mccap = id->mccap;
>>>> -
>>>> -	geo->sec_per_chk = id->clba;
>>>> -	geo->sec_per_lun = geo->sec_per_chk * geo->nr_chks;
>>>> -	geo->all_luns = geo->nr_luns * geo->nr_chnls;
>>>> -
>>>> -	/* 1.2 spec device geometry values */
>>>> -	geo->plane_mode = 1 << geo->ws_seq;
>>>> -	geo->nr_planes = geo->ws_opt / geo->ws_min;
>>>> -	geo->sec_per_pg = geo->ws_min;
>>>> -	geo->sec_per_pl = geo->sec_per_pg * geo->nr_planes;
>>>> -
>>>> -	dev->total_secs = geo->all_luns * geo->sec_per_lun;
>>>> -	dev->lun_map = kcalloc(BITS_TO_LONGS(geo->all_luns),
>>>> +	dev->lun_map = kcalloc(BITS_TO_LONGS(dev_geo->all_luns),
>>>>  					sizeof(unsigned long), GFP_KERNEL);
>>>>  	if (!dev->lun_map)
>>>>  		return -ENOMEM;
>>>> @@ -912,19 +889,17 @@ static void nvm_free(struct nvm_dev *dev)
>>>>    static int nvm_init(struct nvm_dev *dev)
>>>>  {
>>>> -	struct nvm_geo *geo = &dev->geo;
>>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>>  	int ret = -EINVAL;
>>>>  -	if (dev->ops->identity(dev, &dev->identity)) {
>>>> +	if (dev->ops->identity(dev)) {
>>>>  		pr_err("nvm: device could not be identified\n");
>>>>  		goto err;
>>>>  	}
>>>>  -	if (dev->identity.ver_id != 1 && dev->identity.ver_id != 2) {
>>>> -		pr_err("nvm: device ver_id %d not supported by kernel.\n",
>>>> -				dev->identity.ver_id);
>>>> -		goto err;
>>>> -	}
>>>> +	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
>>>> +				dev_geo->ver_id,
>>>> +				dev_geo->c.vmnt);
>>>>    	ret = nvm_core_init(dev);
>>>>  	if (ret) {
>>>> @@ -932,10 +907,10 @@ static int nvm_init(struct nvm_dev *dev)
>>>>  		goto err;
>>>>  	}
>>>>  -	pr_info("nvm: registered %s [%u/%u/%u/%u/%u/%u]\n",
>>>> -			dev->name, geo->sec_per_pg, geo->nr_planes,
>>>> -			geo->ws_per_chk, geo->nr_chks,
>>>> -			geo->all_luns, geo->nr_chnls);
>>>> +	pr_info("nvm: registered %s [%u/%u/%u/%u/%u]\n",
>>>> +			dev->name, dev_geo->c.ws_min, dev_geo->c.ws_opt,
>>>> +			dev_geo->c.num_chk, dev_geo->all_luns,
>>>> +			dev_geo->nr_chnls);
>>>>  	return 0;
>>>>  err:
>>>>  	pr_err("nvm: failed to initialize nvm\n");
>>>> diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
>>>> index 22e61cd4f801..519af8b9eab7 100644
>>>> --- a/drivers/lightnvm/pblk-core.c
>>>> +++ b/drivers/lightnvm/pblk-core.c
>>>> @@ -613,7 +613,7 @@ static int pblk_line_submit_emeta_io(struct pblk *pblk, struct pblk_line *line,
>>>>  	memset(&rqd, 0, sizeof(struct nvm_rq));
>>>>    	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>>> -	rq_len = rq_ppas * geo->sec_size;
>>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>>    	bio = pblk_bio_map_addr(pblk, emeta_buf, rq_ppas, rq_len,
>>>>  					l_mg->emeta_alloc_type, GFP_KERNEL);
>>>> @@ -722,7 +722,7 @@ u64 pblk_line_smeta_start(struct pblk *pblk, struct pblk_line *line)
>>>>  	if (bit >= lm->blk_per_line)
>>>>  		return -1;
>>>>  -	return bit * geo->sec_per_pl;
>>>> +	return bit * geo->c.ws_opt;
>>>>  }
>>>>    static int pblk_line_submit_smeta_io(struct pblk *pblk, struct pblk_line *line,
>>>> @@ -1035,19 +1035,19 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>>>>  	/* Capture bad block information on line mapping bitmaps */
>>>>  	while ((bit = find_next_bit(line->blk_bitmap, lm->blk_per_line,
>>>>  					bit + 1)) < lm->blk_per_line) {
>>>> -		off = bit * geo->sec_per_pl;
>>>> +		off = bit * geo->c.ws_opt;
>>>>  		bitmap_shift_left(l_mg->bb_aux, l_mg->bb_template, off,
>>>>  							lm->sec_per_line);
>>>>  		bitmap_or(line->map_bitmap, line->map_bitmap, l_mg->bb_aux,
>>>>  							lm->sec_per_line);
>>>> -		line->sec_in_line -= geo->sec_per_chk;
>>>> +		line->sec_in_line -= geo->c.clba;
>>>>  		if (bit >= lm->emeta_bb)
>>>>  			nr_bb++;
>>>>  	}
>>>>    	/* Mark smeta metadata sectors as bad sectors */
>>>>  	bit = find_first_zero_bit(line->blk_bitmap, lm->blk_per_line);
>>>> -	off = bit * geo->sec_per_pl;
>>>> +	off = bit * geo->c.ws_opt;
>>>>  	bitmap_set(line->map_bitmap, off, lm->smeta_sec);
>>>>  	line->sec_in_line -= lm->smeta_sec;
>>>>  	line->smeta_ssec = off;
>>>> @@ -1066,10 +1066,10 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>>>>  	emeta_secs = lm->emeta_sec[0];
>>>>  	off = lm->sec_per_line;
>>>>  	while (emeta_secs) {
>>>> -		off -= geo->sec_per_pl;
>>>> +		off -= geo->c.ws_opt;
>>>>  		if (!test_bit(off, line->invalid_bitmap)) {
>>>> -			bitmap_set(line->invalid_bitmap, off, geo->sec_per_pl);
>>>> -			emeta_secs -= geo->sec_per_pl;
>>>> +			bitmap_set(line->invalid_bitmap, off, geo->c.ws_opt);
>>>> +			emeta_secs -= geo->c.ws_opt;
>>>>  		}
>>>>  	}
>>>>  diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c
>>>> index 320f99af99e9..16afea3f5541 100644
>>>> --- a/drivers/lightnvm/pblk-gc.c
>>>> +++ b/drivers/lightnvm/pblk-gc.c
>>>> @@ -88,7 +88,7 @@ static void pblk_gc_line_ws(struct work_struct *work)
>>>>    	up(&gc->gc_sem);
>>>>  -	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->sec_size);
>>>> +	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->c.csecs);
>>>>  	if (!gc_rq->data) {
>>>>  		pr_err("pblk: could not GC line:%d (%d/%d)\n",
>>>>  					line->id, *line->vsc, gc_rq->nr_secs);
>>>> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
>>>> index 5261702e9ff7..95ecb0ec736b 100644
>>>> --- a/drivers/lightnvm/pblk-init.c
>>>> +++ b/drivers/lightnvm/pblk-init.c
>>>> @@ -146,7 +146,7 @@ static int pblk_rwb_init(struct pblk *pblk)
>>>>  		return -ENOMEM;
>>>>    	power_size = get_count_order(nr_entries);
>>>> -	power_seg_sz = get_count_order(geo->sec_size);
>>>> +	power_seg_sz = get_count_order(geo->c.csecs);
>>>>    	return pblk_rb_init(&pblk->rwb, entries, power_size, power_seg_sz);
>>>>  }
>>>> @@ -154,11 +154,11 @@ static int pblk_rwb_init(struct pblk *pblk)
>>>>  /* Minimum pages needed within a lun */
>>>>  #define ADDR_POOL_SIZE 64
>>>>  -static int pblk_set_ppaf(struct pblk *pblk)
>>>> +static int pblk_set_addrf_12(struct nvm_geo *geo,
>>>> +			     struct nvm_addr_format_12 *dst)
>>>>  {
>>>> -	struct nvm_tgt_dev *dev = pblk->dev;
>>>> -	struct nvm_geo *geo = &dev->geo;
>>>> -	struct nvm_addr_format ppaf = geo->ppaf;
>>>> +	struct nvm_addr_format_12 *src =
>>>> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>>>>  	int power_len;
>>>>    	/* Re-calculate channel and lun format to adapt to configuration */
>>>> @@ -167,34 +167,50 @@ static int pblk_set_ppaf(struct pblk *pblk)
>>>>  		pr_err("pblk: supports only power-of-two channel config.\n");
>>>>  		return -EINVAL;
>>>>  	}
>>>> -	ppaf.ch_len = power_len;
>>>> +	dst->ch_len = power_len;
>>>>    	power_len = get_count_order(geo->nr_luns);
>>>>  	if (1 << power_len != geo->nr_luns) {
>>>>  		pr_err("pblk: supports only power-of-two LUN config.\n");
>>>>  		return -EINVAL;
>>>>  	}
>>>> -	ppaf.lun_len = power_len;
>>>> +	dst->lun_len = power_len;
>>>>  -	pblk->ppaf.sec_offset = 0;
>>>> -	pblk->ppaf.pln_offset = ppaf.sect_len;
>>>> -	pblk->ppaf.ch_offset = pblk->ppaf.pln_offset + ppaf.pln_len;
>>>> -	pblk->ppaf.lun_offset = pblk->ppaf.ch_offset + ppaf.ch_len;
>>>> -	pblk->ppaf.pg_offset = pblk->ppaf.lun_offset + ppaf.lun_len;
>>>> -	pblk->ppaf.blk_offset = pblk->ppaf.pg_offset + ppaf.pg_len;
>>>> -	pblk->ppaf.sec_mask = (1ULL << ppaf.sect_len) - 1;
>>>> -	pblk->ppaf.pln_mask = ((1ULL << ppaf.pln_len) - 1) <<
>>>> -							pblk->ppaf.pln_offset;
>>>> -	pblk->ppaf.ch_mask = ((1ULL << ppaf.ch_len) - 1) <<
>>>> -							pblk->ppaf.ch_offset;
>>>> -	pblk->ppaf.lun_mask = ((1ULL << ppaf.lun_len) - 1) <<
>>>> -							pblk->ppaf.lun_offset;
>>>> -	pblk->ppaf.pg_mask = ((1ULL << ppaf.pg_len) - 1) <<
>>>> -							pblk->ppaf.pg_offset;
>>>> -	pblk->ppaf.blk_mask = ((1ULL << ppaf.blk_len) - 1) <<
>>>> -							pblk->ppaf.blk_offset;
>>>> +	dst->blk_len = src->blk_len;
>>>> +	dst->pg_len = src->pg_len;
>>>> +	dst->pln_len = src->pln_len;
>>>> +	dst->sect_len = src->sect_len;
>>>>  -	pblk->ppaf_bitsize = pblk->ppaf.blk_offset + ppaf.blk_len;
>>>> +	dst->sect_offset = 0;
>>>> +	dst->pln_offset = dst->sect_len;
>>>> +	dst->ch_offset = dst->pln_offset + dst->pln_len;
>>>> +	dst->lun_offset = dst->ch_offset + dst->ch_len;
>>>> +	dst->pg_offset = dst->lun_offset + dst->lun_len;
>>>> +	dst->blk_offset = dst->pg_offset + dst->pg_len;
>>>> +
>>>> +	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
>>>> +	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
>>>> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>>>> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>>>> +	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
>>>> +	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
>>>> +
>>>> +	return dst->blk_offset + src->blk_len;
>>>> +}
>>>> +
>>>> +static int pblk_set_ppaf(struct pblk *pblk)
>>>> +{
>>>> +	struct nvm_tgt_dev *dev = pblk->dev;
>>>> +	struct nvm_geo *geo = &dev->geo;
>>>> +	int mod;
>>>> +
>>>> +	div_u64_rem(geo->c.clba, pblk->min_write_pgs, &mod);
>>>> +	if (mod) {
>>>> +		pr_err("pblk: bad configuration of sectors/pages\n");
>>>> +		return -EINVAL;
>>>> +	}
>>>> +
>>>> +	pblk->ppaf_bitsize = pblk_set_addrf_12(geo, (void *)&pblk->ppaf);
>>>>    	return 0;
>>>>  }
>>>> @@ -253,8 +269,7 @@ static int pblk_core_init(struct pblk *pblk)
>>>>  	struct nvm_tgt_dev *dev = pblk->dev;
>>>>  	struct nvm_geo *geo = &dev->geo;
>>>>  -	pblk->pgs_in_buffer = NVM_MEM_PAGE_WRITE * geo->sec_per_pg *
>>>> -						geo->nr_planes * geo->all_luns;
>>>> +	pblk->pgs_in_buffer = geo->c.mw_cunits * geo->c.ws_opt * geo->all_luns;
>>>>    	if (pblk_init_global_caches(pblk))
>>>>  		return -ENOMEM;
>>>> @@ -433,7 +448,7 @@ static void *pblk_bb_get_log(struct pblk *pblk)
>>>>  	int i, nr_blks, blk_per_lun;
>>>>  	int ret;
>>>>  -	blk_per_lun = geo->nr_chks * geo->plane_mode;
>>>> +	blk_per_lun = geo->c.num_chk * geo->c.pln_mode;
>>>>  	nr_blks = blk_per_lun * geo->all_luns;
>>>>    	log = kmalloc(nr_blks, GFP_KERNEL);
>>>> @@ -551,18 +566,18 @@ static unsigned int calc_emeta_len(struct pblk *pblk)
>>>>  	/* Round to sector size so that lba_list starts on its own sector */
>>>>  	lm->emeta_sec[1] = DIV_ROUND_UP(
>>>>  			sizeof(struct line_emeta) + lm->blk_bitmap_len +
>>>> -			sizeof(struct wa_counters), geo->sec_size);
>>>> -	lm->emeta_len[1] = lm->emeta_sec[1] * geo->sec_size;
>>>> +			sizeof(struct wa_counters), geo->c.csecs);
>>>> +	lm->emeta_len[1] = lm->emeta_sec[1] * geo->c.csecs;
>>>>    	/* Round to sector size so that vsc_list starts on its own sector */
>>>>  	lm->dsec_per_line = lm->sec_per_line - lm->emeta_sec[0];
>>>>  	lm->emeta_sec[2] = DIV_ROUND_UP(lm->dsec_per_line * sizeof(u64),
>>>> -			geo->sec_size);
>>>> -	lm->emeta_len[2] = lm->emeta_sec[2] * geo->sec_size;
>>>> +			geo->c.csecs);
>>>> +	lm->emeta_len[2] = lm->emeta_sec[2] * geo->c.csecs;
>>>>    	lm->emeta_sec[3] = DIV_ROUND_UP(l_mg->nr_lines * sizeof(u32),
>>>> -			geo->sec_size);
>>>> -	lm->emeta_len[3] = lm->emeta_sec[3] * geo->sec_size;
>>>> +			geo->c.csecs);
>>>> +	lm->emeta_len[3] = lm->emeta_sec[3] * geo->c.csecs;
>>>>    	lm->vsc_list_len = l_mg->nr_lines * sizeof(u32);
>>>>  @@ -593,13 +608,13 @@ static void pblk_set_provision(struct pblk *pblk, long nr_free_blks)
>>>>  	 * on user capacity consider only provisioned blocks
>>>>  	 */
>>>>  	pblk->rl.total_blocks = nr_free_blks;
>>>> -	pblk->rl.nr_secs = nr_free_blks * geo->sec_per_chk;
>>>> +	pblk->rl.nr_secs = nr_free_blks * geo->c.clba;
>>>>    	/* Consider sectors used for metadata */
>>>>  	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
>>>> -	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
>>>> +	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
>>>>  -	pblk->capacity = (provisioned - blk_meta) * geo->sec_per_chk;
>>>> +	pblk->capacity = (provisioned - blk_meta) * geo->c.clba;
>>>>    	atomic_set(&pblk->rl.free_blocks, nr_free_blks);
>>>>  	atomic_set(&pblk->rl.free_user_blocks, nr_free_blks);
>>>> @@ -710,10 +725,10 @@ static int pblk_lines_init(struct pblk *pblk)
>>>>  	void *chunk_log;
>>>>  	unsigned int smeta_len, emeta_len;
>>>>  	long nr_bad_blks = 0, nr_free_blks = 0;
>>>> -	int bb_distance, max_write_ppas, mod;
>>>> +	int bb_distance, max_write_ppas;
>>>>  	int i, ret;
>>>>  -	pblk->min_write_pgs = geo->sec_per_pl * (geo->sec_size / PAGE_SIZE);
>>>> +	pblk->min_write_pgs = geo->c.ws_opt * (geo->c.csecs / PAGE_SIZE);
>>>>  	max_write_ppas = pblk->min_write_pgs * geo->all_luns;
>>>>  	pblk->max_write_pgs = min_t(int, max_write_ppas, NVM_MAX_VLBA);
>>>>  	pblk_set_sec_per_write(pblk, pblk->min_write_pgs);
>>>> @@ -724,19 +739,13 @@ static int pblk_lines_init(struct pblk *pblk)
>>>>  		return -EINVAL;
>>>>  	}
>>>>  -	div_u64_rem(geo->sec_per_chk, pblk->min_write_pgs, &mod);
>>>> -	if (mod) {
>>>> -		pr_err("pblk: bad configuration of sectors/pages\n");
>>>> -		return -EINVAL;
>>>> -	}
>>>> -
>>>> -	l_mg->nr_lines = geo->nr_chks;
>>>> +	l_mg->nr_lines = geo->c.num_chk;
>>>>  	l_mg->log_line = l_mg->data_line = NULL;
>>>>  	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
>>>>  	l_mg->nr_free_lines = 0;
>>>>  	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
>>>>  -	lm->sec_per_line = geo->sec_per_chk * geo->all_luns;
>>>> +	lm->sec_per_line = geo->c.clba * geo->all_luns;
>>>>  	lm->blk_per_line = geo->all_luns;
>>>>  	lm->blk_bitmap_len = BITS_TO_LONGS(geo->all_luns) * sizeof(long);
>>>>  	lm->sec_bitmap_len = BITS_TO_LONGS(lm->sec_per_line) * sizeof(long);
>>>> @@ -750,8 +759,8 @@ static int pblk_lines_init(struct pblk *pblk)
>>>>  	 */
>>>>  	i = 1;
>>>>  add_smeta_page:
>>>> -	lm->smeta_sec = i * geo->sec_per_pl;
>>>> -	lm->smeta_len = lm->smeta_sec * geo->sec_size;
>>>> +	lm->smeta_sec = i * geo->c.ws_opt;
>>>> +	lm->smeta_len = lm->smeta_sec * geo->c.csecs;
>>>>    	smeta_len = sizeof(struct line_smeta) + lm->lun_bitmap_len;
>>>>  	if (smeta_len > lm->smeta_len) {
>>>> @@ -764,8 +773,8 @@ static int pblk_lines_init(struct pblk *pblk)
>>>>  	 */
>>>>  	i = 1;
>>>>  add_emeta_page:
>>>> -	lm->emeta_sec[0] = i * geo->sec_per_pl;
>>>> -	lm->emeta_len[0] = lm->emeta_sec[0] * geo->sec_size;
>>>> +	lm->emeta_sec[0] = i * geo->c.ws_opt;
>>>> +	lm->emeta_len[0] = lm->emeta_sec[0] * geo->c.csecs;
>>>>    	emeta_len = calc_emeta_len(pblk);
>>>>  	if (emeta_len > lm->emeta_len[0]) {
>>>> @@ -778,7 +787,7 @@ static int pblk_lines_init(struct pblk *pblk)
>>>>  	lm->min_blk_line = 1;
>>>>  	if (geo->all_luns > 1)
>>>>  		lm->min_blk_line += DIV_ROUND_UP(lm->smeta_sec +
>>>> -					lm->emeta_sec[0], geo->sec_per_chk);
>>>> +					lm->emeta_sec[0], geo->c.clba);
>>>>    	if (lm->min_blk_line > lm->blk_per_line) {
>>>>  		pr_err("pblk: config. not supported. Min. LUN in line:%d\n",
>>>> @@ -802,9 +811,9 @@ static int pblk_lines_init(struct pblk *pblk)
>>>>  		goto fail_free_bb_template;
>>>>  	}
>>>>  -	bb_distance = (geo->all_luns) * geo->sec_per_pl;
>>>> +	bb_distance = (geo->all_luns) * geo->c.ws_opt;
>>>>  	for (i = 0; i < lm->sec_per_line; i += bb_distance)
>>>> -		bitmap_set(l_mg->bb_template, i, geo->sec_per_pl);
>>>> +		bitmap_set(l_mg->bb_template, i, geo->c.ws_opt);
>>>>    	INIT_LIST_HEAD(&l_mg->free_list);
>>>>  	INIT_LIST_HEAD(&l_mg->corrupt_list);
>>>> @@ -981,9 +990,9 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>>>>  	struct pblk *pblk;
>>>>  	int ret;
>>>>  -	if (dev->identity.dom & NVM_RSP_L2P) {
>>>> +	if (dev->geo.c.dom & NVM_RSP_L2P) {
>>>>  		pr_err("pblk: host-side L2P table not supported. (%x)\n",
>>>> -							dev->identity.dom);
>>>> +							dev->geo.c.dom);
>>>>  		return ERR_PTR(-EINVAL);
>>>>  	}
>>>>  @@ -1091,7 +1100,7 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>>>>    	blk_queue_write_cache(tqueue, true, false);
>>>>  -	tqueue->limits.discard_granularity = geo->sec_per_chk * geo->sec_size;
>>>> +	tqueue->limits.discard_granularity = geo->c.clba * geo->c.csecs;
>>>>  	tqueue->limits.discard_alignment = 0;
>>>>  	blk_queue_max_discard_sectors(tqueue, UINT_MAX >> 9);
>>>>  	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, tqueue);
>>>> diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c
>>>> index 2f761283f43e..ebb6bae3a3b8 100644
>>>> --- a/drivers/lightnvm/pblk-read.c
>>>> +++ b/drivers/lightnvm/pblk-read.c
>>>> @@ -563,7 +563,7 @@ int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq)
>>>>  	if (!(gc_rq->secs_to_gc))
>>>>  		goto out;
>>>>  -	data_len = (gc_rq->secs_to_gc) * geo->sec_size;
>>>> +	data_len = (gc_rq->secs_to_gc) * geo->c.csecs;
>>>>  	bio = pblk_bio_map_addr(pblk, gc_rq->data, gc_rq->secs_to_gc, data_len,
>>>>  						PBLK_VMALLOC_META, GFP_KERNEL);
>>>>  	if (IS_ERR(bio)) {
>>>> diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
>>>> index aaab9a5c17cc..1574dbbfbb1c 100644
>>>> --- a/drivers/lightnvm/pblk-recovery.c
>>>> +++ b/drivers/lightnvm/pblk-recovery.c
>>>> @@ -184,7 +184,7 @@ static int pblk_calc_sec_in_line(struct pblk *pblk, struct pblk_line *line)
>>>>  	int nr_bb = bitmap_weight(line->blk_bitmap, lm->blk_per_line);
>>>>    	return lm->sec_per_line - lm->smeta_sec - lm->emeta_sec[0] -
>>>> -				nr_bb * geo->sec_per_chk;
>>>> +				nr_bb * geo->c.clba;
>>>>  }
>>>>    struct pblk_recov_alloc {
>>>> @@ -232,7 +232,7 @@ static int pblk_recov_read_oob(struct pblk *pblk, struct pblk_line *line,
>>>>  	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>>>  	if (!rq_ppas)
>>>>  		rq_ppas = pblk->min_write_pgs;
>>>> -	rq_len = rq_ppas * geo->sec_size;
>>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>>    	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>>>>  	if (IS_ERR(bio))
>>>> @@ -351,7 +351,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
>>>>  	if (!pad_rq)
>>>>  		return -ENOMEM;
>>>>  -	data = vzalloc(pblk->max_write_pgs * geo->sec_size);
>>>> +	data = vzalloc(pblk->max_write_pgs * geo->c.csecs);
>>>>  	if (!data) {
>>>>  		ret = -ENOMEM;
>>>>  		goto free_rq;
>>>> @@ -368,7 +368,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
>>>>  		goto fail_free_pad;
>>>>  	}
>>>>  -	rq_len = rq_ppas * geo->sec_size;
>>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>>    	meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, &dma_meta_list);
>>>>  	if (!meta_list) {
>>>> @@ -509,7 +509,7 @@ static int pblk_recov_scan_all_oob(struct pblk *pblk, struct pblk_line *line,
>>>>  	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>>>  	if (!rq_ppas)
>>>>  		rq_ppas = pblk->min_write_pgs;
>>>> -	rq_len = rq_ppas * geo->sec_size;
>>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>>    	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>>>>  	if (IS_ERR(bio))
>>>> @@ -640,7 +640,7 @@ static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line,
>>>>  	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>>>  	if (!rq_ppas)
>>>>  		rq_ppas = pblk->min_write_pgs;
>>>> -	rq_len = rq_ppas * geo->sec_size;
>>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>>    	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>>>>  	if (IS_ERR(bio))
>>>> @@ -745,7 +745,7 @@ static int pblk_recov_l2p_from_oob(struct pblk *pblk, struct pblk_line *line)
>>>>  	ppa_list = (void *)(meta_list) + pblk_dma_meta_size;
>>>>  	dma_ppa_list = dma_meta_list + pblk_dma_meta_size;
>>>>  -	data = kcalloc(pblk->max_write_pgs, geo->sec_size, GFP_KERNEL);
>>>> +	data = kcalloc(pblk->max_write_pgs, geo->c.csecs, GFP_KERNEL);
>>>>  	if (!data) {
>>>>  		ret = -ENOMEM;
>>>>  		goto free_meta_list;
>>>> diff --git a/drivers/lightnvm/pblk-rl.c b/drivers/lightnvm/pblk-rl.c
>>>> index 0d457b162f23..bcab203477ec 100644
>>>> --- a/drivers/lightnvm/pblk-rl.c
>>>> +++ b/drivers/lightnvm/pblk-rl.c
>>>> @@ -200,7 +200,7 @@ void pblk_rl_init(struct pblk_rl *rl, int budget)
>>>>    	/* Consider sectors used for metadata */
>>>>  	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
>>>> -	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
>>>> +	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
>>>>    	rl->high = pblk->op_blks - blk_meta - lm->blk_per_line;
>>>>  	rl->high_pw = get_count_order(rl->high);
>>>> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
>>>> index d93e9b1f083a..5eb21a279361 100644
>>>> --- a/drivers/lightnvm/pblk-sysfs.c
>>>> +++ b/drivers/lightnvm/pblk-sysfs.c
>>>> @@ -113,26 +113,31 @@ 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;
>>>>  -	sz = snprintf(page, PAGE_SIZE - sz,
>>>> -		"g:(b:%d)blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
>>>> -		pblk->ppaf_bitsize,
>>>> -		pblk->ppaf.blk_offset, geo->ppaf.blk_len,
>>>> -		pblk->ppaf.pg_offset, geo->ppaf.pg_len,
>>>> -		pblk->ppaf.lun_offset, geo->ppaf.lun_len,
>>>> -		pblk->ppaf.ch_offset, geo->ppaf.ch_len,
>>>> -		pblk->ppaf.pln_offset, geo->ppaf.pln_len,
>>>> -		pblk->ppaf.sec_offset, geo->ppaf.sect_len);
>>>> +	ppaf = (struct nvm_addr_format_12 *)&pblk->ppaf;
>>>> +	geo_ppaf = (struct nvm_addr_format_12 *)&geo->c.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",
>>>> +			pblk->ppaf_bitsize,
>>>> +			ppaf->ch_offset, ppaf->ch_len,
>>>> +			ppaf->lun_offset, ppaf->lun_len,
>>>> +			ppaf->blk_offset, ppaf->blk_len,
>>>> +			ppaf->pg_offset, ppaf->pg_len,
>>>> +			ppaf->pln_offset, ppaf->pln_len,
>>>> +			ppaf->sect_offset, ppaf->sect_len);
>>>>    	sz += snprintf(page + sz, PAGE_SIZE - sz,
>>>> -		"d:blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
>>>> -		geo->ppaf.blk_offset, geo->ppaf.blk_len,
>>>> -		geo->ppaf.pg_offset, geo->ppaf.pg_len,
>>>> -		geo->ppaf.lun_offset, geo->ppaf.lun_len,
>>>> -		geo->ppaf.ch_offset, geo->ppaf.ch_len,
>>>> -		geo->ppaf.pln_offset, geo->ppaf.pln_len,
>>>> -		geo->ppaf.sect_offset, geo->ppaf.sect_len);
>>>> +		"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->sect_offset, geo_ppaf->sect_len);
>>>>    	return sz;
>>>>  }
>>>> @@ -288,7 +293,7 @@ static ssize_t pblk_sysfs_lines_info(struct pblk *pblk, char *page)
>>>>  				"blk_line:%d, sec_line:%d, sec_blk:%d\n",
>>>>  					lm->blk_per_line,
>>>>  					lm->sec_per_line,
>>>> -					geo->sec_per_chk);
>>>> +					geo->c.clba);
>>>>    	return sz;
>>>>  }
>>>> diff --git a/drivers/lightnvm/pblk-write.c b/drivers/lightnvm/pblk-write.c
>>>> index aae86ed60b98..c49b27539d5a 100644
>>>> --- a/drivers/lightnvm/pblk-write.c
>>>> +++ b/drivers/lightnvm/pblk-write.c
>>>> @@ -333,7 +333,7 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line)
>>>>  	m_ctx = nvm_rq_to_pdu(rqd);
>>>>  	m_ctx->private = meta_line;
>>>>  -	rq_len = rq_ppas * geo->sec_size;
>>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>>  	data = ((void *)emeta->buf) + emeta->mem;
>>>>    	bio = pblk_bio_map_addr(pblk, data, rq_ppas, rq_len,
>>>> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
>>>> index 282dfc8780e8..67ffb53608f7 100644
>>>> --- a/drivers/lightnvm/pblk.h
>>>> +++ b/drivers/lightnvm/pblk.h
>>>> @@ -551,21 +551,6 @@ struct pblk_line_meta {
>>>>  	unsigned int meta_distance;	/* Distance between data and metadata */
>>>>  };
>>>>  -struct pblk_addr_format {
>>>> -	u64	ch_mask;
>>>> -	u64	lun_mask;
>>>> -	u64	pln_mask;
>>>> -	u64	blk_mask;
>>>> -	u64	pg_mask;
>>>> -	u64	sec_mask;
>>>> -	u8	ch_offset;
>>>> -	u8	lun_offset;
>>>> -	u8	pln_offset;
>>>> -	u8	blk_offset;
>>>> -	u8	pg_offset;
>>>> -	u8	sec_offset;
>>>> -};
>>>> -
>>>>  enum {
>>>>  	PBLK_STATE_RUNNING = 0,
>>>>  	PBLK_STATE_STOPPING = 1,
>>>> @@ -585,8 +570,8 @@ struct pblk {
>>>>  	struct pblk_line_mgmt l_mg;		/* Line management */
>>>>  	struct pblk_line_meta lm;		/* Line metadata */
>>>>  +	struct nvm_addr_format ppaf;
>>>>  	int ppaf_bitsize;
>>>> -	struct pblk_addr_format ppaf;
>>>>    	struct pblk_rb rwb;
>>>>  @@ -941,14 +926,12 @@ static inline int pblk_line_vsc(struct pblk_line *line)
>>>>  	return le32_to_cpu(*line->vsc);
>>>>  }
>>>>  -#define NVM_MEM_PAGE_WRITE (8)
>>>> -
>>>>  static inline int pblk_pad_distance(struct pblk *pblk)
>>>>  {
>>>>  	struct nvm_tgt_dev *dev = pblk->dev;
>>>>  	struct nvm_geo *geo = &dev->geo;
>>>>  -	return NVM_MEM_PAGE_WRITE * geo->all_luns * geo->sec_per_pl;
>>>> +	return geo->c.mw_cunits * geo->all_luns * geo->c.ws_opt;
>>>>  }
>>>>    static inline int pblk_ppa_to_line(struct ppa_addr p)
>>>> @@ -964,15 +947,17 @@ 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->ppaf;
>>>>  	struct ppa_addr ppa;
>>>>    	ppa.ppa = 0;
>>>>  	ppa.g.blk = line_id;
>>>> -	ppa.g.pg = (paddr & pblk->ppaf.pg_mask) >> pblk->ppaf.pg_offset;
>>>> -	ppa.g.lun = (paddr & pblk->ppaf.lun_mask) >> pblk->ppaf.lun_offset;
>>>> -	ppa.g.ch = (paddr & pblk->ppaf.ch_mask) >> pblk->ppaf.ch_offset;
>>>> -	ppa.g.pl = (paddr & pblk->ppaf.pln_mask) >> pblk->ppaf.pln_offset;
>>>> -	ppa.g.sec = (paddr & pblk->ppaf.sec_mask) >> pblk->ppaf.sec_offset;
>>>> +	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->sect_offset;
>>>>    	return ppa;
>>>>  }
>>>> @@ -980,13 +965,15 @@ 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->ppaf;
>>>>  	u64 paddr;
>>>>  -	paddr = (u64)p.g.pg << pblk->ppaf.pg_offset;
>>>> -	paddr |= (u64)p.g.lun << pblk->ppaf.lun_offset;
>>>> -	paddr |= (u64)p.g.ch << pblk->ppaf.ch_offset;
>>>> -	paddr |= (u64)p.g.pl << pblk->ppaf.pln_offset;
>>>> -	paddr |= (u64)p.g.sec << pblk->ppaf.sec_offset;
>>>> +	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->sect_offset;
>>>>    	return paddr;
>>>>  }
>>>> @@ -1003,18 +990,15 @@ 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 {
>>>> -		ppa64.g.blk = (ppa32 & pblk->ppaf.blk_mask) >>
>>>> -							pblk->ppaf.blk_offset;
>>>> -		ppa64.g.pg = (ppa32 & pblk->ppaf.pg_mask) >>
>>>> -							pblk->ppaf.pg_offset;
>>>> -		ppa64.g.lun = (ppa32 & pblk->ppaf.lun_mask) >>
>>>> -							pblk->ppaf.lun_offset;
>>>> -		ppa64.g.ch = (ppa32 & pblk->ppaf.ch_mask) >>
>>>> -							pblk->ppaf.ch_offset;
>>>> -		ppa64.g.pl = (ppa32 & pblk->ppaf.pln_mask) >>
>>>> -							pblk->ppaf.pln_offset;
>>>> -		ppa64.g.sec = (ppa32 & pblk->ppaf.sec_mask) >>
>>>> -							pblk->ppaf.sec_offset;
>>>> +		struct nvm_addr_format_12 *ppaf =
>>>> +				(struct nvm_addr_format_12 *)&pblk->ppaf;
>>>> +
>>>> +		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->sect_offset;
>>>>  	}
>>>>    	return ppa64;
>>>> @@ -1030,12 +1014,15 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
>>>>  		ppa32 |= ppa64.c.line;
>>>>  		ppa32 |= 1U << 31;
>>>>  	} else {
>>>> -		ppa32 |= ppa64.g.blk << pblk->ppaf.blk_offset;
>>>> -		ppa32 |= ppa64.g.pg << pblk->ppaf.pg_offset;
>>>> -		ppa32 |= ppa64.g.lun << pblk->ppaf.lun_offset;
>>>> -		ppa32 |= ppa64.g.ch << pblk->ppaf.ch_offset;
>>>> -		ppa32 |= ppa64.g.pl << pblk->ppaf.pln_offset;
>>>> -		ppa32 |= ppa64.g.sec << pblk->ppaf.sec_offset;
>>>> +		struct nvm_addr_format_12 *ppaf =
>>>> +				(struct nvm_addr_format_12 *)&pblk->ppaf;
>>>> +
>>>> +		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->sect_offset;
>>>>  	}
>>>>    	return ppa32;
>>>> @@ -1153,7 +1140,7 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type)
>>>>  	struct nvm_geo *geo = &dev->geo;
>>>>  	int flags;
>>>>  -	flags = geo->plane_mode >> 1;
>>>> +	flags = geo->c.pln_mode >> 1;
>>>>    	if (type == PBLK_WRITE)
>>>>  		flags |= NVM_IO_SCRAMBLE_ENABLE;
>>>> @@ -1174,7 +1161,7 @@ static inline int pblk_set_read_mode(struct pblk *pblk, int type)
>>>>    	flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
>>>>  	if (type == PBLK_READ_SEQUENTIAL)
>>>> -		flags |= geo->plane_mode >> 1;
>>>> +		flags |= geo->c.pln_mode >> 1;
>>>>    	return flags;
>>>>  }
>>>> @@ -1229,10 +1216,10 @@ static inline int pblk_boundary_ppa_checks(struct nvm_tgt_dev *tgt_dev,
>>>>  		if (!ppa->c.is_cached &&
>>>>  				ppa->g.ch < geo->nr_chnls &&
>>>>  				ppa->g.lun < geo->nr_luns &&
>>>> -				ppa->g.pl < geo->nr_planes &&
>>>> -				ppa->g.blk < geo->nr_chks &&
>>>> -				ppa->g.pg < geo->ws_per_chk &&
>>>> -				ppa->g.sec < geo->sec_per_pg)
>>>> +				ppa->g.pl < geo->c.num_pln &&
>>>> +				ppa->g.blk < geo->c.num_chk &&
>>>> +				ppa->g.pg < geo->c.num_pg &&
>>>> +				ppa->g.sec < geo->c.ws_min)
>>>>  			continue;
>>>>    		print_ppa(ppa, "boundary", i);
>>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>>> index 839c0b96466a..c81e64cc20d7 100644
>>>> --- a/drivers/nvme/host/lightnvm.c
>>>> +++ b/drivers/nvme/host/lightnvm.c
>>>> @@ -152,8 +152,8 @@ struct nvme_nvm_id12_addrf {
>>>>  	__u8			blk_len;
>>>>  	__u8			pg_offset;
>>>>  	__u8			pg_len;
>>>> -	__u8			sect_offset;
>>>> -	__u8			sect_len;
>>>> +	__u8			sec_offset;
>>>> +	__u8			sec_len;
>>>>  	__u8			res[4];
>>>>  } __packed;
>>>>  @@ -254,106 +254,157 @@ static inline void _nvme_nvm_check_size(void)
>>>>  	BUILD_BUG_ON(sizeof(struct nvme_nvm_id20) != NVME_IDENTIFY_DATA_SIZE);
>>>>  }
>>>>  -static int init_grp(struct nvm_id *nvm_id, struct nvme_nvm_id12 *id12)
>>>> +static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
>>>> +				 struct nvme_nvm_id12_addrf *src)
>>>> +{
>>>> +	dst->ch_len = src->ch_len;
>>>> +	dst->lun_len = src->lun_len;
>>>> +	dst->blk_len = src->blk_len;
>>>> +	dst->pg_len = src->pg_len;
>>>> +	dst->pln_len = src->pln_len;
>>>> +	dst->sect_len = src->sec_len;
>>>> +
>>>> +	dst->ch_offset = src->ch_offset;
>>>> +	dst->lun_offset = src->lun_offset;
>>>> +	dst->blk_offset = src->blk_offset;
>>>> +	dst->pg_offset = src->pg_offset;
>>>> +	dst->pln_offset = src->pln_offset;
>>>> +	dst->sect_offset = src->sec_offset;
>>>> +
>>>> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>>>> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>>>> +	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
>>>> +	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
>>>> +	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
>>>> +	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
>>>> +}
>>>> +
>>>> +static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>>>> +			     struct nvm_dev_geo *dev_geo)
>>>>  {
>>>>  	struct nvme_nvm_id12_grp *src;
>>>>  	int sec_per_pg, sec_per_pl, pg_per_blk;
>>>>  -	if (id12->cgrps != 1)
>>>> +	if (id->cgrps != 1)
>>>>  		return -EINVAL;
>>>>  -	src = &id12->grp;
>>>> +	src = &id->grp;
>>>>  -	nvm_id->mtype = src->mtype;
>>>> -	nvm_id->fmtype = src->fmtype;
>>>> +	if (src->mtype != 0) {
>>>> +		pr_err("nvm: memory type not supported\n");
>>>> +		return -EINVAL;
>>>> +	}
>>>> +
>>>> +	/* 1.2 spec. only reports a single version id - unfold */
>>>> +	dev_geo->ver_id = id->ver_id;
>>>>  -	nvm_id->num_ch = src->num_ch;
>>>> -	nvm_id->num_lun = src->num_lun;
>>>> +	dev_geo->nr_chnls = src->num_ch;
>>>> +	dev_geo->nr_luns = src->num_lun;
>>>> +	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
>>>>  -	nvm_id->num_chk = le16_to_cpu(src->num_chk);
>>>> -	nvm_id->csecs = le16_to_cpu(src->csecs);
>>>> -	nvm_id->sos = le16_to_cpu(src->sos);
>>>> +	dev_geo->c.num_chk = le16_to_cpu(src->num_chk);
>>>> +	dev_geo->c.csecs = le16_to_cpu(src->csecs);
>>>> +	dev_geo->c.sos = le16_to_cpu(src->sos);
>>>>    	pg_per_blk = le16_to_cpu(src->num_pg);
>>>> -	sec_per_pg = le16_to_cpu(src->fpg_sz) / nvm_id->csecs;
>>>> +	sec_per_pg = le16_to_cpu(src->fpg_sz) / dev_geo->c.csecs;
>>>>  	sec_per_pl = sec_per_pg * src->num_pln;
>>>> -	nvm_id->clba = sec_per_pl * pg_per_blk;
>>>> -	nvm_id->ws_per_chk = pg_per_blk;
>>>> -
>>>> -	nvm_id->mpos = le32_to_cpu(src->mpos);
>>>> -	nvm_id->cpar = le16_to_cpu(src->cpar);
>>>> -	nvm_id->mccap = le32_to_cpu(src->mccap);
>>>> -
>>>> -	nvm_id->ws_opt = nvm_id->ws_min = sec_per_pg;
>>>> -	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
>>>> -
>>>> -	if (nvm_id->mpos & 0x020202) {
>>>> -		nvm_id->ws_seq = NVM_IO_DUAL_ACCESS;
>>>> -		nvm_id->ws_opt <<= 1;
>>>> -	} else if (nvm_id->mpos & 0x040404) {
>>>> -		nvm_id->ws_seq = NVM_IO_QUAD_ACCESS;
>>>> -		nvm_id->ws_opt <<= 2;
>>>> +	dev_geo->c.clba = sec_per_pl * pg_per_blk;
>>>> +
>>>> +	dev_geo->c.ws_min = sec_per_pg;
>>>> +	dev_geo->c.ws_opt = sec_per_pg;
>>>> +	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
>>>> +
>>>> +	dev_geo->c.mccap = le32_to_cpu(src->mccap);
>>>> +
>>>> +	dev_geo->c.trdt = le32_to_cpu(src->trdt);
>>>> +	dev_geo->c.trdm = le32_to_cpu(src->trdm);
>>>> +	dev_geo->c.tprt = le32_to_cpu(src->tprt);
>>>> +	dev_geo->c.tprm = le32_to_cpu(src->tprm);
>>>> +	dev_geo->c.tbet = le32_to_cpu(src->tbet);
>>>> +	dev_geo->c.tbem = le32_to_cpu(src->tbem);
>>>> +
>>>> +	/* 1.2 compatibility */
>>>> +	dev_geo->c.vmnt = id->vmnt;
>>>> +	dev_geo->c.cap = le32_to_cpu(id->cap);
>>>> +	dev_geo->c.dom = le32_to_cpu(id->dom);
>>>> +
>>>> +	dev_geo->c.mtype = src->mtype;
>>>> +	dev_geo->c.fmtype = src->fmtype;
>>>> +
>>>> +	dev_geo->c.cpar = le16_to_cpu(src->cpar);
>>>> +	dev_geo->c.mpos = le32_to_cpu(src->mpos);
>>>> +
>>>> +	dev_geo->c.pln_mode = NVM_PLANE_SINGLE;
>>>> +
>>>> +	if (dev_geo->c.mpos & 0x020202) {
>>>> +		dev_geo->c.pln_mode = NVM_PLANE_DOUBLE;
>>>> +		dev_geo->c.ws_opt <<= 1;
>>>> +	} else if (dev_geo->c.mpos & 0x040404) {
>>>> +		dev_geo->c.pln_mode = NVM_PLANE_QUAD;
>>>> +		dev_geo->c.ws_opt <<= 2;
>>>>  	}
>>>>  -	nvm_id->trdt = le32_to_cpu(src->trdt);
>>>> -	nvm_id->trdm = le32_to_cpu(src->trdm);
>>>> -	nvm_id->tprt = le32_to_cpu(src->tprt);
>>>> -	nvm_id->tprm = le32_to_cpu(src->tprm);
>>>> -	nvm_id->tbet = le32_to_cpu(src->tbet);
>>>> -	nvm_id->tbem = le32_to_cpu(src->tbem);
>>>> -
>>>> -	/* 1.2 compatibility */
>>>> -	nvm_id->num_pln = src->num_pln;
>>>> -	nvm_id->num_pg = le16_to_cpu(src->num_pg);
>>>> -	nvm_id->fpg_sz = le16_to_cpu(src->fpg_sz);
>>>> +	dev_geo->c.num_pln = src->num_pln;
>>>> +	dev_geo->c.num_pg = le16_to_cpu(src->num_pg);
>>>> +	dev_geo->c.fpg_sz = le16_to_cpu(src->fpg_sz);
>>>> +
>>>> +	nvme_nvm_set_addr_12((struct nvm_addr_format_12 *)&dev_geo->c.addrf,
>>>> +								&id->ppaf);
>>>>    	return 0;
>>>>  }
>>>>  -static int nvme_nvm_setup_12(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
>>>> -		struct nvme_nvm_id12 *id)
>>>> +static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
>>>> +				 struct nvme_nvm_id20_addrf *src)
>>>>  {
>>>> -	nvm_id->ver_id = id->ver_id;
>>>> -	nvm_id->vmnt = id->vmnt;
>>>> -	nvm_id->cap = le32_to_cpu(id->cap);
>>>> -	nvm_id->dom = le32_to_cpu(id->dom);
>>>> -	memcpy(&nvm_id->ppaf, &id->ppaf,
>>>> -					sizeof(struct nvm_addr_format));
>>>> -
>>>> -	return init_grp(nvm_id, id);
>>>> +	dst->ch_len = src->grp_len;
>>>> +	dst->lun_len = src->pu_len;
>>>> +	dst->chk_len = src->chk_len;
>>>> +	dst->sec_len = src->lba_len;
>>>> +
>>>> +	dst->sec_offset = 0;
>>>> +	dst->chk_offset = dst->sec_len;
>>>> +	dst->lun_offset = dst->chk_offset + dst->chk_len;
>>>> +	dst->ch_offset = dst->lun_offset + dst->lun_len;
>>>> +
>>>> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>>>> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>>>> +	dst->chk_mask = ((1ULL << dst->chk_len) - 1) << dst->chk_offset;
>>>> +	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>>>>  }
>>>>  -static int nvme_nvm_setup_20(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
>>>> -		struct nvme_nvm_id20 *id)
>>>> +static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>>>> +			     struct nvm_dev_geo *dev_geo)
>>>>  {
>>>> -	nvm_id->ver_id = id->mjr;
>>>> +	dev_geo->ver_id = id->mjr;
>>>>  -	nvm_id->num_ch = le16_to_cpu(id->num_grp);
>>>> -	nvm_id->num_lun = le16_to_cpu(id->num_pu);
>>>> -	nvm_id->num_chk = le32_to_cpu(id->num_chk);
>>>> -	nvm_id->clba = le32_to_cpu(id->clba);
>>>> +	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
>>>> +	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
>>>> +	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
>>>>  -	nvm_id->ws_min = le32_to_cpu(id->ws_min);
>>>> -	nvm_id->ws_opt = le32_to_cpu(id->ws_opt);
>>>> -	nvm_id->mw_cunits = le32_to_cpu(id->mw_cunits);
>>>> +	dev_geo->c.num_chk = le32_to_cpu(id->num_chk);
>>>> +	dev_geo->c.clba = le32_to_cpu(id->clba);
>>>> +	dev_geo->c.csecs = -1;		/* Set by nvme identify */
>>>> +	dev_geo->c.sos = -1;		/* Set bu nvme identify */
>>>>  -	nvm_id->trdt = le32_to_cpu(id->trdt);
>>>> -	nvm_id->trdm = le32_to_cpu(id->trdm);
>>>> -	nvm_id->tprt = le32_to_cpu(id->twrt);
>>>> -	nvm_id->tprm = le32_to_cpu(id->twrm);
>>>> -	nvm_id->tbet = le32_to_cpu(id->tcrst);
>>>> -	nvm_id->tbem = le32_to_cpu(id->tcrsm);
>>>> +	dev_geo->c.ws_min = le32_to_cpu(id->ws_min);
>>>> +	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
>>>> +	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
>>>>  -	/* calculated values */
>>>> -	nvm_id->ws_per_chk = nvm_id->clba / nvm_id->ws_min;
>>>> +	dev_geo->c.trdt = le32_to_cpu(id->trdt);
>>>> +	dev_geo->c.trdm = le32_to_cpu(id->trdm);
>>>> +	dev_geo->c.tprt = le32_to_cpu(id->twrt);
>>>> +	dev_geo->c.tprm = le32_to_cpu(id->twrm);
>>>> +	dev_geo->c.tbet = le32_to_cpu(id->tcrst);
>>>> +	dev_geo->c.tbem = le32_to_cpu(id->tcrsm);
>>>>  -	/* 1.2 compatibility */
>>>> -	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
>>>> +	nvme_nvm_set_addr_20(&dev_geo->c.addrf, &id->lbaf);
>>>>    	return 0;
>>>>  }
>>>>  -static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
>>>> +static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>>>>  {
>>>>  	struct nvme_ns *ns = nvmdev->q->queuedata;
>>>>  	struct nvme_nvm_id12 *id;
>>>> @@ -380,18 +431,18 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
>>>>  	 */
>>>>  	switch (id->ver_id) {
>>>>  	case 1:
>>>> -		ret = nvme_nvm_setup_12(nvmdev, nvm_id, id);
>>>> +		ret = nvme_nvm_setup_12(id, &nvmdev->dev_geo);
>>>>  		break;
>>>>  	case 2:
>>>> -		ret = nvme_nvm_setup_20(nvmdev, nvm_id,
>>>> -				(struct nvme_nvm_id20 *)id);
>>>> +		ret = nvme_nvm_setup_20((struct nvme_nvm_id20 *)id,
>>>> +							&nvmdev->dev_geo);
>>>>  		break;
>>>>  	default:
>>>> -		dev_err(ns->ctrl->device,
>>>> -			"OCSSD revision not supported (%d)\n",
>>>> -			nvm_id->ver_id);
>>>> +		dev_err(ns->ctrl->device, "OCSSD revision not supported (%d)\n",
>>>> +							id->ver_id);
>>>>  		ret = -EINVAL;
>>>>  	}
>>>> +
>>>>  out:
>>>>  	kfree(id);
>>>>  	return ret;
>>>> @@ -401,12 +452,12 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
>>>>  								u8 *blks)
>>>>  {
>>>>  	struct request_queue *q = nvmdev->q;
>>>> -	struct nvm_geo *geo = &nvmdev->geo;
>>>> +	struct nvm_dev_geo *dev_geo = &nvmdev->dev_geo;
>>>>  	struct nvme_ns *ns = q->queuedata;
>>>>  	struct nvme_ctrl *ctrl = ns->ctrl;
>>>>  	struct nvme_nvm_command c = {};
>>>>  	struct nvme_nvm_bb_tbl *bb_tbl;
>>>> -	int nr_blks = geo->nr_chks * geo->plane_mode;
>>>> +	int nr_blks = dev_geo->c.num_chk * dev_geo->c.num_pln;
>>>>  	int tblsz = sizeof(struct nvme_nvm_bb_tbl) + nr_blks;
>>>>  	int ret = 0;
>>>>  @@ -447,7 +498,7 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
>>>>  		goto out;
>>>>  	}
>>>>  -	memcpy(blks, bb_tbl->blk, geo->nr_chks * geo->plane_mode);
>>>> +	memcpy(blks, bb_tbl->blk, dev_geo->c.num_chk * dev_geo->c.num_pln);
>>>>  out:
>>>>  	kfree(bb_tbl);
>>>>  	return ret;
>>>> @@ -815,9 +866,10 @@ int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd, unsigned long arg)
>>>>  void nvme_nvm_update_nvm_info(struct nvme_ns *ns)
>>>>  {
>>>>  	struct nvm_dev *ndev = ns->ndev;
>>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>>  -	ndev->identity.csecs = ndev->geo.sec_size = 1 << ns->lba_shift;
>>>> -	ndev->identity.sos = ndev->geo.oob_size = ns->ms;
>>>> +	dev_geo->c.csecs = 1 << ns->lba_shift;
>>>> +	dev_geo->c.sos = ns->ms;
>>>>  }
>>>>    int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node)
>>>> @@ -850,23 +902,22 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>>>  {
>>>>  	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>>>>  	struct nvm_dev *ndev = ns->ndev;
>>>> -	struct nvm_id *id;
>>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>>  	struct attribute *attr;
>>>>    	if (!ndev)
>>>>  		return 0;
>>>>  -	id = &ndev->identity;
>>>>  	attr = &dattr->attr;
>>>>    	if (strcmp(attr->name, "version") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ver_id);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>>>>  	} else if (strcmp(attr->name, "capabilities") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->cap);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
>>>>  	} else if (strcmp(attr->name, "read_typ") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdt);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>>>>  	} else if (strcmp(attr->name, "read_max") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdm);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdm);
>>>>  	} else {
>>>>  		return scnprintf(page,
>>>>  				 PAGE_SIZE,
>>>> @@ -875,75 +926,79 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>>>  	}
>>>>  }
>>>>  +static ssize_t nvm_dev_attr_show_ppaf(struct nvm_addr_format_12 *ppaf,
>>>> +					 char *page)
>>>> +{
>>>> +	return scnprintf(page, PAGE_SIZE,
>>>> +		"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
>>>> +				ppaf->ch_offset, ppaf->ch_len,
>>>> +				ppaf->lun_offset, ppaf->lun_len,
>>>> +				ppaf->pln_offset, ppaf->pln_len,
>>>> +				ppaf->blk_offset, ppaf->blk_len,
>>>> +				ppaf->pg_offset, ppaf->pg_len,
>>>> +				ppaf->sect_offset, ppaf->sect_len);
>>>> +}
>>>> +
>>>>  static ssize_t nvm_dev_attr_show_12(struct device *dev,
>>>>  		struct device_attribute *dattr, char *page)
>>>>  {
>>>>  	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>>>>  	struct nvm_dev *ndev = ns->ndev;
>>>> -	struct nvm_id *id;
>>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>>  	struct attribute *attr;
>>>>    	if (!ndev)
>>>>  		return 0;
>>>>  -	id = &ndev->identity;
>>>>  	attr = &dattr->attr;
>>>>    	if (strcmp(attr->name, "vendor_opcode") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->vmnt);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.vmnt);
>>>>  	} else if (strcmp(attr->name, "device_mode") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->dom);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.dom);
>>>>  	/* kept for compatibility */
>>>>  	} else if (strcmp(attr->name, "media_manager") == 0) {
>>>>  		return scnprintf(page, PAGE_SIZE, "%s\n", "gennvm");
>>>>  	} else if (strcmp(attr->name, "ppa_format") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE,
>>>> -			"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
>>>> -			id->ppaf.ch_offset, id->ppaf.ch_len,
>>>> -			id->ppaf.lun_offset, id->ppaf.lun_len,
>>>> -			id->ppaf.pln_offset, id->ppaf.pln_len,
>>>> -			id->ppaf.blk_offset, id->ppaf.blk_len,
>>>> -			id->ppaf.pg_offset, id->ppaf.pg_len,
>>>> -			id->ppaf.sect_offset, id->ppaf.sect_len);
>>>> +		return nvm_dev_attr_show_ppaf((void *)&dev_geo->c.addrf, page);
>>>>  	} else if (strcmp(attr->name, "media_type") == 0) {	/* u8 */
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->mtype);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mtype);
>>>>  	} else if (strcmp(attr->name, "flash_media_type") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->fmtype);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fmtype);
>>>>  	} else if (strcmp(attr->name, "num_channels") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
>>>>  	} else if (strcmp(attr->name, "num_luns") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
>>>>  	} else if (strcmp(attr->name, "num_planes") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pln);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pln);
>>>>  	} else if (strcmp(attr->name, "num_blocks") == 0) {	/* u16 */
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
>>>>  	} else if (strcmp(attr->name, "num_pages") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pg);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pg);
>>>>  	} else if (strcmp(attr->name, "page_size") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->fpg_sz);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fpg_sz);
>>>>  	} else if (strcmp(attr->name, "hw_sector_size") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->csecs);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.csecs);
>>>>  	} else if (strcmp(attr->name, "oob_sector_size") == 0) {/* u32 */
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->sos);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.sos);
>>>>  	} else if (strcmp(attr->name, "prog_typ") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
>>>>  	} else if (strcmp(attr->name, "prog_max") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
>>>>  	} else if (strcmp(attr->name, "erase_typ") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
>>>>  	} else if (strcmp(attr->name, "erase_max") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>>>  	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mpos);
>>>> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
>>>>  	} else if (strcmp(attr->name, "media_capabilities") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mccap);
>>>> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
>>>>  	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
>>>>  		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>>>>  	} else {
>>>> -		return scnprintf(page,
>>>> -				 PAGE_SIZE,
>>>> -				 "Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
>>>> -				 attr->name);
>>>> +		return scnprintf(page, PAGE_SIZE,
>>>> +			"Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
>>>> +			attr->name);
>>>>  	}
>>>>  }
>>>>  @@ -952,42 +1007,40 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>>>>  {
>>>>  	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>>>>  	struct nvm_dev *ndev = ns->ndev;
>>>> -	struct nvm_id *id;
>>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>>  	struct attribute *attr;
>>>>    	if (!ndev)
>>>>  		return 0;
>>>>  -	id = &ndev->identity;
>>>>  	attr = &dattr->attr;
>>>>    	if (strcmp(attr->name, "groups") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
>>>>  	} else if (strcmp(attr->name, "punits") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
>>>>  	} else if (strcmp(attr->name, "chunks") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
>>>>  	} else if (strcmp(attr->name, "clba") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->clba);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.clba);
>>>>  	} else if (strcmp(attr->name, "ws_min") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_min);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_min);
>>>>  	} else if (strcmp(attr->name, "ws_opt") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_opt);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_opt);
>>>>  	} else if (strcmp(attr->name, "mw_cunits") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->mw_cunits);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mw_cunits);
>>>>  	} else if (strcmp(attr->name, "write_typ") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
>>>>  	} else if (strcmp(attr->name, "write_max") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
>>>>  	} else if (strcmp(attr->name, "reset_typ") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
>>>>  	} else if (strcmp(attr->name, "reset_max") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>>>  	} else {
>>>> -		return scnprintf(page,
>>>> -				 PAGE_SIZE,
>>>> -				 "Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
>>>> -				 attr->name);
>>>> +		return scnprintf(page, PAGE_SIZE,
>>>> +			"Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
>>>> +			attr->name);
>>>>  	}
>>>>  }
>>>>  @@ -1106,10 +1159,13 @@ static const struct attribute_group nvm_dev_attr_group_20 = {
>>>>    int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>>>>  {
>>>> -	if (!ns->ndev)
>>>> +	struct nvm_dev *ndev = ns->ndev;
>>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>> +
>>>> +	if (!ndev)
>>>>  		return -EINVAL;
>>>>  -	switch (ns->ndev->identity.ver_id) {
>>>> +	switch (dev_geo->ver_id) {
>>>>  	case 1:
>>>>  		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
>>>>  					&nvm_dev_attr_group_12);
>>>> @@ -1123,7 +1179,10 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>>>>    void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
>>>>  {
>>>> -	switch (ns->ndev->identity.ver_id) {
>>>> +	struct nvm_dev *ndev = ns->ndev;
>>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>> +
>>>> +	switch (dev_geo->ver_id) {
>>>>  	case 1:
>>>>  		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
>>>>  					&nvm_dev_attr_group_12);
>>>> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
>>>> index e55b10573c99..18e3751b1632 100644
>>>> --- a/include/linux/lightnvm.h
>>>> +++ b/include/linux/lightnvm.h
>>>> @@ -50,7 +50,7 @@ struct nvm_id;
>>>>  struct nvm_dev;
>>>>  struct nvm_tgt_dev;
>>>>  -typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *);
>>>> +typedef int (nvm_id_fn)(struct nvm_dev *);
>>>>  typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, u8 *);
>>>>  typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct ppa_addr *, int, int);
>>>>  typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
>>>> @@ -152,62 +152,107 @@ struct nvm_id_lp_tbl {
>>>>  	struct nvm_id_lp_mlc mlc;
>>>>  };
>>>>  -struct nvm_addr_format {
>>>> -	u8	ch_offset;
>>>> +struct nvm_addr_format_12 {
>>>>  	u8	ch_len;
>>>> -	u8	lun_offset;
>>>>  	u8	lun_len;
>>>> -	u8	pln_offset;
>>>> +	u8	blk_len;
>>>> +	u8	pg_len;
>>>>  	u8	pln_len;
>>>> +	u8	sect_len;
>>>> +
>>>> +	u8	ch_offset;
>>>> +	u8	lun_offset;
>>>>  	u8	blk_offset;
>>>> -	u8	blk_len;
>>>>  	u8	pg_offset;
>>>> -	u8	pg_len;
>>>> +	u8	pln_offset;
>>>>  	u8	sect_offset;
>>>> -	u8	sect_len;
>>>> +
>>>> +	u64	ch_mask;
>>>> +	u64	lun_mask;
>>>> +	u64	blk_mask;
>>>> +	u64	pg_mask;
>>>> +	u64	pln_mask;
>>>> +	u64	sec_mask;
>>>> +};
>>>> +
>>>> +struct nvm_addr_format {
>>>> +	u8	ch_len;
>>>> +	u8	lun_len;
>>>> +	u8	chk_len;
>>>> +	u8	sec_len;
>>>> +	u8	rsv_len[2];
>>>> +
>>>> +	u8	ch_offset;
>>>> +	u8	lun_offset;
>>>> +	u8	chk_offset;
>>>> +	u8	sec_offset;
>>>> +	u8	rsv_off[2];
>>>> +
>>>> +	u64	ch_mask;
>>>> +	u64	lun_mask;
>>>> +	u64	chk_mask;
>>>> +	u64	sec_mask;
>>>> +	u64	rsv_mask[2];
>>>>  };
>>>>  -struct nvm_id {
>>>> -	u8	ver_id;
>>>> +/* Device common geometry */
>>>> +struct nvm_common_geo {
>>>> +	/* chunk geometry */
>>>> +	u32	num_chk;	/* chunks per lun */
>>>> +	u32	clba;		/* sectors per chunk */
>>>> +	u16	csecs;		/* sector size */
>>>> +	u16	sos;		/* out-of-band area size */
>>>> +
>>>> +	/* device write constrains */
>>>> +	u32	ws_min;		/* minimum write size */
>>>> +	u32	ws_opt;		/* optimal write size */
>>>> +	u32	mw_cunits;	/* distance required for successful read */
>>>> +
>>>> +	/* device capabilities */
>>>> +	u32	mccap;
>>>> +
>>>> +	/* device timings */
>>>> +	u32	trdt;		/* Avg. Tread (ns) */
>>>> +	u32	trdm;		/* Max Tread (ns) */
>>>> +	u32	tprt;		/* Avg. Tprog (ns) */
>>>> +	u32	tprm;		/* Max Tprog (ns) */
>>>> +	u32	tbet;		/* Avg. Terase (ns) */
>>>> +	u32	tbem;		/* Max Terase (ns) */
>>>> +
>>>> +	/* generic address format */
>>>> +	struct nvm_addr_format addrf;
>>>> +
>>>> +	/* 1.2 compatibility */
>>>>  	u8	vmnt;
>>>>  	u32	cap;
>>>>  	u32	dom;
>>>>  -	struct	nvm_addr_format ppaf;
>>>> -
>>>> -	u8	num_ch;
>>>> -	u8	num_lun;
>>>> -	u16	num_chk;
>>>> -	u16	clba;
>>>> -	u16	csecs;
>>>> -	u16	sos;
>>>> -
>>>> -	u32	ws_min;
>>>> -	u32	ws_opt;
>>>> -	u32	mw_cunits;
>>>> -
>>>> -	u32	trdt;
>>>> -	u32	trdm;
>>>> -	u32	tprt;
>>>> -	u32	tprm;
>>>> -	u32	tbet;
>>>> -	u32	tbem;
>>>> -	u32	mpos;
>>>> -	u32	mccap;
>>>> -	u16	cpar;
>>>> -
>>>> -	/* calculated values */
>>>> -	u16	ws_seq;
>>>> -	u16	ws_per_chk;
>>>> -
>>>> -	/* 1.2 compatibility */
>>>>  	u8	mtype;
>>>>  	u8	fmtype;
>>>>  +	u16	cpar;
>>>> +	u32	mpos;
>>>> +
>>>>  	u8	num_pln;
>>>> +	u8	pln_mode;
>>>>  	u16	num_pg;
>>>>  	u16	fpg_sz;
>>>> -} __packed;
>>>> +};
>>>> +
>>>> +/* Device identified geometry */
>>>> +struct nvm_dev_geo {
>>>> +	/* device reported version */
>>>> +	u8	ver_id;
>>>> +
>>>> +	/* full device geometry */
>>>> +	u16	nr_chnls;
>>>> +	u16	nr_luns;
>>>> +
>>>> +	/* calculated values */
>>>> +	u16	all_luns;
>>>> +
>>>> +	struct nvm_common_geo c;
>>>> +};
>>>>    struct nvm_target {
>>>>  	struct list_head list;
>>>> @@ -274,36 +319,22 @@ enum {
>>>>  	NVM_BLK_ST_BAD =	0x8,	/* Bad block */
>>>>  };
>>>>  -
>>>> -/* Device generic information */
>>>> +/* Instance geometry */
>>>>  struct nvm_geo {
>>>> -	/* generic geometry */
>>>> +	/* instance specific geometry */
>>>>  	int nr_chnls;
>>>> -	int all_luns; /* across channels */
>>>> -	int nr_luns; /* per channel */
>>>> -	int nr_chks; /* per lun */
>>>> -
>>>> -	int sec_size;
>>>> -	int oob_size;
>>>> -	int mccap;
>>>> -
>>>> -	int sec_per_chk;
>>>> -	int sec_per_lun;
>>>> -
>>>> -	int ws_min;
>>>> -	int ws_opt;
>>>> -	int ws_seq;
>>>> -	int ws_per_chk;
>>>> +	int nr_luns;		/* per channel */
>>>>    	int op;
>>>>  -	struct nvm_addr_format ppaf;
>>>> +	/* common geometry */
>>>> +	struct nvm_common_geo c;
>>>>  -	/* Legacy 1.2 specific geometry */
>>>> -	int plane_mode; /* drive device in single, double or quad mode */
>>>> -	int nr_planes;
>>>> -	int sec_per_pg; /* only sectors for a single page */
>>>> -	int sec_per_pl; /* all sectors across planes */
>>>> +	/* calculated values */
>>>> +	int all_luns;		/* across channels */
>>>> +	int all_chunks;		/* across channels */
>>>> +
>>>> +	sector_t total_secs;	/* across channels */
>>>>  };
>>>>    /* sub-device structure */
>>>> @@ -314,9 +345,6 @@ struct nvm_tgt_dev {
>>>>  	/* Base ppas for target LUNs */
>>>>  	struct ppa_addr *luns;
>>>>  -	sector_t total_secs;
>>>> -
>>>> -	struct nvm_id identity;
>>>>  	struct request_queue *q;
>>>>    	struct nvm_dev *parent;
>>>> @@ -329,15 +357,11 @@ struct nvm_dev {
>>>>  	struct list_head devices;
>>>>    	/* Device information */
>>>> -	struct nvm_geo geo;
>>>> -
>>>> -	unsigned long total_secs;
>>>> +	struct nvm_dev_geo dev_geo;
>>>>    	unsigned long *lun_map;
>>>>  	void *dma_pool;
>>>>  -	struct nvm_id identity;
>>>> -
>>>>  	/* Backend device */
>>>>  	struct request_queue *q;
>>>>  	char name[DISK_NAME_LEN];
>>>> @@ -357,14 +381,16 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
>>>>  						  struct ppa_addr r)
>>>>  {
>>>>  	struct nvm_geo *geo = &tgt_dev->geo;
>>>> +	struct nvm_addr_format_12 *ppaf =
>>>> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>>>>  	struct ppa_addr l;
>>>>  -	l.ppa = ((u64)r.g.blk) << geo->ppaf.blk_offset;
>>>> -	l.ppa |= ((u64)r.g.pg) << geo->ppaf.pg_offset;
>>>> -	l.ppa |= ((u64)r.g.sec) << geo->ppaf.sect_offset;
>>>> -	l.ppa |= ((u64)r.g.pl) << geo->ppaf.pln_offset;
>>>> -	l.ppa |= ((u64)r.g.lun) << geo->ppaf.lun_offset;
>>>> -	l.ppa |= ((u64)r.g.ch) << geo->ppaf.ch_offset;
>>>> +	l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
>>>> +	l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
>>>> +	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
>>>> +	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
>>>> +	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
>>>> +	l.ppa |= ((u64)r.g.sec) << ppaf->sect_offset;
>>>>    	return l;
>>>>  }
>>>> @@ -373,24 +399,18 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
>>>>  						  struct ppa_addr r)
>>>>  {
>>>>  	struct nvm_geo *geo = &tgt_dev->geo;
>>>> +	struct nvm_addr_format_12 *ppaf =
>>>> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>>>>  	struct ppa_addr l;
>>>>    	l.ppa = 0;
>>>> -	/*
>>>> -	 * (r.ppa << X offset) & X len bitmask. X eq. blk, pg, etc.
>>>> -	 */
>>>> -	l.g.blk = (r.ppa >> geo->ppaf.blk_offset) &
>>>> -					(((1 << geo->ppaf.blk_len) - 1));
>>>> -	l.g.pg |= (r.ppa >> geo->ppaf.pg_offset) &
>>>> -					(((1 << geo->ppaf.pg_len) - 1));
>>>> -	l.g.sec |= (r.ppa >> geo->ppaf.sect_offset) &
>>>> -					(((1 << geo->ppaf.sect_len) - 1));
>>>> -	l.g.pl |= (r.ppa >> geo->ppaf.pln_offset) &
>>>> -					(((1 << geo->ppaf.pln_len) - 1));
>>>> -	l.g.lun |= (r.ppa >> geo->ppaf.lun_offset) &
>>>> -					(((1 << geo->ppaf.lun_len) - 1));
>>>> -	l.g.ch |= (r.ppa >> geo->ppaf.ch_offset) &
>>>> -					(((1 << geo->ppaf.ch_len) - 1));
>>>> +
>>>> +	l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
>>>> +	l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
>>>> +	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
>>>> +	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
>>>> +	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
>>>> +	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sect_offset;
>>>>    	return l;
>>>>  }
>>> 
>>> Thanks for the patch. I appreciate the work, but it is not the way I
>>> want the 2.0 representation to go. The 2.0 variables should stay in
>>> the nvm_geo data structure, and then if any 1.2 variables are on the
>>> side, they can be in a substructure.
>> I don't understand. Everything is in nvm_geo, with the only different
>> that there is nvm_common_geo, which contains the shared geometry between
>> all instances. As mentioned before, if only having nvm_geo, then we are
>> truncating the structure for each instance with different channel/lun
>> values, which is very from a target perspective (the target can access
>> the underlying device's values, which is _very_ error prone). This
>> structure represents all 2.0 variables as they are.I can move all 1.2
>> variables to a sub structure if that helps.
> 
> Let me try to see if I can clarify. From my understanding,the patch is doing three things,
> 
> 1. Replace dev->identify and use a generic data structure
> 2. Introduced nvm_dev_geo to represent both intance and device channels and luns.
> 3. Move pblk addressing logic into core

Yes :)

> 
> Could these be split up? maybe 1 and 3 go together, and the address format go by itself. Maybe not. I'm fine if you say that they should stay together.
> 
> For 1 and 3, Instead of making the nvm_dev_geo the base structure, the code should continue to use nvm_geo (don't move the variables into nvm_geo_common and similar data struct. The nvm_dev->nvm_dev_geo is not pretty, the code already has a reference that the nvm_dev_geo is in the nvm_dev data structure.
> 
> When the code needs the instance specific channels and luns, put them in another data structure (than nvm_dev_geo), and maintain the relationship there.

Ok. Let me give it another try. The only thing that matters to me is
that pblk does not need to go and check for 1.2 and 2.0 more than in the
address converting part (because there is no way around it if
page,plane,sector are not aligned. Apart from that, I'm very open to
having it one way or the other.

Thanks for clarifying!

Javier

[-- Attachment #2: Message signed with OpenPGP --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 99+ messages in thread

* [PATCH 01/20] lightnvm: simplify geometry structure.
@ 2018-02-22 14:13           ` Javier Gonzalez
  0 siblings, 0 replies; 99+ messages in thread
From: Javier Gonzalez @ 2018-02-22 14:13 UTC (permalink / raw)


> On 22 Feb 2018,@13.22, Matias Bj?rling <mb@lightnvm.io> wrote:
> 
> On 02/22/2018 08:44 AM, Javier Gonzalez wrote:
>>> On 22 Feb 2018,@08.25, Matias Bj?rling <mb@lightnvm.io> wrote:
>>> 
>>> On 02/21/2018 10:26 AM, Javier Gonz?lez wrote:
>>>> Currently, the device geometry is stored redundantly in the nvm_id and
>>>> nvm_geo structures at a device level. Moreover, when instantiating
>>>> targets on a specific number of LUNs, these structures are replicated
>>>> and manually modified to fit the instance channel and LUN partitioning.
>>>> Instead, create a generic geometry around two base structures:
>>>> nvm_dev_geo, which describes the geometry of the whole device and
>>>> nvm_geo, which describes the geometry of the instance. Since these share
>>>> a big part of the geometry, create a nvm_common_geo structure that keeps
>>>> the static geoometry values that are shared across instances.
>>>> As we introduce support for 2.0, these structures allow to abstract
>>>> spec. specific values and present a common geometry to targets.
>>>> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
>>>> ---
>>>>  drivers/lightnvm/core.c          | 137 +++++++---------
>>>>  drivers/lightnvm/pblk-core.c     |  16 +-
>>>>  drivers/lightnvm/pblk-gc.c       |   2 +-
>>>>  drivers/lightnvm/pblk-init.c     | 123 +++++++-------
>>>>  drivers/lightnvm/pblk-read.c     |   2 +-
>>>>  drivers/lightnvm/pblk-recovery.c |  14 +-
>>>>  drivers/lightnvm/pblk-rl.c       |   2 +-
>>>>  drivers/lightnvm/pblk-sysfs.c    |  39 +++--
>>>>  drivers/lightnvm/pblk-write.c    |   2 +-
>>>>  drivers/lightnvm/pblk.h          |  93 +++++------
>>>>  drivers/nvme/host/lightnvm.c     | 339 +++++++++++++++++++++++----------------
>>>>  include/linux/lightnvm.h         | 204 ++++++++++++-----------
>>>>  12 files changed, 514 insertions(+), 459 deletions(-)
>>>> diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
>>>> index 689c97b97775..42596afdf64c 100644
>>>> --- a/drivers/lightnvm/core.c
>>>> +++ b/drivers/lightnvm/core.c
>>>> @@ -111,6 +111,7 @@ static void nvm_release_luns_err(struct nvm_dev *dev, int lun_begin,
>>>>  static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
>>>>  {
>>>>  	struct nvm_dev *dev = tgt_dev->parent;
>>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>>  	struct nvm_dev_map *dev_map = tgt_dev->map;
>>>>  	int i, j;
>>>>  @@ -122,7 +123,7 @@ static void nvm_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev, int clear)
>>>>  		if (clear) {
>>>>  			for (j = 0; j < ch_map->nr_luns; j++) {
>>>>  				int lun = j + lun_offs[j];
>>>> -				int lunid = (ch * dev->geo.nr_luns) + lun;
>>>> +				int lunid = (ch * dev_geo->nr_luns) + lun;
>>>>    				WARN_ON(!test_and_clear_bit(lunid,
>>>>  							dev->lun_map));
>>>> @@ -143,19 +144,20 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>>>>  					      u16 lun_begin, u16 lun_end,
>>>>  					      u16 op)
>>>>  {
>>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>>  	struct nvm_tgt_dev *tgt_dev = NULL;
>>>>  	struct nvm_dev_map *dev_rmap = dev->rmap;
>>>>  	struct nvm_dev_map *dev_map;
>>>>  	struct ppa_addr *luns;
>>>>  	int nr_luns = lun_end - lun_begin + 1;
>>>>  	int luns_left = nr_luns;
>>>> -	int nr_chnls = nr_luns / dev->geo.nr_luns;
>>>> -	int nr_chnls_mod = nr_luns % dev->geo.nr_luns;
>>>> -	int bch = lun_begin / dev->geo.nr_luns;
>>>> -	int blun = lun_begin % dev->geo.nr_luns;
>>>> +	int nr_chnls = nr_luns / dev_geo->nr_luns;
>>>> +	int nr_chnls_mod = nr_luns % dev_geo->nr_luns;
>>>> +	int bch = lun_begin / dev_geo->nr_luns;
>>>> +	int blun = lun_begin % dev_geo->nr_luns;
>>>>  	int lunid = 0;
>>>>  	int lun_balanced = 1;
>>>> -	int prev_nr_luns;
>>>> +	int sec_per_lun, prev_nr_luns;
>>>>  	int i, j;
>>>>    	nr_chnls = (nr_chnls_mod == 0) ? nr_chnls : nr_chnls + 1;
>>>> @@ -173,15 +175,15 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>>>>  	if (!luns)
>>>>  		goto err_luns;
>>>>  -	prev_nr_luns = (luns_left > dev->geo.nr_luns) ?
>>>> -					dev->geo.nr_luns : luns_left;
>>>> +	prev_nr_luns = (luns_left > dev_geo->nr_luns) ?
>>>> +					dev_geo->nr_luns : luns_left;
>>>>  	for (i = 0; i < nr_chnls; i++) {
>>>>  		struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[i + bch];
>>>>  		int *lun_roffs = ch_rmap->lun_offs;
>>>>  		struct nvm_ch_map *ch_map = &dev_map->chnls[i];
>>>>  		int *lun_offs;
>>>> -		int luns_in_chnl = (luns_left > dev->geo.nr_luns) ?
>>>> -					dev->geo.nr_luns : luns_left;
>>>> +		int luns_in_chnl = (luns_left > dev_geo->nr_luns) ?
>>>> +					dev_geo->nr_luns : luns_left;
>>>>    		if (lun_balanced && prev_nr_luns != luns_in_chnl)
>>>>  			lun_balanced = 0;
>>>> @@ -215,18 +217,22 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
>>>>  	if (!tgt_dev)
>>>>  		goto err_ch;
>>>>  -	memcpy(&tgt_dev->geo, &dev->geo, sizeof(struct nvm_geo));
>>>>  	/* Target device only owns a portion of the physical device */
>>>>  	tgt_dev->geo.nr_chnls = nr_chnls;
>>>> -	tgt_dev->geo.all_luns = nr_luns;
>>>>  	tgt_dev->geo.nr_luns = (lun_balanced) ? prev_nr_luns : -1;
>>>> +	tgt_dev->geo.all_luns = nr_luns;
>>>> +	tgt_dev->geo.all_chunks = nr_luns * dev_geo->c.num_chk;
>>>> +
>>>>  	tgt_dev->geo.op = op;
>>>> -	tgt_dev->total_secs = nr_luns * tgt_dev->geo.sec_per_lun;
>>>> +
>>>> +	sec_per_lun = dev_geo->c.clba * dev_geo->c.num_chk;
>>>> +	tgt_dev->geo.total_secs = nr_luns * sec_per_lun;
>>>> +
>>>> +	tgt_dev->geo.c = dev_geo->c;
>>>> +
>>>>  	tgt_dev->q = dev->q;
>>>>  	tgt_dev->map = dev_map;
>>>>  	tgt_dev->luns = luns;
>>>> -	memcpy(&tgt_dev->identity, &dev->identity, sizeof(struct nvm_id));
>>>> -
>>>>  	tgt_dev->parent = dev;
>>>>    	return tgt_dev;
>>>> @@ -268,12 +274,12 @@ static struct nvm_tgt_type *nvm_find_target_type(const char *name)
>>>>  	return tt;
>>>>  }
>>>>  -static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
>>>> +static int nvm_config_check_luns(struct nvm_dev_geo *dev_geo, int lun_begin,
>>>>  				 int lun_end)
>>>>  {
>>>> -	if (lun_begin > lun_end || lun_end >= geo->all_luns) {
>>>> +	if (lun_begin > lun_end || lun_end >= dev_geo->all_luns) {
>>>>  		pr_err("nvm: lun out of bound (%u:%u > %u)\n",
>>>> -			lun_begin, lun_end, geo->all_luns - 1);
>>>> +			lun_begin, lun_end, dev_geo->all_luns - 1);
>>>>  		return -EINVAL;
>>>>  	}
>>>>  @@ -283,24 +289,24 @@ static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin,
>>>>  static int __nvm_config_simple(struct nvm_dev *dev,
>>>>  			       struct nvm_ioctl_create_simple *s)
>>>>  {
>>>> -	struct nvm_geo *geo = &dev->geo;
>>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>>    	if (s->lun_begin == -1 && s->lun_end == -1) {
>>>>  		s->lun_begin = 0;
>>>> -		s->lun_end = geo->all_luns - 1;
>>>> +		s->lun_end = dev_geo->all_luns - 1;
>>>>  	}
>>>>  -	return nvm_config_check_luns(geo, s->lun_begin, s->lun_end);
>>>> +	return nvm_config_check_luns(dev_geo, s->lun_begin, s->lun_end);
>>>>  }
>>>>    static int __nvm_config_extended(struct nvm_dev *dev,
>>>>  				 struct nvm_ioctl_create_extended *e)
>>>>  {
>>>> -	struct nvm_geo *geo = &dev->geo;
>>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>>    	if (e->lun_begin == 0xFFFF && e->lun_end == 0xFFFF) {
>>>>  		e->lun_begin = 0;
>>>> -		e->lun_end = dev->geo.all_luns - 1;
>>>> +		e->lun_end = dev_geo->all_luns - 1;
>>>>  	}
>>>>    	/* op not set falls into target's default */
>>>> @@ -313,7 +319,7 @@ static int __nvm_config_extended(struct nvm_dev *dev,
>>>>  		return -EINVAL;
>>>>  	}
>>>>  -	return nvm_config_check_luns(geo, e->lun_begin, e->lun_end);
>>>> +	return nvm_config_check_luns(dev_geo, e->lun_begin, e->lun_end);
>>>>  }
>>>>    static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
>>>> @@ -408,7 +414,7 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
>>>>  	tqueue->queuedata = targetdata;
>>>>    	blk_queue_max_hw_sectors(tqueue,
>>>> -			(dev->geo.sec_size >> 9) * NVM_MAX_VLBA);
>>>> +			(dev->dev_geo.c.csecs >> 9) * NVM_MAX_VLBA);
>>>>    	set_capacity(tdisk, tt->capacity(targetdata));
>>>>  	add_disk(tdisk);
>>>> @@ -497,6 +503,7 @@ static int nvm_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove)
>>>>    static int nvm_register_map(struct nvm_dev *dev)
>>>>  {
>>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>>  	struct nvm_dev_map *rmap;
>>>>  	int i, j;
>>>>  @@ -504,15 +511,15 @@ static int nvm_register_map(struct nvm_dev *dev)
>>>>  	if (!rmap)
>>>>  		goto err_rmap;
>>>>  -	rmap->chnls = kcalloc(dev->geo.nr_chnls, sizeof(struct nvm_ch_map),
>>>> +	rmap->chnls = kcalloc(dev_geo->nr_chnls, sizeof(struct nvm_ch_map),
>>>>  								GFP_KERNEL);
>>>>  	if (!rmap->chnls)
>>>>  		goto err_chnls;
>>>>  -	for (i = 0; i < dev->geo.nr_chnls; i++) {
>>>> +	for (i = 0; i < dev_geo->nr_chnls; i++) {
>>>>  		struct nvm_ch_map *ch_rmap;
>>>>  		int *lun_roffs;
>>>> -		int luns_in_chnl = dev->geo.nr_luns;
>>>> +		int luns_in_chnl = dev_geo->nr_luns;
>>>>    		ch_rmap = &rmap->chnls[i];
>>>>  @@ -543,10 +550,11 @@ static int nvm_register_map(struct nvm_dev *dev)
>>>>    static void nvm_unregister_map(struct nvm_dev *dev)
>>>>  {
>>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>>  	struct nvm_dev_map *rmap = dev->rmap;
>>>>  	int i;
>>>>  -	for (i = 0; i < dev->geo.nr_chnls; i++)
>>>> +	for (i = 0; i < dev_geo->nr_chnls; i++)
>>>>  		kfree(rmap->chnls[i].lun_offs);
>>>>    	kfree(rmap->chnls);
>>>> @@ -675,7 +683,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
>>>>  	int i, plane_cnt, pl_idx;
>>>>  	struct ppa_addr ppa;
>>>>  -	if (geo->plane_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
>>>> +	if (geo->c.pln_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
>>>>  		rqd->nr_ppas = nr_ppas;
>>>>  		rqd->ppa_addr = ppas[0];
>>>>  @@ -689,7 +697,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
>>>>  		return -ENOMEM;
>>>>  	}
>>>>  -	plane_cnt = geo->plane_mode;
>>>> +	plane_cnt = geo->c.pln_mode;
>>>>  	rqd->nr_ppas *= plane_cnt;
>>>>    	for (i = 0; i < nr_ppas; i++) {
>>>> @@ -804,18 +812,18 @@ EXPORT_SYMBOL(nvm_end_io);
>>>>   */
>>>>  int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
>>>>  {
>>>> -	struct nvm_geo *geo = &dev->geo;
>>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>>  	int blk, offset, pl, blktype;
>>>>  -	if (nr_blks != geo->nr_chks * geo->plane_mode)
>>>> +	if (nr_blks != dev_geo->c.num_chk * dev_geo->c.pln_mode)
>>>>  		return -EINVAL;
>>>>  -	for (blk = 0; blk < geo->nr_chks; blk++) {
>>>> -		offset = blk * geo->plane_mode;
>>>> +	for (blk = 0; blk < dev_geo->c.num_chk; blk++) {
>>>> +		offset = blk * dev_geo->c.pln_mode;
>>>>  		blktype = blks[offset];
>>>>    		/* Bad blocks on any planes take precedence over other types */
>>>> -		for (pl = 0; pl < geo->plane_mode; pl++) {
>>>> +		for (pl = 0; pl < dev_geo->c.pln_mode; pl++) {
>>>>  			if (blks[offset + pl] &
>>>>  					(NVM_BLK_T_BAD|NVM_BLK_T_GRWN_BAD)) {
>>>>  				blktype = blks[offset + pl];
>>>> @@ -826,7 +834,7 @@ int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
>>>>  		blks[blk] = blktype;
>>>>  	}
>>>>  -	return geo->nr_chks;
>>>> +	return dev_geo->c.num_chk;
>>>>  }
>>>>  EXPORT_SYMBOL(nvm_bb_tbl_fold);
>>>>  @@ -843,41 +851,10 @@ EXPORT_SYMBOL(nvm_get_tgt_bb_tbl);
>>>>    static int nvm_core_init(struct nvm_dev *dev)
>>>>  {
>>>> -	struct nvm_id *id = &dev->identity;
>>>> -	struct nvm_geo *geo = &dev->geo;
>>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>>  	int ret;
>>>>  -	memcpy(&geo->ppaf, &id->ppaf, sizeof(struct nvm_addr_format));
>>>> -
>>>> -	if (id->mtype != 0) {
>>>> -		pr_err("nvm: memory type not supported\n");
>>>> -		return -EINVAL;
>>>> -	}
>>>> -
>>>> -	/* Whole device values */
>>>> -	geo->nr_chnls = id->num_ch;
>>>> -	geo->nr_luns = id->num_lun;
>>>> -
>>>> -	/* Generic device geometry values */
>>>> -	geo->ws_min = id->ws_min;
>>>> -	geo->ws_opt = id->ws_opt;
>>>> -	geo->ws_seq = id->ws_seq;
>>>> -	geo->ws_per_chk = id->ws_per_chk;
>>>> -	geo->nr_chks = id->num_chk;
>>>> -	geo->mccap = id->mccap;
>>>> -
>>>> -	geo->sec_per_chk = id->clba;
>>>> -	geo->sec_per_lun = geo->sec_per_chk * geo->nr_chks;
>>>> -	geo->all_luns = geo->nr_luns * geo->nr_chnls;
>>>> -
>>>> -	/* 1.2 spec device geometry values */
>>>> -	geo->plane_mode = 1 << geo->ws_seq;
>>>> -	geo->nr_planes = geo->ws_opt / geo->ws_min;
>>>> -	geo->sec_per_pg = geo->ws_min;
>>>> -	geo->sec_per_pl = geo->sec_per_pg * geo->nr_planes;
>>>> -
>>>> -	dev->total_secs = geo->all_luns * geo->sec_per_lun;
>>>> -	dev->lun_map = kcalloc(BITS_TO_LONGS(geo->all_luns),
>>>> +	dev->lun_map = kcalloc(BITS_TO_LONGS(dev_geo->all_luns),
>>>>  					sizeof(unsigned long), GFP_KERNEL);
>>>>  	if (!dev->lun_map)
>>>>  		return -ENOMEM;
>>>> @@ -912,19 +889,17 @@ static void nvm_free(struct nvm_dev *dev)
>>>>    static int nvm_init(struct nvm_dev *dev)
>>>>  {
>>>> -	struct nvm_geo *geo = &dev->geo;
>>>> +	struct nvm_dev_geo *dev_geo = &dev->dev_geo;
>>>>  	int ret = -EINVAL;
>>>>  -	if (dev->ops->identity(dev, &dev->identity)) {
>>>> +	if (dev->ops->identity(dev)) {
>>>>  		pr_err("nvm: device could not be identified\n");
>>>>  		goto err;
>>>>  	}
>>>>  -	if (dev->identity.ver_id != 1 && dev->identity.ver_id != 2) {
>>>> -		pr_err("nvm: device ver_id %d not supported by kernel.\n",
>>>> -				dev->identity.ver_id);
>>>> -		goto err;
>>>> -	}
>>>> +	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
>>>> +				dev_geo->ver_id,
>>>> +				dev_geo->c.vmnt);
>>>>    	ret = nvm_core_init(dev);
>>>>  	if (ret) {
>>>> @@ -932,10 +907,10 @@ static int nvm_init(struct nvm_dev *dev)
>>>>  		goto err;
>>>>  	}
>>>>  -	pr_info("nvm: registered %s [%u/%u/%u/%u/%u/%u]\n",
>>>> -			dev->name, geo->sec_per_pg, geo->nr_planes,
>>>> -			geo->ws_per_chk, geo->nr_chks,
>>>> -			geo->all_luns, geo->nr_chnls);
>>>> +	pr_info("nvm: registered %s [%u/%u/%u/%u/%u]\n",
>>>> +			dev->name, dev_geo->c.ws_min, dev_geo->c.ws_opt,
>>>> +			dev_geo->c.num_chk, dev_geo->all_luns,
>>>> +			dev_geo->nr_chnls);
>>>>  	return 0;
>>>>  err:
>>>>  	pr_err("nvm: failed to initialize nvm\n");
>>>> diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
>>>> index 22e61cd4f801..519af8b9eab7 100644
>>>> --- a/drivers/lightnvm/pblk-core.c
>>>> +++ b/drivers/lightnvm/pblk-core.c
>>>> @@ -613,7 +613,7 @@ static int pblk_line_submit_emeta_io(struct pblk *pblk, struct pblk_line *line,
>>>>  	memset(&rqd, 0, sizeof(struct nvm_rq));
>>>>    	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>>> -	rq_len = rq_ppas * geo->sec_size;
>>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>>    	bio = pblk_bio_map_addr(pblk, emeta_buf, rq_ppas, rq_len,
>>>>  					l_mg->emeta_alloc_type, GFP_KERNEL);
>>>> @@ -722,7 +722,7 @@ u64 pblk_line_smeta_start(struct pblk *pblk, struct pblk_line *line)
>>>>  	if (bit >= lm->blk_per_line)
>>>>  		return -1;
>>>>  -	return bit * geo->sec_per_pl;
>>>> +	return bit * geo->c.ws_opt;
>>>>  }
>>>>    static int pblk_line_submit_smeta_io(struct pblk *pblk, struct pblk_line *line,
>>>> @@ -1035,19 +1035,19 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>>>>  	/* Capture bad block information on line mapping bitmaps */
>>>>  	while ((bit = find_next_bit(line->blk_bitmap, lm->blk_per_line,
>>>>  					bit + 1)) < lm->blk_per_line) {
>>>> -		off = bit * geo->sec_per_pl;
>>>> +		off = bit * geo->c.ws_opt;
>>>>  		bitmap_shift_left(l_mg->bb_aux, l_mg->bb_template, off,
>>>>  							lm->sec_per_line);
>>>>  		bitmap_or(line->map_bitmap, line->map_bitmap, l_mg->bb_aux,
>>>>  							lm->sec_per_line);
>>>> -		line->sec_in_line -= geo->sec_per_chk;
>>>> +		line->sec_in_line -= geo->c.clba;
>>>>  		if (bit >= lm->emeta_bb)
>>>>  			nr_bb++;
>>>>  	}
>>>>    	/* Mark smeta metadata sectors as bad sectors */
>>>>  	bit = find_first_zero_bit(line->blk_bitmap, lm->blk_per_line);
>>>> -	off = bit * geo->sec_per_pl;
>>>> +	off = bit * geo->c.ws_opt;
>>>>  	bitmap_set(line->map_bitmap, off, lm->smeta_sec);
>>>>  	line->sec_in_line -= lm->smeta_sec;
>>>>  	line->smeta_ssec = off;
>>>> @@ -1066,10 +1066,10 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>>>>  	emeta_secs = lm->emeta_sec[0];
>>>>  	off = lm->sec_per_line;
>>>>  	while (emeta_secs) {
>>>> -		off -= geo->sec_per_pl;
>>>> +		off -= geo->c.ws_opt;
>>>>  		if (!test_bit(off, line->invalid_bitmap)) {
>>>> -			bitmap_set(line->invalid_bitmap, off, geo->sec_per_pl);
>>>> -			emeta_secs -= geo->sec_per_pl;
>>>> +			bitmap_set(line->invalid_bitmap, off, geo->c.ws_opt);
>>>> +			emeta_secs -= geo->c.ws_opt;
>>>>  		}
>>>>  	}
>>>>  diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c
>>>> index 320f99af99e9..16afea3f5541 100644
>>>> --- a/drivers/lightnvm/pblk-gc.c
>>>> +++ b/drivers/lightnvm/pblk-gc.c
>>>> @@ -88,7 +88,7 @@ static void pblk_gc_line_ws(struct work_struct *work)
>>>>    	up(&gc->gc_sem);
>>>>  -	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->sec_size);
>>>> +	gc_rq->data = vmalloc(gc_rq->nr_secs * geo->c.csecs);
>>>>  	if (!gc_rq->data) {
>>>>  		pr_err("pblk: could not GC line:%d (%d/%d)\n",
>>>>  					line->id, *line->vsc, gc_rq->nr_secs);
>>>> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
>>>> index 5261702e9ff7..95ecb0ec736b 100644
>>>> --- a/drivers/lightnvm/pblk-init.c
>>>> +++ b/drivers/lightnvm/pblk-init.c
>>>> @@ -146,7 +146,7 @@ static int pblk_rwb_init(struct pblk *pblk)
>>>>  		return -ENOMEM;
>>>>    	power_size = get_count_order(nr_entries);
>>>> -	power_seg_sz = get_count_order(geo->sec_size);
>>>> +	power_seg_sz = get_count_order(geo->c.csecs);
>>>>    	return pblk_rb_init(&pblk->rwb, entries, power_size, power_seg_sz);
>>>>  }
>>>> @@ -154,11 +154,11 @@ static int pblk_rwb_init(struct pblk *pblk)
>>>>  /* Minimum pages needed within a lun */
>>>>  #define ADDR_POOL_SIZE 64
>>>>  -static int pblk_set_ppaf(struct pblk *pblk)
>>>> +static int pblk_set_addrf_12(struct nvm_geo *geo,
>>>> +			     struct nvm_addr_format_12 *dst)
>>>>  {
>>>> -	struct nvm_tgt_dev *dev = pblk->dev;
>>>> -	struct nvm_geo *geo = &dev->geo;
>>>> -	struct nvm_addr_format ppaf = geo->ppaf;
>>>> +	struct nvm_addr_format_12 *src =
>>>> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>>>>  	int power_len;
>>>>    	/* Re-calculate channel and lun format to adapt to configuration */
>>>> @@ -167,34 +167,50 @@ static int pblk_set_ppaf(struct pblk *pblk)
>>>>  		pr_err("pblk: supports only power-of-two channel config.\n");
>>>>  		return -EINVAL;
>>>>  	}
>>>> -	ppaf.ch_len = power_len;
>>>> +	dst->ch_len = power_len;
>>>>    	power_len = get_count_order(geo->nr_luns);
>>>>  	if (1 << power_len != geo->nr_luns) {
>>>>  		pr_err("pblk: supports only power-of-two LUN config.\n");
>>>>  		return -EINVAL;
>>>>  	}
>>>> -	ppaf.lun_len = power_len;
>>>> +	dst->lun_len = power_len;
>>>>  -	pblk->ppaf.sec_offset = 0;
>>>> -	pblk->ppaf.pln_offset = ppaf.sect_len;
>>>> -	pblk->ppaf.ch_offset = pblk->ppaf.pln_offset + ppaf.pln_len;
>>>> -	pblk->ppaf.lun_offset = pblk->ppaf.ch_offset + ppaf.ch_len;
>>>> -	pblk->ppaf.pg_offset = pblk->ppaf.lun_offset + ppaf.lun_len;
>>>> -	pblk->ppaf.blk_offset = pblk->ppaf.pg_offset + ppaf.pg_len;
>>>> -	pblk->ppaf.sec_mask = (1ULL << ppaf.sect_len) - 1;
>>>> -	pblk->ppaf.pln_mask = ((1ULL << ppaf.pln_len) - 1) <<
>>>> -							pblk->ppaf.pln_offset;
>>>> -	pblk->ppaf.ch_mask = ((1ULL << ppaf.ch_len) - 1) <<
>>>> -							pblk->ppaf.ch_offset;
>>>> -	pblk->ppaf.lun_mask = ((1ULL << ppaf.lun_len) - 1) <<
>>>> -							pblk->ppaf.lun_offset;
>>>> -	pblk->ppaf.pg_mask = ((1ULL << ppaf.pg_len) - 1) <<
>>>> -							pblk->ppaf.pg_offset;
>>>> -	pblk->ppaf.blk_mask = ((1ULL << ppaf.blk_len) - 1) <<
>>>> -							pblk->ppaf.blk_offset;
>>>> +	dst->blk_len = src->blk_len;
>>>> +	dst->pg_len = src->pg_len;
>>>> +	dst->pln_len = src->pln_len;
>>>> +	dst->sect_len = src->sect_len;
>>>>  -	pblk->ppaf_bitsize = pblk->ppaf.blk_offset + ppaf.blk_len;
>>>> +	dst->sect_offset = 0;
>>>> +	dst->pln_offset = dst->sect_len;
>>>> +	dst->ch_offset = dst->pln_offset + dst->pln_len;
>>>> +	dst->lun_offset = dst->ch_offset + dst->ch_len;
>>>> +	dst->pg_offset = dst->lun_offset + dst->lun_len;
>>>> +	dst->blk_offset = dst->pg_offset + dst->pg_len;
>>>> +
>>>> +	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
>>>> +	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
>>>> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>>>> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>>>> +	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
>>>> +	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
>>>> +
>>>> +	return dst->blk_offset + src->blk_len;
>>>> +}
>>>> +
>>>> +static int pblk_set_ppaf(struct pblk *pblk)
>>>> +{
>>>> +	struct nvm_tgt_dev *dev = pblk->dev;
>>>> +	struct nvm_geo *geo = &dev->geo;
>>>> +	int mod;
>>>> +
>>>> +	div_u64_rem(geo->c.clba, pblk->min_write_pgs, &mod);
>>>> +	if (mod) {
>>>> +		pr_err("pblk: bad configuration of sectors/pages\n");
>>>> +		return -EINVAL;
>>>> +	}
>>>> +
>>>> +	pblk->ppaf_bitsize = pblk_set_addrf_12(geo, (void *)&pblk->ppaf);
>>>>    	return 0;
>>>>  }
>>>> @@ -253,8 +269,7 @@ static int pblk_core_init(struct pblk *pblk)
>>>>  	struct nvm_tgt_dev *dev = pblk->dev;
>>>>  	struct nvm_geo *geo = &dev->geo;
>>>>  -	pblk->pgs_in_buffer = NVM_MEM_PAGE_WRITE * geo->sec_per_pg *
>>>> -						geo->nr_planes * geo->all_luns;
>>>> +	pblk->pgs_in_buffer = geo->c.mw_cunits * geo->c.ws_opt * geo->all_luns;
>>>>    	if (pblk_init_global_caches(pblk))
>>>>  		return -ENOMEM;
>>>> @@ -433,7 +448,7 @@ static void *pblk_bb_get_log(struct pblk *pblk)
>>>>  	int i, nr_blks, blk_per_lun;
>>>>  	int ret;
>>>>  -	blk_per_lun = geo->nr_chks * geo->plane_mode;
>>>> +	blk_per_lun = geo->c.num_chk * geo->c.pln_mode;
>>>>  	nr_blks = blk_per_lun * geo->all_luns;
>>>>    	log = kmalloc(nr_blks, GFP_KERNEL);
>>>> @@ -551,18 +566,18 @@ static unsigned int calc_emeta_len(struct pblk *pblk)
>>>>  	/* Round to sector size so that lba_list starts on its own sector */
>>>>  	lm->emeta_sec[1] = DIV_ROUND_UP(
>>>>  			sizeof(struct line_emeta) + lm->blk_bitmap_len +
>>>> -			sizeof(struct wa_counters), geo->sec_size);
>>>> -	lm->emeta_len[1] = lm->emeta_sec[1] * geo->sec_size;
>>>> +			sizeof(struct wa_counters), geo->c.csecs);
>>>> +	lm->emeta_len[1] = lm->emeta_sec[1] * geo->c.csecs;
>>>>    	/* Round to sector size so that vsc_list starts on its own sector */
>>>>  	lm->dsec_per_line = lm->sec_per_line - lm->emeta_sec[0];
>>>>  	lm->emeta_sec[2] = DIV_ROUND_UP(lm->dsec_per_line * sizeof(u64),
>>>> -			geo->sec_size);
>>>> -	lm->emeta_len[2] = lm->emeta_sec[2] * geo->sec_size;
>>>> +			geo->c.csecs);
>>>> +	lm->emeta_len[2] = lm->emeta_sec[2] * geo->c.csecs;
>>>>    	lm->emeta_sec[3] = DIV_ROUND_UP(l_mg->nr_lines * sizeof(u32),
>>>> -			geo->sec_size);
>>>> -	lm->emeta_len[3] = lm->emeta_sec[3] * geo->sec_size;
>>>> +			geo->c.csecs);
>>>> +	lm->emeta_len[3] = lm->emeta_sec[3] * geo->c.csecs;
>>>>    	lm->vsc_list_len = l_mg->nr_lines * sizeof(u32);
>>>>  @@ -593,13 +608,13 @@ static void pblk_set_provision(struct pblk *pblk, long nr_free_blks)
>>>>  	 * on user capacity consider only provisioned blocks
>>>>  	 */
>>>>  	pblk->rl.total_blocks = nr_free_blks;
>>>> -	pblk->rl.nr_secs = nr_free_blks * geo->sec_per_chk;
>>>> +	pblk->rl.nr_secs = nr_free_blks * geo->c.clba;
>>>>    	/* Consider sectors used for metadata */
>>>>  	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
>>>> -	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
>>>> +	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
>>>>  -	pblk->capacity = (provisioned - blk_meta) * geo->sec_per_chk;
>>>> +	pblk->capacity = (provisioned - blk_meta) * geo->c.clba;
>>>>    	atomic_set(&pblk->rl.free_blocks, nr_free_blks);
>>>>  	atomic_set(&pblk->rl.free_user_blocks, nr_free_blks);
>>>> @@ -710,10 +725,10 @@ static int pblk_lines_init(struct pblk *pblk)
>>>>  	void *chunk_log;
>>>>  	unsigned int smeta_len, emeta_len;
>>>>  	long nr_bad_blks = 0, nr_free_blks = 0;
>>>> -	int bb_distance, max_write_ppas, mod;
>>>> +	int bb_distance, max_write_ppas;
>>>>  	int i, ret;
>>>>  -	pblk->min_write_pgs = geo->sec_per_pl * (geo->sec_size / PAGE_SIZE);
>>>> +	pblk->min_write_pgs = geo->c.ws_opt * (geo->c.csecs / PAGE_SIZE);
>>>>  	max_write_ppas = pblk->min_write_pgs * geo->all_luns;
>>>>  	pblk->max_write_pgs = min_t(int, max_write_ppas, NVM_MAX_VLBA);
>>>>  	pblk_set_sec_per_write(pblk, pblk->min_write_pgs);
>>>> @@ -724,19 +739,13 @@ static int pblk_lines_init(struct pblk *pblk)
>>>>  		return -EINVAL;
>>>>  	}
>>>>  -	div_u64_rem(geo->sec_per_chk, pblk->min_write_pgs, &mod);
>>>> -	if (mod) {
>>>> -		pr_err("pblk: bad configuration of sectors/pages\n");
>>>> -		return -EINVAL;
>>>> -	}
>>>> -
>>>> -	l_mg->nr_lines = geo->nr_chks;
>>>> +	l_mg->nr_lines = geo->c.num_chk;
>>>>  	l_mg->log_line = l_mg->data_line = NULL;
>>>>  	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
>>>>  	l_mg->nr_free_lines = 0;
>>>>  	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
>>>>  -	lm->sec_per_line = geo->sec_per_chk * geo->all_luns;
>>>> +	lm->sec_per_line = geo->c.clba * geo->all_luns;
>>>>  	lm->blk_per_line = geo->all_luns;
>>>>  	lm->blk_bitmap_len = BITS_TO_LONGS(geo->all_luns) * sizeof(long);
>>>>  	lm->sec_bitmap_len = BITS_TO_LONGS(lm->sec_per_line) * sizeof(long);
>>>> @@ -750,8 +759,8 @@ static int pblk_lines_init(struct pblk *pblk)
>>>>  	 */
>>>>  	i = 1;
>>>>  add_smeta_page:
>>>> -	lm->smeta_sec = i * geo->sec_per_pl;
>>>> -	lm->smeta_len = lm->smeta_sec * geo->sec_size;
>>>> +	lm->smeta_sec = i * geo->c.ws_opt;
>>>> +	lm->smeta_len = lm->smeta_sec * geo->c.csecs;
>>>>    	smeta_len = sizeof(struct line_smeta) + lm->lun_bitmap_len;
>>>>  	if (smeta_len > lm->smeta_len) {
>>>> @@ -764,8 +773,8 @@ static int pblk_lines_init(struct pblk *pblk)
>>>>  	 */
>>>>  	i = 1;
>>>>  add_emeta_page:
>>>> -	lm->emeta_sec[0] = i * geo->sec_per_pl;
>>>> -	lm->emeta_len[0] = lm->emeta_sec[0] * geo->sec_size;
>>>> +	lm->emeta_sec[0] = i * geo->c.ws_opt;
>>>> +	lm->emeta_len[0] = lm->emeta_sec[0] * geo->c.csecs;
>>>>    	emeta_len = calc_emeta_len(pblk);
>>>>  	if (emeta_len > lm->emeta_len[0]) {
>>>> @@ -778,7 +787,7 @@ static int pblk_lines_init(struct pblk *pblk)
>>>>  	lm->min_blk_line = 1;
>>>>  	if (geo->all_luns > 1)
>>>>  		lm->min_blk_line += DIV_ROUND_UP(lm->smeta_sec +
>>>> -					lm->emeta_sec[0], geo->sec_per_chk);
>>>> +					lm->emeta_sec[0], geo->c.clba);
>>>>    	if (lm->min_blk_line > lm->blk_per_line) {
>>>>  		pr_err("pblk: config. not supported. Min. LUN in line:%d\n",
>>>> @@ -802,9 +811,9 @@ static int pblk_lines_init(struct pblk *pblk)
>>>>  		goto fail_free_bb_template;
>>>>  	}
>>>>  -	bb_distance = (geo->all_luns) * geo->sec_per_pl;
>>>> +	bb_distance = (geo->all_luns) * geo->c.ws_opt;
>>>>  	for (i = 0; i < lm->sec_per_line; i += bb_distance)
>>>> -		bitmap_set(l_mg->bb_template, i, geo->sec_per_pl);
>>>> +		bitmap_set(l_mg->bb_template, i, geo->c.ws_opt);
>>>>    	INIT_LIST_HEAD(&l_mg->free_list);
>>>>  	INIT_LIST_HEAD(&l_mg->corrupt_list);
>>>> @@ -981,9 +990,9 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>>>>  	struct pblk *pblk;
>>>>  	int ret;
>>>>  -	if (dev->identity.dom & NVM_RSP_L2P) {
>>>> +	if (dev->geo.c.dom & NVM_RSP_L2P) {
>>>>  		pr_err("pblk: host-side L2P table not supported. (%x)\n",
>>>> -							dev->identity.dom);
>>>> +							dev->geo.c.dom);
>>>>  		return ERR_PTR(-EINVAL);
>>>>  	}
>>>>  @@ -1091,7 +1100,7 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>>>>    	blk_queue_write_cache(tqueue, true, false);
>>>>  -	tqueue->limits.discard_granularity = geo->sec_per_chk * geo->sec_size;
>>>> +	tqueue->limits.discard_granularity = geo->c.clba * geo->c.csecs;
>>>>  	tqueue->limits.discard_alignment = 0;
>>>>  	blk_queue_max_discard_sectors(tqueue, UINT_MAX >> 9);
>>>>  	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, tqueue);
>>>> diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c
>>>> index 2f761283f43e..ebb6bae3a3b8 100644
>>>> --- a/drivers/lightnvm/pblk-read.c
>>>> +++ b/drivers/lightnvm/pblk-read.c
>>>> @@ -563,7 +563,7 @@ int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq)
>>>>  	if (!(gc_rq->secs_to_gc))
>>>>  		goto out;
>>>>  -	data_len = (gc_rq->secs_to_gc) * geo->sec_size;
>>>> +	data_len = (gc_rq->secs_to_gc) * geo->c.csecs;
>>>>  	bio = pblk_bio_map_addr(pblk, gc_rq->data, gc_rq->secs_to_gc, data_len,
>>>>  						PBLK_VMALLOC_META, GFP_KERNEL);
>>>>  	if (IS_ERR(bio)) {
>>>> diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
>>>> index aaab9a5c17cc..1574dbbfbb1c 100644
>>>> --- a/drivers/lightnvm/pblk-recovery.c
>>>> +++ b/drivers/lightnvm/pblk-recovery.c
>>>> @@ -184,7 +184,7 @@ static int pblk_calc_sec_in_line(struct pblk *pblk, struct pblk_line *line)
>>>>  	int nr_bb = bitmap_weight(line->blk_bitmap, lm->blk_per_line);
>>>>    	return lm->sec_per_line - lm->smeta_sec - lm->emeta_sec[0] -
>>>> -				nr_bb * geo->sec_per_chk;
>>>> +				nr_bb * geo->c.clba;
>>>>  }
>>>>    struct pblk_recov_alloc {
>>>> @@ -232,7 +232,7 @@ static int pblk_recov_read_oob(struct pblk *pblk, struct pblk_line *line,
>>>>  	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>>>  	if (!rq_ppas)
>>>>  		rq_ppas = pblk->min_write_pgs;
>>>> -	rq_len = rq_ppas * geo->sec_size;
>>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>>    	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>>>>  	if (IS_ERR(bio))
>>>> @@ -351,7 +351,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
>>>>  	if (!pad_rq)
>>>>  		return -ENOMEM;
>>>>  -	data = vzalloc(pblk->max_write_pgs * geo->sec_size);
>>>> +	data = vzalloc(pblk->max_write_pgs * geo->c.csecs);
>>>>  	if (!data) {
>>>>  		ret = -ENOMEM;
>>>>  		goto free_rq;
>>>> @@ -368,7 +368,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
>>>>  		goto fail_free_pad;
>>>>  	}
>>>>  -	rq_len = rq_ppas * geo->sec_size;
>>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>>    	meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, &dma_meta_list);
>>>>  	if (!meta_list) {
>>>> @@ -509,7 +509,7 @@ static int pblk_recov_scan_all_oob(struct pblk *pblk, struct pblk_line *line,
>>>>  	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>>>  	if (!rq_ppas)
>>>>  		rq_ppas = pblk->min_write_pgs;
>>>> -	rq_len = rq_ppas * geo->sec_size;
>>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>>    	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>>>>  	if (IS_ERR(bio))
>>>> @@ -640,7 +640,7 @@ static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line,
>>>>  	rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
>>>>  	if (!rq_ppas)
>>>>  		rq_ppas = pblk->min_write_pgs;
>>>> -	rq_len = rq_ppas * geo->sec_size;
>>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>>    	bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL);
>>>>  	if (IS_ERR(bio))
>>>> @@ -745,7 +745,7 @@ static int pblk_recov_l2p_from_oob(struct pblk *pblk, struct pblk_line *line)
>>>>  	ppa_list = (void *)(meta_list) + pblk_dma_meta_size;
>>>>  	dma_ppa_list = dma_meta_list + pblk_dma_meta_size;
>>>>  -	data = kcalloc(pblk->max_write_pgs, geo->sec_size, GFP_KERNEL);
>>>> +	data = kcalloc(pblk->max_write_pgs, geo->c.csecs, GFP_KERNEL);
>>>>  	if (!data) {
>>>>  		ret = -ENOMEM;
>>>>  		goto free_meta_list;
>>>> diff --git a/drivers/lightnvm/pblk-rl.c b/drivers/lightnvm/pblk-rl.c
>>>> index 0d457b162f23..bcab203477ec 100644
>>>> --- a/drivers/lightnvm/pblk-rl.c
>>>> +++ b/drivers/lightnvm/pblk-rl.c
>>>> @@ -200,7 +200,7 @@ void pblk_rl_init(struct pblk_rl *rl, int budget)
>>>>    	/* Consider sectors used for metadata */
>>>>  	sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
>>>> -	blk_meta = DIV_ROUND_UP(sec_meta, geo->sec_per_chk);
>>>> +	blk_meta = DIV_ROUND_UP(sec_meta, geo->c.clba);
>>>>    	rl->high = pblk->op_blks - blk_meta - lm->blk_per_line;
>>>>  	rl->high_pw = get_count_order(rl->high);
>>>> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
>>>> index d93e9b1f083a..5eb21a279361 100644
>>>> --- a/drivers/lightnvm/pblk-sysfs.c
>>>> +++ b/drivers/lightnvm/pblk-sysfs.c
>>>> @@ -113,26 +113,31 @@ 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;
>>>>  -	sz = snprintf(page, PAGE_SIZE - sz,
>>>> -		"g:(b:%d)blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
>>>> -		pblk->ppaf_bitsize,
>>>> -		pblk->ppaf.blk_offset, geo->ppaf.blk_len,
>>>> -		pblk->ppaf.pg_offset, geo->ppaf.pg_len,
>>>> -		pblk->ppaf.lun_offset, geo->ppaf.lun_len,
>>>> -		pblk->ppaf.ch_offset, geo->ppaf.ch_len,
>>>> -		pblk->ppaf.pln_offset, geo->ppaf.pln_len,
>>>> -		pblk->ppaf.sec_offset, geo->ppaf.sect_len);
>>>> +	ppaf = (struct nvm_addr_format_12 *)&pblk->ppaf;
>>>> +	geo_ppaf = (struct nvm_addr_format_12 *)&geo->c.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",
>>>> +			pblk->ppaf_bitsize,
>>>> +			ppaf->ch_offset, ppaf->ch_len,
>>>> +			ppaf->lun_offset, ppaf->lun_len,
>>>> +			ppaf->blk_offset, ppaf->blk_len,
>>>> +			ppaf->pg_offset, ppaf->pg_len,
>>>> +			ppaf->pln_offset, ppaf->pln_len,
>>>> +			ppaf->sect_offset, ppaf->sect_len);
>>>>    	sz += snprintf(page + sz, PAGE_SIZE - sz,
>>>> -		"d:blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
>>>> -		geo->ppaf.blk_offset, geo->ppaf.blk_len,
>>>> -		geo->ppaf.pg_offset, geo->ppaf.pg_len,
>>>> -		geo->ppaf.lun_offset, geo->ppaf.lun_len,
>>>> -		geo->ppaf.ch_offset, geo->ppaf.ch_len,
>>>> -		geo->ppaf.pln_offset, geo->ppaf.pln_len,
>>>> -		geo->ppaf.sect_offset, geo->ppaf.sect_len);
>>>> +		"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->sect_offset, geo_ppaf->sect_len);
>>>>    	return sz;
>>>>  }
>>>> @@ -288,7 +293,7 @@ static ssize_t pblk_sysfs_lines_info(struct pblk *pblk, char *page)
>>>>  				"blk_line:%d, sec_line:%d, sec_blk:%d\n",
>>>>  					lm->blk_per_line,
>>>>  					lm->sec_per_line,
>>>> -					geo->sec_per_chk);
>>>> +					geo->c.clba);
>>>>    	return sz;
>>>>  }
>>>> diff --git a/drivers/lightnvm/pblk-write.c b/drivers/lightnvm/pblk-write.c
>>>> index aae86ed60b98..c49b27539d5a 100644
>>>> --- a/drivers/lightnvm/pblk-write.c
>>>> +++ b/drivers/lightnvm/pblk-write.c
>>>> @@ -333,7 +333,7 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line)
>>>>  	m_ctx = nvm_rq_to_pdu(rqd);
>>>>  	m_ctx->private = meta_line;
>>>>  -	rq_len = rq_ppas * geo->sec_size;
>>>> +	rq_len = rq_ppas * geo->c.csecs;
>>>>  	data = ((void *)emeta->buf) + emeta->mem;
>>>>    	bio = pblk_bio_map_addr(pblk, data, rq_ppas, rq_len,
>>>> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
>>>> index 282dfc8780e8..67ffb53608f7 100644
>>>> --- a/drivers/lightnvm/pblk.h
>>>> +++ b/drivers/lightnvm/pblk.h
>>>> @@ -551,21 +551,6 @@ struct pblk_line_meta {
>>>>  	unsigned int meta_distance;	/* Distance between data and metadata */
>>>>  };
>>>>  -struct pblk_addr_format {
>>>> -	u64	ch_mask;
>>>> -	u64	lun_mask;
>>>> -	u64	pln_mask;
>>>> -	u64	blk_mask;
>>>> -	u64	pg_mask;
>>>> -	u64	sec_mask;
>>>> -	u8	ch_offset;
>>>> -	u8	lun_offset;
>>>> -	u8	pln_offset;
>>>> -	u8	blk_offset;
>>>> -	u8	pg_offset;
>>>> -	u8	sec_offset;
>>>> -};
>>>> -
>>>>  enum {
>>>>  	PBLK_STATE_RUNNING = 0,
>>>>  	PBLK_STATE_STOPPING = 1,
>>>> @@ -585,8 +570,8 @@ struct pblk {
>>>>  	struct pblk_line_mgmt l_mg;		/* Line management */
>>>>  	struct pblk_line_meta lm;		/* Line metadata */
>>>>  +	struct nvm_addr_format ppaf;
>>>>  	int ppaf_bitsize;
>>>> -	struct pblk_addr_format ppaf;
>>>>    	struct pblk_rb rwb;
>>>>  @@ -941,14 +926,12 @@ static inline int pblk_line_vsc(struct pblk_line *line)
>>>>  	return le32_to_cpu(*line->vsc);
>>>>  }
>>>>  -#define NVM_MEM_PAGE_WRITE (8)
>>>> -
>>>>  static inline int pblk_pad_distance(struct pblk *pblk)
>>>>  {
>>>>  	struct nvm_tgt_dev *dev = pblk->dev;
>>>>  	struct nvm_geo *geo = &dev->geo;
>>>>  -	return NVM_MEM_PAGE_WRITE * geo->all_luns * geo->sec_per_pl;
>>>> +	return geo->c.mw_cunits * geo->all_luns * geo->c.ws_opt;
>>>>  }
>>>>    static inline int pblk_ppa_to_line(struct ppa_addr p)
>>>> @@ -964,15 +947,17 @@ 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->ppaf;
>>>>  	struct ppa_addr ppa;
>>>>    	ppa.ppa = 0;
>>>>  	ppa.g.blk = line_id;
>>>> -	ppa.g.pg = (paddr & pblk->ppaf.pg_mask) >> pblk->ppaf.pg_offset;
>>>> -	ppa.g.lun = (paddr & pblk->ppaf.lun_mask) >> pblk->ppaf.lun_offset;
>>>> -	ppa.g.ch = (paddr & pblk->ppaf.ch_mask) >> pblk->ppaf.ch_offset;
>>>> -	ppa.g.pl = (paddr & pblk->ppaf.pln_mask) >> pblk->ppaf.pln_offset;
>>>> -	ppa.g.sec = (paddr & pblk->ppaf.sec_mask) >> pblk->ppaf.sec_offset;
>>>> +	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->sect_offset;
>>>>    	return ppa;
>>>>  }
>>>> @@ -980,13 +965,15 @@ 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->ppaf;
>>>>  	u64 paddr;
>>>>  -	paddr = (u64)p.g.pg << pblk->ppaf.pg_offset;
>>>> -	paddr |= (u64)p.g.lun << pblk->ppaf.lun_offset;
>>>> -	paddr |= (u64)p.g.ch << pblk->ppaf.ch_offset;
>>>> -	paddr |= (u64)p.g.pl << pblk->ppaf.pln_offset;
>>>> -	paddr |= (u64)p.g.sec << pblk->ppaf.sec_offset;
>>>> +	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->sect_offset;
>>>>    	return paddr;
>>>>  }
>>>> @@ -1003,18 +990,15 @@ 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 {
>>>> -		ppa64.g.blk = (ppa32 & pblk->ppaf.blk_mask) >>
>>>> -							pblk->ppaf.blk_offset;
>>>> -		ppa64.g.pg = (ppa32 & pblk->ppaf.pg_mask) >>
>>>> -							pblk->ppaf.pg_offset;
>>>> -		ppa64.g.lun = (ppa32 & pblk->ppaf.lun_mask) >>
>>>> -							pblk->ppaf.lun_offset;
>>>> -		ppa64.g.ch = (ppa32 & pblk->ppaf.ch_mask) >>
>>>> -							pblk->ppaf.ch_offset;
>>>> -		ppa64.g.pl = (ppa32 & pblk->ppaf.pln_mask) >>
>>>> -							pblk->ppaf.pln_offset;
>>>> -		ppa64.g.sec = (ppa32 & pblk->ppaf.sec_mask) >>
>>>> -							pblk->ppaf.sec_offset;
>>>> +		struct nvm_addr_format_12 *ppaf =
>>>> +				(struct nvm_addr_format_12 *)&pblk->ppaf;
>>>> +
>>>> +		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->sect_offset;
>>>>  	}
>>>>    	return ppa64;
>>>> @@ -1030,12 +1014,15 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
>>>>  		ppa32 |= ppa64.c.line;
>>>>  		ppa32 |= 1U << 31;
>>>>  	} else {
>>>> -		ppa32 |= ppa64.g.blk << pblk->ppaf.blk_offset;
>>>> -		ppa32 |= ppa64.g.pg << pblk->ppaf.pg_offset;
>>>> -		ppa32 |= ppa64.g.lun << pblk->ppaf.lun_offset;
>>>> -		ppa32 |= ppa64.g.ch << pblk->ppaf.ch_offset;
>>>> -		ppa32 |= ppa64.g.pl << pblk->ppaf.pln_offset;
>>>> -		ppa32 |= ppa64.g.sec << pblk->ppaf.sec_offset;
>>>> +		struct nvm_addr_format_12 *ppaf =
>>>> +				(struct nvm_addr_format_12 *)&pblk->ppaf;
>>>> +
>>>> +		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->sect_offset;
>>>>  	}
>>>>    	return ppa32;
>>>> @@ -1153,7 +1140,7 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type)
>>>>  	struct nvm_geo *geo = &dev->geo;
>>>>  	int flags;
>>>>  -	flags = geo->plane_mode >> 1;
>>>> +	flags = geo->c.pln_mode >> 1;
>>>>    	if (type == PBLK_WRITE)
>>>>  		flags |= NVM_IO_SCRAMBLE_ENABLE;
>>>> @@ -1174,7 +1161,7 @@ static inline int pblk_set_read_mode(struct pblk *pblk, int type)
>>>>    	flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
>>>>  	if (type == PBLK_READ_SEQUENTIAL)
>>>> -		flags |= geo->plane_mode >> 1;
>>>> +		flags |= geo->c.pln_mode >> 1;
>>>>    	return flags;
>>>>  }
>>>> @@ -1229,10 +1216,10 @@ static inline int pblk_boundary_ppa_checks(struct nvm_tgt_dev *tgt_dev,
>>>>  		if (!ppa->c.is_cached &&
>>>>  				ppa->g.ch < geo->nr_chnls &&
>>>>  				ppa->g.lun < geo->nr_luns &&
>>>> -				ppa->g.pl < geo->nr_planes &&
>>>> -				ppa->g.blk < geo->nr_chks &&
>>>> -				ppa->g.pg < geo->ws_per_chk &&
>>>> -				ppa->g.sec < geo->sec_per_pg)
>>>> +				ppa->g.pl < geo->c.num_pln &&
>>>> +				ppa->g.blk < geo->c.num_chk &&
>>>> +				ppa->g.pg < geo->c.num_pg &&
>>>> +				ppa->g.sec < geo->c.ws_min)
>>>>  			continue;
>>>>    		print_ppa(ppa, "boundary", i);
>>>> diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
>>>> index 839c0b96466a..c81e64cc20d7 100644
>>>> --- a/drivers/nvme/host/lightnvm.c
>>>> +++ b/drivers/nvme/host/lightnvm.c
>>>> @@ -152,8 +152,8 @@ struct nvme_nvm_id12_addrf {
>>>>  	__u8			blk_len;
>>>>  	__u8			pg_offset;
>>>>  	__u8			pg_len;
>>>> -	__u8			sect_offset;
>>>> -	__u8			sect_len;
>>>> +	__u8			sec_offset;
>>>> +	__u8			sec_len;
>>>>  	__u8			res[4];
>>>>  } __packed;
>>>>  @@ -254,106 +254,157 @@ static inline void _nvme_nvm_check_size(void)
>>>>  	BUILD_BUG_ON(sizeof(struct nvme_nvm_id20) != NVME_IDENTIFY_DATA_SIZE);
>>>>  }
>>>>  -static int init_grp(struct nvm_id *nvm_id, struct nvme_nvm_id12 *id12)
>>>> +static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
>>>> +				 struct nvme_nvm_id12_addrf *src)
>>>> +{
>>>> +	dst->ch_len = src->ch_len;
>>>> +	dst->lun_len = src->lun_len;
>>>> +	dst->blk_len = src->blk_len;
>>>> +	dst->pg_len = src->pg_len;
>>>> +	dst->pln_len = src->pln_len;
>>>> +	dst->sect_len = src->sec_len;
>>>> +
>>>> +	dst->ch_offset = src->ch_offset;
>>>> +	dst->lun_offset = src->lun_offset;
>>>> +	dst->blk_offset = src->blk_offset;
>>>> +	dst->pg_offset = src->pg_offset;
>>>> +	dst->pln_offset = src->pln_offset;
>>>> +	dst->sect_offset = src->sec_offset;
>>>> +
>>>> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>>>> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>>>> +	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
>>>> +	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
>>>> +	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
>>>> +	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
>>>> +}
>>>> +
>>>> +static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
>>>> +			     struct nvm_dev_geo *dev_geo)
>>>>  {
>>>>  	struct nvme_nvm_id12_grp *src;
>>>>  	int sec_per_pg, sec_per_pl, pg_per_blk;
>>>>  -	if (id12->cgrps != 1)
>>>> +	if (id->cgrps != 1)
>>>>  		return -EINVAL;
>>>>  -	src = &id12->grp;
>>>> +	src = &id->grp;
>>>>  -	nvm_id->mtype = src->mtype;
>>>> -	nvm_id->fmtype = src->fmtype;
>>>> +	if (src->mtype != 0) {
>>>> +		pr_err("nvm: memory type not supported\n");
>>>> +		return -EINVAL;
>>>> +	}
>>>> +
>>>> +	/* 1.2 spec. only reports a single version id - unfold */
>>>> +	dev_geo->ver_id = id->ver_id;
>>>>  -	nvm_id->num_ch = src->num_ch;
>>>> -	nvm_id->num_lun = src->num_lun;
>>>> +	dev_geo->nr_chnls = src->num_ch;
>>>> +	dev_geo->nr_luns = src->num_lun;
>>>> +	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
>>>>  -	nvm_id->num_chk = le16_to_cpu(src->num_chk);
>>>> -	nvm_id->csecs = le16_to_cpu(src->csecs);
>>>> -	nvm_id->sos = le16_to_cpu(src->sos);
>>>> +	dev_geo->c.num_chk = le16_to_cpu(src->num_chk);
>>>> +	dev_geo->c.csecs = le16_to_cpu(src->csecs);
>>>> +	dev_geo->c.sos = le16_to_cpu(src->sos);
>>>>    	pg_per_blk = le16_to_cpu(src->num_pg);
>>>> -	sec_per_pg = le16_to_cpu(src->fpg_sz) / nvm_id->csecs;
>>>> +	sec_per_pg = le16_to_cpu(src->fpg_sz) / dev_geo->c.csecs;
>>>>  	sec_per_pl = sec_per_pg * src->num_pln;
>>>> -	nvm_id->clba = sec_per_pl * pg_per_blk;
>>>> -	nvm_id->ws_per_chk = pg_per_blk;
>>>> -
>>>> -	nvm_id->mpos = le32_to_cpu(src->mpos);
>>>> -	nvm_id->cpar = le16_to_cpu(src->cpar);
>>>> -	nvm_id->mccap = le32_to_cpu(src->mccap);
>>>> -
>>>> -	nvm_id->ws_opt = nvm_id->ws_min = sec_per_pg;
>>>> -	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
>>>> -
>>>> -	if (nvm_id->mpos & 0x020202) {
>>>> -		nvm_id->ws_seq = NVM_IO_DUAL_ACCESS;
>>>> -		nvm_id->ws_opt <<= 1;
>>>> -	} else if (nvm_id->mpos & 0x040404) {
>>>> -		nvm_id->ws_seq = NVM_IO_QUAD_ACCESS;
>>>> -		nvm_id->ws_opt <<= 2;
>>>> +	dev_geo->c.clba = sec_per_pl * pg_per_blk;
>>>> +
>>>> +	dev_geo->c.ws_min = sec_per_pg;
>>>> +	dev_geo->c.ws_opt = sec_per_pg;
>>>> +	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
>>>> +
>>>> +	dev_geo->c.mccap = le32_to_cpu(src->mccap);
>>>> +
>>>> +	dev_geo->c.trdt = le32_to_cpu(src->trdt);
>>>> +	dev_geo->c.trdm = le32_to_cpu(src->trdm);
>>>> +	dev_geo->c.tprt = le32_to_cpu(src->tprt);
>>>> +	dev_geo->c.tprm = le32_to_cpu(src->tprm);
>>>> +	dev_geo->c.tbet = le32_to_cpu(src->tbet);
>>>> +	dev_geo->c.tbem = le32_to_cpu(src->tbem);
>>>> +
>>>> +	/* 1.2 compatibility */
>>>> +	dev_geo->c.vmnt = id->vmnt;
>>>> +	dev_geo->c.cap = le32_to_cpu(id->cap);
>>>> +	dev_geo->c.dom = le32_to_cpu(id->dom);
>>>> +
>>>> +	dev_geo->c.mtype = src->mtype;
>>>> +	dev_geo->c.fmtype = src->fmtype;
>>>> +
>>>> +	dev_geo->c.cpar = le16_to_cpu(src->cpar);
>>>> +	dev_geo->c.mpos = le32_to_cpu(src->mpos);
>>>> +
>>>> +	dev_geo->c.pln_mode = NVM_PLANE_SINGLE;
>>>> +
>>>> +	if (dev_geo->c.mpos & 0x020202) {
>>>> +		dev_geo->c.pln_mode = NVM_PLANE_DOUBLE;
>>>> +		dev_geo->c.ws_opt <<= 1;
>>>> +	} else if (dev_geo->c.mpos & 0x040404) {
>>>> +		dev_geo->c.pln_mode = NVM_PLANE_QUAD;
>>>> +		dev_geo->c.ws_opt <<= 2;
>>>>  	}
>>>>  -	nvm_id->trdt = le32_to_cpu(src->trdt);
>>>> -	nvm_id->trdm = le32_to_cpu(src->trdm);
>>>> -	nvm_id->tprt = le32_to_cpu(src->tprt);
>>>> -	nvm_id->tprm = le32_to_cpu(src->tprm);
>>>> -	nvm_id->tbet = le32_to_cpu(src->tbet);
>>>> -	nvm_id->tbem = le32_to_cpu(src->tbem);
>>>> -
>>>> -	/* 1.2 compatibility */
>>>> -	nvm_id->num_pln = src->num_pln;
>>>> -	nvm_id->num_pg = le16_to_cpu(src->num_pg);
>>>> -	nvm_id->fpg_sz = le16_to_cpu(src->fpg_sz);
>>>> +	dev_geo->c.num_pln = src->num_pln;
>>>> +	dev_geo->c.num_pg = le16_to_cpu(src->num_pg);
>>>> +	dev_geo->c.fpg_sz = le16_to_cpu(src->fpg_sz);
>>>> +
>>>> +	nvme_nvm_set_addr_12((struct nvm_addr_format_12 *)&dev_geo->c.addrf,
>>>> +								&id->ppaf);
>>>>    	return 0;
>>>>  }
>>>>  -static int nvme_nvm_setup_12(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
>>>> -		struct nvme_nvm_id12 *id)
>>>> +static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
>>>> +				 struct nvme_nvm_id20_addrf *src)
>>>>  {
>>>> -	nvm_id->ver_id = id->ver_id;
>>>> -	nvm_id->vmnt = id->vmnt;
>>>> -	nvm_id->cap = le32_to_cpu(id->cap);
>>>> -	nvm_id->dom = le32_to_cpu(id->dom);
>>>> -	memcpy(&nvm_id->ppaf, &id->ppaf,
>>>> -					sizeof(struct nvm_addr_format));
>>>> -
>>>> -	return init_grp(nvm_id, id);
>>>> +	dst->ch_len = src->grp_len;
>>>> +	dst->lun_len = src->pu_len;
>>>> +	dst->chk_len = src->chk_len;
>>>> +	dst->sec_len = src->lba_len;
>>>> +
>>>> +	dst->sec_offset = 0;
>>>> +	dst->chk_offset = dst->sec_len;
>>>> +	dst->lun_offset = dst->chk_offset + dst->chk_len;
>>>> +	dst->ch_offset = dst->lun_offset + dst->lun_len;
>>>> +
>>>> +	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
>>>> +	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
>>>> +	dst->chk_mask = ((1ULL << dst->chk_len) - 1) << dst->chk_offset;
>>>> +	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
>>>>  }
>>>>  -static int nvme_nvm_setup_20(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
>>>> -		struct nvme_nvm_id20 *id)
>>>> +static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
>>>> +			     struct nvm_dev_geo *dev_geo)
>>>>  {
>>>> -	nvm_id->ver_id = id->mjr;
>>>> +	dev_geo->ver_id = id->mjr;
>>>>  -	nvm_id->num_ch = le16_to_cpu(id->num_grp);
>>>> -	nvm_id->num_lun = le16_to_cpu(id->num_pu);
>>>> -	nvm_id->num_chk = le32_to_cpu(id->num_chk);
>>>> -	nvm_id->clba = le32_to_cpu(id->clba);
>>>> +	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
>>>> +	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
>>>> +	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
>>>>  -	nvm_id->ws_min = le32_to_cpu(id->ws_min);
>>>> -	nvm_id->ws_opt = le32_to_cpu(id->ws_opt);
>>>> -	nvm_id->mw_cunits = le32_to_cpu(id->mw_cunits);
>>>> +	dev_geo->c.num_chk = le32_to_cpu(id->num_chk);
>>>> +	dev_geo->c.clba = le32_to_cpu(id->clba);
>>>> +	dev_geo->c.csecs = -1;		/* Set by nvme identify */
>>>> +	dev_geo->c.sos = -1;		/* Set bu nvme identify */
>>>>  -	nvm_id->trdt = le32_to_cpu(id->trdt);
>>>> -	nvm_id->trdm = le32_to_cpu(id->trdm);
>>>> -	nvm_id->tprt = le32_to_cpu(id->twrt);
>>>> -	nvm_id->tprm = le32_to_cpu(id->twrm);
>>>> -	nvm_id->tbet = le32_to_cpu(id->tcrst);
>>>> -	nvm_id->tbem = le32_to_cpu(id->tcrsm);
>>>> +	dev_geo->c.ws_min = le32_to_cpu(id->ws_min);
>>>> +	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
>>>> +	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
>>>>  -	/* calculated values */
>>>> -	nvm_id->ws_per_chk = nvm_id->clba / nvm_id->ws_min;
>>>> +	dev_geo->c.trdt = le32_to_cpu(id->trdt);
>>>> +	dev_geo->c.trdm = le32_to_cpu(id->trdm);
>>>> +	dev_geo->c.tprt = le32_to_cpu(id->twrt);
>>>> +	dev_geo->c.tprm = le32_to_cpu(id->twrm);
>>>> +	dev_geo->c.tbet = le32_to_cpu(id->tcrst);
>>>> +	dev_geo->c.tbem = le32_to_cpu(id->tcrsm);
>>>>  -	/* 1.2 compatibility */
>>>> -	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
>>>> +	nvme_nvm_set_addr_20(&dev_geo->c.addrf, &id->lbaf);
>>>>    	return 0;
>>>>  }
>>>>  -static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
>>>> +static int nvme_nvm_identity(struct nvm_dev *nvmdev)
>>>>  {
>>>>  	struct nvme_ns *ns = nvmdev->q->queuedata;
>>>>  	struct nvme_nvm_id12 *id;
>>>> @@ -380,18 +431,18 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
>>>>  	 */
>>>>  	switch (id->ver_id) {
>>>>  	case 1:
>>>> -		ret = nvme_nvm_setup_12(nvmdev, nvm_id, id);
>>>> +		ret = nvme_nvm_setup_12(id, &nvmdev->dev_geo);
>>>>  		break;
>>>>  	case 2:
>>>> -		ret = nvme_nvm_setup_20(nvmdev, nvm_id,
>>>> -				(struct nvme_nvm_id20 *)id);
>>>> +		ret = nvme_nvm_setup_20((struct nvme_nvm_id20 *)id,
>>>> +							&nvmdev->dev_geo);
>>>>  		break;
>>>>  	default:
>>>> -		dev_err(ns->ctrl->device,
>>>> -			"OCSSD revision not supported (%d)\n",
>>>> -			nvm_id->ver_id);
>>>> +		dev_err(ns->ctrl->device, "OCSSD revision not supported (%d)\n",
>>>> +							id->ver_id);
>>>>  		ret = -EINVAL;
>>>>  	}
>>>> +
>>>>  out:
>>>>  	kfree(id);
>>>>  	return ret;
>>>> @@ -401,12 +452,12 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
>>>>  								u8 *blks)
>>>>  {
>>>>  	struct request_queue *q = nvmdev->q;
>>>> -	struct nvm_geo *geo = &nvmdev->geo;
>>>> +	struct nvm_dev_geo *dev_geo = &nvmdev->dev_geo;
>>>>  	struct nvme_ns *ns = q->queuedata;
>>>>  	struct nvme_ctrl *ctrl = ns->ctrl;
>>>>  	struct nvme_nvm_command c = {};
>>>>  	struct nvme_nvm_bb_tbl *bb_tbl;
>>>> -	int nr_blks = geo->nr_chks * geo->plane_mode;
>>>> +	int nr_blks = dev_geo->c.num_chk * dev_geo->c.num_pln;
>>>>  	int tblsz = sizeof(struct nvme_nvm_bb_tbl) + nr_blks;
>>>>  	int ret = 0;
>>>>  @@ -447,7 +498,7 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
>>>>  		goto out;
>>>>  	}
>>>>  -	memcpy(blks, bb_tbl->blk, geo->nr_chks * geo->plane_mode);
>>>> +	memcpy(blks, bb_tbl->blk, dev_geo->c.num_chk * dev_geo->c.num_pln);
>>>>  out:
>>>>  	kfree(bb_tbl);
>>>>  	return ret;
>>>> @@ -815,9 +866,10 @@ int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd, unsigned long arg)
>>>>  void nvme_nvm_update_nvm_info(struct nvme_ns *ns)
>>>>  {
>>>>  	struct nvm_dev *ndev = ns->ndev;
>>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>>  -	ndev->identity.csecs = ndev->geo.sec_size = 1 << ns->lba_shift;
>>>> -	ndev->identity.sos = ndev->geo.oob_size = ns->ms;
>>>> +	dev_geo->c.csecs = 1 << ns->lba_shift;
>>>> +	dev_geo->c.sos = ns->ms;
>>>>  }
>>>>    int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node)
>>>> @@ -850,23 +902,22 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>>>  {
>>>>  	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>>>>  	struct nvm_dev *ndev = ns->ndev;
>>>> -	struct nvm_id *id;
>>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>>  	struct attribute *attr;
>>>>    	if (!ndev)
>>>>  		return 0;
>>>>  -	id = &ndev->identity;
>>>>  	attr = &dattr->attr;
>>>>    	if (strcmp(attr->name, "version") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ver_id);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->ver_id);
>>>>  	} else if (strcmp(attr->name, "capabilities") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->cap);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
>>>>  	} else if (strcmp(attr->name, "read_typ") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdt);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdt);
>>>>  	} else if (strcmp(attr->name, "read_max") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdm);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.trdm);
>>>>  	} else {
>>>>  		return scnprintf(page,
>>>>  				 PAGE_SIZE,
>>>> @@ -875,75 +926,79 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
>>>>  	}
>>>>  }
>>>>  +static ssize_t nvm_dev_attr_show_ppaf(struct nvm_addr_format_12 *ppaf,
>>>> +					 char *page)
>>>> +{
>>>> +	return scnprintf(page, PAGE_SIZE,
>>>> +		"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
>>>> +				ppaf->ch_offset, ppaf->ch_len,
>>>> +				ppaf->lun_offset, ppaf->lun_len,
>>>> +				ppaf->pln_offset, ppaf->pln_len,
>>>> +				ppaf->blk_offset, ppaf->blk_len,
>>>> +				ppaf->pg_offset, ppaf->pg_len,
>>>> +				ppaf->sect_offset, ppaf->sect_len);
>>>> +}
>>>> +
>>>>  static ssize_t nvm_dev_attr_show_12(struct device *dev,
>>>>  		struct device_attribute *dattr, char *page)
>>>>  {
>>>>  	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>>>>  	struct nvm_dev *ndev = ns->ndev;
>>>> -	struct nvm_id *id;
>>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>>  	struct attribute *attr;
>>>>    	if (!ndev)
>>>>  		return 0;
>>>>  -	id = &ndev->identity;
>>>>  	attr = &dattr->attr;
>>>>    	if (strcmp(attr->name, "vendor_opcode") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->vmnt);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.vmnt);
>>>>  	} else if (strcmp(attr->name, "device_mode") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->dom);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.dom);
>>>>  	/* kept for compatibility */
>>>>  	} else if (strcmp(attr->name, "media_manager") == 0) {
>>>>  		return scnprintf(page, PAGE_SIZE, "%s\n", "gennvm");
>>>>  	} else if (strcmp(attr->name, "ppa_format") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE,
>>>> -			"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
>>>> -			id->ppaf.ch_offset, id->ppaf.ch_len,
>>>> -			id->ppaf.lun_offset, id->ppaf.lun_len,
>>>> -			id->ppaf.pln_offset, id->ppaf.pln_len,
>>>> -			id->ppaf.blk_offset, id->ppaf.blk_len,
>>>> -			id->ppaf.pg_offset, id->ppaf.pg_len,
>>>> -			id->ppaf.sect_offset, id->ppaf.sect_len);
>>>> +		return nvm_dev_attr_show_ppaf((void *)&dev_geo->c.addrf, page);
>>>>  	} else if (strcmp(attr->name, "media_type") == 0) {	/* u8 */
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->mtype);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mtype);
>>>>  	} else if (strcmp(attr->name, "flash_media_type") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->fmtype);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fmtype);
>>>>  	} else if (strcmp(attr->name, "num_channels") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
>>>>  	} else if (strcmp(attr->name, "num_luns") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
>>>>  	} else if (strcmp(attr->name, "num_planes") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pln);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pln);
>>>>  	} else if (strcmp(attr->name, "num_blocks") == 0) {	/* u16 */
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
>>>>  	} else if (strcmp(attr->name, "num_pages") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pg);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_pg);
>>>>  	} else if (strcmp(attr->name, "page_size") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->fpg_sz);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.fpg_sz);
>>>>  	} else if (strcmp(attr->name, "hw_sector_size") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->csecs);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.csecs);
>>>>  	} else if (strcmp(attr->name, "oob_sector_size") == 0) {/* u32 */
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->sos);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.sos);
>>>>  	} else if (strcmp(attr->name, "prog_typ") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
>>>>  	} else if (strcmp(attr->name, "prog_max") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
>>>>  	} else if (strcmp(attr->name, "erase_typ") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
>>>>  	} else if (strcmp(attr->name, "erase_max") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>>>  	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mpos);
>>>> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mpos);
>>>>  	} else if (strcmp(attr->name, "media_capabilities") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mccap);
>>>> +		return scnprintf(page, PAGE_SIZE, "0x%08x\n", dev_geo->c.mccap);
>>>>  	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
>>>>  		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
>>>>  	} else {
>>>> -		return scnprintf(page,
>>>> -				 PAGE_SIZE,
>>>> -				 "Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
>>>> -				 attr->name);
>>>> +		return scnprintf(page, PAGE_SIZE,
>>>> +			"Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
>>>> +			attr->name);
>>>>  	}
>>>>  }
>>>>  @@ -952,42 +1007,40 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
>>>>  {
>>>>  	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>>>>  	struct nvm_dev *ndev = ns->ndev;
>>>> -	struct nvm_id *id;
>>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>>  	struct attribute *attr;
>>>>    	if (!ndev)
>>>>  		return 0;
>>>>  -	id = &ndev->identity;
>>>>  	attr = &dattr->attr;
>>>>    	if (strcmp(attr->name, "groups") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_chnls);
>>>>  	} else if (strcmp(attr->name, "punits") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->nr_luns);
>>>>  	} else if (strcmp(attr->name, "chunks") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.num_chk);
>>>>  	} else if (strcmp(attr->name, "clba") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->clba);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.clba);
>>>>  	} else if (strcmp(attr->name, "ws_min") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_min);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_min);
>>>>  	} else if (strcmp(attr->name, "ws_opt") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_opt);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_opt);
>>>>  	} else if (strcmp(attr->name, "mw_cunits") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->mw_cunits);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mw_cunits);
>>>>  	} else if (strcmp(attr->name, "write_typ") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprt);
>>>>  	} else if (strcmp(attr->name, "write_max") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tprm);
>>>>  	} else if (strcmp(attr->name, "reset_typ") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbet);
>>>>  	} else if (strcmp(attr->name, "reset_max") == 0) {
>>>> -		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
>>>> +		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.tbem);
>>>>  	} else {
>>>> -		return scnprintf(page,
>>>> -				 PAGE_SIZE,
>>>> -				 "Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
>>>> -				 attr->name);
>>>> +		return scnprintf(page, PAGE_SIZE,
>>>> +			"Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
>>>> +			attr->name);
>>>>  	}
>>>>  }
>>>>  @@ -1106,10 +1159,13 @@ static const struct attribute_group nvm_dev_attr_group_20 = {
>>>>    int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>>>>  {
>>>> -	if (!ns->ndev)
>>>> +	struct nvm_dev *ndev = ns->ndev;
>>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>> +
>>>> +	if (!ndev)
>>>>  		return -EINVAL;
>>>>  -	switch (ns->ndev->identity.ver_id) {
>>>> +	switch (dev_geo->ver_id) {
>>>>  	case 1:
>>>>  		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
>>>>  					&nvm_dev_attr_group_12);
>>>> @@ -1123,7 +1179,10 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
>>>>    void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
>>>>  {
>>>> -	switch (ns->ndev->identity.ver_id) {
>>>> +	struct nvm_dev *ndev = ns->ndev;
>>>> +	struct nvm_dev_geo *dev_geo = &ndev->dev_geo;
>>>> +
>>>> +	switch (dev_geo->ver_id) {
>>>>  	case 1:
>>>>  		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
>>>>  					&nvm_dev_attr_group_12);
>>>> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
>>>> index e55b10573c99..18e3751b1632 100644
>>>> --- a/include/linux/lightnvm.h
>>>> +++ b/include/linux/lightnvm.h
>>>> @@ -50,7 +50,7 @@ struct nvm_id;
>>>>  struct nvm_dev;
>>>>  struct nvm_tgt_dev;
>>>>  -typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *);
>>>> +typedef int (nvm_id_fn)(struct nvm_dev *);
>>>>  typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, u8 *);
>>>>  typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct ppa_addr *, int, int);
>>>>  typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
>>>> @@ -152,62 +152,107 @@ struct nvm_id_lp_tbl {
>>>>  	struct nvm_id_lp_mlc mlc;
>>>>  };
>>>>  -struct nvm_addr_format {
>>>> -	u8	ch_offset;
>>>> +struct nvm_addr_format_12 {
>>>>  	u8	ch_len;
>>>> -	u8	lun_offset;
>>>>  	u8	lun_len;
>>>> -	u8	pln_offset;
>>>> +	u8	blk_len;
>>>> +	u8	pg_len;
>>>>  	u8	pln_len;
>>>> +	u8	sect_len;
>>>> +
>>>> +	u8	ch_offset;
>>>> +	u8	lun_offset;
>>>>  	u8	blk_offset;
>>>> -	u8	blk_len;
>>>>  	u8	pg_offset;
>>>> -	u8	pg_len;
>>>> +	u8	pln_offset;
>>>>  	u8	sect_offset;
>>>> -	u8	sect_len;
>>>> +
>>>> +	u64	ch_mask;
>>>> +	u64	lun_mask;
>>>> +	u64	blk_mask;
>>>> +	u64	pg_mask;
>>>> +	u64	pln_mask;
>>>> +	u64	sec_mask;
>>>> +};
>>>> +
>>>> +struct nvm_addr_format {
>>>> +	u8	ch_len;
>>>> +	u8	lun_len;
>>>> +	u8	chk_len;
>>>> +	u8	sec_len;
>>>> +	u8	rsv_len[2];
>>>> +
>>>> +	u8	ch_offset;
>>>> +	u8	lun_offset;
>>>> +	u8	chk_offset;
>>>> +	u8	sec_offset;
>>>> +	u8	rsv_off[2];
>>>> +
>>>> +	u64	ch_mask;
>>>> +	u64	lun_mask;
>>>> +	u64	chk_mask;
>>>> +	u64	sec_mask;
>>>> +	u64	rsv_mask[2];
>>>>  };
>>>>  -struct nvm_id {
>>>> -	u8	ver_id;
>>>> +/* Device common geometry */
>>>> +struct nvm_common_geo {
>>>> +	/* chunk geometry */
>>>> +	u32	num_chk;	/* chunks per lun */
>>>> +	u32	clba;		/* sectors per chunk */
>>>> +	u16	csecs;		/* sector size */
>>>> +	u16	sos;		/* out-of-band area size */
>>>> +
>>>> +	/* device write constrains */
>>>> +	u32	ws_min;		/* minimum write size */
>>>> +	u32	ws_opt;		/* optimal write size */
>>>> +	u32	mw_cunits;	/* distance required for successful read */
>>>> +
>>>> +	/* device capabilities */
>>>> +	u32	mccap;
>>>> +
>>>> +	/* device timings */
>>>> +	u32	trdt;		/* Avg. Tread (ns) */
>>>> +	u32	trdm;		/* Max Tread (ns) */
>>>> +	u32	tprt;		/* Avg. Tprog (ns) */
>>>> +	u32	tprm;		/* Max Tprog (ns) */
>>>> +	u32	tbet;		/* Avg. Terase (ns) */
>>>> +	u32	tbem;		/* Max Terase (ns) */
>>>> +
>>>> +	/* generic address format */
>>>> +	struct nvm_addr_format addrf;
>>>> +
>>>> +	/* 1.2 compatibility */
>>>>  	u8	vmnt;
>>>>  	u32	cap;
>>>>  	u32	dom;
>>>>  -	struct	nvm_addr_format ppaf;
>>>> -
>>>> -	u8	num_ch;
>>>> -	u8	num_lun;
>>>> -	u16	num_chk;
>>>> -	u16	clba;
>>>> -	u16	csecs;
>>>> -	u16	sos;
>>>> -
>>>> -	u32	ws_min;
>>>> -	u32	ws_opt;
>>>> -	u32	mw_cunits;
>>>> -
>>>> -	u32	trdt;
>>>> -	u32	trdm;
>>>> -	u32	tprt;
>>>> -	u32	tprm;
>>>> -	u32	tbet;
>>>> -	u32	tbem;
>>>> -	u32	mpos;
>>>> -	u32	mccap;
>>>> -	u16	cpar;
>>>> -
>>>> -	/* calculated values */
>>>> -	u16	ws_seq;
>>>> -	u16	ws_per_chk;
>>>> -
>>>> -	/* 1.2 compatibility */
>>>>  	u8	mtype;
>>>>  	u8	fmtype;
>>>>  +	u16	cpar;
>>>> +	u32	mpos;
>>>> +
>>>>  	u8	num_pln;
>>>> +	u8	pln_mode;
>>>>  	u16	num_pg;
>>>>  	u16	fpg_sz;
>>>> -} __packed;
>>>> +};
>>>> +
>>>> +/* Device identified geometry */
>>>> +struct nvm_dev_geo {
>>>> +	/* device reported version */
>>>> +	u8	ver_id;
>>>> +
>>>> +	/* full device geometry */
>>>> +	u16	nr_chnls;
>>>> +	u16	nr_luns;
>>>> +
>>>> +	/* calculated values */
>>>> +	u16	all_luns;
>>>> +
>>>> +	struct nvm_common_geo c;
>>>> +};
>>>>    struct nvm_target {
>>>>  	struct list_head list;
>>>> @@ -274,36 +319,22 @@ enum {
>>>>  	NVM_BLK_ST_BAD =	0x8,	/* Bad block */
>>>>  };
>>>>  -
>>>> -/* Device generic information */
>>>> +/* Instance geometry */
>>>>  struct nvm_geo {
>>>> -	/* generic geometry */
>>>> +	/* instance specific geometry */
>>>>  	int nr_chnls;
>>>> -	int all_luns; /* across channels */
>>>> -	int nr_luns; /* per channel */
>>>> -	int nr_chks; /* per lun */
>>>> -
>>>> -	int sec_size;
>>>> -	int oob_size;
>>>> -	int mccap;
>>>> -
>>>> -	int sec_per_chk;
>>>> -	int sec_per_lun;
>>>> -
>>>> -	int ws_min;
>>>> -	int ws_opt;
>>>> -	int ws_seq;
>>>> -	int ws_per_chk;
>>>> +	int nr_luns;		/* per channel */
>>>>    	int op;
>>>>  -	struct nvm_addr_format ppaf;
>>>> +	/* common geometry */
>>>> +	struct nvm_common_geo c;
>>>>  -	/* Legacy 1.2 specific geometry */
>>>> -	int plane_mode; /* drive device in single, double or quad mode */
>>>> -	int nr_planes;
>>>> -	int sec_per_pg; /* only sectors for a single page */
>>>> -	int sec_per_pl; /* all sectors across planes */
>>>> +	/* calculated values */
>>>> +	int all_luns;		/* across channels */
>>>> +	int all_chunks;		/* across channels */
>>>> +
>>>> +	sector_t total_secs;	/* across channels */
>>>>  };
>>>>    /* sub-device structure */
>>>> @@ -314,9 +345,6 @@ struct nvm_tgt_dev {
>>>>  	/* Base ppas for target LUNs */
>>>>  	struct ppa_addr *luns;
>>>>  -	sector_t total_secs;
>>>> -
>>>> -	struct nvm_id identity;
>>>>  	struct request_queue *q;
>>>>    	struct nvm_dev *parent;
>>>> @@ -329,15 +357,11 @@ struct nvm_dev {
>>>>  	struct list_head devices;
>>>>    	/* Device information */
>>>> -	struct nvm_geo geo;
>>>> -
>>>> -	unsigned long total_secs;
>>>> +	struct nvm_dev_geo dev_geo;
>>>>    	unsigned long *lun_map;
>>>>  	void *dma_pool;
>>>>  -	struct nvm_id identity;
>>>> -
>>>>  	/* Backend device */
>>>>  	struct request_queue *q;
>>>>  	char name[DISK_NAME_LEN];
>>>> @@ -357,14 +381,16 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
>>>>  						  struct ppa_addr r)
>>>>  {
>>>>  	struct nvm_geo *geo = &tgt_dev->geo;
>>>> +	struct nvm_addr_format_12 *ppaf =
>>>> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>>>>  	struct ppa_addr l;
>>>>  -	l.ppa = ((u64)r.g.blk) << geo->ppaf.blk_offset;
>>>> -	l.ppa |= ((u64)r.g.pg) << geo->ppaf.pg_offset;
>>>> -	l.ppa |= ((u64)r.g.sec) << geo->ppaf.sect_offset;
>>>> -	l.ppa |= ((u64)r.g.pl) << geo->ppaf.pln_offset;
>>>> -	l.ppa |= ((u64)r.g.lun) << geo->ppaf.lun_offset;
>>>> -	l.ppa |= ((u64)r.g.ch) << geo->ppaf.ch_offset;
>>>> +	l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
>>>> +	l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
>>>> +	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
>>>> +	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
>>>> +	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
>>>> +	l.ppa |= ((u64)r.g.sec) << ppaf->sect_offset;
>>>>    	return l;
>>>>  }
>>>> @@ -373,24 +399,18 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
>>>>  						  struct ppa_addr r)
>>>>  {
>>>>  	struct nvm_geo *geo = &tgt_dev->geo;
>>>> +	struct nvm_addr_format_12 *ppaf =
>>>> +				(struct nvm_addr_format_12 *)&geo->c.addrf;
>>>>  	struct ppa_addr l;
>>>>    	l.ppa = 0;
>>>> -	/*
>>>> -	 * (r.ppa << X offset) & X len bitmask. X eq. blk, pg, etc.
>>>> -	 */
>>>> -	l.g.blk = (r.ppa >> geo->ppaf.blk_offset) &
>>>> -					(((1 << geo->ppaf.blk_len) - 1));
>>>> -	l.g.pg |= (r.ppa >> geo->ppaf.pg_offset) &
>>>> -					(((1 << geo->ppaf.pg_len) - 1));
>>>> -	l.g.sec |= (r.ppa >> geo->ppaf.sect_offset) &
>>>> -					(((1 << geo->ppaf.sect_len) - 1));
>>>> -	l.g.pl |= (r.ppa >> geo->ppaf.pln_offset) &
>>>> -					(((1 << geo->ppaf.pln_len) - 1));
>>>> -	l.g.lun |= (r.ppa >> geo->ppaf.lun_offset) &
>>>> -					(((1 << geo->ppaf.lun_len) - 1));
>>>> -	l.g.ch |= (r.ppa >> geo->ppaf.ch_offset) &
>>>> -					(((1 << geo->ppaf.ch_len) - 1));
>>>> +
>>>> +	l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
>>>> +	l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
>>>> +	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
>>>> +	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
>>>> +	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
>>>> +	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sect_offset;
>>>>    	return l;
>>>>  }
>>> 
>>> Thanks for the patch. I appreciate the work, but it is not the way I
>>> want the 2.0 representation to go. The 2.0 variables should stay in
>>> the nvm_geo data structure, and then if any 1.2 variables are on the
>>> side, they can be in a substructure.
>> I don't understand. Everything is in nvm_geo, with the only different
>> that there is nvm_common_geo, which contains the shared geometry between
>> all instances. As mentioned before, if only having nvm_geo, then we are
>> truncating the structure for each instance with different channel/lun
>> values, which is very from a target perspective (the target can access
>> the underlying device's values, which is _very_ error prone). This
>> structure represents all 2.0 variables as they are.I can move all 1.2
>> variables to a sub structure if that helps.
> 
> Let me try to see if I can clarify. From my understanding,the patch is doing three things,
> 
> 1. Replace dev->identify and use a generic data structure
> 2. Introduced nvm_dev_geo to represent both intance and device channels and luns.
> 3. Move pblk addressing logic into core

Yes :)

> 
> Could these be split up? maybe 1 and 3 go together, and the address format go by itself. Maybe not. I'm fine if you say that they should stay together.
> 
> For 1 and 3, Instead of making the nvm_dev_geo the base structure, the code should continue to use nvm_geo (don't move the variables into nvm_geo_common and similar data struct. The nvm_dev->nvm_dev_geo is not pretty, the code already has a reference that the nvm_dev_geo is in the nvm_dev data structure.
> 
> When the code needs the instance specific channels and luns, put them in another data structure (than nvm_dev_geo), and maintain the relationship there.

Ok. Let me give it another try. The only thing that matters to me is
that pblk does not need to go and check for 1.2 and 2.0 more than in the
address converting part (because there is no way around it if
page,plane,sector are not aligned. Apart from that, I'm very open to
having it one way or the other.

Thanks for clarifying!

Javier
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: Message signed with OpenPGP
URL: <http://lists.infradead.org/pipermail/linux-nvme/attachments/20180222/ad4ff80c/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 99+ messages in thread

end of thread, other threads:[~2018-02-22 14:13 UTC | newest]

Thread overview: 99+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-21  9:26 [PATCH V2 00/20] lightnvm: pblk: implement 2.0 support Javier González
2018-02-21  9:26 ` Javier González
2018-02-21  9:26 ` [PATCH 01/20] lightnvm: simplify geometry structure Javier González
2018-02-21  9:26   ` Javier González
2018-02-22  7:25   ` Matias Bjørling
2018-02-22  7:25     ` Matias Bjørling
2018-02-22  7:44     ` Javier Gonzalez
2018-02-22  7:44       ` Javier Gonzalez
2018-02-22 12:22       ` Matias Bjørling
2018-02-22 12:22         ` Matias Bjørling
2018-02-22 14:13         ` Javier Gonzalez
2018-02-22 14:13           ` Javier Gonzalez
2018-02-21  9:26 ` [PATCH 02/20] lightnvm: add controller capabilities to 2.0 Javier González
2018-02-21  9:26   ` Javier González
2018-02-22  7:26   ` Matias Bjørling
2018-02-22  7:26     ` Matias Bjørling
2018-02-21  9:26 ` [PATCH 03/20] lightnvm: fix capabilities for 2.0 sysfs Javier González
2018-02-21  9:26   ` Javier González
2018-02-22  7:28   ` Matias Bjørling
2018-02-22  7:28     ` Matias Bjørling
2018-02-22  7:47     ` Javier Gonzalez
2018-02-22  7:47       ` Javier Gonzalez
2018-02-22  9:39       ` Matias Bjørling
2018-02-22  9:39         ` Matias Bjørling
2018-02-22 10:25         ` Javier Gonzalez
2018-02-22 10:25           ` Javier Gonzalez
2018-02-22 10:25           ` Javier Gonzalez
2018-02-22 11:10           ` Matias Bjørling
2018-02-22 11:10             ` Matias Bjørling
2018-02-22 11:12             ` Javier Gonzalez
2018-02-22 11:12               ` Javier Gonzalez
2018-02-21  9:26 ` [PATCH 04/20] lightnvm: add minor version to generic geometry Javier González
2018-02-21  9:26   ` Javier González
2018-02-22  7:34   ` Matias Bjørling
2018-02-22  7:34     ` Matias Bjørling
2018-02-22  7:53     ` Javier González
2018-02-22  7:53       ` Javier González
2018-02-21  9:26 ` [PATCH 05/20] lightnvm: rename number of channels and luns Javier González
2018-02-21  9:26   ` Javier González
2018-02-21  9:26 ` [PATCH 06/20] lightnvm: add shorten OCSSD version in geo Javier González
2018-02-21  9:26   ` Javier González
2018-02-21  9:26 ` [PATCH 07/20] lightnvm: rename sect_* to sec_* Javier González
2018-02-21  9:26   ` Javier González
2018-02-22  7:43   ` Matias Bjørling
2018-02-22  7:43     ` Matias Bjørling
2018-02-21  9:26 ` [PATCH 08/20] lightnvm: complete geo structure with maxoc* Javier González
2018-02-21  9:26   ` Javier González
2018-02-22  7:45   ` Matias Bjørling
2018-02-22  7:45     ` Matias Bjørling
2018-02-22  7:55     ` Javier Gonzalez
2018-02-22  7:55       ` Javier Gonzalez
2018-02-22  9:45       ` Matias Bjørling
2018-02-22  9:45         ` Matias Bjørling
2018-02-22  9:52         ` Javier Gonzalez
2018-02-22  9:52           ` Javier Gonzalez
2018-02-22 10:00           ` Matias Bjørling
2018-02-22 10:00             ` Matias Bjørling
2018-02-22 10:03             ` Javier Gonzalez
2018-02-22 10:03               ` Javier Gonzalez
2018-02-21  9:26 ` [PATCH 09/20] lightnvm: use generic identify structure Javier González
2018-02-21  9:26   ` Javier González
2018-02-22  7:47   ` Matias Bjørling
2018-02-22  7:47     ` Matias Bjørling
2018-02-22  7:49     ` Javier González
2018-02-22  7:49       ` Javier González
2018-02-22  9:41       ` Matias Bjørling
2018-02-22  9:41         ` Matias Bjørling
2018-02-21  9:26 ` [PATCH 10/20] lightnvm: pblk: rename ppaf* to addrf* Javier González
2018-02-21  9:26   ` Javier González
2018-02-21  9:26   ` Javier González
2018-02-22  7:47   ` Matias Bjørling
2018-02-22  7:47     ` Matias Bjørling
2018-02-22  7:47     ` Matias Bjørling
2018-02-21  9:26 ` [PATCH 11/20] lightnvm: pblk: check for supported version Javier González
2018-02-21  9:26   ` Javier González
2018-02-22  7:48   ` Matias Bjørling
2018-02-22  7:48     ` Matias Bjørling
2018-02-21  9:26 ` [PATCH 12/20] lightnvm: complete 2.0 values in sysfs Javier González
2018-02-21  9:26   ` Javier González
2018-02-21  9:26 ` [PATCH 13/20] lightnvm: add support for 2.0 address format Javier González
2018-02-21  9:26   ` Javier González
2018-02-22  9:24   ` Matias Bjørling
2018-02-22  9:24     ` Matias Bjørling
2018-02-21  9:26 ` [PATCH 14/20] lightnvm: make address conversions depend on generic device Javier González
2018-02-21  9:26   ` Javier González
2018-02-21  9:26 ` [PATCH 15/20] nvme: make nvme_get_log_ext available Javier González
2018-02-21  9:26   ` Javier González
2018-02-21  9:26 ` [PATCH 16/20] lightnvm: implement get log report chunk helpers Javier González
2018-02-21  9:26   ` Javier González
2018-02-21  9:26 ` [PATCH 17/20] lightnvm: define chunk states Javier González
2018-02-21  9:26   ` Javier González
2018-02-21  9:26 ` [PATCH 18/20] lightnvm: pblk: implement get log report chunk Javier González
2018-02-21  9:26   ` Javier González
2018-02-21  9:26 ` [PATCH 19/20] lightnvm: pblk: refactor init/exit sequences Javier González
2018-02-21  9:26   ` Javier González
2018-02-21  9:26 ` [PATCH 20/20] lightnvm: pblk: implement 2.0 support Javier González
2018-02-21  9:26   ` Javier González
2018-02-21 14:30   ` Javier González
2018-02-21 14:30     ` Javier González

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.