linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [GIT PULL 00/37] lightnvm patches for 4.17
@ 2018-03-29 22:04 Matias Bjørling
  2018-03-29 22:04 ` [GIT PULL 01/37] lightnvm/pblk-gc: Delete an error message for a failed memory allocation in pblk_gc_line_prepare_ws() Matias Bjørling
                   ` (37 more replies)
  0 siblings, 38 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:04 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

Hi Jens,

Here is a bunch of patches for 4.17. They include:

 - Open-Channel 2.0 support by Javier and I.
 - Lots of refactoring patches to enable 2.0 support.
 - Fixes to pblk from Hans, Markus, and Dan.
 - Introduction of write amplication and padding counters. From Hans.
 - Fix from Johannes to unify the permission checks for the lightnvm
   ioctls.
 - Fixes from Heiner for bad block initialization and
   over-provisioning validation.

Please pick up when convenient.

-Matias

Dan Carpenter (1):
  lightnvm: pblk: remove some unnecessary NULL checks

Hans Holmberg (8):
  lightnvm: pblk: handle bad sectors in the emeta area correctly
  lightnvm: pblk: check data lines version on recovery
  lightnvm: pblk: export write amplification counters to sysfs
  lightnvm: pblk: add padding distribution sysfs attribute
  lightnvm: pblk: delete writer kick timer before stopping thread
  lightnvm: pblk: allow allocation of new lines during shutdown
  lightnvm: pblk: prevent race in pblk_rb_flush_point_set
  lightnvm: pblk: don't recover unwritten lines

Heiner Litz (2):
  lightnvm: fix bad block initialization
  lightnvm: Avoid validation of default op value

Javier González (14):
  lightnvm: pblk: refactor bad block identification
  lightnvm: pblk: refactor init/exit sequences
  lightnvm: simplify geometry structure
  lightnvm: add minor version to generic geometry
  lightnvm: add shorten OCSSD version in geo
  lightnvm: complete geo structure with maxoc*
  lightnvm: normalize geometry nomenclature
  lightnvm: add support for 2.0 address format
  lightnvm: make address conversions depend on generic device
  lightnvm: implement get log report chunk helpers
  lightnvm: pblk: check for supported version
  lightnvm: pblk: rename ppaf* to addrf*
  lightnvm: pblk: implement get log report chunk
  lightnvm: pblk: implement 2.0 support

Johannes Thumshirn (1):
  lightnvm: centralize permission check for lightnvm ioctl

Markus Elfring (1):
  lightnvm/pblk-gc: Delete an error message for a failed memory
    allocation in pblk_gc_line_prepare_ws()

Matias Bjørling (10):
  lightnvm: remove chnl_offset in nvme_nvm_identity
  lightnvm: remove mlc pairs structure
  lightnvm: remove multiple groups in 1.2 data structure
  lightnvm: make 1.2 data structures explicit
  lightnvm: flatten nvm_id_group into nvm_id
  lightnvm: add 2.0 geometry identification
  lightnvm: remove max_rq_size
  lightnvm: remove nvm_dev_ops->max_phys_sect
  nvme: lightnvm: add late setup of block size and metadata
  lightnvm: remove function name in strings

 drivers/lightnvm/core.c          | 238 +++++------
 drivers/lightnvm/pblk-cache.c    |   4 +
 drivers/lightnvm/pblk-core.c     | 202 +++++++---
 drivers/lightnvm/pblk-gc.c       |  12 +-
 drivers/lightnvm/pblk-init.c     | 850 +++++++++++++++++++++++----------------
 drivers/lightnvm/pblk-map.c      |   6 +-
 drivers/lightnvm/pblk-rb.c       |  21 +-
 drivers/lightnvm/pblk-read.c     |   2 +-
 drivers/lightnvm/pblk-recovery.c |  91 ++++-
 drivers/lightnvm/pblk-rl.c       |   2 +-
 drivers/lightnvm/pblk-sysfs.c    | 235 +++++++++--
 drivers/lightnvm/pblk-write.c    |   2 +-
 drivers/lightnvm/pblk.h          | 304 ++++++++++----
 drivers/nvme/host/core.c         |   6 +-
 drivers/nvme/host/lightnvm.c     | 747 ++++++++++++++++++++++++++--------
 drivers/nvme/host/nvme.h         |   2 +
 include/linux/lightnvm.h         | 338 ++++++++++------
 17 files changed, 2090 insertions(+), 972 deletions(-)

-- 
2.11.0

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

* [GIT PULL 01/37] lightnvm/pblk-gc: Delete an error message for a failed memory allocation in pblk_gc_line_prepare_ws()
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
@ 2018-03-29 22:04 ` Matias Bjørling
  2018-03-29 22:04 ` [GIT PULL 02/37] lightnvm: remove chnl_offset in nvme_nvm_identity Matias Bjørling
                   ` (36 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:04 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Markus Elfring,
	Matias Bjørling

From: Markus Elfring <elfring@users.sourceforge.net>

Omit an extra message for a memory allocation failure in this function.

This issue was detected by using the Coccinelle software.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
Reviewed-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/pblk-gc.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c
index 3d899383666e..31f17d6f14ee 100644
--- a/drivers/lightnvm/pblk-gc.c
+++ b/drivers/lightnvm/pblk-gc.c
@@ -147,10 +147,8 @@ static void pblk_gc_line_prepare_ws(struct work_struct *work)
 	int ret;
 
 	invalid_bitmap = kmalloc(lm->sec_bitmap_len, GFP_KERNEL);
-	if (!invalid_bitmap) {
-		pr_err("pblk: could not allocate GC invalid bitmap\n");
+	if (!invalid_bitmap)
 		goto fail_free_ws;
-	}
 
 	emeta_buf = pblk_malloc(lm->emeta_len[0], l_mg->emeta_alloc_type,
 								GFP_KERNEL);
-- 
2.11.0

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

* [GIT PULL 02/37] lightnvm: remove chnl_offset in nvme_nvm_identity
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
  2018-03-29 22:04 ` [GIT PULL 01/37] lightnvm/pblk-gc: Delete an error message for a failed memory allocation in pblk_gc_line_prepare_ws() Matias Bjørling
@ 2018-03-29 22:04 ` Matias Bjørling
  2018-03-29 22:04 ` [GIT PULL 03/37] lightnvm: pblk: handle bad sectors in the emeta area correctly Matias Bjørling
                   ` (35 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:04 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

The identity structure is initialized to zero in the beginning of
the nvme_nvm_identity function. The chnl_offset is separately set to
zero. Since both the variable and assignment is never changed, remove
them.

Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/nvme/host/lightnvm.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 50ef71ee3d86..f9c38a8d54e1 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -59,8 +59,7 @@ struct nvme_nvm_identity {
 	__u64			rsvd[2];
 	__le64			prp1;
 	__le64			prp2;
-	__le32			chnl_off;
-	__u32			rsvd11[5];
+	__u32			rsvd11[6];
 };
 
 struct nvme_nvm_getbbtbl {
@@ -279,7 +278,6 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
 
 	c.identity.opcode = nvme_nvm_admin_identity;
 	c.identity.nsid = cpu_to_le32(ns->head->ns_id);
-	c.identity.chnl_off = 0;
 
 	nvme_nvm_id = kmalloc(sizeof(struct nvme_nvm_id), GFP_KERNEL);
 	if (!nvme_nvm_id)
-- 
2.11.0

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

* [GIT PULL 03/37] lightnvm: pblk: handle bad sectors in the emeta area correctly
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
  2018-03-29 22:04 ` [GIT PULL 01/37] lightnvm/pblk-gc: Delete an error message for a failed memory allocation in pblk_gc_line_prepare_ws() Matias Bjørling
  2018-03-29 22:04 ` [GIT PULL 02/37] lightnvm: remove chnl_offset in nvme_nvm_identity Matias Bjørling
@ 2018-03-29 22:04 ` Matias Bjørling
  2018-03-29 22:04 ` [GIT PULL 04/37] lightnvm: pblk: check data lines version on recovery Matias Bjørling
                   ` (34 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:04 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Hans Holmberg,
	Matias Bjørling

From: Hans Holmberg <hans.holmberg@cnexlabs.com>

Unless we check if there are bad sectors in the entire emeta-area
we risk ending up with valid bitmap / available sector count inconsistency.
This results in lines with a bad chunk at the last LUN marked as bad,
so go through the whole emeta area and mark up the invalid sectors.

Signed-off-by: Hans Holmberg <hans.holmberg@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/pblk-core.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index 0487b9340c1d..9027cf2ed1d8 100644
--- a/drivers/lightnvm/pblk-core.c
+++ b/drivers/lightnvm/pblk-core.c
@@ -1021,6 +1021,7 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
 	int nr_bb = 0;
 	u64 off;
 	int bit = -1;
+	int emeta_secs;
 
 	line->sec_in_line = lm->sec_per_line;
 
@@ -1055,18 +1056,18 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
 	/* Mark emeta metadata sectors as bad sectors. We need to consider bad
 	 * blocks to make sure that there are enough sectors to store emeta
 	 */
-	off = lm->sec_per_line - lm->emeta_sec[0];
-	bitmap_set(line->invalid_bitmap, off, lm->emeta_sec[0]);
-	while (nr_bb) {
+	emeta_secs = lm->emeta_sec[0];
+	off = lm->sec_per_line;
+	while (emeta_secs) {
 		off -= geo->sec_per_pl;
 		if (!test_bit(off, line->invalid_bitmap)) {
 			bitmap_set(line->invalid_bitmap, off, geo->sec_per_pl);
-			nr_bb--;
+			emeta_secs -= geo->sec_per_pl;
 		}
 	}
 
-	line->sec_in_line -= lm->emeta_sec[0];
 	line->emeta_ssec = off;
+	line->sec_in_line -= lm->emeta_sec[0];
 	line->nr_valid_lbas = 0;
 	line->left_msecs = line->sec_in_line;
 	*line->vsc = cpu_to_le32(line->sec_in_line);
-- 
2.11.0

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

* [GIT PULL 04/37] lightnvm: pblk: check data lines version on recovery
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (2 preceding siblings ...)
  2018-03-29 22:04 ` [GIT PULL 03/37] lightnvm: pblk: handle bad sectors in the emeta area correctly Matias Bjørling
@ 2018-03-29 22:04 ` Matias Bjørling
  2018-03-29 22:04 ` [GIT PULL 05/37] lightnvm: pblk: export write amplification counters to sysfs Matias Bjørling
                   ` (33 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:04 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Hans Holmberg,
	Matias Bjørling

From: Hans Holmberg <hans.holmberg@cnexlabs.com>

As a preparation for future bumps of data line persistent storage
versions, we need to start checking the emeta line version during
recovery. Also slit up the current emeta/smeta version into two
bytes (major,minor).

Recovering lines with the same major number as the current pblk data
line version must succeed. This means that any changes in the
persistent format must be:

 (1) Backward compatible: if we switch back to and older
     kernel, recovery of lines stored with major == current_major
     and minor > current_minor must succeed.

 (2) Forward compatible: switching to a newer kernel,
     recovery of lines stored with major=current_major and
     minor < minor must handle the data format differences
     gracefully(i.e. initialize new data structures to default values).

If we detect lines that have a different major number than
the current we must abort recovery. The user must manually
migrate the data in this case.

Previously the version stored in the emeta header was copied
from smeta, which has version 1, so we need to set the minor
version to 1.

Signed-off-by: Hans Holmberg <hans.holmberg@cnexlabs.com>
Signed-off-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/pblk-core.c     |  9 ++++++++-
 drivers/lightnvm/pblk-recovery.c | 26 ++++++++++++++++++++++++--
 drivers/lightnvm/pblk.h          | 16 ++++++++++++++--
 3 files changed, 46 insertions(+), 5 deletions(-)

diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index 9027cf2ed1d8..155e42a26293 100644
--- a/drivers/lightnvm/pblk-core.c
+++ b/drivers/lightnvm/pblk-core.c
@@ -975,7 +975,8 @@ static int pblk_line_init_metadata(struct pblk *pblk, struct pblk_line *line,
 	memcpy(smeta_buf->header.uuid, pblk->instance_uuid, 16);
 	smeta_buf->header.id = cpu_to_le32(line->id);
 	smeta_buf->header.type = cpu_to_le16(line->type);
-	smeta_buf->header.version = SMETA_VERSION;
+	smeta_buf->header.version_major = SMETA_VERSION_MAJOR;
+	smeta_buf->header.version_minor = SMETA_VERSION_MINOR;
 
 	/* Start metadata */
 	smeta_buf->seq_nr = cpu_to_le64(line->seq_nr);
@@ -998,6 +999,12 @@ static int pblk_line_init_metadata(struct pblk *pblk, struct pblk_line *line,
 	/* End metadata */
 	memcpy(&emeta_buf->header, &smeta_buf->header,
 						sizeof(struct line_header));
+
+	emeta_buf->header.version_major = EMETA_VERSION_MAJOR;
+	emeta_buf->header.version_minor = EMETA_VERSION_MINOR;
+	emeta_buf->header.crc = cpu_to_le32(
+			pblk_calc_meta_header_crc(pblk, &emeta_buf->header));
+
 	emeta_buf->seq_nr = cpu_to_le64(line->seq_nr);
 	emeta_buf->nr_lbas = cpu_to_le64(line->sec_in_line);
 	emeta_buf->nr_valid_lbas = cpu_to_le64(0);
diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
index 1d5e961bf5e0..a30fe203d454 100644
--- a/drivers/lightnvm/pblk-recovery.c
+++ b/drivers/lightnvm/pblk-recovery.c
@@ -826,6 +826,25 @@ static u64 pblk_line_emeta_start(struct pblk *pblk, struct pblk_line *line)
 	return emeta_start;
 }
 
+static int pblk_recov_check_line_version(struct pblk *pblk,
+					 struct line_emeta *emeta)
+{
+	struct line_header *header = &emeta->header;
+
+	if (header->version_major != EMETA_VERSION_MAJOR) {
+		pr_err("pblk: line major version mismatch: %d, expected: %d\n",
+		       header->version_major, EMETA_VERSION_MAJOR);
+		return 1;
+	}
+
+#ifdef NVM_DEBUG
+	if (header->version_minor > EMETA_VERSION_MINOR)
+		pr_info("pblk: newer line minor version found: %d\n", line_v);
+#endif
+
+	return 0;
+}
+
 struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
 {
 	struct pblk_line_meta *lm = &pblk->lm;
@@ -873,9 +892,9 @@ struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
 		if (le32_to_cpu(smeta_buf->header.identifier) != PBLK_MAGIC)
 			continue;
 
-		if (smeta_buf->header.version != SMETA_VERSION) {
+		if (smeta_buf->header.version_major != SMETA_VERSION_MAJOR) {
 			pr_err("pblk: found incompatible line version %u\n",
-					le16_to_cpu(smeta_buf->header.version));
+					smeta_buf->header.version_major);
 			return ERR_PTR(-EINVAL);
 		}
 
@@ -943,6 +962,9 @@ struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
 			goto next;
 		}
 
+		if (pblk_recov_check_line_version(pblk, line->emeta->buf))
+			return ERR_PTR(-EINVAL);
+
 		if (pblk_recov_l2p_from_emeta(pblk, line))
 			pblk_recov_l2p_from_oob(pblk, line);
 
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 8c357fb6538e..fae2526f80b2 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -320,14 +320,26 @@ enum {
 };
 
 #define PBLK_MAGIC 0x70626c6b /*pblk*/
-#define SMETA_VERSION cpu_to_le16(1)
+
+/* emeta/smeta persistent storage format versions:
+ * Changes in major version requires offline migration.
+ * Changes in minor version are handled automatically during
+ * recovery.
+ */
+
+#define SMETA_VERSION_MAJOR (0)
+#define SMETA_VERSION_MINOR (1)
+
+#define EMETA_VERSION_MAJOR (0)
+#define EMETA_VERSION_MINOR (1)
 
 struct line_header {
 	__le32 crc;
 	__le32 identifier;	/* pblk identifier */
 	__u8 uuid[16];		/* instance uuid */
 	__le16 type;		/* line type */
-	__le16 version;		/* type version */
+	__u8 version_major;	/* version major */
+	__u8 version_minor;	/* version minor */
 	__le32 id;		/* line id for current line */
 };
 
-- 
2.11.0

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

* [GIT PULL 05/37] lightnvm: pblk: export write amplification counters to sysfs
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (3 preceding siblings ...)
  2018-03-29 22:04 ` [GIT PULL 04/37] lightnvm: pblk: check data lines version on recovery Matias Bjørling
@ 2018-03-29 22:04 ` Matias Bjørling
  2018-03-29 22:04 ` [GIT PULL 06/37] lightnvm: remove mlc pairs structure Matias Bjørling
                   ` (32 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:04 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Hans Holmberg,
	Matias Bjørling

From: Hans Holmberg <hans.holmberg@cnexlabs.com>

In a SSD, write amplification, WA, is defined as the average
number of page writes per user page write. Write amplification
negatively affects write performance and decreases the lifetime
of the disk, so it's a useful metric to add to sysfs.

In plkb's case, the number of writes per user sector is the sum of:

    (1) number of user writes
    (2) number of sectors written by the garbage collector
    (3) number of sectors padded (i.e. due to syncs)

This patch adds persistent counters for 1-3 and two sysfs attributes
to export these along with WA calculated with five decimals:

    write_amp_mileage: the accumulated write amplification stats
                      for the lifetime of the pblk instance

    write_amp_trip: resetable stats to facilitate delta measurements,
                    values reset at creation and if 0 is written
                    to the attribute.

64-bit counters are used as a 32 bit counter would wrap around
already after about 17 TB worth of user data. It will take a
long long time before the 64 bit sector counters wrap around.

The counters are stored after the bad block bitmap in the first
emeta sector of each written line. There is plenty of space in the
first emeta sector, so we don't need to bump the major version of
the line data format.

Signed-off-by: Hans Holmberg <hans.holmberg@cnexlabs.com>
Signed-off-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/pblk-cache.c    |  4 ++
 drivers/lightnvm/pblk-core.c     |  6 +++
 drivers/lightnvm/pblk-init.c     | 11 +++++-
 drivers/lightnvm/pblk-map.c      |  2 +
 drivers/lightnvm/pblk-rb.c       |  3 ++
 drivers/lightnvm/pblk-recovery.c | 25 ++++++++++++
 drivers/lightnvm/pblk-sysfs.c    | 85 +++++++++++++++++++++++++++++++++++++++-
 drivers/lightnvm/pblk.h          | 42 ++++++++++++++++----
 8 files changed, 168 insertions(+), 10 deletions(-)

diff --git a/drivers/lightnvm/pblk-cache.c b/drivers/lightnvm/pblk-cache.c
index 000fcad38136..29a23111b31c 100644
--- a/drivers/lightnvm/pblk-cache.c
+++ b/drivers/lightnvm/pblk-cache.c
@@ -63,6 +63,8 @@ int pblk_write_to_cache(struct pblk *pblk, struct bio *bio, unsigned long flags)
 		bio_advance(bio, PBLK_EXPOSED_PAGE_SIZE);
 	}
 
+	atomic64_add(nr_entries, &pblk->user_wa);
+
 #ifdef CONFIG_NVM_DEBUG
 	atomic_long_add(nr_entries, &pblk->inflight_writes);
 	atomic_long_add(nr_entries, &pblk->req_writes);
@@ -117,6 +119,8 @@ int pblk_write_gc_to_cache(struct pblk *pblk, struct pblk_gc_rq *gc_rq)
 	WARN_ONCE(gc_rq->secs_to_gc != valid_entries,
 					"pblk: inconsistent GC write\n");
 
+	atomic64_add(valid_entries, &pblk->gc_wa);
+
 #ifdef CONFIG_NVM_DEBUG
 	atomic_long_add(valid_entries, &pblk->inflight_writes);
 	atomic_long_add(valid_entries, &pblk->recov_gc_writes);
diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index 155e42a26293..22e61cd4f801 100644
--- a/drivers/lightnvm/pblk-core.c
+++ b/drivers/lightnvm/pblk-core.c
@@ -1630,11 +1630,16 @@ void pblk_line_close_meta(struct pblk *pblk, struct pblk_line *line)
 	struct pblk_line_meta *lm = &pblk->lm;
 	struct pblk_emeta *emeta = line->emeta;
 	struct line_emeta *emeta_buf = emeta->buf;
+	struct wa_counters *wa = emeta_to_wa(lm, emeta_buf);
 
 	/* No need for exact vsc value; avoid a big line lock and take aprox. */
 	memcpy(emeta_to_vsc(pblk, emeta_buf), l_mg->vsc_list, lm->vsc_list_len);
 	memcpy(emeta_to_bb(emeta_buf), line->blk_bitmap, lm->blk_bitmap_len);
 
+	wa->user = cpu_to_le64(atomic64_read(&pblk->user_wa));
+	wa->pad = cpu_to_le64(atomic64_read(&pblk->pad_wa));
+	wa->gc = cpu_to_le64(atomic64_read(&pblk->gc_wa));
+
 	emeta_buf->nr_valid_lbas = cpu_to_le64(line->nr_valid_lbas);
 	emeta_buf->crc = cpu_to_le32(pblk_calc_emeta_crc(pblk, emeta_buf));
 
@@ -1837,6 +1842,7 @@ void pblk_update_map_dev(struct pblk *pblk, sector_t lba,
 #endif
 	/* Invalidate and discard padded entries */
 	if (lba == ADDR_EMPTY) {
+		atomic64_inc(&pblk->pad_wa);
 #ifdef CONFIG_NVM_DEBUG
 		atomic_long_inc(&pblk->padded_wb);
 #endif
diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 5b46924ac66c..0ffc17ccf1cc 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -559,8 +559,8 @@ 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,
-			geo->sec_size);
+			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;
 
 	/* Round to sector size so that vsc_list starts on its own sector */
@@ -991,6 +991,13 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 	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;
+
 #ifdef CONFIG_NVM_DEBUG
 	atomic_long_set(&pblk->inflight_writes, 0);
 	atomic_long_set(&pblk->padded_writes, 0);
diff --git a/drivers/lightnvm/pblk-map.c b/drivers/lightnvm/pblk-map.c
index 7445e6430c52..04e08d76ea5f 100644
--- a/drivers/lightnvm/pblk-map.c
+++ b/drivers/lightnvm/pblk-map.c
@@ -65,6 +65,8 @@ static void pblk_map_page_data(struct pblk *pblk, unsigned int sentry,
 			lba_list[paddr] = cpu_to_le64(w_ctx->lba);
 			if (lba_list[paddr] != addr_empty)
 				line->nr_valid_lbas++;
+			else
+				atomic64_inc(&pblk->pad_wa);
 		} else {
 			lba_list[paddr] = meta_list[i].lba = addr_empty;
 			__pblk_map_invalidate(pblk, line, paddr);
diff --git a/drivers/lightnvm/pblk-rb.c b/drivers/lightnvm/pblk-rb.c
index ec8fc314646b..7044b5599cc4 100644
--- a/drivers/lightnvm/pblk-rb.c
+++ b/drivers/lightnvm/pblk-rb.c
@@ -622,6 +622,9 @@ unsigned int pblk_rb_read_to_bio(struct pblk_rb *rb, struct nvm_rq *rqd,
 		}
 	}
 
+	atomic64_add(pad, &((struct pblk *)
+			(container_of(rb, struct pblk, rwb)))->pad_wa);
+
 #ifdef CONFIG_NVM_DEBUG
 	atomic_long_add(pad, &((struct pblk *)
 			(container_of(rb, struct pblk, rwb)))->padded_writes);
diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
index a30fe203d454..e75a1af2eebe 100644
--- a/drivers/lightnvm/pblk-recovery.c
+++ b/drivers/lightnvm/pblk-recovery.c
@@ -845,6 +845,29 @@ static int pblk_recov_check_line_version(struct pblk *pblk,
 	return 0;
 }
 
+static void pblk_recov_wa_counters(struct pblk *pblk,
+				   struct line_emeta *emeta)
+{
+	struct pblk_line_meta *lm = &pblk->lm;
+	struct line_header *header = &emeta->header;
+	struct wa_counters *wa = emeta_to_wa(lm, emeta);
+
+	/* WA counters were introduced in emeta version 0.2 */
+	if (header->version_major > 0 || header->version_minor >= 2) {
+		u64 user = le64_to_cpu(wa->user);
+		u64 pad = le64_to_cpu(wa->pad);
+		u64 gc = le64_to_cpu(wa->gc);
+
+		atomic64_set(&pblk->user_wa, user);
+		atomic64_set(&pblk->pad_wa, pad);
+		atomic64_set(&pblk->gc_wa, gc);
+
+		pblk->user_rst_wa = user;
+		pblk->pad_rst_wa = pad;
+		pblk->gc_rst_wa = gc;
+	}
+}
+
 struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
 {
 	struct pblk_line_meta *lm = &pblk->lm;
@@ -965,6 +988,8 @@ struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
 		if (pblk_recov_check_line_version(pblk, line->emeta->buf))
 			return ERR_PTR(-EINVAL);
 
+		pblk_recov_wa_counters(pblk, line->emeta->buf);
+
 		if (pblk_recov_l2p_from_emeta(pblk, line))
 			pblk_recov_l2p_from_oob(pblk, line);
 
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index 620bab853579..beed99936c89 100644
--- a/drivers/lightnvm/pblk-sysfs.c
+++ b/drivers/lightnvm/pblk-sysfs.c
@@ -298,6 +298,48 @@ static ssize_t pblk_sysfs_get_sec_per_write(struct pblk *pblk, char *page)
 	return snprintf(page, PAGE_SIZE, "%d\n", pblk->sec_per_write);
 }
 
+static ssize_t pblk_get_write_amp(u64 user, u64 gc, u64 pad,
+				  char *page)
+{
+	int sz;
+
+
+	sz = snprintf(page, PAGE_SIZE,
+			"user:%lld gc:%lld pad:%lld WA:",
+			user, gc, pad);
+
+	if (!user) {
+		sz += snprintf(page + sz, PAGE_SIZE - sz, "NaN\n");
+	} else {
+		u64 wa_int;
+		u32 wa_frac;
+
+		wa_int = (user + gc + pad) * 100000;
+		wa_int = div_u64(wa_int, user);
+		wa_int = div_u64_rem(wa_int, 100000, &wa_frac);
+
+		sz += snprintf(page + sz, PAGE_SIZE - sz, "%llu.%05u\n",
+							wa_int, wa_frac);
+	}
+
+	return sz;
+}
+
+static ssize_t pblk_sysfs_get_write_amp_mileage(struct pblk *pblk, char *page)
+{
+	return pblk_get_write_amp(atomic64_read(&pblk->user_wa),
+		atomic64_read(&pblk->gc_wa), atomic64_read(&pblk->pad_wa),
+		page);
+}
+
+static ssize_t pblk_sysfs_get_write_amp_trip(struct pblk *pblk, char *page)
+{
+	return pblk_get_write_amp(
+		atomic64_read(&pblk->user_wa) - pblk->user_rst_wa,
+		atomic64_read(&pblk->gc_wa) - pblk->gc_rst_wa,
+		atomic64_read(&pblk->pad_wa) - pblk->pad_rst_wa, page);
+}
+
 #ifdef CONFIG_NVM_DEBUG
 static ssize_t pblk_sysfs_stats_debug(struct pblk *pblk, char *page)
 {
@@ -360,6 +402,30 @@ static ssize_t pblk_sysfs_set_sec_per_write(struct pblk *pblk,
 	return len;
 }
 
+static ssize_t pblk_sysfs_set_write_amp_trip(struct pblk *pblk,
+			const char *page, size_t len)
+{
+	size_t c_len;
+	int reset_value;
+
+	c_len = strcspn(page, "\n");
+	if (c_len >= len)
+		return -EINVAL;
+
+	if (kstrtouint(page, 0, &reset_value))
+		return -EINVAL;
+
+	if (reset_value !=  0)
+		return -EINVAL;
+
+	pblk->user_rst_wa = atomic64_read(&pblk->user_wa);
+	pblk->pad_rst_wa = atomic64_read(&pblk->pad_wa);
+	pblk->gc_rst_wa = atomic64_read(&pblk->gc_wa);
+
+	return len;
+}
+
+
 static struct attribute sys_write_luns = {
 	.name = "write_luns",
 	.mode = 0444,
@@ -410,6 +476,16 @@ static struct attribute sys_max_sec_per_write = {
 	.mode = 0644,
 };
 
+static struct attribute sys_write_amp_mileage = {
+	.name = "write_amp_mileage",
+	.mode = 0444,
+};
+
+static struct attribute sys_write_amp_trip = {
+	.name = "write_amp_trip",
+	.mode = 0644,
+};
+
 #ifdef CONFIG_NVM_DEBUG
 static struct attribute sys_stats_debug_attr = {
 	.name = "stats",
@@ -428,6 +504,8 @@ static struct attribute *pblk_attrs[] = {
 	&sys_stats_ppaf_attr,
 	&sys_lines_attr,
 	&sys_lines_info_attr,
+	&sys_write_amp_mileage,
+	&sys_write_amp_trip,
 #ifdef CONFIG_NVM_DEBUG
 	&sys_stats_debug_attr,
 #endif
@@ -457,6 +535,10 @@ static ssize_t pblk_sysfs_show(struct kobject *kobj, struct attribute *attr,
 		return pblk_sysfs_lines_info(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)
+		return pblk_sysfs_get_write_amp_mileage(pblk, buf);
+	else if (strcmp(attr->name, "write_amp_trip") == 0)
+		return pblk_sysfs_get_write_amp_trip(pblk, buf);
 #ifdef CONFIG_NVM_DEBUG
 	else if (strcmp(attr->name, "stats") == 0)
 		return pblk_sysfs_stats_debug(pblk, buf);
@@ -473,7 +555,8 @@ static ssize_t pblk_sysfs_store(struct kobject *kobj, struct attribute *attr,
 		return pblk_sysfs_gc_force(pblk, buf, len);
 	else if (strcmp(attr->name, "max_sec_per_write") == 0)
 		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);
 	return 0;
 }
 
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index fae2526f80b2..4b7d8618631f 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -331,7 +331,7 @@ enum {
 #define SMETA_VERSION_MINOR (1)
 
 #define EMETA_VERSION_MAJOR (0)
-#define EMETA_VERSION_MINOR (1)
+#define EMETA_VERSION_MINOR (2)
 
 struct line_header {
 	__le32 crc;
@@ -361,11 +361,13 @@ struct line_smeta {
 	__le64 lun_bitmap[];
 };
 
+
 /*
  * Metadata layout in media:
  *	First sector:
  *		1. struct line_emeta
  *		2. bad block bitmap (u64 * window_wr_lun)
+ *		3. write amplification counters
  *	Mid sectors (start at lbas_sector):
  *		3. nr_lbas (u64) forming lba list
  *	Last sectors (start at vsc_sector):
@@ -389,7 +391,15 @@ struct line_emeta {
 	__le32 next_id;		/* Line id for next line */
 	__le64 nr_lbas;		/* Number of lbas mapped in line */
 	__le64 nr_valid_lbas;	/* Number of valid lbas mapped in line */
-	__le64 bb_bitmap[];	/* Updated bad block bitmap for line */
+	__le64 bb_bitmap[];     /* Updated bad block bitmap for line */
+};
+
+
+/* Write amplification counters stored on media */
+struct wa_counters {
+	__le64 user;		/* Number of user written sectors */
+	__le64 gc;		/* Number of sectors written by GC*/
+	__le64 pad;		/* Number of padded sectors */
 };
 
 struct pblk_emeta {
@@ -519,10 +529,11 @@ struct pblk_line_meta {
 	unsigned int smeta_sec;		/* Sectors needed for smeta */
 
 	unsigned int emeta_len[4];	/* Lengths for emeta:
-					 *  [0]: Total length
-					 *  [1]: struct line_emeta length
-					 *  [2]: L2P portion length
-					 *  [3]: vsc list length
+					 *  [0]: Total
+					 *  [1]: struct line_emeta +
+					 *       bb_bitmap + struct wa_counters
+					 *  [2]: L2P portion
+					 *  [3]: vsc
 					 */
 	unsigned int emeta_sec[4];	/* Sectors needed for emeta. Same layout
 					 * as emeta_len
@@ -604,8 +615,19 @@ struct pblk {
 	int sec_per_write;
 
 	unsigned char instance_uuid[16];
+
+	/* Persistent write amplification counters, 4kb sector I/Os */
+	atomic64_t user_wa;		/* Sectors written by user */
+	atomic64_t gc_wa;		/* Sectors written by GC */
+	atomic64_t pad_wa;		/* Padded sectors written */
+
+	/* Reset values for delta write amplification measurements */
+	u64 user_rst_wa;
+	u64 gc_rst_wa;
+	u64 pad_rst_wa;
+
 #ifdef CONFIG_NVM_DEBUG
-	/* All debug counters apply to 4kb sector I/Os */
+	/* Non-persistent debug counters, 4kb sector I/Os */
 	atomic_long_t inflight_writes;	/* Inflight writes (user and gc) */
 	atomic_long_t padded_writes;	/* Sectors padded due to flush/fua */
 	atomic_long_t padded_wb;	/* Sectors padded in write buffer */
@@ -900,6 +922,12 @@ static inline void *emeta_to_bb(struct line_emeta *emeta)
 	return emeta->bb_bitmap;
 }
 
+static inline void *emeta_to_wa(struct pblk_line_meta *lm,
+				struct line_emeta *emeta)
+{
+	return emeta->bb_bitmap + lm->blk_bitmap_len;
+}
+
 static inline void *emeta_to_lbas(struct pblk *pblk, struct line_emeta *emeta)
 {
 	return ((void *)emeta + pblk->lm.emeta_len[1]);
-- 
2.11.0

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

* [GIT PULL 06/37] lightnvm: remove mlc pairs structure
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (4 preceding siblings ...)
  2018-03-29 22:04 ` [GIT PULL 05/37] lightnvm: pblk: export write amplification counters to sysfs Matias Bjørling
@ 2018-03-29 22:04 ` Matias Bjørling
  2018-03-29 22:04 ` [GIT PULL 07/37] lightnvm: remove multiple groups in 1.2 data structure Matias Bjørling
                   ` (31 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:04 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier,
	Matias Bjørling, Matias Bjørling

From: Matias Bjørling <m@bjorling.me>

The known implementations of the 1.2 specification, and upcoming 2.0
implementation all expose a sequential list of pages to write.
Remove the data structure, as it is no longer needed.

Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/nvme/host/lightnvm.c | 14 +-------------
 1 file changed, 1 insertion(+), 13 deletions(-)

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index f9c38a8d54e1..940c9b9a2a09 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -115,17 +115,6 @@ struct nvme_nvm_command {
 	};
 };
 
-#define NVME_NVM_LP_MLC_PAIRS 886
-struct nvme_nvm_lp_mlc {
-	__le16			num_pairs;
-	__u8			pairs[NVME_NVM_LP_MLC_PAIRS];
-};
-
-struct nvme_nvm_lp_tbl {
-	__u8			id[8];
-	struct nvme_nvm_lp_mlc	mlc;
-};
-
 struct nvme_nvm_id_group {
 	__u8			mtype;
 	__u8			fmtype;
@@ -149,8 +138,7 @@ struct nvme_nvm_id_group {
 	__le32			mpos;
 	__le32			mccap;
 	__le16			cpar;
-	__u8			reserved[10];
-	struct nvme_nvm_lp_tbl lptbl;
+	__u8			reserved[906];
 } __packed;
 
 struct nvme_nvm_addr_format {
-- 
2.11.0

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

* [GIT PULL 07/37] lightnvm: remove multiple groups in 1.2 data structure
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (5 preceding siblings ...)
  2018-03-29 22:04 ` [GIT PULL 06/37] lightnvm: remove mlc pairs structure Matias Bjørling
@ 2018-03-29 22:04 ` Matias Bjørling
  2018-03-29 22:04 ` [GIT PULL 08/37] lightnvm: pblk: add padding distribution sysfs attribute Matias Bjørling
                   ` (30 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:04 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

Only one id group from the 1.2 specification is supported. Make
sure that only the first group is accessible.

Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/nvme/host/lightnvm.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 940c9b9a2a09..dc0b1335c7c6 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -166,7 +166,8 @@ struct nvme_nvm_id {
 	__le32			dom;
 	struct nvme_nvm_addr_format ppaf;
 	__u8			resv[228];
-	struct nvme_nvm_id_group groups[4];
+	struct nvme_nvm_id_group group;
+	__u8			resv2[2880];
 } __packed;
 
 struct nvme_nvm_bb_tbl {
@@ -208,7 +209,7 @@ static int init_grps(struct nvm_id *nvm_id, struct nvme_nvm_id *nvme_nvm_id)
 	if (nvme_nvm_id->cgrps != 1)
 		return -EINVAL;
 
-	src = &nvme_nvm_id->groups[0];
+	src = &nvme_nvm_id->group;
 	grp = &nvm_id->grp;
 
 	grp->mtype = src->mtype;
-- 
2.11.0

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

* [GIT PULL 08/37] lightnvm: pblk: add padding distribution sysfs attribute
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (6 preceding siblings ...)
  2018-03-29 22:04 ` [GIT PULL 07/37] lightnvm: remove multiple groups in 1.2 data structure Matias Bjørling
@ 2018-03-29 22:04 ` Matias Bjørling
  2018-03-29 22:04 ` [GIT PULL 09/37] lightnvm: pblk: delete writer kick timer before stopping thread Matias Bjørling
                   ` (29 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:04 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Hans Holmberg,
	Matias Bjørling

From: Hans Holmberg <hans.holmberg@cnexlabs.com>

When pblk receives a sync, all data up to that point in the write buffer
must be comitted to persistent storage, and as flash memory comes with a
minimal write size there is a significant cost involved both in terms
of time for completing the sync and in terms of write amplification
padded sectors for filling up to the minimal write size.

In order to get a better understanding of the costs involved for syncs,
Add a sysfs attribute to pblk: padded_dist, showing a normalized
distribution of sectors padded. In order to facilitate measurements of
specific workloads during the lifetime of the pblk instance, the
distribution can be reset by writing 0 to the attribute.

Do this by introducing counters for each possible padding:
{0..(minimal write size - 1)} and calculate the normalized distribution
when showing the attribute.

Signed-off-by: Hans Holmberg <hans.holmberg@cnexlabs.com>
Signed-off-by: Javier González <javier@cnexlabs.com>
Rearranged total_buckets statement in pblk_sysfs_get_padding_dist
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/pblk-init.c  | 16 +++++++-
 drivers/lightnvm/pblk-rb.c    | 17 +++++----
 drivers/lightnvm/pblk-sysfs.c | 87 ++++++++++++++++++++++++++++++++++++++++++-
 drivers/lightnvm/pblk.h       |  6 ++-
 4 files changed, 113 insertions(+), 13 deletions(-)

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 0ffc17ccf1cc..8416910ee8bf 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -921,6 +921,7 @@ static void pblk_free(struct pblk *pblk)
 {
 	pblk_luns_free(pblk);
 	pblk_lines_free(pblk);
+	kfree(pblk->pad_dist);
 	pblk_line_meta_free(pblk);
 	pblk_core_free(pblk);
 	pblk_l2p_free(pblk);
@@ -998,11 +999,13 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 	pblk->pad_rst_wa = 0;
 	pblk->gc_rst_wa = 0;
 
+	atomic64_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);
 	atomic_long_set(&pblk->padded_wb, 0);
-	atomic_long_set(&pblk->nr_flush, 0);
 	atomic_long_set(&pblk->req_writes, 0);
 	atomic_long_set(&pblk->sub_writes, 0);
 	atomic_long_set(&pblk->sync_writes, 0);
@@ -1034,10 +1037,17 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 		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_line_meta;
+		goto fail_free_pad_dist;
 	}
 
 	ret = pblk_l2p_init(pblk);
@@ -1097,6 +1107,8 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 	pblk_l2p_free(pblk);
 fail_free_core:
 	pblk_core_free(pblk);
+fail_free_pad_dist:
+	kfree(pblk->pad_dist);
 fail_free_line_meta:
 	pblk_line_meta_free(pblk);
 fail_free_luns:
diff --git a/drivers/lightnvm/pblk-rb.c b/drivers/lightnvm/pblk-rb.c
index 7044b5599cc4..8b1434060fb3 100644
--- a/drivers/lightnvm/pblk-rb.c
+++ b/drivers/lightnvm/pblk-rb.c
@@ -437,9 +437,7 @@ static int pblk_rb_may_write_flush(struct pblk_rb *rb, unsigned int nr_entries,
 	if (bio->bi_opf & REQ_PREFLUSH) {
 		struct pblk *pblk = container_of(rb, struct pblk, rwb);
 
-#ifdef CONFIG_NVM_DEBUG
-		atomic_long_inc(&pblk->nr_flush);
-#endif
+		atomic64_inc(&pblk->nr_flush);
 		if (pblk_rb_flush_point_set(&pblk->rwb, bio, mem))
 			*io_ret = NVM_IO_OK;
 	}
@@ -620,14 +618,17 @@ unsigned int pblk_rb_read_to_bio(struct pblk_rb *rb, struct nvm_rq *rqd,
 			pr_err("pblk: could not pad page in write bio\n");
 			return NVM_IO_ERR;
 		}
+
+		if (pad < pblk->min_write_pgs)
+			atomic64_inc(&pblk->pad_dist[pad - 1]);
+		else
+			pr_warn("pblk: padding more than min. sectors\n");
+
+		atomic64_add(pad, &pblk->pad_wa);
 	}
 
-	atomic64_add(pad, &((struct pblk *)
-			(container_of(rb, struct pblk, rwb)))->pad_wa);
-
 #ifdef CONFIG_NVM_DEBUG
-	atomic_long_add(pad, &((struct pblk *)
-			(container_of(rb, struct pblk, rwb)))->padded_writes);
+	atomic_long_add(pad, &pblk->padded_writes);
 #endif
 
 	return NVM_IO_OK;
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index beed99936c89..c2cf6c939752 100644
--- a/drivers/lightnvm/pblk-sysfs.c
+++ b/drivers/lightnvm/pblk-sysfs.c
@@ -340,15 +340,62 @@ static ssize_t pblk_sysfs_get_write_amp_trip(struct pblk *pblk, char *page)
 		atomic64_read(&pblk->pad_wa) - pblk->pad_rst_wa, page);
 }
 
+static long long bucket_percentage(unsigned long long bucket,
+				   unsigned long long total)
+{
+	int p = bucket * 100;
+
+	p = div_u64(p, total);
+
+	return p;
+}
+
+static ssize_t pblk_sysfs_get_padding_dist(struct pblk *pblk, char *page)
+{
+	int sz = 0;
+	unsigned long long total;
+	unsigned long long total_buckets = 0;
+	int buckets = pblk->min_write_pgs - 1;
+	int i;
+
+	total = atomic64_read(&pblk->nr_flush) - pblk->nr_flush_rst;
+	if (!total) {
+		for (i = 0; i < (buckets + 1); i++)
+			sz += snprintf(page + sz, PAGE_SIZE - sz,
+				"%d:0 ", i);
+		sz += snprintf(page + sz, PAGE_SIZE - sz, "\n");
+
+		return sz;
+	}
+
+	for (i = 0; i < buckets; i++)
+		total_buckets += atomic64_read(&pblk->pad_dist[i]);
+
+	sz += snprintf(page + sz, PAGE_SIZE - sz, "0:%lld%% ",
+		bucket_percentage(total - total_buckets, total));
+
+	for (i = 0; i < buckets; i++) {
+		unsigned long long p;
+
+		p = bucket_percentage(atomic64_read(&pblk->pad_dist[i]),
+					  total);
+		sz += snprintf(page + sz, PAGE_SIZE - sz, "%d:%lld%% ",
+				i + 1, p);
+	}
+	sz += snprintf(page + sz, PAGE_SIZE - sz, "\n");
+
+	return sz;
+}
+
 #ifdef CONFIG_NVM_DEBUG
 static ssize_t pblk_sysfs_stats_debug(struct pblk *pblk, char *page)
 {
 	return snprintf(page, PAGE_SIZE,
-		"%lu\t%lu\t%lu\t%lu\t%lu\t%lu\t%lu\t%lu\t%lu\t%lu\t%lu\t%lu\t%lu\n",
+		"%lu\t%lu\t%ld\t%llu\t%ld\t%lu\t%lu\t%lu\t%lu\t%lu\t%lu\t%lu\t%lu\n",
 			atomic_long_read(&pblk->inflight_writes),
 			atomic_long_read(&pblk->inflight_reads),
 			atomic_long_read(&pblk->req_writes),
-			atomic_long_read(&pblk->nr_flush),
+			(u64)atomic64_read(&pblk->nr_flush),
 			atomic_long_read(&pblk->padded_writes),
 			atomic_long_read(&pblk->padded_wb),
 			atomic_long_read(&pblk->sub_writes),
@@ -426,6 +473,32 @@ static ssize_t pblk_sysfs_set_write_amp_trip(struct pblk *pblk,
 }
 
 
+static ssize_t pblk_sysfs_set_padding_dist(struct pblk *pblk,
+			const char *page, size_t len)
+{
+	size_t c_len;
+	int reset_value;
+	int buckets = pblk->min_write_pgs - 1;
+	int i;
+
+	c_len = strcspn(page, "\n");
+	if (c_len >= len)
+		return -EINVAL;
+
+	if (kstrtouint(page, 0, &reset_value))
+		return -EINVAL;
+
+	if (reset_value !=  0)
+		return -EINVAL;
+
+	for (i = 0; i < buckets; i++)
+		atomic64_set(&pblk->pad_dist[i], 0);
+
+	pblk->nr_flush_rst = atomic64_read(&pblk->nr_flush);
+
+	return len;
+}
+
 static struct attribute sys_write_luns = {
 	.name = "write_luns",
 	.mode = 0444,
@@ -486,6 +559,11 @@ static struct attribute sys_write_amp_trip = {
 	.mode = 0644,
 };
 
+static struct attribute sys_padding_dist = {
+	.name = "padding_dist",
+	.mode = 0644,
+};
+
 #ifdef CONFIG_NVM_DEBUG
 static struct attribute sys_stats_debug_attr = {
 	.name = "stats",
@@ -506,6 +584,7 @@ static struct attribute *pblk_attrs[] = {
 	&sys_lines_info_attr,
 	&sys_write_amp_mileage,
 	&sys_write_amp_trip,
+	&sys_padding_dist,
 #ifdef CONFIG_NVM_DEBUG
 	&sys_stats_debug_attr,
 #endif
@@ -539,6 +618,8 @@ static ssize_t pblk_sysfs_show(struct kobject *kobj, struct attribute *attr,
 		return pblk_sysfs_get_write_amp_mileage(pblk, buf);
 	else if (strcmp(attr->name, "write_amp_trip") == 0)
 		return pblk_sysfs_get_write_amp_trip(pblk, buf);
+	else if (strcmp(attr->name, "padding_dist") == 0)
+		return pblk_sysfs_get_padding_dist(pblk, buf);
 #ifdef CONFIG_NVM_DEBUG
 	else if (strcmp(attr->name, "stats") == 0)
 		return pblk_sysfs_stats_debug(pblk, buf);
@@ -557,6 +638,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, "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 4b7d8618631f..17e2f242f7da 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -626,12 +626,16 @@ struct pblk {
 	u64 gc_rst_wa;
 	u64 pad_rst_wa;
 
+	/* Counters used for calculating padding distribution */
+	atomic64_t *pad_dist;		/* Padding distribution buckets */
+	u64 nr_flush_rst;		/* Flushes reset value for pad dist.*/
+	atomic64_t nr_flush;		/* Number of flush/fua I/O */
+
 #ifdef CONFIG_NVM_DEBUG
 	/* Non-persistent debug counters, 4kb sector I/Os */
 	atomic_long_t inflight_writes;	/* Inflight writes (user and gc) */
 	atomic_long_t padded_writes;	/* Sectors padded due to flush/fua */
 	atomic_long_t padded_wb;	/* Sectors padded in write buffer */
-	atomic_long_t nr_flush;		/* Number of flush/fua I/O */
 	atomic_long_t req_writes;	/* Sectors stored on write buffer */
 	atomic_long_t sub_writes;	/* Sectors submitted from buffer */
 	atomic_long_t sync_writes;	/* Sectors synced to media */
-- 
2.11.0

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

* [GIT PULL 09/37] lightnvm: pblk: delete writer kick timer before stopping thread
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (7 preceding siblings ...)
  2018-03-29 22:04 ` [GIT PULL 08/37] lightnvm: pblk: add padding distribution sysfs attribute Matias Bjørling
@ 2018-03-29 22:04 ` Matias Bjørling
  2018-03-29 22:04 ` [GIT PULL 10/37] lightnvm: pblk: allow allocation of new lines during shutdown Matias Bjørling
                   ` (28 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:04 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Hans Holmberg,
	Matias Bjørling

From: Hans Holmberg <hans.holmberg@cnexlabs.com>

Unless we delete the timer that wakes up the write thread
before we stop the thread we risk re-starting the thread, so
delete the timer first.

Signed-off-by: Hans Holmberg <hans.holmberg@cnexlabs.com>
Reviewed-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/pblk-init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 8416910ee8bf..49c65f1dd48b 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -912,9 +912,9 @@ static void pblk_writer_stop(struct pblk *pblk)
 	WARN(pblk_rb_sync_count(&pblk->rwb),
 			"Stopping not fully synced write buffer\n");
 
+	del_timer_sync(&pblk->wtimer);
 	if (pblk->writer_ts)
 		kthread_stop(pblk->writer_ts);
-	del_timer(&pblk->wtimer);
 }
 
 static void pblk_free(struct pblk *pblk)
-- 
2.11.0

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

* [GIT PULL 10/37] lightnvm: pblk: allow allocation of new lines during shutdown
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (8 preceding siblings ...)
  2018-03-29 22:04 ` [GIT PULL 09/37] lightnvm: pblk: delete writer kick timer before stopping thread Matias Bjørling
@ 2018-03-29 22:04 ` Matias Bjørling
  2018-03-29 22:04 ` [GIT PULL 11/37] lightnvm: pblk: prevent race in pblk_rb_flush_point_set Matias Bjørling
                   ` (27 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:04 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Hans Holmberg,
	Matias Bjørling

From: Hans Holmberg <hans.holmberg@cnexlabs.com>

When shutting down pblk the write buffer is flushed and if the
current line can't fit the data in the write buffer we need
to allocate a new line, so remove the check that prevents this.

Signed-off-by: Hans Holmberg <hans.holmberg@cnexlabs.com>
Reviewed-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/pblk-core.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index 22e61cd4f801..8848443a0721 100644
--- a/drivers/lightnvm/pblk-core.c
+++ b/drivers/lightnvm/pblk-core.c
@@ -1407,13 +1407,6 @@ struct pblk_line *pblk_line_replace_data(struct pblk *pblk)
 	l_mg->data_line = new;
 
 	spin_lock(&l_mg->free_lock);
-	if (pblk->state != PBLK_STATE_RUNNING) {
-		l_mg->data_line = NULL;
-		l_mg->data_next = NULL;
-		spin_unlock(&l_mg->free_lock);
-		goto out;
-	}
-
 	pblk_line_setup_metadata(new, l_mg, &pblk->lm);
 	spin_unlock(&l_mg->free_lock);
 
-- 
2.11.0

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

* [GIT PULL 11/37] lightnvm: pblk: prevent race in pblk_rb_flush_point_set
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (9 preceding siblings ...)
  2018-03-29 22:04 ` [GIT PULL 10/37] lightnvm: pblk: allow allocation of new lines during shutdown Matias Bjørling
@ 2018-03-29 22:04 ` Matias Bjørling
  2018-03-29 22:04 ` [GIT PULL 12/37] lightnvm: pblk: refactor bad block identification Matias Bjørling
                   ` (26 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:04 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Hans Holmberg,
	Matias Bjørling

From: Hans Holmberg <hans.holmberg@cnexlabs.com>

Make sure that we are not advancing the sync pointer while
we're adding bios to the write buffer entry completion list.

This race condition results in bios not completing and was identified
by a hang when running xfstest generic/113.

Signed-off-by: Hans Holmberg <hans.holmberg@cnexlabs.com>
Reviewed-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/pblk-rb.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/lightnvm/pblk-rb.c b/drivers/lightnvm/pblk-rb.c
index 8b1434060fb3..52fdd85dbc97 100644
--- a/drivers/lightnvm/pblk-rb.c
+++ b/drivers/lightnvm/pblk-rb.c
@@ -355,10 +355,13 @@ static int pblk_rb_flush_point_set(struct pblk_rb *rb, struct bio *bio,
 	struct pblk_rb_entry *entry;
 	unsigned int sync, flush_point;
 
+	pblk_rb_sync_init(rb, NULL);
 	sync = READ_ONCE(rb->sync);
 
-	if (pos == sync)
+	if (pos == sync) {
+		pblk_rb_sync_end(rb, NULL);
 		return 0;
+	}
 
 #ifdef CONFIG_NVM_DEBUG
 	atomic_inc(&rb->inflight_flush_point);
@@ -367,8 +370,6 @@ static int pblk_rb_flush_point_set(struct pblk_rb *rb, struct bio *bio,
 	flush_point = (pos == 0) ? (rb->nr_entries - 1) : (pos - 1);
 	entry = &rb->entries[flush_point];
 
-	pblk_rb_sync_init(rb, NULL);
-
 	/* Protect flush points */
 	smp_store_release(&rb->flush_point, flush_point);
 
-- 
2.11.0

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

* [GIT PULL 12/37] lightnvm: pblk: refactor bad block identification
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (10 preceding siblings ...)
  2018-03-29 22:04 ` [GIT PULL 11/37] lightnvm: pblk: prevent race in pblk_rb_flush_point_set Matias Bjørling
@ 2018-03-29 22:04 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 13/37] lightnvm: make 1.2 data structures explicit Matias Bjørling
                   ` (25 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:04 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier,
	Javier González, Matias Bjørling

From: Javier González <jg@lightnvm.io>

In preparation for the OCSSD 2.0 spec. bad block identification,
refactor the current code to generalize bad block get/set functions and
structures.

Signed-off-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/pblk-core.c |   3 -
 drivers/lightnvm/pblk-init.c | 211 ++++++++++++++++++++++---------------------
 drivers/lightnvm/pblk.h      |   6 --
 3 files changed, 110 insertions(+), 110 deletions(-)

diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index 8848443a0721..5c363ccde0e3 100644
--- a/drivers/lightnvm/pblk-core.c
+++ b/drivers/lightnvm/pblk-core.c
@@ -1025,7 +1025,6 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
 	struct nvm_geo *geo = &dev->geo;
 	struct pblk_line_meta *lm = &pblk->lm;
 	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
-	int nr_bb = 0;
 	u64 off;
 	int bit = -1;
 	int emeta_secs;
@@ -1041,8 +1040,6 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *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;
-		if (bit >= lm->emeta_bb)
-			nr_bb++;
 	}
 
 	/* Mark smeta metadata sectors as bad sectors */
diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 49c65f1dd48b..141036bd6afa 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -365,7 +365,25 @@ static void pblk_luns_free(struct pblk *pblk)
 	kfree(pblk->luns);
 }
 
-static void pblk_free_line_bitmaps(struct pblk_line *line)
+static void pblk_line_mg_free(struct pblk *pblk)
+{
+	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
+	int i;
+
+	kfree(l_mg->bb_template);
+	kfree(l_mg->bb_aux);
+	kfree(l_mg->vsc_list);
+
+	for (i = 0; i < PBLK_DATA_LINES; i++) {
+		kfree(l_mg->sline_meta[i]);
+		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)
 {
 	kfree(line->blk_bitmap);
 	kfree(line->erase_bitmap);
@@ -382,40 +400,16 @@ static void pblk_lines_free(struct pblk *pblk)
 		line = &pblk->lines[i];
 
 		pblk_line_free(pblk, line);
-		pblk_free_line_bitmaps(line);
+		pblk_line_meta_free(line);
 	}
 	spin_unlock(&l_mg->free_lock);
 }
 
-static void pblk_line_meta_free(struct pblk *pblk)
+static int pblk_bb_get_tbl(struct nvm_tgt_dev *dev, struct pblk_lun *rlun,
+			   u8 *blks, int nr_blks)
 {
-	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
-	int i;
-
-	kfree(l_mg->bb_template);
-	kfree(l_mg->bb_aux);
-	kfree(l_mg->vsc_list);
-
-	for (i = 0; i < PBLK_DATA_LINES; i++) {
-		kfree(l_mg->sline_meta[i]);
-		pblk_mfree(l_mg->eline_meta[i]->buf, l_mg->emeta_alloc_type);
-		kfree(l_mg->eline_meta[i]);
-	}
-
-	kfree(pblk->lines);
-}
-
-static int pblk_bb_discovery(struct nvm_tgt_dev *dev, struct pblk_lun *rlun)
-{
-	struct nvm_geo *geo = &dev->geo;
 	struct ppa_addr ppa;
-	u8 *blks;
-	int nr_blks, ret;
-
-	nr_blks = geo->nr_chks * geo->plane_mode;
-	blks = kmalloc(nr_blks, GFP_KERNEL);
-	if (!blks)
-		return -ENOMEM;
+	int ret;
 
 	ppa.ppa = 0;
 	ppa.g.ch = rlun->bppa.g.ch;
@@ -423,34 +417,56 @@ static int pblk_bb_discovery(struct nvm_tgt_dev *dev, struct pblk_lun *rlun)
 
 	ret = nvm_get_tgt_bb_tbl(dev, ppa, blks);
 	if (ret)
-		goto out;
+		return ret;
 
 	nr_blks = nvm_bb_tbl_fold(dev->parent, blks, nr_blks);
-	if (nr_blks < 0) {
-		ret = nr_blks;
-		goto out;
-	}
-
-	rlun->bb_list = blks;
+	if (nr_blks < 0)
+		return -EIO;
 
 	return 0;
-out:
-	kfree(blks);
-	return ret;
+}
+
+static void *pblk_bb_get_log(struct pblk *pblk)
+{
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	u8 *log;
+	int i, nr_blks, blk_per_lun;
+	int ret;
+
+	blk_per_lun = geo->nr_chks * geo->plane_mode;
+	nr_blks = blk_per_lun * geo->all_luns;
+
+	log = kmalloc(nr_blks, GFP_KERNEL);
+	if (!log)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < geo->all_luns; i++) {
+		struct pblk_lun *rlun = &pblk->luns[i];
+		u8 *log_pos = log + i * blk_per_lun;
+
+		ret = pblk_bb_get_tbl(dev, rlun, log_pos, blk_per_lun);
+		if (ret) {
+			kfree(log);
+			return ERR_PTR(-EIO);
+		}
+	}
+
+	return log;
 }
 
 static int pblk_bb_line(struct pblk *pblk, struct pblk_line *line,
-			int blk_per_line)
+			u8 *bb_log, int blk_per_line)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
-	struct pblk_lun *rlun;
-	int bb_cnt = 0;
-	int i;
+	int i, bb_cnt = 0;
 
 	for (i = 0; i < blk_per_line; i++) {
-		rlun = &pblk->luns[i];
-		if (rlun->bb_list[line->id] == NVM_BLK_T_FREE)
+		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);
@@ -460,29 +476,12 @@ static int pblk_bb_line(struct pblk *pblk, struct pblk_line *line,
 	return bb_cnt;
 }
 
-static int pblk_alloc_line_bitmaps(struct pblk *pblk, struct pblk_line *line)
-{
-	struct pblk_line_meta *lm = &pblk->lm;
-
-	line->blk_bitmap = kzalloc(lm->blk_bitmap_len, GFP_KERNEL);
-	if (!line->blk_bitmap)
-		return -ENOMEM;
-
-	line->erase_bitmap = kzalloc(lm->blk_bitmap_len, GFP_KERNEL);
-	if (!line->erase_bitmap) {
-		kfree(line->blk_bitmap);
-		return -ENOMEM;
-	}
-
-	return 0;
-}
-
 static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
 	struct pblk_lun *rlun;
-	int i, ret;
+	int i;
 
 	/* TODO: Implement unbalanced LUN support */
 	if (geo->nr_luns < 0) {
@@ -505,13 +504,6 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
 		rlun->bppa = luns[lunid];
 
 		sema_init(&rlun->wr_sem, 1);
-
-		ret = pblk_bb_discovery(dev, rlun);
-		if (ret) {
-			while (--i >= 0)
-				kfree(pblk->luns[i].bb_list);
-			return ret;
-		}
 	}
 
 	return 0;
@@ -689,6 +681,26 @@ 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)
+{
+	struct pblk_line_meta *lm = &pblk->lm;
+
+	line->blk_bitmap = kzalloc(lm->blk_bitmap_len, GFP_KERNEL);
+	if (!line->blk_bitmap)
+		return -ENOMEM;
+
+	line->erase_bitmap = kzalloc(lm->blk_bitmap_len, GFP_KERNEL);
+	if (!line->erase_bitmap) {
+		kfree(line->blk_bitmap);
+		return -ENOMEM;
+	}
+
+	*nr_bad_blks = pblk_bb_line(pblk, line, chunk_log, lm->blk_per_line);
+
+	return 0;
+}
+
 static int pblk_lines_init(struct pblk *pblk)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
@@ -696,8 +708,9 @@ static int pblk_lines_init(struct pblk *pblk)
 	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_bad_blks, nr_free_blks;
+	long nr_bad_blks = 0, nr_free_blks = 0;
 	int bb_distance, max_write_ppas, mod;
 	int i, ret;
 
@@ -771,13 +784,12 @@ static int pblk_lines_init(struct pblk *pblk)
 	if (lm->min_blk_line > lm->blk_per_line) {
 		pr_err("pblk: config. not supported. Min. LUN in line:%d\n",
 							lm->blk_per_line);
-		ret = -EINVAL;
-		goto fail;
+		return -EINVAL;
 	}
 
 	ret = pblk_lines_alloc_metadata(pblk);
 	if (ret)
-		goto fail;
+		return ret;
 
 	l_mg->bb_template = kzalloc(lm->sec_bitmap_len, GFP_KERNEL);
 	if (!l_mg->bb_template) {
@@ -821,9 +833,16 @@ static int pblk_lines_init(struct pblk *pblk)
 		goto fail_free_bb_aux;
 	}
 
-	nr_free_blks = 0;
+	chunk_log = pblk_bb_get_log(pblk);
+	if (IS_ERR(chunk_log)) {
+		pr_err("pblk: could not get bad block log (%lu)\n",
+							PTR_ERR(chunk_log));
+		ret = PTR_ERR(chunk_log);
+		goto fail_free_bb_aux;
+	}
+
 	for (i = 0; i < l_mg->nr_lines; i++) {
-		int blk_in_line;
+		int chk_in_line;
 
 		line = &pblk->lines[i];
 
@@ -835,26 +854,20 @@ static int pblk_lines_init(struct pblk *pblk)
 		line->vsc = &l_mg->vsc_list[i];
 		spin_lock_init(&line->lock);
 
-		ret = pblk_alloc_line_bitmaps(pblk, line);
+		ret = pblk_setup_line_meta(pblk, line, chunk_log, &nr_bad_blks);
 		if (ret)
-			goto fail_free_lines;
+			goto fail_free_chunk_log;
 
-		nr_bad_blks = pblk_bb_line(pblk, line, lm->blk_per_line);
-		if (nr_bad_blks < 0 || nr_bad_blks > lm->blk_per_line) {
-			pblk_free_line_bitmaps(line);
-			ret = -EINVAL;
-			goto fail_free_lines;
-		}
-
-		blk_in_line = lm->blk_per_line - nr_bad_blks;
-		if (blk_in_line < lm->min_blk_line) {
+		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 += blk_in_line;
-		atomic_set(&line->blk_in_line, blk_in_line);
+		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);
@@ -862,23 +875,19 @@ static int pblk_lines_init(struct pblk *pblk)
 
 	pblk_set_provision(pblk, nr_free_blks);
 
-	/* Cleanup per-LUN bad block lists - managed within lines on run-time */
-	for (i = 0; i < geo->all_luns; i++)
-		kfree(pblk->luns[i].bb_list);
-
+	kfree(chunk_log);
 	return 0;
-fail_free_lines:
+
+fail_free_chunk_log:
+	kfree(chunk_log);
 	while (--i >= 0)
-		pblk_free_line_bitmaps(&pblk->lines[i]);
+		pblk_line_meta_free(&pblk->lines[i]);
 fail_free_bb_aux:
 	kfree(l_mg->bb_aux);
 fail_free_bb_template:
 	kfree(l_mg->bb_template);
 fail_free_meta:
-	pblk_line_meta_free(pblk);
-fail:
-	for (i = 0; i < geo->all_luns; i++)
-		kfree(pblk->luns[i].bb_list);
+	pblk_line_mg_free(pblk);
 
 	return ret;
 }
@@ -922,7 +931,7 @@ static void pblk_free(struct pblk *pblk)
 	pblk_luns_free(pblk);
 	pblk_lines_free(pblk);
 	kfree(pblk->pad_dist);
-	pblk_line_meta_free(pblk);
+	pblk_line_mg_free(pblk);
 	pblk_core_free(pblk);
 	pblk_l2p_free(pblk);
 
@@ -1110,7 +1119,7 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 fail_free_pad_dist:
 	kfree(pblk->pad_dist);
 fail_free_line_meta:
-	pblk_line_meta_free(pblk);
+	pblk_line_mg_free(pblk);
 fail_free_luns:
 	pblk_luns_free(pblk);
 fail:
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 17e2f242f7da..f0309d8172c0 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -201,12 +201,6 @@ struct pblk_rb {
 
 struct pblk_lun {
 	struct ppa_addr bppa;
-
-	u8 *bb_list;			/* Bad block list for LUN. Only used on
-					 * bring up. Bad blocks are managed
-					 * within lines on run-time.
-					 */
-
 	struct semaphore wr_sem;
 };
 
-- 
2.11.0

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

* [GIT PULL 13/37] lightnvm: make 1.2 data structures explicit
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (11 preceding siblings ...)
  2018-03-29 22:04 ` [GIT PULL 12/37] lightnvm: pblk: refactor bad block identification Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 14/37] lightnvm: flatten nvm_id_group into nvm_id Matias Bjørling
                   ` (24 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

Make the 1.2 data structures explicit, so it will be easy to identify
the 2.0 data structures. Also fix the order of which the nvme_nvm_*
are declared, such that they follow the nvme_nvm_command order.

Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/nvme/host/lightnvm.c | 82 ++++++++++++++++++++++----------------------
 1 file changed, 41 insertions(+), 41 deletions(-)

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index dc0b1335c7c6..60db3f1b59da 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -51,6 +51,21 @@ struct nvme_nvm_ph_rw {
 	__le64			resv;
 };
 
+struct nvme_nvm_erase_blk {
+	__u8			opcode;
+	__u8			flags;
+	__u16			command_id;
+	__le32			nsid;
+	__u64			rsvd[2];
+	__le64			prp1;
+	__le64			prp2;
+	__le64			spba;
+	__le16			length;
+	__le16			control;
+	__le32			dsmgmt;
+	__le64			resv;
+};
+
 struct nvme_nvm_identity {
 	__u8			opcode;
 	__u8			flags;
@@ -89,33 +104,18 @@ struct nvme_nvm_setbbtbl {
 	__u32			rsvd4[3];
 };
 
-struct nvme_nvm_erase_blk {
-	__u8			opcode;
-	__u8			flags;
-	__u16			command_id;
-	__le32			nsid;
-	__u64			rsvd[2];
-	__le64			prp1;
-	__le64			prp2;
-	__le64			spba;
-	__le16			length;
-	__le16			control;
-	__le32			dsmgmt;
-	__le64			resv;
-};
-
 struct nvme_nvm_command {
 	union {
 		struct nvme_common_command common;
-		struct nvme_nvm_identity identity;
 		struct nvme_nvm_ph_rw ph_rw;
+		struct nvme_nvm_erase_blk erase;
+		struct nvme_nvm_identity identity;
 		struct nvme_nvm_getbbtbl get_bb;
 		struct nvme_nvm_setbbtbl set_bb;
-		struct nvme_nvm_erase_blk erase;
 	};
 };
 
-struct nvme_nvm_id_group {
+struct nvme_nvm_id12_grp {
 	__u8			mtype;
 	__u8			fmtype;
 	__le16			res16;
@@ -141,7 +141,7 @@ struct nvme_nvm_id_group {
 	__u8			reserved[906];
 } __packed;
 
-struct nvme_nvm_addr_format {
+struct nvme_nvm_id12_addrf {
 	__u8			ch_offset;
 	__u8			ch_len;
 	__u8			lun_offset;
@@ -157,16 +157,16 @@ struct nvme_nvm_addr_format {
 	__u8			res[4];
 } __packed;
 
-struct nvme_nvm_id {
+struct nvme_nvm_id12 {
 	__u8			ver_id;
 	__u8			vmnt;
 	__u8			cgrps;
 	__u8			res;
 	__le32			cap;
 	__le32			dom;
-	struct nvme_nvm_addr_format ppaf;
+	struct nvme_nvm_id12_addrf ppaf;
 	__u8			resv[228];
-	struct nvme_nvm_id_group group;
+	struct nvme_nvm_id12_grp grp;
 	__u8			resv2[2880];
 } __packed;
 
@@ -191,25 +191,25 @@ static inline void _nvme_nvm_check_size(void)
 {
 	BUILD_BUG_ON(sizeof(struct nvme_nvm_identity) != 64);
 	BUILD_BUG_ON(sizeof(struct nvme_nvm_ph_rw) != 64);
+	BUILD_BUG_ON(sizeof(struct nvme_nvm_erase_blk) != 64);
 	BUILD_BUG_ON(sizeof(struct nvme_nvm_getbbtbl) != 64);
 	BUILD_BUG_ON(sizeof(struct nvme_nvm_setbbtbl) != 64);
-	BUILD_BUG_ON(sizeof(struct nvme_nvm_erase_blk) != 64);
-	BUILD_BUG_ON(sizeof(struct nvme_nvm_id_group) != 960);
-	BUILD_BUG_ON(sizeof(struct nvme_nvm_addr_format) != 16);
-	BUILD_BUG_ON(sizeof(struct nvme_nvm_id) != NVME_IDENTIFY_DATA_SIZE);
+	BUILD_BUG_ON(sizeof(struct nvme_nvm_id12_grp) != 960);
+	BUILD_BUG_ON(sizeof(struct nvme_nvm_id12_addrf) != 16);
+	BUILD_BUG_ON(sizeof(struct nvme_nvm_id12) != NVME_IDENTIFY_DATA_SIZE);
 	BUILD_BUG_ON(sizeof(struct nvme_nvm_bb_tbl) != 64);
 }
 
-static int init_grps(struct nvm_id *nvm_id, struct nvme_nvm_id *nvme_nvm_id)
+static int init_grp(struct nvm_id *nvm_id, struct nvme_nvm_id12 *id12)
 {
-	struct nvme_nvm_id_group *src;
+	struct nvme_nvm_id12_grp *src;
 	struct nvm_id_group *grp;
 	int sec_per_pg, sec_per_pl, pg_per_blk;
 
-	if (nvme_nvm_id->cgrps != 1)
+	if (id12->cgrps != 1)
 		return -EINVAL;
 
-	src = &nvme_nvm_id->group;
+	src = &id12->grp;
 	grp = &nvm_id->grp;
 
 	grp->mtype = src->mtype;
@@ -261,34 +261,34 @@ static int init_grps(struct nvm_id *nvm_id, struct nvme_nvm_id *nvme_nvm_id)
 static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
 {
 	struct nvme_ns *ns = nvmdev->q->queuedata;
-	struct nvme_nvm_id *nvme_nvm_id;
+	struct nvme_nvm_id12 *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);
 
-	nvme_nvm_id = kmalloc(sizeof(struct nvme_nvm_id), GFP_KERNEL);
-	if (!nvme_nvm_id)
+	id = kmalloc(sizeof(struct nvme_nvm_id12), GFP_KERNEL);
+	if (!id)
 		return -ENOMEM;
 
 	ret = nvme_submit_sync_cmd(ns->ctrl->admin_q, (struct nvme_command *)&c,
-				nvme_nvm_id, sizeof(struct nvme_nvm_id));
+				id, sizeof(struct nvme_nvm_id12));
 	if (ret) {
 		ret = -EIO;
 		goto out;
 	}
 
-	nvm_id->ver_id = nvme_nvm_id->ver_id;
-	nvm_id->vmnt = nvme_nvm_id->vmnt;
-	nvm_id->cap = le32_to_cpu(nvme_nvm_id->cap);
-	nvm_id->dom = le32_to_cpu(nvme_nvm_id->dom);
-	memcpy(&nvm_id->ppaf, &nvme_nvm_id->ppaf,
+	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));
 
-	ret = init_grps(nvm_id, nvme_nvm_id);
+	ret = init_grp(nvm_id, id);
 out:
-	kfree(nvme_nvm_id);
+	kfree(id);
 	return ret;
 }
 
-- 
2.11.0

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

* [GIT PULL 14/37] lightnvm: flatten nvm_id_group into nvm_id
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (12 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 13/37] lightnvm: make 1.2 data structures explicit Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 15/37] lightnvm: add 2.0 geometry identification Matias Bjørling
                   ` (23 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

There are no groups in the 2.0 specification, make sure that the
nvm_id structure is flattened before 2.0 data structures are added.

Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/core.c      |  25 ++++++-----
 drivers/nvme/host/lightnvm.c | 100 +++++++++++++++++++++----------------------
 include/linux/lightnvm.h     |  53 +++++++++++------------
 3 files changed, 86 insertions(+), 92 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 5f1988df1593..db4a1b8f1561 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -851,33 +851,32 @@ EXPORT_SYMBOL(nvm_get_tgt_bb_tbl);
 static int nvm_core_init(struct nvm_dev *dev)
 {
 	struct nvm_id *id = &dev->identity;
-	struct nvm_id_group *grp = &id->grp;
 	struct nvm_geo *geo = &dev->geo;
 	int ret;
 
 	memcpy(&geo->ppaf, &id->ppaf, sizeof(struct nvm_addr_format));
 
-	if (grp->mtype != 0) {
+	if (id->mtype != 0) {
 		pr_err("nvm: memory type not supported\n");
 		return -EINVAL;
 	}
 
 	/* Whole device values */
-	geo->nr_chnls = grp->num_ch;
-	geo->nr_luns = grp->num_lun;
+	geo->nr_chnls = id->num_ch;
+	geo->nr_luns = id->num_lun;
 
 	/* Generic device geometry values */
-	geo->ws_min = grp->ws_min;
-	geo->ws_opt = grp->ws_opt;
-	geo->ws_seq = grp->ws_seq;
-	geo->ws_per_chk = grp->ws_per_chk;
-	geo->nr_chks = grp->num_chk;
-	geo->sec_size = grp->csecs;
-	geo->oob_size = grp->sos;
-	geo->mccap = grp->mccap;
+	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->sec_size = id->csecs;
+	geo->oob_size = id->sos;
+	geo->mccap = id->mccap;
 	geo->max_rq_size = dev->ops->max_phys_sect * geo->sec_size;
 
-	geo->sec_per_chk = grp->clba;
+	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;
 
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 60db3f1b59da..6412551ecc65 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -203,57 +203,55 @@ static inline void _nvme_nvm_check_size(void)
 static int init_grp(struct nvm_id *nvm_id, struct nvme_nvm_id12 *id12)
 {
 	struct nvme_nvm_id12_grp *src;
-	struct nvm_id_group *grp;
 	int sec_per_pg, sec_per_pl, pg_per_blk;
 
 	if (id12->cgrps != 1)
 		return -EINVAL;
 
 	src = &id12->grp;
-	grp = &nvm_id->grp;
 
-	grp->mtype = src->mtype;
-	grp->fmtype = src->fmtype;
+	nvm_id->mtype = src->mtype;
+	nvm_id->fmtype = src->fmtype;
 
-	grp->num_ch = src->num_ch;
-	grp->num_lun = src->num_lun;
+	nvm_id->num_ch = src->num_ch;
+	nvm_id->num_lun = src->num_lun;
 
-	grp->num_chk = le16_to_cpu(src->num_chk);
-	grp->csecs = le16_to_cpu(src->csecs);
-	grp->sos = le16_to_cpu(src->sos);
+	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);
 
 	pg_per_blk = le16_to_cpu(src->num_pg);
-	sec_per_pg = le16_to_cpu(src->fpg_sz) / grp->csecs;
+	sec_per_pg = le16_to_cpu(src->fpg_sz) / nvm_id->csecs;
 	sec_per_pl = sec_per_pg * src->num_pln;
-	grp->clba = sec_per_pl * pg_per_blk;
-	grp->ws_per_chk = pg_per_blk;
+	nvm_id->clba = sec_per_pl * pg_per_blk;
+	nvm_id->ws_per_chk = pg_per_blk;
 
-	grp->mpos = le32_to_cpu(src->mpos);
-	grp->cpar = le16_to_cpu(src->cpar);
-	grp->mccap = le32_to_cpu(src->mccap);
+	nvm_id->mpos = le32_to_cpu(src->mpos);
+	nvm_id->cpar = le16_to_cpu(src->cpar);
+	nvm_id->mccap = le32_to_cpu(src->mccap);
 
-	grp->ws_opt = grp->ws_min = sec_per_pg;
-	grp->ws_seq = NVM_IO_SNGL_ACCESS;
+	nvm_id->ws_opt = nvm_id->ws_min = sec_per_pg;
+	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
 
-	if (grp->mpos & 0x020202) {
-		grp->ws_seq = NVM_IO_DUAL_ACCESS;
-		grp->ws_opt <<= 1;
-	} else if (grp->mpos & 0x040404) {
-		grp->ws_seq = NVM_IO_QUAD_ACCESS;
-		grp->ws_opt <<= 2;
+	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;
 	}
 
-	grp->trdt = le32_to_cpu(src->trdt);
-	grp->trdm = le32_to_cpu(src->trdm);
-	grp->tprt = le32_to_cpu(src->tprt);
-	grp->tprm = le32_to_cpu(src->tprm);
-	grp->tbet = le32_to_cpu(src->tbet);
-	grp->tbem = le32_to_cpu(src->tbem);
+	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 */
-	grp->num_pln = src->num_pln;
-	grp->num_pg = le16_to_cpu(src->num_pg);
-	grp->fpg_sz = le16_to_cpu(src->fpg_sz);
+	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);
 
 	return 0;
 }
@@ -740,14 +738,12 @@ 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_id_group *grp;
 	struct attribute *attr;
 
 	if (!ndev)
 		return 0;
 
 	id = &ndev->identity;
-	grp = &id->grp;
 	attr = &dattr->attr;
 
 	if (strcmp(attr->name, "version") == 0) {
@@ -771,41 +767,41 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
 			id->ppaf.pg_offset, id->ppaf.pg_len,
 			id->ppaf.sect_offset, id->ppaf.sect_len);
 	} else if (strcmp(attr->name, "media_type") == 0) {	/* u8 */
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->mtype);
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->mtype);
 	} else if (strcmp(attr->name, "flash_media_type") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->fmtype);
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->fmtype);
 	} else if (strcmp(attr->name, "num_channels") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_ch);
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_ch);
 	} else if (strcmp(attr->name, "num_luns") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_lun);
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
 	} else if (strcmp(attr->name, "num_planes") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_pln);
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pln);
 	} else if (strcmp(attr->name, "num_blocks") == 0) {	/* u16 */
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_chk);
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
 	} else if (strcmp(attr->name, "num_pages") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_pg);
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_pg);
 	} else if (strcmp(attr->name, "page_size") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->fpg_sz);
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->fpg_sz);
 	} else if (strcmp(attr->name, "hw_sector_size") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->csecs);
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->csecs);
 	} else if (strcmp(attr->name, "oob_sector_size") == 0) {/* u32 */
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->sos);
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->sos);
 	} else if (strcmp(attr->name, "read_typ") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->trdt);
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdt);
 	} else if (strcmp(attr->name, "read_max") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->trdm);
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdm);
 	} else if (strcmp(attr->name, "prog_typ") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->tprt);
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
 	} else if (strcmp(attr->name, "prog_max") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->tprm);
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
 	} else if (strcmp(attr->name, "erase_typ") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->tbet);
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
 	} else if (strcmp(attr->name, "erase_max") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->tbem);
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
 	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
-		return scnprintf(page, PAGE_SIZE, "0x%08x\n", grp->mpos);
+		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mpos);
 	} else if (strcmp(attr->name, "media_capabilities") == 0) {
-		return scnprintf(page, PAGE_SIZE, "0x%08x\n", grp->mccap);
+		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mccap);
 	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n",
 				ndev->ops->max_phys_sect);
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 7f4b60abdf27..94b704a8d83d 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -154,9 +154,29 @@ struct nvm_id_lp_tbl {
 	struct nvm_id_lp_mlc mlc;
 };
 
-struct nvm_id_group {
-	u8	mtype;
-	u8	fmtype;
+struct nvm_addr_format {
+	u8	ch_offset;
+	u8	ch_len;
+	u8	lun_offset;
+	u8	lun_len;
+	u8	pln_offset;
+	u8	pln_len;
+	u8	blk_offset;
+	u8	blk_len;
+	u8	pg_offset;
+	u8	pg_len;
+	u8	sect_offset;
+	u8	sect_len;
+};
+
+struct nvm_id {
+	u8	ver_id;
+	u8	vmnt;
+	u32	cap;
+	u32	dom;
+
+	struct	nvm_addr_format ppaf;
+
 	u8	num_ch;
 	u8	num_lun;
 	u16	num_chk;
@@ -180,33 +200,12 @@ struct nvm_id_group {
 	u16	cpar;
 
 	/* 1.2 compatibility */
+	u8	mtype;
+	u8	fmtype;
+
 	u8	num_pln;
 	u16	num_pg;
 	u16	fpg_sz;
-};
-
-struct nvm_addr_format {
-	u8	ch_offset;
-	u8	ch_len;
-	u8	lun_offset;
-	u8	lun_len;
-	u8	pln_offset;
-	u8	pln_len;
-	u8	blk_offset;
-	u8	blk_len;
-	u8	pg_offset;
-	u8	pg_len;
-	u8	sect_offset;
-	u8	sect_len;
-};
-
-struct nvm_id {
-	u8	ver_id;
-	u8	vmnt;
-	u32	cap;
-	u32	dom;
-	struct nvm_addr_format ppaf;
-	struct nvm_id_group grp;
 } __packed;
 
 struct nvm_target {
-- 
2.11.0

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

* [GIT PULL 15/37] lightnvm: add 2.0 geometry identification
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (13 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 14/37] lightnvm: flatten nvm_id_group into nvm_id Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 16/37] lightnvm: remove max_rq_size Matias Bjørling
                   ` (22 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

Implement the geometry data structures for 2.0 and enable a drive
to be identified as one, including exposing the appropriate 2.0
sysfs entries.

Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/core.c      |   8 +-
 drivers/nvme/host/lightnvm.c | 334 +++++++++++++++++++++++++++++++++++++------
 include/linux/lightnvm.h     |  11 +-
 3 files changed, 297 insertions(+), 56 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index db4a1b8f1561..521f520a1bb4 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -931,11 +931,9 @@ static int nvm_init(struct nvm_dev *dev)
 		goto err;
 	}
 
-	pr_debug("nvm: ver:%x nvm_vendor:%x\n",
-			dev->identity.ver_id, dev->identity.vmnt);
-
-	if (dev->identity.ver_id != 1) {
-		pr_err("nvm: device not supported by kernel.");
+	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;
 	}
 
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 6412551ecc65..8b243af8a949 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -184,6 +184,58 @@ struct nvme_nvm_bb_tbl {
 	__u8	blk[0];
 };
 
+struct nvme_nvm_id20_addrf {
+	__u8			grp_len;
+	__u8			pu_len;
+	__u8			chk_len;
+	__u8			lba_len;
+	__u8			resv[4];
+};
+
+struct nvme_nvm_id20 {
+	__u8			mjr;
+	__u8			mnr;
+	__u8			resv[6];
+
+	struct nvme_nvm_id20_addrf lbaf;
+
+	__le32			mccap;
+	__u8			resv2[12];
+
+	__u8			wit;
+	__u8			resv3[31];
+
+	/* Geometry */
+	__le16			num_grp;
+	__le16			num_pu;
+	__le32			num_chk;
+	__le32			clba;
+	__u8			resv4[52];
+
+	/* Write data requirements */
+	__le32			ws_min;
+	__le32			ws_opt;
+	__le32			mw_cunits;
+	__le32			maxoc;
+	__le32			maxocpu;
+	__u8			resv5[44];
+
+	/* Performance related metrics */
+	__le32			trdt;
+	__le32			trdm;
+	__le32			twrt;
+	__le32			twrm;
+	__le32			tcrst;
+	__le32			tcrsm;
+	__u8			resv6[40];
+
+	/* Reserved area */
+	__u8			resv7[2816];
+
+	/* Vendor specific */
+	__u8			vs[1024];
+};
+
 /*
  * Check we didn't inadvertently grow the command struct
  */
@@ -198,6 +250,8 @@ static inline void _nvme_nvm_check_size(void)
 	BUILD_BUG_ON(sizeof(struct nvme_nvm_id12_addrf) != 16);
 	BUILD_BUG_ON(sizeof(struct nvme_nvm_id12) != NVME_IDENTIFY_DATA_SIZE);
 	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);
 }
 
 static int init_grp(struct nvm_id *nvm_id, struct nvme_nvm_id12 *id12)
@@ -256,6 +310,49 @@ static int init_grp(struct nvm_id *nvm_id, struct nvme_nvm_id12 *id12)
 	return 0;
 }
 
+static int nvme_nvm_setup_12(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
+		struct nvme_nvm_id12 *id)
+{
+	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);
+}
+
+static int nvme_nvm_setup_20(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
+		struct nvme_nvm_id20 *id)
+{
+	nvm_id->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);
+
+	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);
+
+	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);
+
+	/* calculated values */
+	nvm_id->ws_per_chk = nvm_id->clba / nvm_id->ws_min;
+
+	/* 1.2 compatibility */
+	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
+
+	return 0;
+}
+
 static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
 {
 	struct nvme_ns *ns = nvmdev->q->queuedata;
@@ -277,14 +374,24 @@ static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
 		goto out;
 	}
 
-	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));
-
-	ret = init_grp(nvm_id, id);
+	/*
+	 * 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) {
+	case 1:
+		ret = nvme_nvm_setup_12(nvmdev, nvm_id, id);
+		break;
+	case 2:
+		ret = nvme_nvm_setup_20(nvmdev, nvm_id,
+				(struct nvme_nvm_id20 *)id);
+		break;
+	default:
+		dev_err(ns->ctrl->device,
+			"OCSSD revision not supported (%d)\n",
+			nvm_id->ver_id);
+		ret = -EINVAL;
+	}
 out:
 	kfree(id);
 	return ret;
@@ -733,7 +840,7 @@ void nvme_nvm_unregister(struct nvme_ns *ns)
 }
 
 static ssize_t nvm_dev_attr_show(struct device *dev,
-				 struct device_attribute *dattr, char *page)
+		struct device_attribute *dattr, char *page)
 {
 	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
 	struct nvm_dev *ndev = ns->ndev;
@@ -748,10 +855,36 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
 
 	if (strcmp(attr->name, "version") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", id->ver_id);
-	} else if (strcmp(attr->name, "vendor_opcode") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->vmnt);
 	} else if (strcmp(attr->name, "capabilities") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", id->cap);
+	} else if (strcmp(attr->name, "read_typ") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdt);
+	} else if (strcmp(attr->name, "read_max") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdm);
+	} else {
+		return scnprintf(page,
+				 PAGE_SIZE,
+				 "Unhandled attr(%s) in `nvm_dev_attr_show`\n",
+				 attr->name);
+	}
+}
+
+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 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);
 	} else if (strcmp(attr->name, "device_mode") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", id->dom);
 	/* kept for compatibility */
@@ -786,10 +919,6 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
 		return scnprintf(page, PAGE_SIZE, "%u\n", id->csecs);
 	} else if (strcmp(attr->name, "oob_sector_size") == 0) {/* u32 */
 		return scnprintf(page, PAGE_SIZE, "%u\n", id->sos);
-	} else if (strcmp(attr->name, "read_typ") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdt);
-	} else if (strcmp(attr->name, "read_max") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->trdm);
 	} else if (strcmp(attr->name, "prog_typ") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
 	} else if (strcmp(attr->name, "prog_max") == 0) {
@@ -808,48 +937,99 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
 	} else {
 		return scnprintf(page,
 				 PAGE_SIZE,
-				 "Unhandled attr(%s) in `nvm_dev_attr_show`\n",
+				 "Unhandled attr(%s) in `nvm_dev_attr_show_12`\n",
 				 attr->name);
 	}
 }
 
-#define NVM_DEV_ATTR_RO(_name)						\
+static ssize_t nvm_dev_attr_show_20(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 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);
+	} else if (strcmp(attr->name, "punits") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_lun);
+	} else if (strcmp(attr->name, "chunks") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->num_chk);
+	} else if (strcmp(attr->name, "clba") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->clba);
+	} else if (strcmp(attr->name, "ws_min") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_min);
+	} else if (strcmp(attr->name, "ws_opt") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->ws_opt);
+	} else if (strcmp(attr->name, "mw_cunits") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->mw_cunits);
+	} else if (strcmp(attr->name, "write_typ") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprt);
+	} else if (strcmp(attr->name, "write_max") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->tprm);
+	} else if (strcmp(attr->name, "reset_typ") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbet);
+	} else if (strcmp(attr->name, "reset_max") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", id->tbem);
+	} else {
+		return scnprintf(page,
+				 PAGE_SIZE,
+				 "Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
+				 attr->name);
+	}
+}
+
+#define NVM_DEV_ATTR_RO(_name)					\
 	DEVICE_ATTR(_name, S_IRUGO, nvm_dev_attr_show, NULL)
+#define NVM_DEV_ATTR_12_RO(_name)					\
+	DEVICE_ATTR(_name, S_IRUGO, nvm_dev_attr_show_12, NULL)
+#define NVM_DEV_ATTR_20_RO(_name)					\
+	DEVICE_ATTR(_name, S_IRUGO, nvm_dev_attr_show_20, NULL)
 
+/* general attributes */
 static NVM_DEV_ATTR_RO(version);
-static NVM_DEV_ATTR_RO(vendor_opcode);
 static NVM_DEV_ATTR_RO(capabilities);
-static NVM_DEV_ATTR_RO(device_mode);
-static NVM_DEV_ATTR_RO(ppa_format);
-static NVM_DEV_ATTR_RO(media_manager);
 
-static NVM_DEV_ATTR_RO(media_type);
-static NVM_DEV_ATTR_RO(flash_media_type);
-static NVM_DEV_ATTR_RO(num_channels);
-static NVM_DEV_ATTR_RO(num_luns);
-static NVM_DEV_ATTR_RO(num_planes);
-static NVM_DEV_ATTR_RO(num_blocks);
-static NVM_DEV_ATTR_RO(num_pages);
-static NVM_DEV_ATTR_RO(page_size);
-static NVM_DEV_ATTR_RO(hw_sector_size);
-static NVM_DEV_ATTR_RO(oob_sector_size);
 static NVM_DEV_ATTR_RO(read_typ);
 static NVM_DEV_ATTR_RO(read_max);
-static NVM_DEV_ATTR_RO(prog_typ);
-static NVM_DEV_ATTR_RO(prog_max);
-static NVM_DEV_ATTR_RO(erase_typ);
-static NVM_DEV_ATTR_RO(erase_max);
-static NVM_DEV_ATTR_RO(multiplane_modes);
-static NVM_DEV_ATTR_RO(media_capabilities);
-static NVM_DEV_ATTR_RO(max_phys_secs);
 
-static struct attribute *nvm_dev_attrs[] = {
+/* 1.2 values */
+static NVM_DEV_ATTR_12_RO(vendor_opcode);
+static NVM_DEV_ATTR_12_RO(device_mode);
+static NVM_DEV_ATTR_12_RO(ppa_format);
+static NVM_DEV_ATTR_12_RO(media_manager);
+static NVM_DEV_ATTR_12_RO(media_type);
+static NVM_DEV_ATTR_12_RO(flash_media_type);
+static NVM_DEV_ATTR_12_RO(num_channels);
+static NVM_DEV_ATTR_12_RO(num_luns);
+static NVM_DEV_ATTR_12_RO(num_planes);
+static NVM_DEV_ATTR_12_RO(num_blocks);
+static NVM_DEV_ATTR_12_RO(num_pages);
+static NVM_DEV_ATTR_12_RO(page_size);
+static NVM_DEV_ATTR_12_RO(hw_sector_size);
+static NVM_DEV_ATTR_12_RO(oob_sector_size);
+static NVM_DEV_ATTR_12_RO(prog_typ);
+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(max_phys_secs);
+
+static struct attribute *nvm_dev_attrs_12[] = {
 	&dev_attr_version.attr,
+	&dev_attr_capabilities.attr,
+
 	&dev_attr_vendor_opcode.attr,
-	&dev_attr_capabilities.attr,
 	&dev_attr_device_mode.attr,
 	&dev_attr_media_manager.attr,
-
 	&dev_attr_ppa_format.attr,
 	&dev_attr_media_type.attr,
 	&dev_attr_flash_media_type.attr,
@@ -870,22 +1050,82 @@ static struct attribute *nvm_dev_attrs[] = {
 	&dev_attr_multiplane_modes.attr,
 	&dev_attr_media_capabilities.attr,
 	&dev_attr_max_phys_secs.attr,
+
+	NULL,
+};
+
+static const struct attribute_group nvm_dev_attr_group_12 = {
+	.name		= "lightnvm",
+	.attrs		= nvm_dev_attrs_12,
+};
+
+/* 2.0 values */
+static NVM_DEV_ATTR_20_RO(groups);
+static NVM_DEV_ATTR_20_RO(punits);
+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(mw_cunits);
+static NVM_DEV_ATTR_20_RO(write_typ);
+static NVM_DEV_ATTR_20_RO(write_max);
+static NVM_DEV_ATTR_20_RO(reset_typ);
+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_groups.attr,
+	&dev_attr_punits.attr,
+	&dev_attr_chunks.attr,
+	&dev_attr_clba.attr,
+	&dev_attr_ws_min.attr,
+	&dev_attr_ws_opt.attr,
+	&dev_attr_mw_cunits.attr,
+
+	&dev_attr_read_typ.attr,
+	&dev_attr_read_max.attr,
+	&dev_attr_write_typ.attr,
+	&dev_attr_write_max.attr,
+	&dev_attr_reset_typ.attr,
+	&dev_attr_reset_max.attr,
+
 	NULL,
 };
 
-static const struct attribute_group nvm_dev_attr_group = {
+static const struct attribute_group nvm_dev_attr_group_20 = {
 	.name		= "lightnvm",
-	.attrs		= nvm_dev_attrs,
+	.attrs		= nvm_dev_attrs_20,
 };
 
 int nvme_nvm_register_sysfs(struct nvme_ns *ns)
 {
-	return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
-					&nvm_dev_attr_group);
+	if (!ns->ndev)
+		return -EINVAL;
+
+	switch (ns->ndev->identity.ver_id) {
+	case 1:
+		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
+					&nvm_dev_attr_group_12);
+	case 2:
+		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
+					&nvm_dev_attr_group_20);
+	}
+
+	return -EINVAL;
 }
 
 void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
 {
-	sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
-					&nvm_dev_attr_group);
+	switch (ns->ndev->identity.ver_id) {
+	case 1:
+		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
+					&nvm_dev_attr_group_12);
+		break;
+	case 2:
+		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
+					&nvm_dev_attr_group_20);
+		break;
+	}
 }
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 94b704a8d83d..b717c000b712 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -184,10 +184,9 @@ struct nvm_id {
 	u16	csecs;
 	u16	sos;
 
-	u16	ws_min;
-	u16	ws_opt;
-	u16	ws_seq;
-	u16	ws_per_chk;
+	u32	ws_min;
+	u32	ws_opt;
+	u32	mw_cunits;
 
 	u32	trdt;
 	u32	trdm;
@@ -199,6 +198,10 @@ struct nvm_id {
 	u32	mccap;
 	u16	cpar;
 
+	/* calculated values */
+	u16	ws_seq;
+	u16	ws_per_chk;
+
 	/* 1.2 compatibility */
 	u8	mtype;
 	u8	fmtype;
-- 
2.11.0

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

* [GIT PULL 16/37] lightnvm: remove max_rq_size
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (14 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 15/37] lightnvm: add 2.0 geometry identification Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 17/37] lightnvm: remove nvm_dev_ops->max_phys_sect Matias Bjørling
                   ` (21 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

The field is no longer used.

Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/core.c  | 1 -
 include/linux/lightnvm.h | 2 --
 2 files changed, 3 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 521f520a1bb4..a59ad29600c3 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -874,7 +874,6 @@ static int nvm_core_init(struct nvm_dev *dev)
 	geo->sec_size = id->csecs;
 	geo->oob_size = id->sos;
 	geo->mccap = id->mccap;
-	geo->max_rq_size = dev->ops->max_phys_sect * geo->sec_size;
 
 	geo->sec_per_chk = id->clba;
 	geo->sec_per_lun = geo->sec_per_chk * geo->nr_chks;
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index b717c000b712..67b4fa8e4906 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -295,8 +295,6 @@ struct nvm_geo {
 	int ws_seq;
 	int ws_per_chk;
 
-	int max_rq_size;
-
 	int op;
 
 	struct nvm_addr_format ppaf;
-- 
2.11.0

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

* [GIT PULL 17/37] lightnvm: remove nvm_dev_ops->max_phys_sect
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (15 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 16/37] lightnvm: remove max_rq_size Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 18/37] nvme: lightnvm: add late setup of block size and metadata Matias Bjørling
                   ` (20 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

The value of max_phys_sect is always static. Instead of
defining it in the nvm_dev_ops structure, declare it as a global
value.

Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/core.c          | 28 +++++++---------------------
 drivers/lightnvm/pblk-init.c     |  9 ++++-----
 drivers/lightnvm/pblk-recovery.c |  8 ++------
 drivers/nvme/host/lightnvm.c     |  5 +----
 include/linux/lightnvm.h         |  5 ++---
 5 files changed, 16 insertions(+), 39 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index a59ad29600c3..9704db219866 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -407,7 +407,8 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
 	tdisk->private_data = targetdata;
 	tqueue->queuedata = targetdata;
 
-	blk_queue_max_hw_sectors(tqueue, 8 * dev->ops->max_phys_sect);
+	blk_queue_max_hw_sectors(tqueue,
+			(dev->geo.sec_size >> 9) * NVM_MAX_VLBA);
 
 	set_capacity(tdisk, tt->capacity(targetdata));
 	add_disk(tdisk);
@@ -719,7 +720,7 @@ int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *ppas,
 	struct nvm_rq rqd;
 	int ret;
 
-	if (nr_ppas > dev->ops->max_phys_sect) {
+	if (nr_ppas > NVM_MAX_VLBA) {
 		pr_err("nvm: unable to update all blocks atomically\n");
 		return -EINVAL;
 	}
@@ -740,14 +741,6 @@ int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *ppas,
 }
 EXPORT_SYMBOL(nvm_set_tgt_bb_tbl);
 
-int nvm_max_phys_sects(struct nvm_tgt_dev *tgt_dev)
-{
-	struct nvm_dev *dev = tgt_dev->parent;
-
-	return dev->ops->max_phys_sect;
-}
-EXPORT_SYMBOL(nvm_max_phys_sects);
-
 int nvm_submit_io(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd)
 {
 	struct nvm_dev *dev = tgt_dev->parent;
@@ -965,17 +958,10 @@ int nvm_register(struct nvm_dev *dev)
 	if (!dev->q || !dev->ops)
 		return -EINVAL;
 
-	if (dev->ops->max_phys_sect > 256) {
-		pr_info("nvm: max sectors supported is 256.\n");
-		return -EINVAL;
-	}
-
-	if (dev->ops->max_phys_sect > 1) {
-		dev->dma_pool = dev->ops->create_dma_pool(dev, "ppalist");
-		if (!dev->dma_pool) {
-			pr_err("nvm: could not create dma pool\n");
-			return -ENOMEM;
-		}
+	dev->dma_pool = dev->ops->create_dma_pool(dev, "ppalist");
+	if (!dev->dma_pool) {
+		pr_err("nvm: could not create dma pool\n");
+		return -ENOMEM;
 	}
 
 	ret = nvm_init(dev);
diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 141036bd6afa..43b835678f48 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -260,8 +260,7 @@ static int pblk_core_init(struct pblk *pblk)
 		return -ENOMEM;
 
 	/* Internal bios can be at most the sectors signaled by the device. */
-	pblk->page_bio_pool = mempool_create_page_pool(nvm_max_phys_sects(dev),
-									0);
+	pblk->page_bio_pool = mempool_create_page_pool(NVM_MAX_VLBA, 0);
 	if (!pblk->page_bio_pool)
 		goto free_global_caches;
 
@@ -716,12 +715,12 @@ static int pblk_lines_init(struct pblk *pblk)
 
 	pblk->min_write_pgs = geo->sec_per_pl * (geo->sec_size / PAGE_SIZE);
 	max_write_ppas = pblk->min_write_pgs * geo->all_luns;
-	pblk->max_write_pgs = (max_write_ppas < nvm_max_phys_sects(dev)) ?
-				max_write_ppas : nvm_max_phys_sects(dev);
+	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: cannot support device max_phys_sect\n");
+		pr_err("pblk: vector list too big(%u > %u)\n",
+				pblk->max_write_pgs, PBLK_MAX_REQ_ADDRS);
 		return -EINVAL;
 	}
 
diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
index e75a1af2eebe..aaab9a5c17cc 100644
--- a/drivers/lightnvm/pblk-recovery.c
+++ b/drivers/lightnvm/pblk-recovery.c
@@ -21,17 +21,15 @@ void pblk_submit_rec(struct work_struct *work)
 	struct pblk_rec_ctx *recovery =
 			container_of(work, struct pblk_rec_ctx, ws_rec);
 	struct pblk *pblk = recovery->pblk;
-	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_rq *rqd = recovery->rqd;
 	struct pblk_c_ctx *c_ctx = nvm_rq_to_pdu(rqd);
-	int max_secs = nvm_max_phys_sects(dev);
 	struct bio *bio;
 	unsigned int nr_rec_secs;
 	unsigned int pgs_read;
 	int ret;
 
 	nr_rec_secs = bitmap_weight((unsigned long int *)&rqd->ppa_status,
-								max_secs);
+								NVM_MAX_VLBA);
 
 	bio = bio_alloc(GFP_KERNEL, nr_rec_secs);
 
@@ -74,8 +72,6 @@ int pblk_recov_setup_rq(struct pblk *pblk, struct pblk_c_ctx *c_ctx,
 			struct pblk_rec_ctx *recovery, u64 *comp_bits,
 			unsigned int comp)
 {
-	struct nvm_tgt_dev *dev = pblk->dev;
-	int max_secs = nvm_max_phys_sects(dev);
 	struct nvm_rq *rec_rqd;
 	struct pblk_c_ctx *rec_ctx;
 	int nr_entries = c_ctx->nr_valid + c_ctx->nr_padded;
@@ -86,7 +82,7 @@ int pblk_recov_setup_rq(struct pblk *pblk, struct pblk_c_ctx *c_ctx,
 	/* Copy completion bitmap, but exclude the first X completed entries */
 	bitmap_shift_right((unsigned long int *)&rec_rqd->ppa_status,
 				(unsigned long int *)comp_bits,
-				comp, max_secs);
+				comp, NVM_MAX_VLBA);
 
 	/* Save the context for the entries that need to be re-written and
 	 * update current context with the completed entries.
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 8b243af8a949..e38d835b15b5 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -612,8 +612,6 @@ static struct nvm_dev_ops nvme_nvm_dev_ops = {
 	.destroy_dma_pool	= nvme_nvm_destroy_dma_pool,
 	.dev_dma_alloc		= nvme_nvm_dev_dma_alloc,
 	.dev_dma_free		= nvme_nvm_dev_dma_free,
-
-	.max_phys_sect		= 64,
 };
 
 static int nvme_nvm_submit_user_cmd(struct request_queue *q,
@@ -932,8 +930,7 @@ static ssize_t nvm_dev_attr_show_12(struct device *dev,
 	} else if (strcmp(attr->name, "media_capabilities") == 0) {
 		return scnprintf(page, PAGE_SIZE, "0x%08x\n", id->mccap);
 	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n",
-				ndev->ops->max_phys_sect);
+		return scnprintf(page, PAGE_SIZE, "%u\n", NVM_MAX_VLBA);
 	} else {
 		return scnprintf(page,
 				 PAGE_SIZE,
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 67b4fa8e4906..e55b10573c99 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -73,8 +73,6 @@ struct nvm_dev_ops {
 	nvm_destroy_dma_pool_fn	*destroy_dma_pool;
 	nvm_dev_dma_alloc_fn	*dev_dma_alloc;
 	nvm_dev_dma_free_fn	*dev_dma_free;
-
-	unsigned int		max_phys_sect;
 };
 
 #ifdef CONFIG_NVM
@@ -228,6 +226,8 @@ struct nvm_target {
 #define NVM_VERSION_MINOR 0
 #define NVM_VERSION_PATCH 0
 
+#define NVM_MAX_VLBA (64) /* max logical blocks in a vector command */
+
 struct nvm_rq;
 typedef void (nvm_end_io_fn)(struct nvm_rq *);
 
@@ -436,7 +436,6 @@ extern void nvm_unregister(struct nvm_dev *);
 
 extern int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *, struct ppa_addr *,
 			      int, int);
-extern int nvm_max_phys_sects(struct nvm_tgt_dev *);
 extern int nvm_submit_io(struct nvm_tgt_dev *, struct nvm_rq *);
 extern int nvm_submit_io_sync(struct nvm_tgt_dev *, struct nvm_rq *);
 extern void nvm_end_io(struct nvm_rq *);
-- 
2.11.0

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

* [GIT PULL 18/37] nvme: lightnvm: add late setup of block size and metadata
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (16 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 17/37] lightnvm: remove nvm_dev_ops->max_phys_sect Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 19/37] lightnvm: fix bad block initialization Matias Bjørling
                   ` (19 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

The nvme driver sets up the size of the nvme namespace in two steps.
First it initializes the device with standard logical block and
metadata sizes, and then sets the correct logical block and metadata
size. Due to the OCSSD 2.0 specification relies on the namespace to
expose these sizes for correct initialization, let it be updated
appropriately on the LightNVM side as well.

Signed-off-by: Matias Bjørling <mb@lightnvm.io>
Acked-by: Keith Busch <keith.busch@intel.com>
---
 drivers/lightnvm/core.c      | 3 ---
 drivers/nvme/host/core.c     | 2 ++
 drivers/nvme/host/lightnvm.c | 8 ++++++++
 drivers/nvme/host/nvme.h     | 2 ++
 4 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 9704db219866..3eec948d1b7e 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -864,8 +864,6 @@ static int nvm_core_init(struct nvm_dev *dev)
 	geo->ws_seq = id->ws_seq;
 	geo->ws_per_chk = id->ws_per_chk;
 	geo->nr_chks = id->num_chk;
-	geo->sec_size = id->csecs;
-	geo->oob_size = id->sos;
 	geo->mccap = id->mccap;
 
 	geo->sec_per_chk = id->clba;
@@ -893,7 +891,6 @@ static int nvm_core_init(struct nvm_dev *dev)
 	if (ret)
 		goto err_fmtype;
 
-	blk_queue_logical_block_size(dev->q, geo->sec_size);
 	return 0;
 err_fmtype:
 	kfree(dev->lun_map);
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 9ee919422669..e7ec2fb5c59a 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1448,6 +1448,8 @@ static void __nvme_revalidate_disk(struct gendisk *disk, struct nvme_id_ns *id)
 	if (ns->noiob)
 		nvme_set_chunk_size(ns);
 	nvme_update_disk_info(disk, ns, id);
+	if (ns->ndev)
+		nvme_nvm_update_nvm_info(ns);
 #ifdef CONFIG_NVME_MULTIPATH
 	if (ns->head->disk)
 		nvme_update_disk_info(ns->head->disk, ns, id);
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index e38d835b15b5..839c0b96466a 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -812,6 +812,14 @@ 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;
+
+	ndev->identity.csecs = ndev->geo.sec_size = 1 << ns->lba_shift;
+	ndev->identity.sos = ndev->geo.oob_size = ns->ms;
+}
+
 int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node)
 {
 	struct request_queue *q = ns->queue;
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index c393e4b56f39..aa10842a6709 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -500,12 +500,14 @@ static inline void nvme_mpath_check_last_path(struct nvme_ns *ns)
 #endif /* CONFIG_NVME_MULTIPATH */
 
 #ifdef CONFIG_NVM
+void nvme_nvm_update_nvm_info(struct nvme_ns *ns);
 int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node);
 void nvme_nvm_unregister(struct nvme_ns *ns);
 int nvme_nvm_register_sysfs(struct nvme_ns *ns);
 void nvme_nvm_unregister_sysfs(struct nvme_ns *ns);
 int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd, unsigned long arg);
 #else
+static inline void nvme_nvm_update_nvm_info(struct nvme_ns *ns) {};
 static inline int nvme_nvm_register(struct nvme_ns *ns, char *disk_name,
 				    int node)
 {
-- 
2.11.0

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

* [GIT PULL 19/37] lightnvm: fix bad block initialization
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (17 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 18/37] nvme: lightnvm: add late setup of block size and metadata Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 20/37] lightnvm: centralize permission check for lightnvm ioctl Matias Bjørling
                   ` (18 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Heiner Litz,
	Matias Bjørling

From: Heiner Litz <hlitz@ucsc.edu>

fix reading bad block device information to correctly setup the per line
blk_bitmap during lightnvm initialization

Signed-off-by: Heiner Litz <hlitz@ucsc.edu>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/pblk-init.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 43b835678f48..ee936c1ff764 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -460,10 +460,11 @@ static int pblk_bb_line(struct pblk *pblk, struct pblk_line *line,
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
 	int i, bb_cnt = 0;
+	int blk_per_lun = geo->nr_chks * geo->plane_mode;
 
 	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;
+		u8 *lun_bb_log = bb_log + i * blk_per_lun;
 
 		if (lun_bb_log[line->id] == NVM_BLK_T_FREE)
 			continue;
-- 
2.11.0

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

* [GIT PULL 20/37] lightnvm: centralize permission check for lightnvm ioctl
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (18 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 19/37] lightnvm: fix bad block initialization Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 21/37] lightnvm: Avoid validation of default op value Matias Bjørling
                   ` (17 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier,
	Johannes Thumshirn, Matias Bjørling

From: Johannes Thumshirn <jthumshirn@suse.de>

Currently all functions for handling the lightnvm core ioctl commands
do a check for CAP_SYS_ADMIN.

Change this to fail early in nvm_ctl_ioctl(), so we don't have to
duplicate the permission checks all over.

Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/core.c | 21 +++------------------
 1 file changed, 3 insertions(+), 18 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 3eec948d1b7e..5b197d6bb6d9 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -1019,9 +1019,6 @@ static long nvm_ioctl_info(struct file *file, void __user *arg)
 	struct nvm_tgt_type *tt;
 	int tgt_iter = 0;
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
 	info = memdup_user(arg, sizeof(struct nvm_ioctl_info));
 	if (IS_ERR(info))
 		return -EFAULT;
@@ -1060,9 +1057,6 @@ static long nvm_ioctl_get_devices(struct file *file, void __user *arg)
 	struct nvm_dev *dev;
 	int i = 0;
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
 	devices = kzalloc(sizeof(struct nvm_ioctl_get_devices), GFP_KERNEL);
 	if (!devices)
 		return -ENOMEM;
@@ -1103,9 +1097,6 @@ static long nvm_ioctl_dev_create(struct file *file, void __user *arg)
 {
 	struct nvm_ioctl_create create;
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
 	if (copy_from_user(&create, arg, sizeof(struct nvm_ioctl_create)))
 		return -EFAULT;
 
@@ -1141,9 +1132,6 @@ static long nvm_ioctl_dev_remove(struct file *file, void __user *arg)
 	struct nvm_dev *dev;
 	int ret = 0;
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
 	if (copy_from_user(&remove, arg, sizeof(struct nvm_ioctl_remove)))
 		return -EFAULT;
 
@@ -1168,9 +1156,6 @@ static long nvm_ioctl_dev_init(struct file *file, void __user *arg)
 {
 	struct nvm_ioctl_dev_init init;
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
 	if (copy_from_user(&init, arg, sizeof(struct nvm_ioctl_dev_init)))
 		return -EFAULT;
 
@@ -1187,9 +1172,6 @@ static long nvm_ioctl_dev_factory(struct file *file, void __user *arg)
 {
 	struct nvm_ioctl_dev_factory fact;
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
 	if (copy_from_user(&fact, arg, sizeof(struct nvm_ioctl_dev_factory)))
 		return -EFAULT;
 
@@ -1205,6 +1187,9 @@ static long nvm_ctl_ioctl(struct file *file, uint cmd, unsigned long arg)
 {
 	void __user *argp = (void __user *)arg;
 
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
 	switch (cmd) {
 	case NVM_INFO:
 		return nvm_ioctl_info(file, argp);
-- 
2.11.0

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

* [GIT PULL 21/37] lightnvm: Avoid validation of default op value
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (19 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 20/37] lightnvm: centralize permission check for lightnvm ioctl Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 22/37] lightnvm: pblk: refactor init/exit sequences Matias Bjørling
                   ` (16 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Heiner Litz,
	Matias Bjørling

From: Heiner Litz <hlitz@ucsc.edu>

Fixes: 38401d231de65 ("lightnvm: set target over-provision on create ioctl")
Signed-off-by: Heiner Litz <hlitz@ucsc.edu>
Reviewed-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/core.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 5b197d6bb6d9..c4f12b1ae8b8 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -304,11 +304,9 @@ static int __nvm_config_extended(struct nvm_dev *dev,
 	}
 
 	/* op not set falls into target's default */
-	if (e->op == 0xFFFF)
+	if (e->op == 0xFFFF) {
 		e->op = NVM_TARGET_DEFAULT_OP;
-
-	if (e->op < NVM_TARGET_MIN_OP ||
-	    e->op > NVM_TARGET_MAX_OP) {
+	} else if (e->op < NVM_TARGET_MIN_OP || e->op > NVM_TARGET_MAX_OP) {
 		pr_err("nvm: invalid over provisioning value\n");
 		return -EINVAL;
 	}
-- 
2.11.0

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

* [GIT PULL 22/37] lightnvm: pblk: refactor init/exit sequences
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (20 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 21/37] lightnvm: Avoid validation of default op value Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 23/37] lightnvm: simplify geometry structure Matias Bjørling
                   ` (15 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

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

Refactor init and exit sequences to eliminate dependencies among init
modules and improve readability.

Signed-off-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/pblk-init.c | 415 +++++++++++++++++++++----------------------
 1 file changed, 207 insertions(+), 208 deletions(-)

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index ee936c1ff764..8f1d622801df 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)
@@ -159,7 +192,13 @@ static int pblk_set_ppaf(struct pblk *pblk)
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
 	struct nvm_addr_format ppaf = geo->ppaf;
-	int power_len;
+	int mod, power_len;
+
+	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;
+	}
 
 	/* Re-calculate channel and lun format to adapt to configuration */
 	power_len = get_count_order(geo->nr_chnls);
@@ -252,12 +291,39 @@ 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;
+
+	atomic64_set(&pblk->nr_flush, 0);
+	pblk->nr_flush_rst = 0;
 
 	pblk->pgs_in_buffer = NVM_MEM_PAGE_WRITE * geo->sec_per_pg *
 						geo->nr_planes * geo->all_luns;
 
+	pblk->min_write_pgs = geo->sec_per_pl * (geo->sec_size / 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;
+	}
+
+	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);
@@ -307,10 +373,8 @@ static int pblk_core_init(struct pblk *pblk)
 	if (pblk_set_ppaf(pblk))
 		goto free_r_end_wq;
 
-	if (pblk_rwb_init(pblk))
-		goto free_r_end_wq;
-
 	INIT_LIST_HEAD(&pblk->compl_list);
+
 	return 0;
 
 free_r_end_wq:
@@ -333,6 +397,8 @@ static int pblk_core_init(struct pblk *pblk)
 	mempool_destroy(pblk->page_bio_pool);
 free_global_caches:
 	pblk_free_global_caches(pblk);
+fail_free_pad_dist:
+	kfree(pblk->pad_dist);
 	return -ENOMEM;
 }
 
@@ -354,14 +420,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);
-}
-
-static void pblk_luns_free(struct pblk *pblk)
-{
-	kfree(pblk->luns);
+	kfree(pblk->pad_dist);
 }
 
 static void pblk_line_mg_free(struct pblk *pblk)
@@ -378,8 +438,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)
@@ -402,6 +460,11 @@ 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->luns);
+	kfree(pblk->lines);
 }
 
 static int pblk_bb_get_tbl(struct nvm_tgt_dev *dev, struct pblk_lun *rlun,
@@ -476,7 +539,7 @@ static int pblk_bb_line(struct pblk *pblk, struct pblk_line *line,
 	return bb_cnt;
 }
 
-static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
+static int pblk_luns_init(struct pblk *pblk)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
@@ -501,7 +564,7 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
 		int lunid = lun_raw + ch * geo->nr_luns;
 
 		rlun = &pblk->luns[i];
-		rlun->bppa = luns[lunid];
+		rlun->bppa = dev->luns[lunid];
 
 		sema_init(&rlun->wr_sem, 1);
 	}
@@ -509,38 +572,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)
 {
@@ -606,11 +637,70 @@ 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)
+static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
+				void *chunk_log, long *nr_bad_blks)
 {
+	struct pblk_line_meta *lm = &pblk->lm;
+
+	line->blk_bitmap = kzalloc(lm->blk_bitmap_len, GFP_KERNEL);
+	if (!line->blk_bitmap)
+		return -ENOMEM;
+
+	line->erase_bitmap = kzalloc(lm->blk_bitmap_len, GFP_KERNEL);
+	if (!line->erase_bitmap) {
+		kfree(line->blk_bitmap);
+		return -ENOMEM;
+	}
+
+	*nr_bad_blks = pblk_bb_line(pblk, line, chunk_log, lm->blk_per_line);
+
+	return 0;
+}
+
+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;
-	int i;
+	int i, bb_distance;
+
+	l_mg->nr_lines = geo->nr_chks;
+	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);
+
+	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
@@ -656,13 +746,13 @@ static int pblk_lines_alloc_metadata(struct pblk *pblk)
 		}
 	}
 
-	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);
 
+	bb_distance = (geo->all_luns) * geo->ws_opt;
+	for (i = 0; i < lm->sec_per_line; i += bb_distance)
+		bitmap_set(l_mg->bb_template, i, geo->ws_opt);
+
 	return 0;
 
 fail_free_emeta:
@@ -673,69 +763,25 @@ static int pblk_lines_alloc_metadata(struct pblk *pblk)
 			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]);
-
+	kfree(l_mg->bb_aux);
+fail_free_bb_template:
+	kfree(l_mg->bb_template);
+fail_free_vsc_list:
+	kfree(l_mg->vsc_list);
+fail:
 	return -ENOMEM;
 }
 
-static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
-				void *chunk_log, long *nr_bad_blks)
-{
-	struct pblk_line_meta *lm = &pblk->lm;
-
-	line->blk_bitmap = kzalloc(lm->blk_bitmap_len, GFP_KERNEL);
-	if (!line->blk_bitmap)
-		return -ENOMEM;
-
-	line->erase_bitmap = kzalloc(lm->blk_bitmap_len, GFP_KERNEL);
-	if (!line->erase_bitmap) {
-		kfree(line->blk_bitmap);
-		return -ENOMEM;
-	}
-
-	*nr_bad_blks = pblk_bb_line(pblk, line, chunk_log, lm->blk_per_line);
-
-	return 0;
-}
-
-static int pblk_lines_init(struct pblk *pblk)
+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_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_bad_blks = 0, nr_free_blks = 0;
-	int bb_distance, max_write_ppas, mod;
-	int i, ret;
-
-	pblk->min_write_pgs = geo->sec_per_pl * (geo->sec_size / 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;
-	}
-
-	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->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);
+	int i;
 
 	lm->sec_per_line = geo->sec_per_chk * geo->all_luns;
 	lm->blk_per_line = geo->all_luns;
@@ -787,58 +833,43 @@ 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_meta *lm = &pblk->lm;
+	struct pblk_line *line;
+	void *chunk_log;
+	long nr_bad_blks = 0, nr_free_blks = 0;
+	int i, ret;
+
+	ret = pblk_line_meta_init(pblk);
+	if (ret)
+		return ret;
+
+	ret = pblk_line_mg_init(pblk);
 	if (ret)
 		return ret;
 
-	l_mg->bb_template = kzalloc(lm->sec_bitmap_len, GFP_KERNEL);
-	if (!l_mg->bb_template) {
-		ret = -ENOMEM;
+	ret = pblk_luns_init(pblk);
+	if (ret)
 		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->sec_per_pl;
-	for (i = 0; i < lm->sec_per_line; i += bb_distance)
-		bitmap_set(l_mg->bb_template, i, geo->sec_per_pl);
-
-	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;
-	}
 
 	chunk_log = pblk_bb_get_log(pblk);
 	if (IS_ERR(chunk_log)) {
 		pr_err("pblk: could not get bad block log (%lu)\n",
 							PTR_ERR(chunk_log));
 		ret = PTR_ERR(chunk_log);
-		goto fail_free_bb_aux;
+		goto fail_free_luns;
+	}
+
+	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++) {
@@ -856,7 +887,7 @@ static int pblk_lines_init(struct pblk *pblk)
 
 		ret = pblk_setup_line_meta(pblk, line, chunk_log, &nr_bad_blks);
 		if (ret)
-			goto fail_free_chunk_log;
+			goto fail_free_lines;
 
 		chk_in_line = lm->blk_per_line - nr_bad_blks;
 		if (nr_bad_blks < 0 || nr_bad_blks > lm->blk_per_line ||
@@ -878,14 +909,14 @@ 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_bb_aux:
-	kfree(l_mg->bb_aux);
-fail_free_bb_template:
-	kfree(l_mg->bb_template);
+	kfree(pblk->lines);
+fail_free_chunk_log:
+	kfree(chunk_log);
+fail_free_luns:
+	kfree(pblk->luns);
 fail_free_meta:
 	pblk_line_mg_free(pblk);
 
@@ -928,12 +959,10 @@ 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);
 
 	kfree(pblk);
 }
@@ -998,19 +1027,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;
-
-	atomic64_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);
@@ -1034,48 +1050,35 @@ 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;
 	}
 
-	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);
@@ -1110,18 +1113,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:
 	kfree(pblk);
 	return ERR_PTR(ret);
-- 
2.11.0

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

* [GIT PULL 23/37] lightnvm: simplify geometry structure
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (21 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 22/37] lightnvm: pblk: refactor init/exit sequences Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 24/37] lightnvm: add minor version to generic geometry Matias Bjørling
                   ` (14 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

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

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 nvm_geo, which can be used by
(i) the underlying device to describe the geometry of the whole device,
and (ii) instances to describe their geometry independently.

Signed-off-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/core.c          |  70 +++-----
 drivers/lightnvm/pblk-core.c     |  16 +-
 drivers/lightnvm/pblk-gc.c       |   2 +-
 drivers/lightnvm/pblk-init.c     | 113 +++++++------
 drivers/lightnvm/pblk-read.c     |   2 +-
 drivers/lightnvm/pblk-recovery.c |  14 +-
 drivers/lightnvm/pblk-rl.c       |   2 +-
 drivers/lightnvm/pblk-sysfs.c    |  35 ++--
 drivers/lightnvm/pblk-write.c    |   2 +-
 drivers/lightnvm/pblk.h          |  83 ++++------
 drivers/nvme/host/lightnvm.c     | 339 +++++++++++++++++++++++----------------
 include/linux/lightnvm.h         | 198 +++++++++++------------
 12 files changed, 451 insertions(+), 425 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index c4f12b1ae8b8..9dec936ac1dc 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -155,7 +155,7 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
 	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;
@@ -215,18 +215,23 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
 	if (!tgt_dev)
 		goto err_ch;
 
+	/* Inherit device geometry from parent */
 	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.nr_chks;
+
 	tgt_dev->geo.op = op;
-	tgt_dev->total_secs = nr_luns * tgt_dev->geo.sec_per_lun;
+
+	sec_per_lun = dev->geo.clba * dev->geo.nr_chks;
+	tgt_dev->geo.total_secs = nr_luns * sec_per_lun;
+
 	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;
@@ -296,8 +301,6 @@ static int __nvm_config_simple(struct nvm_dev *dev,
 static int __nvm_config_extended(struct nvm_dev *dev,
 				 struct nvm_ioctl_create_extended *e)
 {
-	struct nvm_geo *geo = &dev->geo;
-
 	if (e->lun_begin == 0xFFFF && e->lun_end == 0xFFFF) {
 		e->lun_begin = 0;
 		e->lun_end = dev->geo.all_luns - 1;
@@ -311,7 +314,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)
@@ -406,7 +409,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->geo.csecs >> 9) * NVM_MAX_VLBA);
 
 	set_capacity(tdisk, tt->capacity(targetdata));
 	add_disk(tdisk);
@@ -841,40 +844,9 @@ 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;
 	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),
 					sizeof(unsigned long), GFP_KERNEL);
 	if (!dev->lun_map)
@@ -913,16 +885,14 @@ static int nvm_init(struct nvm_dev *dev)
 	struct nvm_geo *geo = &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",
+				geo->ver_id,
+				geo->vmnt);
 
 	ret = nvm_core_init(dev);
 	if (ret) {
@@ -930,10 +900,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, geo->ws_min, geo->ws_opt,
+			geo->nr_chks, geo->all_luns,
+			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 5c363ccde0e3..52c0c3e5ec6e 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->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->ws_opt;
 }
 
 static int pblk_line_submit_smeta_io(struct pblk *pblk, struct pblk_line *line,
@@ -1034,17 +1034,17 @@ 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->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->clba;
 	}
 
 	/* 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->ws_opt;
 	bitmap_set(line->map_bitmap, off, lm->smeta_sec);
 	line->sec_in_line -= lm->smeta_sec;
 	line->smeta_ssec = off;
@@ -1063,10 +1063,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->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->ws_opt);
+			emeta_secs -= geo->ws_opt;
 		}
 	}
 
diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c
index 31f17d6f14ee..7143b0f740fb 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->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 8f1d622801df..2fca27d0a9b5 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -179,7 +179,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->csecs);
 
 	return pblk_rb_init(&pblk->rwb, entries, power_size, power_seg_sz);
 }
@@ -187,18 +187,10 @@ 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_addrf_12 *dst)
 {
-	struct nvm_tgt_dev *dev = pblk->dev;
-	struct nvm_geo *geo = &dev->geo;
-	struct nvm_addr_format ppaf = geo->ppaf;
-	int mod, power_len;
-
-	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;
-	}
+	struct nvm_addrf_12 *src = (struct nvm_addrf_12 *)&geo->addrf;
+	int power_len;
 
 	/* Re-calculate channel and lun format to adapt to configuration */
 	power_len = get_count_order(geo->nr_chnls);
@@ -206,34 +198,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->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;
 }
@@ -303,10 +311,9 @@ static int pblk_core_init(struct pblk *pblk)
 	atomic64_set(&pblk->nr_flush, 0);
 	pblk->nr_flush_rst = 0;
 
-	pblk->pgs_in_buffer = NVM_MEM_PAGE_WRITE * geo->sec_per_pg *
-						geo->nr_planes * geo->all_luns;
+	pblk->pgs_in_buffer = geo->mw_cunits * geo->all_luns;
 
-	pblk->min_write_pgs = geo->sec_per_pl * (geo->sec_size / PAGE_SIZE);
+	pblk->min_write_pgs = geo->ws_opt * (geo->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);
@@ -583,18 +590,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->csecs);
+	lm->emeta_len[1] = lm->emeta_sec[1] * geo->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->csecs);
+	lm->emeta_len[2] = lm->emeta_sec[2] * geo->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->csecs);
+	lm->emeta_len[3] = lm->emeta_sec[3] * geo->csecs;
 
 	lm->vsc_list_len = l_mg->nr_lines * sizeof(u32);
 
@@ -625,13 +632,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->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->clba);
 
-	pblk->capacity = (provisioned - blk_meta) * geo->sec_per_chk;
+	pblk->capacity = (provisioned - blk_meta) * geo->clba;
 
 	atomic_set(&pblk->rl.free_blocks, nr_free_blks);
 	atomic_set(&pblk->rl.free_user_blocks, nr_free_blks);
@@ -783,7 +790,7 @@ static int pblk_line_meta_init(struct pblk *pblk)
 	unsigned int smeta_len, emeta_len;
 	int i;
 
-	lm->sec_per_line = geo->sec_per_chk * geo->all_luns;
+	lm->sec_per_line = geo->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);
@@ -797,8 +804,8 @@ static int pblk_line_meta_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->ws_opt;
+	lm->smeta_len = lm->smeta_sec * geo->csecs;
 
 	smeta_len = sizeof(struct line_smeta) + lm->lun_bitmap_len;
 	if (smeta_len > lm->smeta_len) {
@@ -811,8 +818,8 @@ static int pblk_line_meta_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->ws_opt;
+	lm->emeta_len[0] = lm->emeta_sec[0] * geo->csecs;
 
 	emeta_len = calc_emeta_len(pblk);
 	if (emeta_len > lm->emeta_len[0]) {
@@ -825,7 +832,7 @@ static int pblk_line_meta_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->clba);
 
 	if (lm->min_blk_line > lm->blk_per_line) {
 		pr_err("pblk: config. not supported. Min. LUN in line:%d\n",
@@ -1009,9 +1016,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.dom & NVM_RSP_L2P) {
 		pr_err("pblk: host-side L2P table not supported. (%x)\n",
-							dev->identity.dom);
+							dev->geo.dom);
 		return ERR_PTR(-EINVAL);
 	}
 
@@ -1093,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->clba * geo->csecs;
 	tqueue->limits.discard_alignment = 0;
 	blk_queue_max_discard_sectors(tqueue, UINT_MAX >> 9);
 	blk_queue_flag_set(QUEUE_FLAG_DISCARD, tqueue);
diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c
index 2f761283f43e..9eee10f69df0 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->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..26356429dc72 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->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->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->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->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->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->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->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..883a7113b19d 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->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 c2cf6c939752..2474ef4366fa 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_addrf_12 *ppaf;
+	struct nvm_addrf_12 *geo_ppaf;
 	ssize_t sz = 0;
 
-	sz = snprintf(page, PAGE_SIZE - sz,
+	ppaf = (struct nvm_addrf_12 *)&pblk->ppaf;
+	geo_ppaf = (struct nvm_addrf_12 *)&geo->addrf;
+
+	sz = snprintf(page, PAGE_SIZE,
 		"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);
+			pblk->ppaf_bitsize,
+			ppaf->blk_offset, ppaf->blk_len,
+			ppaf->pg_offset, ppaf->pg_len,
+			ppaf->lun_offset, ppaf->lun_len,
+			ppaf->ch_offset, ppaf->ch_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);
+			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);
 
 	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->clba);
 
 	return sz;
 }
diff --git a/drivers/lightnvm/pblk-write.c b/drivers/lightnvm/pblk-write.c
index aae86ed60b98..3e6f1ebd743a 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->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 f0309d8172c0..898c4e49f77d 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_addrf 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->mw_cunits * geo->all_luns * geo->ws_opt;
 }
 
 static inline int pblk_ppa_to_line(struct ppa_addr p)
@@ -964,15 +947,16 @@ 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_addrf_12 *ppaf = (struct nvm_addrf_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 +964,14 @@ 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_addrf_12 *ppaf = (struct nvm_addrf_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 +988,14 @@ 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_addrf_12 *ppaf = (struct nvm_addrf_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 +1011,14 @@ 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_addrf_12 *ppaf = (struct nvm_addrf_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;
@@ -1229,10 +1212,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.pl < geo->num_pln &&
 				ppa->g.blk < geo->nr_chks &&
-				ppa->g.pg < geo->ws_per_chk &&
-				ppa->g.sec < geo->sec_per_pg)
+				ppa->g.pg < geo->num_pg &&
+				ppa->g.sec < geo->ws_min)
 			continue;
 
 		print_ppa(ppa, "boundary", i);
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 839c0b96466a..29c8f44eb25b 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,160 @@ 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_addrf_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_geo *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;
+	}
+
+	geo->ver_id = id->ver_id;
+
+	geo->nr_chnls = src->num_ch;
+	geo->nr_luns = src->num_lun;
+	geo->all_luns = geo->nr_chnls * geo->nr_luns;
 
-	nvm_id->num_ch = src->num_ch;
-	nvm_id->num_lun = src->num_lun;
+	geo->nr_chks = le16_to_cpu(src->num_chk);
 
-	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);
+	geo->csecs = le16_to_cpu(src->csecs);
+	geo->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) / geo->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;
+	geo->clba = sec_per_pl * pg_per_blk;
+
+	geo->all_chunks = geo->all_luns * geo->nr_chks;
+	geo->total_secs = geo->clba * geo->all_chunks;
+
+	geo->ws_min = sec_per_pg;
+	geo->ws_opt = sec_per_pg;
+	geo->mw_cunits = geo->ws_opt << 3;	/* default to MLC safe values */
+
+	geo->mccap = le32_to_cpu(src->mccap);
+
+	geo->trdt = le32_to_cpu(src->trdt);
+	geo->trdm = le32_to_cpu(src->trdm);
+	geo->tprt = le32_to_cpu(src->tprt);
+	geo->tprm = le32_to_cpu(src->tprm);
+	geo->tbet = le32_to_cpu(src->tbet);
+	geo->tbem = le32_to_cpu(src->tbem);
+
+	/* 1.2 compatibility */
+	geo->vmnt = id->vmnt;
+	geo->cap = le32_to_cpu(id->cap);
+	geo->dom = le32_to_cpu(id->dom);
+
+	geo->mtype = src->mtype;
+	geo->fmtype = src->fmtype;
+
+	geo->cpar = le16_to_cpu(src->cpar);
+	geo->mpos = le32_to_cpu(src->mpos);
+
+	geo->plane_mode = NVM_PLANE_SINGLE;
+
+	if (geo->mpos & 0x020202) {
+		geo->plane_mode = NVM_PLANE_DOUBLE;
+		geo->ws_opt <<= 1;
+	} else if (geo->mpos & 0x040404) {
+		geo->plane_mode = NVM_PLANE_QUAD;
+		geo->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);
+	geo->num_pln = src->num_pln;
+	geo->num_pg = le16_to_cpu(src->num_pg);
+	geo->fpg_sz = le16_to_cpu(src->fpg_sz);
+
+	nvme_nvm_set_addr_12((struct nvm_addrf_12 *)&geo->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_addrf *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_geo *geo)
 {
-	nvm_id->ver_id = id->mjr;
+	geo->ver_id = id->mjr;
+
+	geo->nr_chnls = le16_to_cpu(id->num_grp);
+	geo->nr_luns = le16_to_cpu(id->num_pu);
+	geo->all_luns = geo->nr_chnls * geo->nr_luns;
 
-	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);
+	geo->nr_chks = le32_to_cpu(id->num_chk);
+	geo->clba = le32_to_cpu(id->clba);
 
-	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);
+	geo->all_chunks = geo->all_luns * geo->nr_chks;
+	geo->total_secs = geo->clba * geo->all_chunks;
 
-	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);
+	geo->ws_min = le32_to_cpu(id->ws_min);
+	geo->ws_opt = le32_to_cpu(id->ws_opt);
+	geo->mw_cunits = le32_to_cpu(id->mw_cunits);
 
-	/* calculated values */
-	nvm_id->ws_per_chk = nvm_id->clba / nvm_id->ws_min;
+	geo->trdt = le32_to_cpu(id->trdt);
+	geo->trdm = le32_to_cpu(id->trdm);
+	geo->tprt = le32_to_cpu(id->twrt);
+	geo->tprm = le32_to_cpu(id->twrm);
+	geo->tbet = le32_to_cpu(id->tcrst);
+	geo->tbem = le32_to_cpu(id->tcrsm);
 
-	/* 1.2 compatibility */
-	nvm_id->ws_seq = NVM_IO_SNGL_ACCESS;
+	nvme_nvm_set_addr_20(&geo->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 +434,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->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->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;
@@ -406,7 +460,7 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
 	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 = geo->nr_chks * geo->num_pln;
 	int tblsz = sizeof(struct nvme_nvm_bb_tbl) + nr_blks;
 	int ret = 0;
 
@@ -447,7 +501,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, geo->nr_chks * geo->num_pln);
 out:
 	kfree(bb_tbl);
 	return ret;
@@ -815,9 +869,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_geo *geo = &ndev->geo;
 
-	ndev->identity.csecs = ndev->geo.sec_size = 1 << ns->lba_shift;
-	ndev->identity.sos = ndev->geo.oob_size = ns->ms;
+	geo->csecs = 1 << ns->lba_shift;
+	geo->sos = ns->ms;
 }
 
 int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node)
@@ -850,23 +905,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_geo *geo = &ndev->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", 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", geo->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", geo->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", geo->trdm);
 	} else {
 		return scnprintf(page,
 				 PAGE_SIZE,
@@ -875,75 +929,78 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
 	}
 }
 
+static ssize_t nvm_dev_attr_show_ppaf(struct nvm_addrf_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_geo *geo = &ndev->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", geo->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", geo->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 *)&geo->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", geo->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", geo->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", 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", 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", geo->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", geo->nr_chks);
 	} 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", geo->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", geo->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", geo->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", geo->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", geo->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", geo->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", geo->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", geo->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", geo->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", geo->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 +1009,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_geo *geo = &ndev->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", 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", 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", geo->nr_chks);
 	} else if (strcmp(attr->name, "clba") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->clba);
+		return scnprintf(page, PAGE_SIZE, "%u\n", geo->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", geo->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", geo->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", geo->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", geo->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", geo->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", geo->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", geo->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 +1161,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_geo *geo = &ndev->geo;
+
+	if (!ndev)
 		return -EINVAL;
 
-	switch (ns->ndev->identity.ver_id) {
+	switch (geo->ver_id) {
 	case 1:
 		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
 					&nvm_dev_attr_group_12);
@@ -1123,7 +1181,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_geo *geo = &ndev->geo;
+
+	switch (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..6e650563b379 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,48 @@ struct nvm_id_lp_tbl {
 	struct nvm_id_lp_mlc mlc;
 };
 
-struct nvm_addr_format {
-	u8	ch_offset;
+struct nvm_addrf_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;
-};
-
-struct nvm_id {
-	u8	ver_id;
-	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;
+	u64	ch_mask;
+	u64	lun_mask;
+	u64	blk_mask;
+	u64	pg_mask;
+	u64	pln_mask;
+	u64	sec_mask;
+};
 
-	u8	num_pln;
-	u16	num_pg;
-	u16	fpg_sz;
-} __packed;
+struct nvm_addrf {
+	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_target {
 	struct list_head list;
@@ -274,36 +260,63 @@ enum {
 	NVM_BLK_ST_BAD =	0x8,	/* Bad block */
 };
 
-
-/* Device generic information */
+/* Instance geometry */
 struct nvm_geo {
-	/* generic geometry */
+	/* device reported version */
+	u8	ver_id;
+
+	/* instance specific geometry */
 	int nr_chnls;
-	int all_luns; /* across channels */
-	int nr_luns; /* per channel */
-	int nr_chks; /* per lun */
+	int nr_luns;		/* per channel */
 
-	int sec_size;
-	int oob_size;
-	int mccap;
+	/* calculated values */
+	int all_luns;		/* across channels */
+	int all_chunks;		/* across channels */
 
-	int sec_per_chk;
-	int sec_per_lun;
+	int op;			/* over-provision in instance */
 
-	int ws_min;
-	int ws_opt;
-	int ws_seq;
-	int ws_per_chk;
+	sector_t total_secs;	/* across channels */
 
-	int op;
+	/* chunk geometry */
+	u32	nr_chks;	/* chunks per lun */
+	u32	clba;		/* sectors per chunk */
+	u16	csecs;		/* sector size */
+	u16	sos;		/* out-of-band area size */
 
-	struct nvm_addr_format ppaf;
+	/* device write constrains */
+	u32	ws_min;		/* minimum write size */
+	u32	ws_opt;		/* optimal write size */
+	u32	mw_cunits;	/* distance required for successful read */
 
-	/* 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 */
+	/* 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_addrf addrf;
+
+	/* 1.2 compatibility */
+	u8	vmnt;
+	u32	cap;
+	u32	dom;
+
+	u8	mtype;
+	u8	fmtype;
+
+	u16	cpar;
+	u32	mpos;
+
+	u8	num_pln;
+	u8	plane_mode;
+	u16	num_pg;
+	u16	fpg_sz;
 };
 
 /* sub-device structure */
@@ -314,9 +327,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;
@@ -331,13 +341,9 @@ struct nvm_dev {
 	/* Device information */
 	struct nvm_geo geo;
 
-	unsigned long total_secs;
-
 	unsigned long *lun_map;
 	void *dma_pool;
 
-	struct nvm_id identity;
-
 	/* Backend device */
 	struct request_queue *q;
 	char name[DISK_NAME_LEN];
@@ -357,14 +363,15 @@ 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_addrf_12 *ppaf = (struct nvm_addrf_12 *)&geo->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 +380,17 @@ 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_addrf_12 *ppaf = (struct nvm_addrf_12 *)&geo->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.11.0

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

* [GIT PULL 24/37] lightnvm: add minor version to generic geometry
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (22 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 23/37] lightnvm: simplify geometry structure Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 25/37] lightnvm: add shorten OCSSD version in geo Matias Bjørling
                   ` (13 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

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

Separate the version between major and minor on the generic geometry and
represent it through sysfs in the 2.0 path. The 1.2 path only shows the
major version to preserve the existing user space interface.

Signed-off-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 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 9dec936ac1dc..103e0ad9622c 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -890,8 +890,8 @@ static int nvm_init(struct nvm_dev *dev)
 		goto err;
 	}
 
-	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
-				geo->ver_id,
+	pr_debug("nvm: ver:%u.%u nvm_vendor:%x\n",
+				geo->major_ver_id, geo->minor_ver_id,
 				geo->vmnt);
 
 	ret = nvm_core_init(dev);
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 29c8f44eb25b..de4105544956 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -295,7 +295,9 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
 		return -EINVAL;
 	}
 
-	geo->ver_id = id->ver_id;
+	/* 1.2 spec. only reports a single version id - unfold */
+	geo->major_ver_id = id->ver_id;
+	geo->minor_ver_id = 2;
 
 	geo->nr_chnls = src->num_ch;
 	geo->nr_luns = src->num_lun;
@@ -379,7 +381,14 @@ static void nvme_nvm_set_addr_20(struct nvm_addrf *dst,
 static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 			     struct nvm_geo *geo)
 {
-	geo->ver_id = id->mjr;
+	geo->major_ver_id = id->mjr;
+	geo->minor_ver_id = id->mnr;
+
+	if (!(geo->major_ver_id == 2 && geo->minor_ver_id == 0)) {
+		pr_err("nvm: OCSSD version not supported (v%d.%d)\n",
+				geo->major_ver_id, geo->minor_ver_id);
+		return -EINVAL;
+	}
 
 	geo->nr_chnls = le16_to_cpu(id->num_grp);
 	geo->nr_luns = le16_to_cpu(id->num_pu);
@@ -914,7 +923,13 @@ 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", geo->ver_id);
+		if (geo->major_ver_id == 1)
+			return scnprintf(page, PAGE_SIZE, "%u\n",
+						geo->major_ver_id);
+		else
+			return scnprintf(page, PAGE_SIZE, "%u.%u\n",
+						geo->major_ver_id,
+						geo->minor_ver_id);
 	} else if (strcmp(attr->name, "capabilities") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", geo->cap);
 	} else if (strcmp(attr->name, "read_typ") == 0) {
@@ -1167,7 +1182,7 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
 	if (!ndev)
 		return -EINVAL;
 
-	switch (geo->ver_id) {
+	switch (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_geo *geo = &ndev->geo;
 
-	switch (geo->ver_id) {
+	switch (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 6e650563b379..7ed8b92d6744 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -263,7 +263,8 @@ enum {
 /* Instance geometry */
 struct nvm_geo {
 	/* device reported version */
-	u8	ver_id;
+	u8	major_ver_id;
+	u8	minor_ver_id;
 
 	/* instance specific geometry */
 	int nr_chnls;
-- 
2.11.0

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

* [GIT PULL 25/37] lightnvm: add shorten OCSSD version in geo
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (23 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 24/37] lightnvm: add minor version to generic geometry Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 26/37] lightnvm: complete geo structure with maxoc* Matias Bjørling
                   ` (12 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

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

Create a shorten version to use in the generic geometry.

Signed-off-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 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 de4105544956..f7f7769e7588 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,
 	geo->major_ver_id = id->ver_id;
 	geo->minor_ver_id = 2;
 
+	/* Set compacted version for upper layers */
+	geo->version = NVM_OCSSD_SPEC_12;
+
 	geo->nr_chnls = src->num_ch;
 	geo->nr_luns = src->num_lun;
 	geo->all_luns = geo->nr_chnls * geo->nr_luns;
@@ -384,6 +387,9 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 	geo->major_ver_id = id->mjr;
 	geo->minor_ver_id = id->mnr;
 
+	/* Set compacted version for upper layers */
+	geo->version = NVM_OCSSD_SPEC_20;
+
 	if (!(geo->major_ver_id == 2 && geo->minor_ver_id == 0)) {
 		pr_err("nvm: OCSSD version not supported (v%d.%d)\n",
 				geo->major_ver_id, geo->minor_ver_id);
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 7ed8b92d6744..a073c0c76260 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 {
@@ -266,6 +271,9 @@ struct nvm_geo {
 	u8	major_ver_id;
 	u8	minor_ver_id;
 
+	/* kernel short version */
+	u8	version;
+
 	/* instance specific geometry */
 	int nr_chnls;
 	int nr_luns;		/* per channel */
-- 
2.11.0

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

* [GIT PULL 26/37] lightnvm: complete geo structure with maxoc*
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (24 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 25/37] lightnvm: add shorten OCSSD version in geo Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 27/37] lightnvm: normalize geometry nomenclature Matias Bjørling
                   ` (11 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

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

Complete the generic geometry structure with the maxoc and maxocpu
felds, present in the 2.0 spec. Also, expose them through sysfs.

Signed-off-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/nvme/host/lightnvm.c | 17 +++++++++++++++++
 include/linux/lightnvm.h     |  2 ++
 2 files changed, 19 insertions(+)

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index f7f7769e7588..41b38ebdb1f3 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -323,6 +323,13 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
 	geo->ws_opt = sec_per_pg;
 	geo->mw_cunits = geo->ws_opt << 3;	/* default to MLC safe values */
 
+	/* Do not impose values for maximum number of open blocks as it is
+	 * unspecified in 1.2. Users of 1.2 must be aware of this and eventually
+	 * specify these values through a quirk if restrictions apply.
+	 */
+	geo->maxoc = geo->all_luns * geo->nr_chks;
+	geo->maxocpu = geo->nr_chks;
+
 	geo->mccap = le32_to_cpu(src->mccap);
 
 	geo->trdt = le32_to_cpu(src->trdt);
@@ -409,6 +416,8 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 	geo->ws_min = le32_to_cpu(id->ws_min);
 	geo->ws_opt = le32_to_cpu(id->ws_opt);
 	geo->mw_cunits = le32_to_cpu(id->mw_cunits);
+	geo->maxoc = le32_to_cpu(id->maxoc);
+	geo->maxocpu = le32_to_cpu(id->maxocpu);
 
 	geo->trdt = le32_to_cpu(id->trdt);
 	geo->trdm = le32_to_cpu(id->trdm);
@@ -1050,6 +1059,10 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
 		return scnprintf(page, PAGE_SIZE, "%u\n", geo->ws_min);
 	} else if (strcmp(attr->name, "ws_opt") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", geo->ws_opt);
+	} else if (strcmp(attr->name, "maxoc") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", geo->maxoc);
+	} else if (strcmp(attr->name, "maxocpu") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", geo->maxocpu);
 	} else if (strcmp(attr->name, "mw_cunits") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", geo->mw_cunits);
 	} else if (strcmp(attr->name, "write_typ") == 0) {
@@ -1147,6 +1160,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);
@@ -1163,6 +1178,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,
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index a073c0c76260..870959a58fef 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -296,6 +296,8 @@ struct nvm_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.11.0

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

* [GIT PULL 27/37] lightnvm: normalize geometry nomenclature
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (25 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 26/37] lightnvm: complete geo structure with maxoc* Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 28/37] lightnvm: add support for 2.0 address format Matias Bjørling
                   ` (10 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

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

Normalize nomenclature for naming channels, luns, chunks, planes and
sectors as well as derivations in order to improve readability.

Signed-off-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/core.c       | 89 +++++++++++++++++++++----------------------
 drivers/lightnvm/pblk-core.c  |  4 +-
 drivers/lightnvm/pblk-init.c  | 30 +++++++--------
 drivers/lightnvm/pblk-sysfs.c |  4 +-
 drivers/lightnvm/pblk.h       | 20 +++++-----
 drivers/nvme/host/lightnvm.c  | 54 +++++++++++++-------------
 include/linux/lightnvm.h      | 16 ++++----
 7 files changed, 108 insertions(+), 109 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 103e0ad9622c..94b3b423840b 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)
@@ -114,15 +114,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));
@@ -147,47 +147,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)
@@ -209,7 +208,7 @@ 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)
@@ -219,15 +218,15 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
 	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.nr_luns = (lun_balanced) ? prev_nr_luns : -1;
-	tgt_dev->geo.all_luns = nr_luns;
-	tgt_dev->geo.all_chunks = nr_luns * dev->geo.nr_chks;
+	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.num_chk;
 
 	tgt_dev->geo.op = op;
 
-	sec_per_lun = dev->geo.clba * dev->geo.nr_chks;
-	tgt_dev->geo.total_secs = nr_luns * sec_per_lun;
+	sec_per_lun = dev->geo.clba * dev->geo.num_chk;
+	tgt_dev->geo.total_secs = num_lun * sec_per_lun;
 
 	tgt_dev->q = dev->q;
 	tgt_dev->map = dev_map;
@@ -505,20 +504,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)
@@ -547,7 +546,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);
@@ -676,7 +675,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->pln_mode == NVM_PLANE_SINGLE && nr_ppas == 1) {
 		rqd->nr_ppas = nr_ppas;
 		rqd->ppa_addr = ppas[0];
 
@@ -690,7 +689,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->pln_mode;
 	rqd->nr_ppas *= plane_cnt;
 
 	for (i = 0; i < nr_ppas; i++) {
@@ -808,15 +807,15 @@ int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
 	struct nvm_geo *geo = &dev->geo;
 	int blk, offset, pl, blktype;
 
-	if (nr_blks != geo->nr_chks * geo->plane_mode)
+	if (nr_blks != geo->num_chk * geo->pln_mode)
 		return -EINVAL;
 
-	for (blk = 0; blk < geo->nr_chks; blk++) {
-		offset = blk * geo->plane_mode;
+	for (blk = 0; blk < geo->num_chk; blk++) {
+		offset = blk * geo->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 < geo->pln_mode; pl++) {
 			if (blks[offset + pl] &
 					(NVM_BLK_T_BAD|NVM_BLK_T_GRWN_BAD)) {
 				blktype = blks[offset + pl];
@@ -827,7 +826,7 @@ int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
 		blks[blk] = blktype;
 	}
 
-	return geo->nr_chks;
+	return geo->num_chk;
 }
 EXPORT_SYMBOL(nvm_bb_tbl_fold);
 
@@ -901,9 +900,9 @@ static int nvm_init(struct nvm_dev *dev)
 	}
 
 	pr_info("nvm: registered %s [%u/%u/%u/%u/%u]\n",
-			dev->name, geo->ws_min, geo->ws_opt,
-			geo->nr_chks, geo->all_luns,
-			geo->nr_chnls);
+			dev->name, dev->geo.ws_min, dev->geo.ws_opt,
+			dev->geo.num_chk, dev->geo.all_luns,
+			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 52c0c3e5ec6e..64c87dd4f1cd 100644
--- a/drivers/lightnvm/pblk-core.c
+++ b/drivers/lightnvm/pblk-core.c
@@ -1742,10 +1742,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 2fca27d0a9b5..4656d1ff81a6 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -193,15 +193,15 @@ static int pblk_set_addrf_12(struct nvm_geo *geo, struct nvm_addrf_12 *dst)
 	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;
 	}
@@ -210,16 +210,16 @@ static int pblk_set_addrf_12(struct nvm_geo *geo, struct nvm_addrf_12 *dst)
 	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;
@@ -503,7 +503,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->num_chk * geo->pln_mode;
 	nr_blks = blk_per_lun * geo->all_luns;
 
 	log = kmalloc(nr_blks, GFP_KERNEL);
@@ -530,7 +530,7 @@ static int pblk_bb_line(struct pblk *pblk, struct pblk_line *line,
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
 	int i, bb_cnt = 0;
-	int blk_per_lun = geo->nr_chks * geo->plane_mode;
+	int blk_per_lun = geo->num_chk * geo->pln_mode;
 
 	for (i = 0; i < blk_per_line; i++) {
 		struct pblk_lun *rlun = &pblk->luns[i];
@@ -554,7 +554,7 @@ static int pblk_luns_init(struct pblk *pblk)
 	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;
 	}
@@ -566,9 +566,9 @@ static int pblk_luns_init(struct pblk *pblk)
 
 	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 = dev->luns[lunid];
@@ -672,7 +672,7 @@ static int pblk_line_mg_init(struct pblk *pblk)
 	struct pblk_line_meta *lm = &pblk->lm;
 	int i, bb_distance;
 
-	l_mg->nr_lines = geo->nr_chks;
+	l_mg->nr_lines = geo->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;
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index 2474ef4366fa..3e9364f60b44 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->lun_offset, ppaf->lun_len,
 			ppaf->ch_offset, ppaf->ch_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,
 		"d:blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%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->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);
+			geo_ppaf->sec_offset, geo_ppaf->sec_len);
 
 	return sz;
 }
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 898c4e49f77d..dcdad255ccb5 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,
@@ -956,7 +956,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;
 }
@@ -971,7 +971,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;
 }
@@ -995,7 +995,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;
@@ -1018,7 +1018,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;
@@ -1136,7 +1136,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->pln_mode >> 1;
 
 	if (type == PBLK_WRITE)
 		flags |= NVM_IO_SCRAMBLE_ENABLE;
@@ -1157,7 +1157,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->pln_mode >> 1;
 
 	return flags;
 }
@@ -1210,10 +1210,10 @@ 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->num_pln &&
-				ppa->g.blk < geo->nr_chks &&
+				ppa->g.blk < geo->num_chk &&
 				ppa->g.pg < geo->num_pg &&
 				ppa->g.sec < geo->ws_min)
 			continue;
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 41b38ebdb1f3..08f0f6b5bc06 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_addrf_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,
@@ -302,11 +302,11 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
 	/* Set compacted version for upper layers */
 	geo->version = NVM_OCSSD_SPEC_12;
 
-	geo->nr_chnls = src->num_ch;
-	geo->nr_luns = src->num_lun;
-	geo->all_luns = geo->nr_chnls * geo->nr_luns;
+	geo->num_ch = src->num_ch;
+	geo->num_lun = src->num_lun;
+	geo->all_luns = geo->num_ch * geo->num_lun;
 
-	geo->nr_chks = le16_to_cpu(src->num_chk);
+	geo->num_chk = le16_to_cpu(src->num_chk);
 
 	geo->csecs = le16_to_cpu(src->csecs);
 	geo->sos = le16_to_cpu(src->sos);
@@ -316,7 +316,7 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
 	sec_per_pl = sec_per_pg * src->num_pln;
 	geo->clba = sec_per_pl * pg_per_blk;
 
-	geo->all_chunks = geo->all_luns * geo->nr_chks;
+	geo->all_chunks = geo->all_luns * geo->num_chk;
 	geo->total_secs = geo->clba * geo->all_chunks;
 
 	geo->ws_min = sec_per_pg;
@@ -327,8 +327,8 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
 	 * unspecified in 1.2. Users of 1.2 must be aware of this and eventually
 	 * specify these values through a quirk if restrictions apply.
 	 */
-	geo->maxoc = geo->all_luns * geo->nr_chks;
-	geo->maxocpu = geo->nr_chks;
+	geo->maxoc = geo->all_luns * geo->num_chk;
+	geo->maxocpu = geo->num_chk;
 
 	geo->mccap = le32_to_cpu(src->mccap);
 
@@ -350,13 +350,13 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
 	geo->cpar = le16_to_cpu(src->cpar);
 	geo->mpos = le32_to_cpu(src->mpos);
 
-	geo->plane_mode = NVM_PLANE_SINGLE;
+	geo->pln_mode = NVM_PLANE_SINGLE;
 
 	if (geo->mpos & 0x020202) {
-		geo->plane_mode = NVM_PLANE_DOUBLE;
+		geo->pln_mode = NVM_PLANE_DOUBLE;
 		geo->ws_opt <<= 1;
 	} else if (geo->mpos & 0x040404) {
-		geo->plane_mode = NVM_PLANE_QUAD;
+		geo->pln_mode = NVM_PLANE_QUAD;
 		geo->ws_opt <<= 2;
 	}
 
@@ -403,14 +403,14 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 		return -EINVAL;
 	}
 
-	geo->nr_chnls = le16_to_cpu(id->num_grp);
-	geo->nr_luns = le16_to_cpu(id->num_pu);
-	geo->all_luns = geo->nr_chnls * geo->nr_luns;
+	geo->num_ch = le16_to_cpu(id->num_grp);
+	geo->num_lun = le16_to_cpu(id->num_pu);
+	geo->all_luns = geo->num_ch * geo->num_lun;
 
-	geo->nr_chks = le32_to_cpu(id->num_chk);
+	geo->num_chk = le32_to_cpu(id->num_chk);
 	geo->clba = le32_to_cpu(id->clba);
 
-	geo->all_chunks = geo->all_luns * geo->nr_chks;
+	geo->all_chunks = geo->all_luns * geo->num_chk;
 	geo->total_secs = geo->clba * geo->all_chunks;
 
 	geo->ws_min = le32_to_cpu(id->ws_min);
@@ -484,7 +484,7 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa,
 	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->num_pln;
+	int nr_blks = geo->num_chk * geo->num_pln;
 	int tblsz = sizeof(struct nvme_nvm_bb_tbl) + nr_blks;
 	int ret = 0;
 
@@ -525,7 +525,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->num_pln);
+	memcpy(blks, bb_tbl->blk, geo->num_chk * geo->num_pln);
 out:
 	kfree(bb_tbl);
 	return ret;
@@ -968,7 +968,7 @@ static ssize_t nvm_dev_attr_show_ppaf(struct nvm_addrf_12 *ppaf, char *page)
 				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,
@@ -998,13 +998,13 @@ 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", geo->fmtype);
 	} else if (strcmp(attr->name, "num_channels") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", geo->nr_chnls);
+		return scnprintf(page, PAGE_SIZE, "%u\n", geo->num_ch);
 	} else if (strcmp(attr->name, "num_luns") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", geo->nr_luns);
+		return scnprintf(page, PAGE_SIZE, "%u\n", geo->num_lun);
 	} else if (strcmp(attr->name, "num_planes") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", geo->num_pln);
 	} else if (strcmp(attr->name, "num_blocks") == 0) {	/* u16 */
-		return scnprintf(page, PAGE_SIZE, "%u\n", geo->nr_chks);
+		return scnprintf(page, PAGE_SIZE, "%u\n", geo->num_chk);
 	} else if (strcmp(attr->name, "num_pages") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", geo->num_pg);
 	} else if (strcmp(attr->name, "page_size") == 0) {
@@ -1048,11 +1048,11 @@ 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", geo->nr_chnls);
+		return scnprintf(page, PAGE_SIZE, "%u\n", geo->num_ch);
 	} else if (strcmp(attr->name, "punits") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", geo->nr_luns);
+		return scnprintf(page, PAGE_SIZE, "%u\n", geo->num_lun);
 	} else if (strcmp(attr->name, "chunks") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", geo->nr_chks);
+		return scnprintf(page, PAGE_SIZE, "%u\n", geo->num_chk);
 	} else if (strcmp(attr->name, "clba") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", geo->clba);
 	} else if (strcmp(attr->name, "ws_min") == 0) {
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 870959a58fef..00295d9f9522 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -163,14 +163,14 @@ struct nvm_addrf_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;
@@ -275,8 +275,8 @@ struct nvm_geo {
 	u8	version;
 
 	/* instance specific geometry */
-	int nr_chnls;
-	int nr_luns;		/* per channel */
+	int num_ch;
+	int num_lun;		/* per channel */
 
 	/* calculated values */
 	int all_luns;		/* across channels */
@@ -287,7 +287,7 @@ struct nvm_geo {
 	sector_t total_secs;	/* across channels */
 
 	/* chunk geometry */
-	u32	nr_chks;	/* chunks per lun */
+	u32	num_chk;	/* chunks per lun */
 	u32	clba;		/* sectors per chunk */
 	u16	csecs;		/* sector size */
 	u16	sos;		/* out-of-band area size */
@@ -325,7 +325,7 @@ struct nvm_geo {
 	u32	mpos;
 
 	u8	num_pln;
-	u8	plane_mode;
+	u8	pln_mode;
 	u16	num_pg;
 	u16	fpg_sz;
 };
@@ -382,7 +382,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;
 }
@@ -401,7 +401,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.11.0

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

* [GIT PULL 28/37] lightnvm: add support for 2.0 address format
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (26 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 27/37] lightnvm: normalize geometry nomenclature Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 29/37] lightnvm: make address conversions depend on generic device Matias Bjørling
                   ` (9 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

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

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.

Also, convert the generic operations to the generic format in pblk.

Signed-off-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/core.c       |  20 ++++-----
 drivers/lightnvm/pblk-core.c  |  10 ++---
 drivers/lightnvm/pblk-map.c   |   4 +-
 drivers/lightnvm/pblk-sysfs.c |   4 +-
 drivers/lightnvm/pblk.h       |   4 +-
 include/linux/lightnvm.h      | 101 +++++++++++++++++++++++++++++++-----------
 6 files changed, 95 insertions(+), 48 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 94b3b423840b..63d948cc6dec 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -194,8 +194,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;
@@ -556,22 +556,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/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index 64c87dd4f1cd..c3eb135fce07 100644
--- a/drivers/lightnvm/pblk-core.c
+++ b/drivers/lightnvm/pblk-core.c
@@ -885,7 +885,7 @@ int pblk_line_erase(struct pblk *pblk, struct pblk_line *line)
 		}
 
 		ppa = pblk->luns[bit].bppa; /* set ch and lun */
-		ppa.g.blk = line->id;
+		ppa.a.blk = line->id;
 
 		atomic_dec(&line->left_eblks);
 		WARN_ON(test_and_set_bit(bit, line->erase_bitmap));
@@ -1683,8 +1683,8 @@ static void __pblk_down_page(struct pblk *pblk, struct ppa_addr *ppa_list,
 	int i;
 
 	for (i = 1; i < nr_ppas; i++)
-		WARN_ON(ppa_list[0].g.lun != ppa_list[i].g.lun ||
-				ppa_list[0].g.ch != ppa_list[i].g.ch);
+		WARN_ON(ppa_list[0].a.lun != ppa_list[i].a.lun ||
+				ppa_list[0].a.ch != ppa_list[i].a.ch);
 #endif
 
 	ret = down_timeout(&rlun->wr_sem, msecs_to_jiffies(30000));
@@ -1728,8 +1728,8 @@ void pblk_up_page(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas)
 	int i;
 
 	for (i = 1; i < nr_ppas; i++)
-		WARN_ON(ppa_list[0].g.lun != ppa_list[i].g.lun ||
-				ppa_list[0].g.ch != ppa_list[i].g.ch);
+		WARN_ON(ppa_list[0].a.lun != ppa_list[i].a.lun ||
+				ppa_list[0].a.ch != ppa_list[i].a.ch);
 #endif
 
 	rlun = &pblk->luns[pos];
diff --git a/drivers/lightnvm/pblk-map.c b/drivers/lightnvm/pblk-map.c
index 04e08d76ea5f..20dbaa89c9df 100644
--- a/drivers/lightnvm/pblk-map.c
+++ b/drivers/lightnvm/pblk-map.c
@@ -127,7 +127,7 @@ void pblk_map_erase_rq(struct pblk *pblk, struct nvm_rq *rqd,
 			atomic_dec(&e_line->left_eblks);
 
 			*erase_ppa = rqd->ppa_list[i];
-			erase_ppa->g.blk = e_line->id;
+			erase_ppa->a.blk = e_line->id;
 
 			spin_unlock(&e_line->lock);
 
@@ -168,6 +168,6 @@ void pblk_map_erase_rq(struct pblk *pblk, struct nvm_rq *rqd,
 		set_bit(bit, e_line->erase_bitmap);
 		atomic_dec(&e_line->left_eblks);
 		*erase_ppa = pblk->luns[bit].bppa; /* set ch and lun */
-		erase_ppa->g.blk = e_line->id;
+		erase_ppa->a.blk = e_line->id;
 	}
 }
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index 3e9364f60b44..2489ea0edfa0 100644
--- a/drivers/lightnvm/pblk-sysfs.c
+++ b/drivers/lightnvm/pblk-sysfs.c
@@ -39,8 +39,8 @@ static ssize_t pblk_sysfs_luns_show(struct pblk *pblk, char *page)
 		sz += snprintf(page + sz, PAGE_SIZE - sz,
 				"pblk: pos:%d, ch:%d, lun:%d - %d\n",
 					i,
-					rlun->bppa.g.ch,
-					rlun->bppa.g.lun,
+					rlun->bppa.a.ch,
+					rlun->bppa.a.lun,
 					active);
 	}
 
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index dcdad255ccb5..6607c41b23c0 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -936,12 +936,12 @@ static inline int pblk_pad_distance(struct pblk *pblk)
 
 static inline int pblk_ppa_to_line(struct ppa_addr p)
 {
-	return p.g.blk;
+	return p.a.blk;
 }
 
 static inline int pblk_ppa_to_pos(struct nvm_geo *geo, struct ppa_addr p)
 {
-	return p.g.lun * geo->num_ch + p.g.ch;
+	return p.a.lun * geo->num_ch + p.a.ch;
 }
 
 static inline struct ppa_addr addr_to_gen_ppa(struct pblk *pblk, u64 paddr,
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 00295d9f9522..f2549b4b8626 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -16,12 +16,21 @@ 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_BLK_BITS (16)
+#define NVM_GEN_RESERVED (32)
+
+/* 1.2 format */
+#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_SEC_BITS (24)
+#define NVM_20_RESERVED (8)
 
 enum {
 	NVM_OCSSD_SPEC_12 = 12,
@@ -31,16 +40,34 @@ 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 blk		: NVM_GEN_BLK_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_GEN_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 grp		: NVM_GEN_CH_BITS;
+			u64 pu		: NVM_GEN_LUN_BITS;
+			u64 chk		: NVM_GEN_BLK_BITS;
+			u64 sec		: NVM_20_SEC_BITS;
+			u64 reserved	: NVM_20_RESERVED;
+		} m;
+
 		struct {
 			u64 line	: 63;
 			u64 is_cached	: 1;
@@ -374,15 +401,25 @@ 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_addrf_12 *ppaf = (struct nvm_addrf_12 *)&geo->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->version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addrf_12 *ppaf = (struct nvm_addrf_12 *)&geo->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_addrf *lbaf = &geo->addrf;
+
+		l.ppa = ((u64)r.m.grp) << lbaf->ch_offset;
+		l.ppa |= ((u64)r.m.pu) << lbaf->lun_offset;
+		l.ppa |= ((u64)r.m.chk) << lbaf->chk_offset;
+		l.ppa |= ((u64)r.m.sec) << lbaf->sec_offset;
+	}
 
 	return l;
 }
@@ -391,17 +428,27 @@ 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_addrf_12 *ppaf = (struct nvm_addrf_12 *)&geo->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->version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addrf_12 *ppaf = (struct nvm_addrf_12 *)&geo->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_addrf *lbaf = &geo->addrf;
+
+		l.m.grp = (r.ppa & lbaf->ch_mask) >> lbaf->ch_offset;
+		l.m.pu = (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.11.0

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

* [GIT PULL 29/37] lightnvm: make address conversions depend on generic device
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (27 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 28/37] lightnvm: add support for 2.0 address format Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 30/37] lightnvm: implement get log report chunk helpers Matias Bjørling
                   ` (8 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

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

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>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 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 63d948cc6dec..77901bf17416 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -581,7 +581,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]);
 	}
 }
 
@@ -591,7 +591,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 f2549b4b8626..f3b273e543c3 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -397,10 +397,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_geo *geo = &dev->geo;
 	struct ppa_addr l;
 
 	if (geo->version == NVM_OCSSD_SPEC_12) {
@@ -424,10 +424,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_geo *geo = &dev->geo;
 	struct ppa_addr l;
 
 	l.ppa = 0;
-- 
2.11.0

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

* [GIT PULL 30/37] lightnvm: implement get log report chunk helpers
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (28 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 29/37] lightnvm: make address conversions depend on generic device Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 31/37] lightnvm: pblk: check for supported version Matias Bjørling
                   ` (7 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

From: Javier González <javier@cnexlabs.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. It makes nvme_get_log_ext available
outside of nvme core so that we can use it form lightnvm.

Signed-off-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/core.c      | 11 +++++++
 drivers/nvme/host/core.c     |  4 +--
 drivers/nvme/host/lightnvm.c | 74 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/lightnvm.h     | 24 ++++++++++++++
 4 files changed, 111 insertions(+), 2 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 77901bf17416..63171cdce270 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -712,6 +712,17 @@ static void nvm_free_rqd_ppalist(struct nvm_tgt_dev *tgt_dev,
 	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/core.c b/drivers/nvme/host/core.c
index e7ec2fb5c59a..f81e3b323366 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -2219,8 +2219,8 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
 }
 
 int nvme_get_log_ext(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
-			    u8 log_page, void *log,
-			    size_t size, size_t offset)
+		     u8 log_page, void *log,
+		     size_t size, size_t offset)
 {
 	struct nvme_command c = { };
 	unsigned long dwlen = size / 4 - 1;
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 08f0f6b5bc06..ffd64a83c8c3 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -35,6 +35,10 @@ enum nvme_nvm_admin_opcode {
 	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;
@@ -236,6 +240,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
  */
@@ -252,6 +266,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_addrf_12 *dst,
@@ -552,6 +569,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_geo *geo = &ndev->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.pu * geo->num_chk;
+	log_pos += ppa.m.grp * geo->num_lun * geo->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)
 {
@@ -683,6 +755,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 f3b273e543c3..da45efa09bb2 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;
 
@@ -227,6 +232,20 @@ struct nvm_addrf {
 	u64	rsv_mask[2];
 };
 
+/*
+ * 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;
@@ -492,6 +511,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.11.0

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

* [GIT PULL 31/37] lightnvm: pblk: check for supported version
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (29 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 30/37] lightnvm: implement get log report chunk helpers Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 32/37] lightnvm: pblk: rename ppaf* to addrf* Matias Bjørling
                   ` (6 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

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

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>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 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 4656d1ff81a6..34ff47705293 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -1016,9 +1016,15 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 	struct pblk *pblk;
 	int ret;
 
-	if (dev->geo.dom & NVM_RSP_L2P) {
+	if (geo->version != NVM_OCSSD_SPEC_12) {
+		pr_err("pblk: OCSSD version not supported (%u)\n",
+							geo->version);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (geo->version == NVM_OCSSD_SPEC_12 && geo->dom & NVM_RSP_L2P) {
 		pr_err("pblk: host-side L2P table not supported. (%x)\n",
-							dev->geo.dom);
+							geo->dom);
 		return ERR_PTR(-EINVAL);
 	}
 
-- 
2.11.0

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

* [GIT PULL 32/37] lightnvm: pblk: rename ppaf* to addrf*
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (30 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 31/37] lightnvm: pblk: check for supported version Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 33/37] lightnvm: pblk: implement get log report chunk Matias Bjørling
                   ` (5 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

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

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>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 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 34ff47705293..5b381700ef30 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;
@@ -229,7 +229,7 @@ static int pblk_set_addrf_12(struct nvm_geo *geo, struct nvm_addrf_12 *dst)
 	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;
@@ -241,7 +241,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;
 }
@@ -377,7 +377,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;
 
 	INIT_LIST_HEAD(&pblk->compl_list);
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index 2489ea0edfa0..fd2caad39d49 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_addrf_12 *geo_ppaf;
 	ssize_t sz = 0;
 
-	ppaf = (struct nvm_addrf_12 *)&pblk->ppaf;
+	ppaf = (struct nvm_addrf_12 *)&pblk->addrf;
 	geo_ppaf = (struct nvm_addrf_12 *)&geo->addrf;
 
 	sz = snprintf(page, PAGE_SIZE,
 		"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->addrf_len,
 			ppaf->blk_offset, ppaf->blk_len,
 			ppaf->pg_offset, ppaf->pg_len,
 			ppaf->lun_offset, ppaf->lun_len,
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 6607c41b23c0..40aee9e48af4 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_addrf ppaf;
-	int ppaf_bitsize;
+	struct nvm_addrf addrf;
+	int addrf_len;
 
 	struct pblk_rb rwb;
 
@@ -947,7 +947,7 @@ 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_addrf_12 *ppaf = (struct nvm_addrf_12 *)&pblk->ppaf;
+	struct nvm_addrf_12 *ppaf = (struct nvm_addrf_12 *)&pblk->addrf;
 	struct ppa_addr ppa;
 
 	ppa.ppa = 0;
@@ -964,7 +964,7 @@ 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_addrf_12 *ppaf = (struct nvm_addrf_12 *)&pblk->ppaf;
+	struct nvm_addrf_12 *ppaf = (struct nvm_addrf_12 *)&pblk->addrf;
 	u64 paddr;
 
 	paddr = (u64)p.g.ch << ppaf->ch_offset;
@@ -988,7 +988,7 @@ 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_addrf_12 *ppaf = (struct nvm_addrf_12 *)&pblk->ppaf;
+		struct nvm_addrf_12 *ppaf = (struct nvm_addrf_12 *)&pblk->addrf;
 
 		ppa64.g.ch = (ppa32 & ppaf->ch_mask) >> ppaf->ch_offset;
 		ppa64.g.lun = (ppa32 & ppaf->lun_mask) >> ppaf->lun_offset;
@@ -1011,7 +1011,7 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
 		ppa32 |= ppa64.c.line;
 		ppa32 |= 1U << 31;
 	} else {
-		struct nvm_addrf_12 *ppaf = (struct nvm_addrf_12 *)&pblk->ppaf;
+		struct nvm_addrf_12 *ppaf = (struct nvm_addrf_12 *)&pblk->addrf;
 
 		ppa32 |= ppa64.g.ch << ppaf->ch_offset;
 		ppa32 |= ppa64.g.lun << ppaf->lun_offset;
@@ -1029,7 +1029,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]);
@@ -1045,7 +1045,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.11.0

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

* [GIT PULL 33/37] lightnvm: pblk: implement get log report chunk
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (31 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 32/37] lightnvm: pblk: rename ppaf* to addrf* Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 34/37] lightnvm: pblk: implement 2.0 support Matias Bjørling
                   ` (4 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

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

In preparation of pblk supporting 2.0, implement the get log report
chunk in pblk. Also, define the chunk states as given in the 2.0 spec.

Signed-off-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/pblk-core.c | 138 +++++++++++++++++++++++----
 drivers/lightnvm/pblk-init.c | 222 ++++++++++++++++++++++++++++++-------------
 drivers/lightnvm/pblk.h      |   7 ++
 include/linux/lightnvm.h     |  13 +++
 4 files changed, 298 insertions(+), 82 deletions(-)

diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index c3eb135fce07..94d5d97c9d8a 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,26 +59,38 @@ 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->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);
 }
 
 static void __pblk_end_io_erase(struct pblk *pblk, struct nvm_rq *rqd)
 {
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	struct nvm_chk_meta *chunk;
 	struct pblk_line *line;
+	int pos;
 
 	line = &pblk->lines[pblk_ppa_to_line(rqd->ppa_addr)];
+	pos = pblk_ppa_to_pos(geo, rqd->ppa_addr);
+	chunk = &line->chks[pos];
+
 	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);
+		chunk->state = NVM_CHK_ST_OFFLINE;
+		pblk_mark_bb(pblk, line, rqd->ppa_addr);
+	} else {
+		chunk->state = NVM_CHK_ST_FREE;
 	}
 
 	atomic_dec(&pblk->inflight_io);
@@ -92,6 +105,49 @@ 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) {
+		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.grp * geo->num_chk * geo->num_lun;
+	int lun_off = ppa.m.pu * geo->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)
 {
@@ -1091,10 +1147,34 @@ 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++) {
+		struct pblk_lun *rlun = &pblk->luns[i];
+		int pos = pblk_ppa_to_pos(geo, rlun->bppa);
+		int state = line->chks[pos].state;
+
+		/* Free chunks should not be erased */
+		if (state & NVM_CHK_ST_FREE) {
+			set_bit(pblk_ppa_to_pos(geo, rlun->bppa),
+							line->erase_bitmap);
+			blk_to_erase--;
+		}
+	}
+
+	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)
@@ -1107,7 +1187,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);
@@ -1119,15 +1213,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;
@@ -1583,12 +1674,14 @@ static void pblk_line_should_sync_meta(struct pblk *pblk)
 
 void pblk_line_close(struct pblk *pblk, struct pblk_line *line)
 {
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
+	struct pblk_line_meta *lm = &pblk->lm;
 	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
 	struct list_head *move_list;
+	int i;
 
 #ifdef CONFIG_NVM_DEBUG
-	struct pblk_line_meta *lm = &pblk->lm;
-
 	WARN(!bitmap_full(line->map_bitmap, lm->sec_per_line),
 				"pblk: corrupt closed line %d\n", line->id);
 #endif
@@ -1610,6 +1703,15 @@ void pblk_line_close(struct pblk *pblk, struct pblk_line *line)
 	line->smeta = NULL;
 	line->emeta = NULL;
 
+	for (i = 0; i < lm->blk_per_line; i++) {
+		struct pblk_lun *rlun = &pblk->luns[i];
+		int pos = pblk_ppa_to_pos(geo, rlun->bppa);
+		int state = line->chks[pos].state;
+
+		if (!(state & NVM_CHK_ST_OFFLINE))
+			state = NVM_CHK_ST_CLOSED;
+	}
+
 	spin_unlock(&line->lock);
 	spin_unlock(&l_mg->gc_lock);
 }
diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 5b381700ef30..27b4974930b4 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -451,6 +451,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)
@@ -495,55 +496,44 @@ static int pblk_bb_get_tbl(struct nvm_tgt_dev *dev, struct pblk_lun *rlun,
 	return 0;
 }
 
-static void *pblk_bb_get_log(struct pblk *pblk)
+static void *pblk_bb_get_meta(struct pblk *pblk)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
-	u8 *log;
+	u8 *meta;
 	int i, nr_blks, blk_per_lun;
 	int ret;
 
 	blk_per_lun = geo->num_chk * geo->pln_mode;
 	nr_blks = blk_per_lun * geo->all_luns;
 
-	log = kmalloc(nr_blks, GFP_KERNEL);
-	if (!log)
+	meta = kmalloc(nr_blks, GFP_KERNEL);
+	if (!meta)
 		return ERR_PTR(-ENOMEM);
 
 	for (i = 0; i < geo->all_luns; i++) {
 		struct pblk_lun *rlun = &pblk->luns[i];
-		u8 *log_pos = log + i * blk_per_lun;
+		u8 *meta_pos = meta + i * blk_per_lun;
 
-		ret = pblk_bb_get_tbl(dev, rlun, log_pos, blk_per_lun);
+		ret = pblk_bb_get_tbl(dev, rlun, meta_pos, blk_per_lun);
 		if (ret) {
-			kfree(log);
+			kfree(meta);
 			return ERR_PTR(-EIO);
 		}
 	}
 
-	return log;
+	return meta;
 }
 
-static int pblk_bb_line(struct pblk *pblk, struct pblk_line *line,
-			u8 *bb_log, int blk_per_line)
+static void *pblk_chunk_get_meta(struct pblk *pblk)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
-	int i, bb_cnt = 0;
-	int blk_per_lun = geo->num_chk * geo->pln_mode;
 
-	for (i = 0; i < blk_per_line; i++) {
-		struct pblk_lun *rlun = &pblk->luns[i];
-		u8 *lun_bb_log = bb_log + i * blk_per_lun;
-
-		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->version == NVM_OCSSD_SPEC_12)
+		return pblk_bb_get_meta(pblk);
+	else
+		return pblk_chunk_get_info(pblk);
 }
 
 static int pblk_luns_init(struct pblk *pblk)
@@ -644,8 +634,131 @@ 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_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_meta)
+{
+	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->num_chk * geo->pln_mode;
+
+	for (i = 0; i < lm->blk_per_line; i++) {
+		struct pblk_lun *rlun = &pblk->luns[i];
+		struct nvm_chk_meta *chunk;
+		int pos = pblk_ppa_to_pos(geo, rlun->bppa);
+		u8 *lun_bb_meta = chunk_meta + pos * chk_per_lun;
+
+		chunk = &line->chks[pos];
+
+		/*
+		 * 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_meta[line->id] == NVM_BLK_T_FREE)
+			chunk->state =  NVM_CHK_ST_FREE;
+		else
+			chunk->state = NVM_CHK_ST_OFFLINE;
+
+		chunk->type = NVM_CHK_TP_W_SEQ;
+		chunk->wi = 0;
+		chunk->slba = -1;
+		chunk->cnlb = geo->clba;
+		chunk->wp = 0;
+
+		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
+			continue;
+
+		set_bit(pos, 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_lun *rlun = &pblk->luns[i];
+		struct nvm_chk_meta *chunk;
+		struct nvm_chk_meta *chunk_meta;
+		struct ppa_addr ppa;
+		int pos;
+
+		ppa = rlun->bppa;
+		pos = pblk_ppa_to_pos(geo, ppa);
+		chunk = &line->chks[pos];
+
+		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(pos, 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_meta, 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->version == NVM_OCSSD_SPEC_12)
+		nr_bad_chks = pblk_setup_line_meta_12(pblk, line, chunk_meta);
+	else
+		nr_bad_chks = pblk_setup_line_meta_20(pblk, line, chunk_meta);
+
+	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;
 
@@ -659,7 +772,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 nvm_chk_meta),
+								GFP_KERNEL);
+	if (!line->chks) {
+		kfree(line->erase_bitmap);
+		kfree(line->blk_bitmap);
+		return -ENOMEM;
+	}
 
 	return 0;
 }
@@ -846,10 +965,9 @@ static int pblk_line_meta_init(struct pblk *pblk)
 static int pblk_lines_init(struct pblk *pblk)
 {
 	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
-	struct pblk_line_meta *lm = &pblk->lm;
 	struct pblk_line *line;
-	void *chunk_log;
-	long nr_bad_blks = 0, nr_free_blks = 0;
+	void *chunk_meta;
+	long nr_free_chks = 0;
 	int i, ret;
 
 	ret = pblk_line_meta_init(pblk);
@@ -864,11 +982,9 @@ static int pblk_lines_init(struct pblk *pblk)
 	if (ret)
 		goto fail_free_meta;
 
-	chunk_log = pblk_bb_get_log(pblk);
-	if (IS_ERR(chunk_log)) {
-		pr_err("pblk: could not get bad block log (%lu)\n",
-							PTR_ERR(chunk_log));
-		ret = PTR_ERR(chunk_log);
+	chunk_meta = pblk_chunk_get_meta(pblk);
+	if (IS_ERR(chunk_meta)) {
+		ret = PTR_ERR(chunk_meta);
 		goto fail_free_luns;
 	}
 
@@ -876,52 +992,30 @@ static int pblk_lines_init(struct pblk *pblk)
 								GFP_KERNEL);
 	if (!pblk->lines) {
 		ret = -ENOMEM;
-		goto fail_free_chunk_log;
+		goto fail_free_chunk_meta;
 	}
 
 	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_lines;
 
-		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_meta, i);
 	}
 
-	pblk_set_provision(pblk, nr_free_blks);
+	pblk_set_provision(pblk, nr_free_chks);
 
-	kfree(chunk_log);
+	kfree(chunk_meta);
 	return 0;
 
 fail_free_lines:
 	while (--i >= 0)
 		pblk_line_meta_free(&pblk->lines[i]);
 	kfree(pblk->lines);
-fail_free_chunk_log:
-	kfree(chunk_log);
+fail_free_chunk_meta:
+	kfree(chunk_meta);
 fail_free_luns:
 	kfree(pblk->luns);
 fail_free_meta:
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 40aee9e48af4..39e47e3d6f23 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -297,6 +297,7 @@ enum {
 	PBLK_LINETYPE_DATA = 2,
 
 	/* Line state */
+	PBLK_LINESTATE_NEW = 9,
 	PBLK_LINESTATE_FREE = 10,
 	PBLK_LINESTATE_OPEN = 11,
 	PBLK_LINESTATE_CLOSED = 12,
@@ -426,6 +427,8 @@ struct pblk_line {
 
 	unsigned long *lun_bitmap;	/* Bitmap for LUNs mapped in line */
 
+	struct nvm_chk_meta *chks;	/* Chunks forming line */
+
 	struct pblk_smeta *smeta;	/* Start metadata */
 	struct pblk_emeta *emeta;	/* End medatada */
 
@@ -729,6 +732,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);
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index da45efa09bb2..6e0859b9d4d2 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -232,6 +232,19 @@ struct nvm_addrf {
 	u64	rsv_mask[2];
 };
 
+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,
+
+	/* 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.11.0

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

* [GIT PULL 34/37] lightnvm: pblk: implement 2.0 support
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (32 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 33/37] lightnvm: pblk: implement get log report chunk Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 35/37] lightnvm: pblk: don't recover unwritten lines Matias Bjørling
                   ` (3 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

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

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>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/pblk-init.c  |  56 ++++++++++--
 drivers/lightnvm/pblk-sysfs.c |  46 +++++++---
 drivers/lightnvm/pblk.h       | 192 +++++++++++++++++++++++++++++++++---------
 3 files changed, 232 insertions(+), 62 deletions(-)

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 27b4974930b4..91a5bc2556a3 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -229,20 +229,62 @@ static int pblk_set_addrf_12(struct nvm_geo *geo, struct nvm_addrf_12 *dst)
 	return dst->blk_offset + src->blk_len;
 }
 
+static int pblk_set_addrf_20(struct nvm_geo *geo, struct nvm_addrf *adst,
+			     struct pblk_addrf *udst)
+{
+	struct nvm_addrf *src = &geo->addrf;
+
+	adst->ch_len = get_count_order(geo->num_ch);
+	adst->lun_len = get_count_order(geo->num_lun);
+	adst->chk_len = src->chk_len;
+	adst->sec_len = src->sec_len;
+
+	adst->sec_offset = 0;
+	adst->ch_offset = adst->sec_len;
+	adst->lun_offset = adst->ch_offset + adst->ch_len;
+	adst->chk_offset = adst->lun_offset + adst->lun_len;
+
+	adst->sec_mask = ((1ULL << adst->sec_len) - 1) << adst->sec_offset;
+	adst->chk_mask = ((1ULL << adst->chk_len) - 1) << adst->chk_offset;
+	adst->lun_mask = ((1ULL << adst->lun_len) - 1) << adst->lun_offset;
+	adst->ch_mask = ((1ULL << adst->ch_len) - 1) << adst->ch_offset;
+
+	udst->sec_stripe = geo->ws_opt;
+	udst->ch_stripe = geo->num_ch;
+	udst->lun_stripe = geo->num_lun;
+
+	udst->sec_lun_stripe = udst->sec_stripe * udst->ch_stripe;
+	udst->sec_ws_stripe = udst->sec_lun_stripe * udst->lun_stripe;
+
+	return adst->chk_offset + adst->chk_len;
+}
+
 static int pblk_set_addrf(struct pblk *pblk)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
 	int mod;
 
-	div_u64_rem(geo->clba, pblk->min_write_pgs, &mod);
-	if (mod) {
-		pr_err("pblk: bad configuration of sectors/pages\n");
+	switch (geo->version) {
+	case NVM_OCSSD_SPEC_12:
+		div_u64_rem(geo->clba, pblk->min_write_pgs, &mod);
+		if (mod) {
+			pr_err("pblk: bad configuration of sectors/pages\n");
+			return -EINVAL;
+		}
+
+		pblk->addrf_len = pblk_set_addrf_12(geo, (void *)&pblk->addrf);
+		break;
+	case NVM_OCSSD_SPEC_20:
+		pblk->addrf_len = pblk_set_addrf_20(geo, (void *)&pblk->addrf,
+								&pblk->uaddrf);
+		break;
+	default:
+		pr_err("pblk: OCSSD revision not supported (%d)\n",
+								geo->version);
 		return -EINVAL;
 	}
 
-	pblk->addrf_len = pblk_set_addrf_12(geo, (void *)&pblk->addrf);
-
 	return 0;
 }
 
@@ -1110,7 +1152,9 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 	struct pblk *pblk;
 	int ret;
 
-	if (geo->version != NVM_OCSSD_SPEC_12) {
+	/* pblk supports 1.2 and 2.0 versions */
+	if (!(geo->version == NVM_OCSSD_SPEC_12 ||
+					geo->version == NVM_OCSSD_SPEC_20)) {
 		pr_err("pblk: OCSSD version not supported (%u)\n",
 							geo->version);
 		return ERR_PTR(-EINVAL);
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index fd2caad39d49..e61909af23a5 100644
--- a/drivers/lightnvm/pblk-sysfs.c
+++ b/drivers/lightnvm/pblk-sysfs.c
@@ -113,15 +113,14 @@ 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_addrf_12 *ppaf;
-	struct nvm_addrf_12 *geo_ppaf;
 	ssize_t sz = 0;
 
-	ppaf = (struct nvm_addrf_12 *)&pblk->addrf;
-	geo_ppaf = (struct nvm_addrf_12 *)&geo->addrf;
+	if (geo->version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addrf_12 *ppaf = (struct nvm_addrf_12 *)&pblk->addrf;
+		struct nvm_addrf_12 *gppaf = (struct nvm_addrf_12 *)&geo->addrf;
 
-	sz = snprintf(page, PAGE_SIZE,
-		"g:(b:%d)blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
+		sz = snprintf(page, PAGE_SIZE,
+			"g:(b:%d)blk:%d/%d,pg:%d/%d,lun:%d/%d,ch:%d/%d,pl:%d/%d,sec:%d/%d\n",
 			pblk->addrf_len,
 			ppaf->blk_offset, ppaf->blk_len,
 			ppaf->pg_offset, ppaf->pg_len,
@@ -130,14 +129,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,
-		"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->sec_offset, geo_ppaf->sec_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",
+			gppaf->blk_offset, gppaf->blk_len,
+			gppaf->pg_offset, gppaf->pg_len,
+			gppaf->lun_offset, gppaf->lun_len,
+			gppaf->ch_offset, gppaf->ch_len,
+			gppaf->pln_offset, gppaf->pln_len,
+			gppaf->sec_offset, gppaf->sec_len);
+	} else {
+		struct nvm_addrf *ppaf = &pblk->addrf;
+		struct nvm_addrf *gppaf = &geo->addrf;
+
+		sz = snprintf(page, PAGE_SIZE,
+			"pblk:(s:%d)ch:%d/%d,lun:%d/%d,chk:%d/%d/sec:%d/%d\n",
+			pblk->addrf_len,
+			ppaf->ch_offset, ppaf->ch_len,
+			ppaf->lun_offset, ppaf->lun_len,
+			ppaf->chk_offset, ppaf->chk_len,
+			ppaf->sec_offset, ppaf->sec_len);
+
+		sz += snprintf(page + sz, PAGE_SIZE - sz,
+			"device:ch:%d/%d,lun:%d/%d,chk:%d/%d,sec:%d/%d\n",
+			gppaf->ch_offset, gppaf->ch_len,
+			gppaf->lun_offset, gppaf->lun_len,
+			gppaf->chk_offset, gppaf->chk_len,
+			gppaf->sec_offset, gppaf->sec_len);
+	}
 
 	return sz;
 }
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 39e47e3d6f23..9c682acfc5d1 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -561,6 +561,18 @@ enum {
 	PBLK_STATE_STOPPED = 3,
 };
 
+/* Internal format to support not power-of-2 device formats */
+struct pblk_addrf {
+	/* gen to dev */
+	int sec_stripe;
+	int ch_stripe;
+	int lun_stripe;
+
+	/* dev to gen */
+	int sec_lun_stripe;
+	int sec_ws_stripe;
+};
+
 struct pblk {
 	struct nvm_tgt_dev *dev;
 	struct gendisk *disk;
@@ -573,7 +585,8 @@ struct pblk {
 	struct pblk_line_mgmt l_mg;		/* Line management */
 	struct pblk_line_meta lm;		/* Line metadata */
 
-	struct nvm_addrf addrf;
+	struct nvm_addrf addrf;		/* Aligned address format */
+	struct pblk_addrf uaddrf;	/* Unaligned address format */
 	int addrf_len;
 
 	struct pblk_rb rwb;
@@ -954,16 +967,39 @@ 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_addrf_12 *ppaf = (struct nvm_addrf_12 *)&pblk->addrf;
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
 	struct ppa_addr ppa;
 
-	ppa.ppa = 0;
-	ppa.g.blk = line_id;
-	ppa.g.pg = (paddr & ppaf->pg_mask) >> ppaf->pg_offset;
-	ppa.g.lun = (paddr & ppaf->lun_mask) >> ppaf->lun_offset;
-	ppa.g.ch = (paddr & ppaf->ch_mask) >> ppaf->ch_offset;
-	ppa.g.pl = (paddr & ppaf->pln_mask) >> ppaf->pln_offset;
-	ppa.g.sec = (paddr & ppaf->sec_mask) >> ppaf->sec_offset;
+	if (geo->version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addrf_12 *ppaf = (struct nvm_addrf_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_addrf *uaddrf = &pblk->uaddrf;
+		int secs, chnls, luns;
+
+		ppa.ppa = 0;
+
+		ppa.m.chk = line_id;
+
+		paddr = div_u64_rem(paddr, uaddrf->sec_stripe, &secs);
+		ppa.m.sec = secs;
+
+		paddr = div_u64_rem(paddr, uaddrf->ch_stripe, &chnls);
+		ppa.m.grp = chnls;
+
+		paddr = div_u64_rem(paddr, uaddrf->lun_stripe, &luns);
+		ppa.m.pu = luns;
+
+		ppa.m.sec += uaddrf->sec_stripe * paddr;
+	}
 
 	return ppa;
 }
@@ -971,14 +1007,30 @@ 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_addrf_12 *ppaf = (struct nvm_addrf_12 *)&pblk->addrf;
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
 	u64 paddr;
 
-	paddr = (u64)p.g.ch << ppaf->ch_offset;
-	paddr |= (u64)p.g.lun << ppaf->lun_offset;
-	paddr |= (u64)p.g.pg << ppaf->pg_offset;
-	paddr |= (u64)p.g.pl << ppaf->pln_offset;
-	paddr |= (u64)p.g.sec << ppaf->sec_offset;
+	if (geo->version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addrf_12 *ppaf = (struct nvm_addrf_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_addrf *uaddrf = &pblk->uaddrf;
+		u64 secs = p.m.sec;
+		int sec_stripe;
+
+		paddr = (u64)p.m.grp * uaddrf->sec_stripe;
+		paddr += (u64)p.m.pu * uaddrf->sec_lun_stripe;
+
+		secs = div_u64_rem(secs, uaddrf->sec_stripe, &sec_stripe);
+		paddr += secs * uaddrf->sec_ws_stripe;
+		paddr += sec_stripe;
+	}
 
 	return paddr;
 }
@@ -995,14 +1047,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_addrf_12 *ppaf = (struct nvm_addrf_12 *)&pblk->addrf;
+		struct nvm_tgt_dev *dev = pblk->dev;
+		struct nvm_geo *geo = &dev->geo;
 
-		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;
+		if (geo->version == NVM_OCSSD_SPEC_12) {
+			struct nvm_addrf_12 *ppaf =
+					(struct nvm_addrf_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;
+		} else {
+			struct nvm_addrf *lbaf = &pblk->addrf;
+
+			ppa64.m.grp = (ppa32 & lbaf->ch_mask) >>
+							lbaf->ch_offset;
+			ppa64.m.pu = (ppa32 & lbaf->lun_mask) >>
+							lbaf->lun_offset;
+			ppa64.m.chk = (ppa32 & lbaf->chk_mask) >>
+							lbaf->chk_offset;
+			ppa64.m.sec = (ppa32 & lbaf->sec_mask) >>
+							lbaf->sec_offset;
+		}
 	}
 
 	return ppa64;
@@ -1018,14 +1093,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_addrf_12 *ppaf = (struct nvm_addrf_12 *)&pblk->addrf;
+		struct nvm_tgt_dev *dev = pblk->dev;
+		struct nvm_geo *geo = &dev->geo;
 
-		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;
+		if (geo->version == NVM_OCSSD_SPEC_12) {
+			struct nvm_addrf_12 *ppaf =
+					(struct nvm_addrf_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;
+		} else {
+			struct nvm_addrf *lbaf = &pblk->addrf;
+
+			ppa32 |= ppa64.m.grp << lbaf->ch_offset;
+			ppa32 |= ppa64.m.pu << lbaf->lun_offset;
+			ppa32 |= ppa64.m.chk << lbaf->chk_offset;
+			ppa32 |= ppa64.m.sec << lbaf->sec_offset;
+		}
 	}
 
 	return ppa32;
@@ -1143,6 +1231,9 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type)
 	struct nvm_geo *geo = &dev->geo;
 	int flags;
 
+	if (geo->version == NVM_OCSSD_SPEC_20)
+		return 0;
+
 	flags = geo->pln_mode >> 1;
 
 	if (type == PBLK_WRITE)
@@ -1162,6 +1253,9 @@ static inline int pblk_set_read_mode(struct pblk *pblk, int type)
 	struct nvm_geo *geo = &dev->geo;
 	int flags;
 
+	if (geo->version == NVM_OCSSD_SPEC_20)
+		return 0;
+
 	flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
 	if (type == PBLK_READ_SEQUENTIAL)
 		flags |= geo->pln_mode >> 1;
@@ -1175,16 +1269,21 @@ static inline int pblk_io_aligned(struct pblk *pblk, int nr_secs)
 }
 
 #ifdef CONFIG_NVM_DEBUG
-static inline void print_ppa(struct ppa_addr *p, char *msg, int error)
+static inline void print_ppa(struct nvm_geo *geo, struct ppa_addr *p,
+			     char *msg, int error)
 {
 	if (p->c.is_cached) {
 		pr_err("ppa: (%s: %x) cache line: %llu\n",
 				msg, error, (u64)p->c.line);
-	} else {
+	} else if (geo->version == NVM_OCSSD_SPEC_12) {
 		pr_err("ppa: (%s: %x):ch:%d,lun:%d,blk:%d,pg:%d,pl:%d,sec:%d\n",
 			msg, error,
 			p->g.ch, p->g.lun, p->g.blk,
 			p->g.pg, p->g.pl, p->g.sec);
+	} else {
+		pr_err("ppa: (%s: %x):ch:%d,lun:%d,chk:%d,sec:%d\n",
+			msg, error,
+			p->m.grp, p->m.pu, p->m.chk, p->m.sec);
 	}
 }
 
@@ -1194,13 +1293,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);
@@ -1216,16 +1315,25 @@ static inline int pblk_boundary_ppa_checks(struct nvm_tgt_dev *tgt_dev,
 	for (i = 0; i < nr_ppas; i++) {
 		ppa = &ppas[i];
 
-		if (!ppa->c.is_cached &&
-				ppa->g.ch < geo->num_ch &&
-				ppa->g.lun < geo->num_lun &&
-				ppa->g.pl < geo->num_pln &&
-				ppa->g.blk < geo->num_chk &&
-				ppa->g.pg < geo->num_pg &&
-				ppa->g.sec < geo->ws_min)
-			continue;
+		if (geo->version == NVM_OCSSD_SPEC_12) {
+			if (!ppa->c.is_cached &&
+					ppa->g.ch < geo->num_ch &&
+					ppa->g.lun < geo->num_lun &&
+					ppa->g.pl < geo->num_pln &&
+					ppa->g.blk < geo->num_chk &&
+					ppa->g.pg < geo->num_pg &&
+					ppa->g.sec < geo->ws_min)
+				continue;
+		} else {
+			if (!ppa->c.is_cached &&
+					ppa->m.grp < geo->num_ch &&
+					ppa->m.pu < geo->num_lun &&
+					ppa->m.chk < geo->num_chk &&
+					ppa->m.sec < geo->clba)
+				continue;
+		}
 
-		print_ppa(ppa, "boundary", i);
+		print_ppa(geo, ppa, "boundary", i);
 
 		return 1;
 	}
-- 
2.11.0

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

* [GIT PULL 35/37] lightnvm: pblk: don't recover unwritten lines
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (33 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 34/37] lightnvm: pblk: implement 2.0 support Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 36/37] lightnvm: pblk: remove some unnecessary NULL checks Matias Bjørling
                   ` (2 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Hans Holmberg,
	Matias Bjørling

From: Hans Holmberg <hans.holmberg@cnexlabs.com>

If the line has not been written to, we should not
try to recover any data from it, so check the state of the
chunks in the line before attempting to read smeta.

Signed-off-by: Hans Holmberg <hans.holmberg@cnexlabs.com>
Signed-off-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/pblk-recovery.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
index 26356429dc72..3e079c2afa6e 100644
--- a/drivers/lightnvm/pblk-recovery.c
+++ b/drivers/lightnvm/pblk-recovery.c
@@ -864,6 +864,21 @@ static void pblk_recov_wa_counters(struct pblk *pblk,
 	}
 }
 
+static int pblk_line_was_written(struct pblk_line *line,
+			    struct pblk_line_meta *lm)
+{
+
+	int i;
+	int state_mask = NVM_CHK_ST_OFFLINE | NVM_CHK_ST_FREE;
+
+	for (i = 0; i < lm->blk_per_line; i++) {
+		if (!(line->chks[i].state & state_mask))
+			return 1;
+	}
+
+	return 0;
+}
+
 struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
 {
 	struct pblk_line_meta *lm = &pblk->lm;
@@ -900,6 +915,9 @@ struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
 		line->lun_bitmap = ((void *)(smeta_buf)) +
 						sizeof(struct line_smeta);
 
+		if (!pblk_line_was_written(line, lm))
+			continue;
+
 		/* Lines that cannot be read are assumed as not written here */
 		if (pblk_line_read_smeta(pblk, line))
 			continue;
-- 
2.11.0

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

* [GIT PULL 36/37] lightnvm: pblk: remove some unnecessary NULL checks
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (34 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 35/37] lightnvm: pblk: don't recover unwritten lines Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 22:05 ` [GIT PULL 37/37] lightnvm: remove function name in strings Matias Bjørling
  2018-03-29 23:30 ` [GIT PULL 00/37] lightnvm patches for 4.17 Jens Axboe
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Dan Carpenter,
	Matias Bjørling

From: Dan Carpenter <dan.carpenter@oracle.com>

Smatch complains that flush_workqueue() dereferences the work queue
pointer but then we check if it's NULL on the next line when it's too
late.  These NULL checks can be removed because the module won't load if
we can't allocate the work queues.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/lightnvm/pblk-gc.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c
index 7143b0f740fb..6851a5c67189 100644
--- a/drivers/lightnvm/pblk-gc.c
+++ b/drivers/lightnvm/pblk-gc.c
@@ -664,12 +664,10 @@ void pblk_gc_exit(struct pblk *pblk)
 		kthread_stop(gc->gc_reader_ts);
 
 	flush_workqueue(gc->gc_reader_wq);
-	if (gc->gc_reader_wq)
-		destroy_workqueue(gc->gc_reader_wq);
+	destroy_workqueue(gc->gc_reader_wq);
 
 	flush_workqueue(gc->gc_line_reader_wq);
-	if (gc->gc_line_reader_wq)
-		destroy_workqueue(gc->gc_line_reader_wq);
+	destroy_workqueue(gc->gc_line_reader_wq);
 
 	if (gc->gc_writer_ts)
 		kthread_stop(gc->gc_writer_ts);
-- 
2.11.0

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

* [GIT PULL 37/37] lightnvm: remove function name in strings
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (35 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 36/37] lightnvm: pblk: remove some unnecessary NULL checks Matias Bjørling
@ 2018-03-29 22:05 ` Matias Bjørling
  2018-03-29 23:30 ` [GIT PULL 00/37] lightnvm patches for 4.17 Jens Axboe
  37 siblings, 0 replies; 39+ messages in thread
From: Matias Bjørling @ 2018-03-29 22:05 UTC (permalink / raw)
  To: axboe
  Cc: linux-block, linux-kernel, keith.busch, javier, Matias Bjørling

For the sysfs functions, the function names are embedded into their
error strings. If the function name later changes, the string may
not be updated accordingly. Update the strings to use __func__
to avoid this.

Signed-off-by: Matias Bjørling <mb@lightnvm.io>
---
 drivers/nvme/host/lightnvm.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index ffd64a83c8c3..41279da799ed 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -1028,8 +1028,8 @@ static ssize_t nvm_dev_attr_show(struct device *dev,
 	} else {
 		return scnprintf(page,
 				 PAGE_SIZE,
-				 "Unhandled attr(%s) in `nvm_dev_attr_show`\n",
-				 attr->name);
+				 "Unhandled attr(%s) in `%s`\n",
+				 attr->name, __func__);
 	}
 }
 
@@ -1103,8 +1103,8 @@ static ssize_t nvm_dev_attr_show_12(struct device *dev,
 		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);
+			"Unhandled attr(%s) in `%s`\n",
+			attr->name, __func__);
 	}
 }
 
@@ -1149,8 +1149,8 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
 		return scnprintf(page, PAGE_SIZE, "%u\n", geo->tbem);
 	} else {
 		return scnprintf(page, PAGE_SIZE,
-			"Unhandled attr(%s) in `nvm_dev_attr_show_20`\n",
-			attr->name);
+			"Unhandled attr(%s) in `%s`\n",
+			attr->name, __func__);
 	}
 }
 
-- 
2.11.0

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

* Re: [GIT PULL 00/37] lightnvm patches for 4.17
  2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
                   ` (36 preceding siblings ...)
  2018-03-29 22:05 ` [GIT PULL 37/37] lightnvm: remove function name in strings Matias Bjørling
@ 2018-03-29 23:30 ` Jens Axboe
  37 siblings, 0 replies; 39+ messages in thread
From: Jens Axboe @ 2018-03-29 23:30 UTC (permalink / raw)
  To: Matias Bjørling; +Cc: linux-block, linux-kernel, keith.busch, javier

On 3/29/18 4:04 PM, Matias Bjørling wrote:
> Hi Jens,
> 
> Here is a bunch of patches for 4.17. They include:
> 
>  - Open-Channel 2.0 support by Javier and I.
>  - Lots of refactoring patches to enable 2.0 support.
>  - Fixes to pblk from Hans, Markus, and Dan.
>  - Introduction of write amplication and padding counters. From Hans.
>  - Fix from Johannes to unify the permission checks for the lightnvm
>    ioctls.
>  - Fixes from Heiner for bad block initialization and
>    over-provisioning validation.
> 
> Please pick up when convenient.

Applied, thanks.

-- 
Jens Axboe

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

end of thread, other threads:[~2018-03-29 23:30 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-29 22:04 [GIT PULL 00/37] lightnvm patches for 4.17 Matias Bjørling
2018-03-29 22:04 ` [GIT PULL 01/37] lightnvm/pblk-gc: Delete an error message for a failed memory allocation in pblk_gc_line_prepare_ws() Matias Bjørling
2018-03-29 22:04 ` [GIT PULL 02/37] lightnvm: remove chnl_offset in nvme_nvm_identity Matias Bjørling
2018-03-29 22:04 ` [GIT PULL 03/37] lightnvm: pblk: handle bad sectors in the emeta area correctly Matias Bjørling
2018-03-29 22:04 ` [GIT PULL 04/37] lightnvm: pblk: check data lines version on recovery Matias Bjørling
2018-03-29 22:04 ` [GIT PULL 05/37] lightnvm: pblk: export write amplification counters to sysfs Matias Bjørling
2018-03-29 22:04 ` [GIT PULL 06/37] lightnvm: remove mlc pairs structure Matias Bjørling
2018-03-29 22:04 ` [GIT PULL 07/37] lightnvm: remove multiple groups in 1.2 data structure Matias Bjørling
2018-03-29 22:04 ` [GIT PULL 08/37] lightnvm: pblk: add padding distribution sysfs attribute Matias Bjørling
2018-03-29 22:04 ` [GIT PULL 09/37] lightnvm: pblk: delete writer kick timer before stopping thread Matias Bjørling
2018-03-29 22:04 ` [GIT PULL 10/37] lightnvm: pblk: allow allocation of new lines during shutdown Matias Bjørling
2018-03-29 22:04 ` [GIT PULL 11/37] lightnvm: pblk: prevent race in pblk_rb_flush_point_set Matias Bjørling
2018-03-29 22:04 ` [GIT PULL 12/37] lightnvm: pblk: refactor bad block identification Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 13/37] lightnvm: make 1.2 data structures explicit Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 14/37] lightnvm: flatten nvm_id_group into nvm_id Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 15/37] lightnvm: add 2.0 geometry identification Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 16/37] lightnvm: remove max_rq_size Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 17/37] lightnvm: remove nvm_dev_ops->max_phys_sect Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 18/37] nvme: lightnvm: add late setup of block size and metadata Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 19/37] lightnvm: fix bad block initialization Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 20/37] lightnvm: centralize permission check for lightnvm ioctl Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 21/37] lightnvm: Avoid validation of default op value Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 22/37] lightnvm: pblk: refactor init/exit sequences Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 23/37] lightnvm: simplify geometry structure Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 24/37] lightnvm: add minor version to generic geometry Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 25/37] lightnvm: add shorten OCSSD version in geo Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 26/37] lightnvm: complete geo structure with maxoc* Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 27/37] lightnvm: normalize geometry nomenclature Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 28/37] lightnvm: add support for 2.0 address format Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 29/37] lightnvm: make address conversions depend on generic device Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 30/37] lightnvm: implement get log report chunk helpers Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 31/37] lightnvm: pblk: check for supported version Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 32/37] lightnvm: pblk: rename ppaf* to addrf* Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 33/37] lightnvm: pblk: implement get log report chunk Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 34/37] lightnvm: pblk: implement 2.0 support Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 35/37] lightnvm: pblk: don't recover unwritten lines Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 36/37] lightnvm: pblk: remove some unnecessary NULL checks Matias Bjørling
2018-03-29 22:05 ` [GIT PULL 37/37] lightnvm: remove function name in strings Matias Bjørling
2018-03-29 23:30 ` [GIT PULL 00/37] lightnvm patches for 4.17 Jens Axboe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).