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

IyBDaGFuZ2VzIHNpbmNlIFYyOgoKQXBwbHkgTWF0aWFzJyBmZWVkYmFjazoKIC0gUmVtb3ZlIGdl
bmVyaWMgbnZtX2lkIGlkZW50aWZ5IHN0cnVjdHVyZS4KIC0gRG8gbm90IHJlbWFwIGNhcGFiaWxp
dGllcyAoY2FwKSB0byBtZWRpYSBhbmQgY29udHJvbGxlZCBjYXBhYmlsaXRpZXMKICAgKG1jY2Fw
KS4gSW5zdGVhZCwgYWRkIGEgY29tbWVudCB0byBwcmV2ZW50IGNvbmZ1c2lvbiB3aGVuCiAgIGNy
b3NzY2hlY2tpbmcgd2l0aCAyLjAgc3BlYy4KIC0gQ2hhbmdlIG1heG9jIGFuZCBtYXhvY3B1IGRl
ZmF1bHRzIGZyb20gMSBibG9jayB0byB0aGUgbWF4IG51bWJlciBvZgogICBibG9ja3MuCiAtIFJl
LWltcGxlbWVudCB0aGUgZ2VuZXJpYyBnZW9tZXRyeSB0byB1c2UgbnZtX2dlbyBvbiBib3RoIGRl
dmljZSBhbmQKICAgdGFyZ2V0cy4gTWFpbnRhaW4gbnZtX2NvbW1vbl9nZW8gdG8gbWFrZSBpdCBl
YXNpZXIgdG8gY29weSB0aGUgY29tbW9uCiAgIHBhcnQgb2YgdGhlIGdlb21ldHJ5ICh3aXRob3V0
IGhhdmluZyB0byBvdmVyd3JpdGUgdGFyZ2V0LXNwZWNpZmljCiAgIGZpZWxkcywgd2hpY2ggaXMg
dWdseSBhbmQgZXJyb3IgcHJvbmUpLiBNYXRpYXMsIGlmIHlvdSBzdGlsbCB3YW50IHRvCiAgIGdl
dCByaWQgb2YgdGhpcywgd2UgY2FuIGRvIGl0LgogLSBSZS1vcmRlciBwYXRjaGVzIHdpdGggcmVu
YW1pbmcgdG8gbWFrZSB0aGVtIG1vcmUgbWVhbmluZ2Z1bC4gVGhlc2UKICAgYmVsb25nIHRvIHRo
ZSBzZXJpZXMsIHNpbmNlIHRoZSBuYW1lIGNoYW5nZXMgYXJlIG1vdGl2YXRlZCBieSAyLjAKICAg
aW5jbHVzaW9ucy4gVGhlIG9ubHkgZXhjZXB0aW9uIHdvdWxkIGJlIDM2ZDEwYmZkMzIzNCwgYnV0
IEkgaG9wZSBpdAogICBpcyBPSyBJIGluY2x1ZGUgaXQgaGVyZS4KCkFsc28sCiAtIEVsaW1pbmF0
ZSBhIGRlcGVuZGVuY3kgYmV0d2VlbiBsdW5zIGFuZCBsaW5lcyBpbiB0aGUgaW5pdC9leGl0CiAg
IHJlZmFjdG9yaW5nLgogLSBVc2UgdGhlIGdsb2JhbCBhZGRyZXNzIGZvcm1hdCB3aGVuIHBvc3Np
YmxlIHRvIGF2b2lkIGRlZmF1bHRpbmcgb24KICAgdGhlIDEuMiBwYXRoLiBUaGlzIHdpbGwgc2Fm
ZSBoZWFkYWNoZXMgaWYgdGhlIGFkZHJlc3MgZm9ybWF0IGNoYW5nZXMKICAgYXQgc29tZSBwb2lu
dC4KCkkgdG9vayBvdXQgdGhlIHBhdGNoIGFsbG93aW5nIHRvIGRvIGJpdCBzaGlmdHMgb24gbm9u
IHBvd2VyLW9mLTIgbWVkaWEKZm9ybWF0cyBvbiBwYmxrJ3MgbWFwcGluZyBzaW5jZSBpdCByZXF1
aXJlcyB0b3VjaGluZyBtYW55IHBsYWNlcyB0aGF0CmFyZSBub3QgMi4wIHJlbGF0ZWQuIEknbGwg
c3VibWl0IHRoaXMgc2VwYXJhdGVseS4KCiMgQ2hhbmdlcyBzaW5jZSBWMToKCkFwcGx5IE1hdGlh
cycgZmVlZGJhY2s6CiAtIFJlYmFzZSBvbiB0b3Agb2YgTWF0aWFzJyBsYXRlc3QgcGF0Y2hlcy4K
IC0gVXNlIG52bWVfZ2V0X2xvZ19leHQgdG8gc3VibWl0IHJlcG9ydCBjaHVuayBhbmQgZXhwb3J0
IGl0LgogLSBSZS13cml0ZSByZXBvcnQgY2h1bmsgYmFzZWQgb24gTWF0aWFzJyBzdWdnZXN0aW9u
cy4gSGVyZSwgSQogICBtYWludGFpbmVkIHRoZSBsYmEgaW50ZXJmYWNlLCBidXQgaXQgd2FzIG5l
Y2Vzc2FyeSB0byByZWRvIHRoZQogICBhZGRyZXNzIGZvcm1hdHRpbmcgdG8gbWF0Y2ggdGhlIGNo
dW5rIGxvZyBwYWdlIGZvcm1hdC4gRm9yIHBibGssCiAgIHRoaXMgbWVhbnMgYSBkb3VibGUgYWRk
cmVzcyB0cmFuc2Zvcm1hdGlvbiwgYnV0IGl0IGVuYWJsZXMgdGhlCiAgIHN0YW5kYXJkIHBhdGgg
dG8gdXNlIGxiYXMsIHBsdXMsIHRoaXMgaXMgbm90IGluIHRoZSBmYXN0IHBhdGguCiAtIEZvbGQg
YWRkcmVzcyBmb3JtYXQgdG9nZXRoZXIgd2l0aCBhZGRyZXNzIHRyYW5zZm9ybWF0aW9ucy4KIC0g
U3BsaXQgdGhlIGdlbmVyaWMgZ2VvbWV0cnkgcGF0Y2ggaW4gZGlmZmVyZW50IHBhdGNoZXMuCiAt
IFJlbW92ZSByZWZhY3RvcmluZyBvZiBsaWd0aG52bSdzIGNvcmUgc3lzZnMuCgpGZWVkYmFjayBu
b3QgYXBwbGllZDoKIC0gTm90IGxldHRpbmcgcGJsayBrbm93IGFib3V0IDEuMiBhbmQgMi4wIGJh
ZCBibG9jayBwYXRocy4KICAgU2luY2UgdGhlIGludGVyZmFjZXMgZm9yIGdldC9zZXQgYmFkIGJs
b2NrIGFuZCByZXBvcnQgY2h1bmsgYXJlIHNvCiAgIGRpZmZlcmVudCwgbW92aW5nIHRoaXMgbG9n
aWMgdG8gY29yZSBhZGRzIGFzc3VtcHRpb25zIG9uIGhvdyB0aGUKICAgdGFyZ2V0cyB3b3VsZCB3
YW50IHRvIGdldCB0aGUgZGF0YSBiYWNrLiBBIHdheSBvZiBkb2luZyB0aGlzIGlzCiAgIGNyZWF0
aW5nIGEgbG9naWNhbCByZXBvcnQgY2h1bmsgb24gdGhlIDEuMiBwYXRoLCBidXQgdGhpcyB3b3Vs
ZAogICBtZWFuIHRoYXQgdmFsdWVzIGxpa2UgdGhlIHdlYXItaW5kZXggYXJlIGludmFsaWQsIHdo
aWNoIHJlcXVpcmVzCiAgIHRoZSB0YXJnZXQga25vd2xlZGdlLiBJJ20gb3BlbiB0byBzdWdnZXN0
aW9ucyBoZXJlLgoKQWxzbzoKIC0gRG8gc29tZSBmdXJ0aGVyIHJlbmFtaW5ncwogLSBDcmVhdGUg
YSBnZW5lcmljIGFkZHJlc3MgZm9ybWF0IHRvIG1ha2UgaXQgZXhwbGljaXQgd2hlcmUgd2Ugc2hh
cmUKICAgMS4yIGFuZCAyLjAgZmllbGRzIHRvIGF2b2lkIGFkZHJlc3MgZm9ybWF0dGluZyBpbiB0
aGUgZmFzdCBwYXRoLgogLSBBZGQgbmV3IGZpZWxkcyB0byBzeXNmcyB0byBjb21wbGV0ZSBzcGVj
IGFuZCBzaG93IG1ham9yL21pbm9yCiAgIHZlcnNpb25zICh2ZXJzaW9uIGFuZCBzdWJ2ZXJzaW9u
IHRvIHJlc3BlY3QgY3VycmVudCBpbnRlcmZhY2UpLgoKSW1wbGVtZW50IDIuMCBzdXBwb3J0IGlu
IHBibGsuIFRoaXMgaW5jbHVkZXMgdGhlIGFkZHJlc3MgZm9ybWF0dGluZyBhbmQKbWFwcGluZyBw
YXRocywgYXMgd2VsbCBhcyB0aGUgc3lzZnMgZW50cmllcyBmb3IgdGhlbS4KCkphdmllcgoKSmF2
aWVyIEdvbnrDoWxleiAoMTkpOgogIGxpZ2h0bnZtOiBzaW1wbGlmeSBnZW9tZXRyeSBzdHJ1Y3R1
cmUuCiAgbGlnaHRudm06IGFkZCBjb250cm9sbGVyIGNhcGFiaWxpdGllcyB0byAyLjAKICBsaWdo
dG52bTogYWRkIG1pbm9yIHZlcnNpb24gdG8gZ2VuZXJpYyBnZW9tZXRyeQogIGxpZ2h0bnZtOiBh
ZGQgc2hvcnRlbiBPQ1NTRCB2ZXJzaW9uIGluIGdlbwogIGxpZ2h0bnZtOiBjb21wbGV0ZSBnZW8g
c3RydWN0dXJlIHdpdGggbWF4b2MqCiAgbGlnaHRudm06IHBibGs6IGNoZWNrIGZvciBzdXBwb3J0
ZWQgdmVyc2lvbgogIGxpZ2h0bnZtOiBjb21wbGV0ZSAyLjAgdmFsdWVzIGluIHN5c2ZzCiAgbGln
aHRudm06IHJlbmFtZSBudW1iZXIgb2YgY2hhbm5lbHMgYW5kIGx1bnMKICBsaWdodG52bTogcmVu
YW1lIHNlY3RfKiB0byBzZWNfKgogIGxpZ2h0bnZtOiBhZGQgc3VwcG9ydCBmb3IgMi4wIGFkZHJl
c3MgZm9ybWF0CiAgbGlnaHRudm06IHBibGs6IHJlbmFtZSBwcGFmKiB0byBhZGRyZioKICBsaWdo
dG52bjogcGJsazogdXNlIGdlbmVyaWMgYWRkcmVzcyBmb3JtYXQKICBsaWdodG52bTogbWFrZSBh
ZGRyZXNzIGNvbnZlcnNpb25zIGRlcGVuZCBvbiBnZW5lcmljIGRldmljZQogIG52bWU6IG1ha2Ug
bnZtZV9nZXRfbG9nX2V4dCBhdmFpbGFibGUKICBsaWdodG52bTogaW1wbGVtZW50IGdldCBsb2cg
cmVwb3J0IGNodW5rIGhlbHBlcnMKICBsaWdodG52bTogZGVmaW5lIGNodW5rIHN0YXRlcwogIGxp
Z2h0bnZtOiBwYmxrOiBpbXBsZW1lbnQgZ2V0IGxvZyByZXBvcnQgY2h1bmsKICBsaWdodG52bTog
cGJsazogcmVmYWN0b3IgaW5pdC9leGl0IHNlcXVlbmNlcwogIGxpZ2h0bnZtOiBwYmxrOiBpbXBs
ZW1lbnQgMi4wIHN1cHBvcnQKCiBkcml2ZXJzL2xpZ2h0bnZtL2NvcmUuYyAgICAgICAgICB8IDE5
OSArKysrKy0tLS0tCiBkcml2ZXJzL2xpZ2h0bnZtL3BibGstY29yZS5jICAgICB8IDE1MSArKysr
Ky0tCiBkcml2ZXJzL2xpZ2h0bnZtL3BibGstZ2MuYyAgICAgICB8ICAgMiArLQogZHJpdmVycy9s
aWdodG52bS9wYmxrLWluaXQuYyAgICAgfCA4MzMgKysrKysrKysrKysrKysrKysrKysrKystLS0t
LS0tLS0tLS0tLS0tCiBkcml2ZXJzL2xpZ2h0bnZtL3BibGstbWFwLmMgICAgICB8ICAgNCArLQog
ZHJpdmVycy9saWdodG52bS9wYmxrLXJlYWQuYyAgICAgfCAgIDIgKy0KIGRyaXZlcnMvbGlnaHRu
dm0vcGJsay1yZWNvdmVyeS5jIHwgIDE0ICstCiBkcml2ZXJzL2xpZ2h0bnZtL3BibGstcmwuYyAg
ICAgICB8ICAgMiArLQogZHJpdmVycy9saWdodG52bS9wYmxrLXN5c2ZzLmMgICAgfCAxMzQgKysr
KysrLQogZHJpdmVycy9saWdodG52bS9wYmxrLXdyaXRlLmMgICAgfCAgIDIgKy0KIGRyaXZlcnMv
bGlnaHRudm0vcGJsay5oICAgICAgICAgIHwgMjU1ICsrKysrKysrLS0tLQogZHJpdmVycy9udm1l
L2hvc3QvbGlnaHRudm0uYyAgICAgfCA0NTggKysrKysrKysrKysrKystLS0tLS0tCiBkcml2ZXJz
L252bWUvaG9zdC9udm1lLmggICAgICAgICB8ICAgMyArCiBpbmNsdWRlL2xpbnV4L2xpZ2h0bnZt
LmggICAgICAgICB8IDMzOCArKysrKysrKysrLS0tLS0tCiAxNCBmaWxlcyBjaGFuZ2VkLCAxNTU5
IGluc2VydGlvbnMoKyksIDgzOCBkZWxldGlvbnMoLSkKCi0tIAoyLjcuNAoKCl9fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCkxpbnV4LW52bWUgbWFpbGluZyBs
aXN0CkxpbnV4LW52bWVAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFk
Lm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LW52bWUK

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

* [PATCH V3 00/19] lightnvm: pblk: implement 2.0 support
@ 2018-02-26 13:16 ` Javier González
  0 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:16 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

# Changes since V2:

Apply Matias' feedback:
 - Remove generic nvm_id identify structure.
 - Do not remap capabilities (cap) to media and controlled capabilities
   (mccap). Instead, add a comment to prevent confusion when
   crosschecking with 2.0 spec.
 - Change maxoc and maxocpu defaults from 1 block to the max number of
   blocks.
 - Re-implement the generic geometry to use nvm_geo on both device and
   targets. Maintain nvm_common_geo to make it easier to copy the common
   part of the geometry (without having to overwrite target-specific
   fields, which is ugly and error prone). Matias, if you still want to
   get rid of this, we can do it.
 - Re-order patches with renaming to make them more meaningful. These
   belong to the series, since the name changes are motivated by 2.0
   inclusions. The only exception would be 36d10bfd3234, but I hope it
   is OK I include it here.

Also,
 - Eliminate a dependency between luns and lines in the init/exit
   refactoring.
 - Use the global address format when possible to avoid defaulting on
   the 1.2 path. This will safe headaches if the address format changes
   at some point.

I took out the patch allowing to do bit shifts on non power-of-2 media
formats on pblk's mapping since it requires touching many places that
are not 2.0 related. I'll submit this separately.

# Changes since V1:

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

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

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

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

Javier

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

 drivers/lightnvm/core.c          | 199 +++++-----
 drivers/lightnvm/pblk-core.c     | 151 +++++--
 drivers/lightnvm/pblk-gc.c       |   2 +-
 drivers/lightnvm/pblk-init.c     | 833 +++++++++++++++++++++++----------------
 drivers/lightnvm/pblk-map.c      |   4 +-
 drivers/lightnvm/pblk-read.c     |   2 +-
 drivers/lightnvm/pblk-recovery.c |  14 +-
 drivers/lightnvm/pblk-rl.c       |   2 +-
 drivers/lightnvm/pblk-sysfs.c    | 134 ++++++-
 drivers/lightnvm/pblk-write.c    |   2 +-
 drivers/lightnvm/pblk.h          | 255 ++++++++----
 drivers/nvme/host/lightnvm.c     | 458 ++++++++++++++-------
 drivers/nvme/host/nvme.h         |   3 +
 include/linux/lightnvm.h         | 338 ++++++++++------
 14 files changed, 1559 insertions(+), 838 deletions(-)

-- 
2.7.4

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

* [PATCH V3 00/19] lightnvm: pblk: implement 2.0 support
@ 2018-02-26 13:16 ` Javier González
  0 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:16 UTC (permalink / raw)


# Changes since V2:

Apply Matias' feedback:
 - Remove generic nvm_id identify structure.
 - Do not remap capabilities (cap) to media and controlled capabilities
   (mccap). Instead, add a comment to prevent confusion when
   crosschecking with 2.0 spec.
 - Change maxoc and maxocpu defaults from 1 block to the max number of
   blocks.
 - Re-implement the generic geometry to use nvm_geo on both device and
   targets. Maintain nvm_common_geo to make it easier to copy the common
   part of the geometry (without having to overwrite target-specific
   fields, which is ugly and error prone). Matias, if you still want to
   get rid of this, we can do it.
 - Re-order patches with renaming to make them more meaningful. These
   belong to the series, since the name changes are motivated by 2.0
   inclusions. The only exception would be 36d10bfd3234, but I hope it
   is OK I include it here.

Also,
 - Eliminate a dependency between luns and lines in the init/exit
   refactoring.
 - Use the global address format when possible to avoid defaulting on
   the 1.2 path. This will safe headaches if the address format changes
   at some point.

I took out the patch allowing to do bit shifts on non power-of-2 media
formats on pblk's mapping since it requires touching many places that
are not 2.0 related. I'll submit this separately.

# Changes since V1:

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

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

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

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

Javier

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

 drivers/lightnvm/core.c          | 199 +++++-----
 drivers/lightnvm/pblk-core.c     | 151 +++++--
 drivers/lightnvm/pblk-gc.c       |   2 +-
 drivers/lightnvm/pblk-init.c     | 833 +++++++++++++++++++++++----------------
 drivers/lightnvm/pblk-map.c      |   4 +-
 drivers/lightnvm/pblk-read.c     |   2 +-
 drivers/lightnvm/pblk-recovery.c |  14 +-
 drivers/lightnvm/pblk-rl.c       |   2 +-
 drivers/lightnvm/pblk-sysfs.c    | 134 ++++++-
 drivers/lightnvm/pblk-write.c    |   2 +-
 drivers/lightnvm/pblk.h          | 255 ++++++++----
 drivers/nvme/host/lightnvm.c     | 458 ++++++++++++++-------
 drivers/nvme/host/nvme.h         |   3 +
 include/linux/lightnvm.h         | 338 ++++++++++------
 14 files changed, 1559 insertions(+), 838 deletions(-)

-- 
2.7.4

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

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

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

Instead, create a generic geometry around 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.

Since these share a big part of the geometry, create a nvm_common_geo
structure that keeps the static geoometry values that are shared across
instances.

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

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

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

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

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


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

Instead, create a generic geometry around 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.

Since these share a big part of the geometry, create a nvm_common_geo
structure that keeps the static geoometry values that are shared across
instances.

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

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

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

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

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

QXNzaWduIG1pc3NpbmcgbWNjYXAgdmFsdWUgb24gMi4wIHBhdGgKClNpZ25lZC1vZmYtYnk6IEph
dmllciBHb256w6FsZXogPGphdmllckBjbmV4bGFicy5jb20+Ci0tLQogZHJpdmVycy9udm1lL2hv
c3QvbGlnaHRudm0uYyB8IDQgKysrLQogaW5jbHVkZS9saW51eC9saWdodG52bS5oICAgICB8IDgg
KysrKystLS0KIDIgZmlsZXMgY2hhbmdlZCwgOCBpbnNlcnRpb25zKCspLCA0IGRlbGV0aW9ucygt
KQoKZGlmZiAtLWdpdCBhL2RyaXZlcnMvbnZtZS9ob3N0L2xpZ2h0bnZtLmMgYi9kcml2ZXJzL252
bWUvaG9zdC9saWdodG52bS5jCmluZGV4IDhmNTQxMzMxYjFhOS4uMTAzOTJhNjY0YjUwIDEwMDY0
NAotLS0gYS9kcml2ZXJzL252bWUvaG9zdC9saWdodG52bS5jCisrKyBiL2RyaXZlcnMvbnZtZS9o
b3N0L2xpZ2h0bnZtLmMKQEAgLTMxOCw3ICszMTgsNyBAQCBzdGF0aWMgaW50IG52bWVfbnZtX3Nl
dHVwXzEyKHN0cnVjdCBudm1lX252bV9pZDEyICppZCwKIAlkZXZfZ2VvLT5jLndzX29wdCA9IHNl
Y19wZXJfcGc7CiAJZGV2X2dlby0+Yy5td19jdW5pdHMgPSA4OwkJLyogZGVmYXVsdCB0byBNTEMg
c2FmZSB2YWx1ZXMgKi8KIAotCWRldl9nZW8tPmMubWNjYXAgPSBsZTMyX3RvX2NwdShzcmMtPm1j
Y2FwKTsKKwlkZXZfZ2VvLT5jLmNhcCA9IGxlMzJfdG9fY3B1KHNyYy0+bWNjYXApOwogCiAJZGV2
X2dlby0+Yy50cmR0ID0gbGUzMl90b19jcHUoc3JjLT50cmR0KTsKIAlkZXZfZ2VvLT5jLnRyZG0g
PSBsZTMyX3RvX2NwdShzcmMtPnRyZG0pOwpAQCAtMzk5LDYgKzM5OSw4IEBAIHN0YXRpYyBpbnQg
bnZtZV9udm1fc2V0dXBfMjAoc3RydWN0IG52bWVfbnZtX2lkMjAgKmlkLAogCWRldl9nZW8tPmMu
d3Nfb3B0ID0gbGUzMl90b19jcHUoaWQtPndzX29wdCk7CiAJZGV2X2dlby0+Yy5td19jdW5pdHMg
PSBsZTMyX3RvX2NwdShpZC0+bXdfY3VuaXRzKTsKIAorCWRldl9nZW8tPmMuY2FwID0gbGUzMl90
b19jcHUoaWQtPm1jY2FwKTsKKwogCWRldl9nZW8tPmMudHJkdCA9IGxlMzJfdG9fY3B1KGlkLT50
cmR0KTsKIAlkZXZfZ2VvLT5jLnRyZG0gPSBsZTMyX3RvX2NwdShpZC0+dHJkbSk7CiAJZGV2X2dl
by0+Yy50cHJ0ID0gbGUzMl90b19jcHUoaWQtPnR3cnQpOwpkaWZmIC0tZ2l0IGEvaW5jbHVkZS9s
aW51eC9saWdodG52bS5oIGIvaW5jbHVkZS9saW51eC9saWdodG52bS5oCmluZGV4IDQ1MzdjMDE0
MDM4Ni4uNDI3MDRjNGNhOWFmIDEwMDY0NAotLS0gYS9pbmNsdWRlL2xpbnV4L2xpZ2h0bnZtLmgK
KysrIGIvaW5jbHVkZS9saW51eC9saWdodG52bS5oCkBAIC0yNzMsOCArMjczLDEwIEBAIHN0cnVj
dCBudm1fY29tbW9uX2dlbyB7CiAJdTMyCXdzX29wdDsJCS8qIG9wdGltYWwgd3JpdGUgc2l6ZSAq
LwogCXUzMgltd19jdW5pdHM7CS8qIGRpc3RhbmNlIHJlcXVpcmVkIGZvciBzdWNjZXNzZnVsIHJl
YWQgKi8KIAotCS8qIGRldmljZSBjYXBhYmlsaXRpZXMgKi8KLQl1MzIJbWNjYXA7CisJLyogZGV2
aWNlIGNhcGFiaWxpdGllcy4gTm90ZSB0aGF0IHRoaXMgcmVwcmVzZW50cyBjYXBhYmlsaXRpZXMg
aW4gMS4yCisJICogYW5kIG1lZGlhIGFuZCBjb250cm9sbGVyIGNhcGFiaWxpdGllcyBpbiAyLjAK
KwkgKi8KKwl1MzIJY2FwOwogCiAJLyogZGV2aWNlIHRpbWluZ3MgKi8KIAl1MzIJdHJkdDsJCS8q
IEF2Zy4gVHJlYWQgKG5zKSAqLwpAQCAtMjg5LDcgKzI5MSw3IEBAIHN0cnVjdCBudm1fY29tbW9u
X2dlbyB7CiAKIAkvKiAxLjIgY29tcGF0aWJpbGl0eSAqLwogCXU4CXZtbnQ7Ci0JdTMyCWNhcDsK
Kwl1MzIJbWNjYXA7CiAJdTMyCWRvbTsKIAogCXU4CW10eXBlOwotLSAKMi43LjQKCgpfX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpMaW51eC1udm1lIG1haWxp
bmcgbGlzdApMaW51eC1udm1lQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJh
ZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1udm1lCg==

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

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

Assign missing mccap value on 2.0 path

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

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 8f541331b1a9..10392a664b50 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -318,7 +318,7 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
 	dev_geo->c.ws_opt = sec_per_pg;
 	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
 
-	dev_geo->c.mccap = le32_to_cpu(src->mccap);
+	dev_geo->c.cap = le32_to_cpu(src->mccap);
 
 	dev_geo->c.trdt = le32_to_cpu(src->trdt);
 	dev_geo->c.trdm = le32_to_cpu(src->trdm);
@@ -399,6 +399,8 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
 	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
 
+	dev_geo->c.cap = le32_to_cpu(id->mccap);
+
 	dev_geo->c.trdt = le32_to_cpu(id->trdt);
 	dev_geo->c.trdm = le32_to_cpu(id->trdm);
 	dev_geo->c.tprt = le32_to_cpu(id->twrt);
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 4537c0140386..42704c4ca9af 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -273,8 +273,10 @@ struct nvm_common_geo {
 	u32	ws_opt;		/* optimal write size */
 	u32	mw_cunits;	/* distance required for successful read */
 
-	/* device capabilities */
-	u32	mccap;
+	/* device capabilities. Note that this represents capabilities in 1.2
+	 * and media and controller capabilities in 2.0
+	 */
+	u32	cap;
 
 	/* device timings */
 	u32	trdt;		/* Avg. Tread (ns) */
@@ -289,7 +291,7 @@ struct nvm_common_geo {
 
 	/* 1.2 compatibility */
 	u8	vmnt;
-	u32	cap;
+	u32	mccap;
 	u32	dom;
 
 	u8	mtype;
-- 
2.7.4

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

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


Assign missing mccap value on 2.0 path

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

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 8f541331b1a9..10392a664b50 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -318,7 +318,7 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
 	dev_geo->c.ws_opt = sec_per_pg;
 	dev_geo->c.mw_cunits = 8;		/* default to MLC safe values */
 
-	dev_geo->c.mccap = le32_to_cpu(src->mccap);
+	dev_geo->c.cap = le32_to_cpu(src->mccap);
 
 	dev_geo->c.trdt = le32_to_cpu(src->trdt);
 	dev_geo->c.trdm = le32_to_cpu(src->trdm);
@@ -399,6 +399,8 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
 	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
 
+	dev_geo->c.cap = le32_to_cpu(id->mccap);
+
 	dev_geo->c.trdt = le32_to_cpu(id->trdt);
 	dev_geo->c.trdm = le32_to_cpu(id->trdm);
 	dev_geo->c.tprt = le32_to_cpu(id->twrt);
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 4537c0140386..42704c4ca9af 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -273,8 +273,10 @@ struct nvm_common_geo {
 	u32	ws_opt;		/* optimal write size */
 	u32	mw_cunits;	/* distance required for successful read */
 
-	/* device capabilities */
-	u32	mccap;
+	/* device capabilities. Note that this represents capabilities in 1.2
+	 * and media and controller capabilities in 2.0
+	 */
+	u32	cap;
 
 	/* device timings */
 	u32	trdt;		/* Avg. Tread (ns) */
@@ -289,7 +291,7 @@ struct nvm_common_geo {
 
 	/* 1.2 compatibility */
 	u8	vmnt;
-	u32	cap;
+	u32	mccap;
 	u32	dom;
 
 	u8	mtype;
-- 
2.7.4

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

* [PATCH 03/19] lightnvm: add minor version to generic geometry
  2018-02-26 13:16 ` Javier González
  (?)
@ 2018-02-26 13:17   ` Javier González
  -1 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)
  To: mb; +Cc: linux-block, Javier González, linux-kernel, linux-nvme

U2VwYXJhdGUgdGhlIHZlcnNpb24gYmV0d2VlbiBtYWpvciBhbmQgbWlub3Igb24gdGhlIGdlbmVy
aWMgZ2VvbWV0cnkgYW5kCnJlcHJlc2VudCBpdCB0aHJvdWdoIHN5c2ZzIGluIHRoZSAyLjAgcGF0
aC4gVGhlIDEuMiBwYXRoIG9ubHkgc2hvd3MgdGhlIG1ham9yCnZlcnNpb24gdG8gcHJlc2VydmUg
dGhlIGV4aXN0aW5nIHVzZXIgc3BhY2UgaW50ZXJmYWNlLgoKU2lnbmVkLW9mZi1ieTogSmF2aWVy
IEdvbnrDoWxleiA8amF2aWVyQGNuZXhsYWJzLmNvbT4KLS0tCiBkcml2ZXJzL2xpZ2h0bnZtL2Nv
cmUuYyAgICAgIHwgIDQgKystLQogZHJpdmVycy9udm1lL2hvc3QvbGlnaHRudm0uYyB8IDI1ICsr
KysrKysrKysrKysrKysrKysrLS0tLS0KIGluY2x1ZGUvbGludXgvbGlnaHRudm0uaCAgICAgfCAg
MyArKy0KIDMgZmlsZXMgY2hhbmdlZCwgMjQgaW5zZXJ0aW9ucygrKSwgOCBkZWxldGlvbnMoLSkK
CmRpZmYgLS1naXQgYS9kcml2ZXJzL2xpZ2h0bnZtL2NvcmUuYyBiL2RyaXZlcnMvbGlnaHRudm0v
Y29yZS5jCmluZGV4IDQzZTNkNmJiNWJlNi4uOTZmNGU2MmQzODNiIDEwMDY0NAotLS0gYS9kcml2
ZXJzL2xpZ2h0bnZtL2NvcmUuYworKysgYi9kcml2ZXJzL2xpZ2h0bnZtL2NvcmUuYwpAQCAtODk3
LDggKzg5Nyw4IEBAIHN0YXRpYyBpbnQgbnZtX2luaXQoc3RydWN0IG52bV9kZXYgKmRldikKIAkJ
Z290byBlcnI7CiAJfQogCi0JcHJfZGVidWcoIm52bTogdmVyOiV1IG52bV92ZW5kb3I6JXhcbiIs
Ci0JCQkJZGV2X2dlby0+dmVyX2lkLAorCXByX2RlYnVnKCJudm06IHZlcjoldS4ldSBudm1fdmVu
ZG9yOiV4XG4iLAorCQkJCWRldl9nZW8tPm1ham9yX3Zlcl9pZCwgZGV2X2dlby0+bWlub3JfdmVy
X2lkLAogCQkJCWRldl9nZW8tPmMudm1udCk7CiAKIAlyZXQgPSBudm1fY29yZV9pbml0KGRldik7
CmRpZmYgLS1naXQgYS9kcml2ZXJzL252bWUvaG9zdC9saWdodG52bS5jIGIvZHJpdmVycy9udm1l
L2hvc3QvbGlnaHRudm0uYwppbmRleCAxMDM5MmE2NjRiNTAuLjhiZWZiNjBlZWFjYiAxMDA2NDQK
LS0tIGEvZHJpdmVycy9udm1lL2hvc3QvbGlnaHRudm0uYworKysgYi9kcml2ZXJzL252bWUvaG9z
dC9saWdodG52bS5jCkBAIC0yOTUsNyArMjk1LDkgQEAgc3RhdGljIGludCBudm1lX252bV9zZXR1
cF8xMihzdHJ1Y3QgbnZtZV9udm1faWQxMiAqaWQsCiAJCXJldHVybiAtRUlOVkFMOwogCX0KIAot
CWRldl9nZW8tPnZlcl9pZCA9IGlkLT52ZXJfaWQ7CisJLyogMS4yIHNwZWMuIG9ubHkgcmVwb3J0
cyBhIHNpbmdsZSB2ZXJzaW9uIGlkIC0gdW5mb2xkICovCisJZGV2X2dlby0+bWFqb3JfdmVyX2lk
ID0gaWQtPnZlcl9pZDsKKwlkZXZfZ2VvLT5taW5vcl92ZXJfaWQgPSAyOwogCiAJZGV2X2dlby0+
bnJfY2hubHMgPSBzcmMtPm51bV9jaDsKIAlkZXZfZ2VvLT5ucl9sdW5zID0gc3JjLT5udW1fbHVu
OwpAQCAtMzgwLDcgKzM4MiwxNCBAQCBzdGF0aWMgdm9pZCBudm1lX252bV9zZXRfYWRkcl8yMChz
dHJ1Y3QgbnZtX2FkZHJfZm9ybWF0ICpkc3QsCiBzdGF0aWMgaW50IG52bWVfbnZtX3NldHVwXzIw
KHN0cnVjdCBudm1lX252bV9pZDIwICppZCwKIAkJCSAgICAgc3RydWN0IG52bV9nZW8gKmRldl9n
ZW8pCiB7Ci0JZGV2X2dlby0+dmVyX2lkID0gaWQtPm1qcjsKKwlkZXZfZ2VvLT5tYWpvcl92ZXJf
aWQgPSBpZC0+bWpyOworCWRldl9nZW8tPm1pbm9yX3Zlcl9pZCA9IGlkLT5tbnI7CisKKwlpZiAo
IShkZXZfZ2VvLT5tYWpvcl92ZXJfaWQgPT0gMiAmJiBkZXZfZ2VvLT5taW5vcl92ZXJfaWQgPT0g
MCkpIHsKKwkJcHJfZXJyKCJudm06IE9DU1NEIHZlcnNpb24gbm90IHN1cHBvcnRlZCAodiVkLiVk
KVxuIiwKKwkJCQlkZXZfZ2VvLT5tYWpvcl92ZXJfaWQsIGRldl9nZW8tPm1pbm9yX3Zlcl9pZCk7
CisJCXJldHVybiAtRUlOVkFMOworCX0KIAogCWRldl9nZW8tPm5yX2NobmxzID0gbGUxNl90b19j
cHUoaWQtPm51bV9ncnApOwogCWRldl9nZW8tPm5yX2x1bnMgPSBsZTE2X3RvX2NwdShpZC0+bnVt
X3B1KTsKQEAgLTkyMCw3ICs5MjksMTMgQEAgc3RhdGljIHNzaXplX3QgbnZtX2Rldl9hdHRyX3No
b3coc3RydWN0IGRldmljZSAqZGV2LAogCWF0dHIgPSAmZGF0dHItPmF0dHI7CiAKIAlpZiAoc3Ry
Y21wKGF0dHItPm5hbWUsICJ2ZXJzaW9uIikgPT0gMCkgewotCQlyZXR1cm4gc2NucHJpbnRmKHBh
Z2UsIFBBR0VfU0laRSwgIiV1XG4iLCBkZXZfZ2VvLT52ZXJfaWQpOworCQlpZiAoZGV2X2dlby0+
bWFqb3JfdmVyX2lkID09IDEpCisJCQlyZXR1cm4gc2NucHJpbnRmKHBhZ2UsIFBBR0VfU0laRSwg
IiV1XG4iLAorCQkJCQkJZGV2X2dlby0+bWFqb3JfdmVyX2lkKTsKKwkJZWxzZQorCQkJcmV0dXJu
IHNjbnByaW50ZihwYWdlLCBQQUdFX1NJWkUsICIldS4ldVxuIiwKKwkJCQkJCWRldl9nZW8tPm1h
am9yX3Zlcl9pZCwKKwkJCQkJCWRldl9nZW8tPm1pbm9yX3Zlcl9pZCk7CiAJfSBlbHNlIGlmIChz
dHJjbXAoYXR0ci0+bmFtZSwgImNhcGFiaWxpdGllcyIpID09IDApIHsKIAkJcmV0dXJuIHNjbnBy
aW50ZihwYWdlLCBQQUdFX1NJWkUsICIldVxuIiwgZGV2X2dlby0+Yy5jYXApOwogCX0gZWxzZSBp
ZiAoc3RyY21wKGF0dHItPm5hbWUsICJyZWFkX3R5cCIpID09IDApIHsKQEAgLTExNzQsNyArMTE4
OSw3IEBAIGludCBudm1lX252bV9yZWdpc3Rlcl9zeXNmcyhzdHJ1Y3QgbnZtZV9ucyAqbnMpCiAJ
aWYgKCFuZGV2KQogCQlyZXR1cm4gLUVJTlZBTDsKIAotCXN3aXRjaCAoZGV2X2dlby0+dmVyX2lk
KSB7CisJc3dpdGNoIChkZXZfZ2VvLT5tYWpvcl92ZXJfaWQpIHsKIAljYXNlIDE6CiAJCXJldHVy
biBzeXNmc19jcmVhdGVfZ3JvdXAoJmRpc2tfdG9fZGV2KG5zLT5kaXNrKS0+a29iaiwKIAkJCQkJ
Jm52bV9kZXZfYXR0cl9ncm91cF8xMik7CkBAIC0xMTkxLDcgKzEyMDYsNyBAQCB2b2lkIG52bWVf
bnZtX3VucmVnaXN0ZXJfc3lzZnMoc3RydWN0IG52bWVfbnMgKm5zKQogCXN0cnVjdCBudm1fZGV2
ICpuZGV2ID0gbnMtPm5kZXY7CiAJc3RydWN0IG52bV9nZW8gKmRldl9nZW8gPSAmbmRldi0+Z2Vv
OwogCi0Jc3dpdGNoIChkZXZfZ2VvLT52ZXJfaWQpIHsKKwlzd2l0Y2ggKGRldl9nZW8tPm1ham9y
X3Zlcl9pZCkgewogCWNhc2UgMToKIAkJc3lzZnNfcmVtb3ZlX2dyb3VwKCZkaXNrX3RvX2Rldihu
cy0+ZGlzayktPmtvYmosCiAJCQkJCSZudm1fZGV2X2F0dHJfZ3JvdXBfMTIpOwpkaWZmIC0tZ2l0
IGEvaW5jbHVkZS9saW51eC9saWdodG52bS5oIGIvaW5jbHVkZS9saW51eC9saWdodG52bS5oCmlu
ZGV4IDQyNzA0YzRjYTlhZi4uY2NhZjhhMzAyMDJkIDEwMDY0NAotLS0gYS9pbmNsdWRlL2xpbnV4
L2xpZ2h0bnZtLmgKKysrIGIvaW5jbHVkZS9saW51eC9saWdodG52bS5oCkBAIC0zMDksNyArMzA5
LDggQEAgc3RydWN0IG52bV9jb21tb25fZ2VvIHsKIC8qIEluc3RhbmNlIGdlb21ldHJ5ICovCiBz
dHJ1Y3QgbnZtX2dlbyB7CiAJLyogZGV2aWNlIHJlcG9ydGVkIHZlcnNpb24gKi8KLQl1OAl2ZXJf
aWQ7CisJdTgJbWFqb3JfdmVyX2lkOworCXU4CW1pbm9yX3Zlcl9pZDsKIAogCS8qIGluc3RhbmNl
IHNwZWNpZmljIGdlb21ldHJ5ICovCiAJaW50IG5yX2NobmxzOwotLSAKMi43LjQKCgpfX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpMaW51eC1udm1lIG1haWxp
bmcgbGlzdApMaW51eC1udm1lQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJh
ZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1udm1lCg==

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

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

Separate the version between major and minor on the generic geometry 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>
---
 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 43e3d6bb5be6..96f4e62d383b 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -897,8 +897,8 @@ static int nvm_init(struct nvm_dev *dev)
 		goto err;
 	}
 
-	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
-				dev_geo->ver_id,
+	pr_debug("nvm: ver:%u.%u nvm_vendor:%x\n",
+				dev_geo->major_ver_id, dev_geo->minor_ver_id,
 				dev_geo->c.vmnt);
 
 	ret = nvm_core_init(dev);
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 10392a664b50..8befb60eeacb 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;
 	}
 
-	dev_geo->ver_id = id->ver_id;
+	/* 1.2 spec. only reports a single version id - unfold */
+	dev_geo->major_ver_id = id->ver_id;
+	dev_geo->minor_ver_id = 2;
 
 	dev_geo->nr_chnls = src->num_ch;
 	dev_geo->nr_luns = src->num_lun;
@@ -380,7 +382,14 @@ static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
 static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 			     struct nvm_geo *dev_geo)
 {
-	dev_geo->ver_id = id->mjr;
+	dev_geo->major_ver_id = id->mjr;
+	dev_geo->minor_ver_id = id->mnr;
+
+	if (!(dev_geo->major_ver_id == 2 && dev_geo->minor_ver_id == 0)) {
+		pr_err("nvm: OCSSD version not supported (v%d.%d)\n",
+				dev_geo->major_ver_id, dev_geo->minor_ver_id);
+		return -EINVAL;
+	}
 
 	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
 	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
@@ -920,7 +929,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", dev_geo->ver_id);
+		if (dev_geo->major_ver_id == 1)
+			return scnprintf(page, PAGE_SIZE, "%u\n",
+						dev_geo->major_ver_id);
+		else
+			return scnprintf(page, PAGE_SIZE, "%u.%u\n",
+						dev_geo->major_ver_id,
+						dev_geo->minor_ver_id);
 	} else if (strcmp(attr->name, "capabilities") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
 	} else if (strcmp(attr->name, "read_typ") == 0) {
@@ -1174,7 +1189,7 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
 	if (!ndev)
 		return -EINVAL;
 
-	switch (dev_geo->ver_id) {
+	switch (dev_geo->major_ver_id) {
 	case 1:
 		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
 					&nvm_dev_attr_group_12);
@@ -1191,7 +1206,7 @@ void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
 	struct nvm_dev *ndev = ns->ndev;
 	struct nvm_geo *dev_geo = &ndev->geo;
 
-	switch (dev_geo->ver_id) {
+	switch (dev_geo->major_ver_id) {
 	case 1:
 		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
 					&nvm_dev_attr_group_12);
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 42704c4ca9af..ccaf8a30202d 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -309,7 +309,8 @@ struct nvm_common_geo {
 /* 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.7.4

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

* [PATCH 03/19] lightnvm: add minor version to generic geometry
@ 2018-02-26 13:17   ` Javier González
  0 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)


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 at cnexlabs.com>
---
 drivers/lightnvm/core.c      |  4 ++--
 drivers/nvme/host/lightnvm.c | 25 ++++++++++++++++++++-----
 include/linux/lightnvm.h     |  3 ++-
 3 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 43e3d6bb5be6..96f4e62d383b 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -897,8 +897,8 @@ static int nvm_init(struct nvm_dev *dev)
 		goto err;
 	}
 
-	pr_debug("nvm: ver:%u nvm_vendor:%x\n",
-				dev_geo->ver_id,
+	pr_debug("nvm: ver:%u.%u nvm_vendor:%x\n",
+				dev_geo->major_ver_id, dev_geo->minor_ver_id,
 				dev_geo->c.vmnt);
 
 	ret = nvm_core_init(dev);
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 10392a664b50..8befb60eeacb 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;
 	}
 
-	dev_geo->ver_id = id->ver_id;
+	/* 1.2 spec. only reports a single version id - unfold */
+	dev_geo->major_ver_id = id->ver_id;
+	dev_geo->minor_ver_id = 2;
 
 	dev_geo->nr_chnls = src->num_ch;
 	dev_geo->nr_luns = src->num_lun;
@@ -380,7 +382,14 @@ static void nvme_nvm_set_addr_20(struct nvm_addr_format *dst,
 static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 			     struct nvm_geo *dev_geo)
 {
-	dev_geo->ver_id = id->mjr;
+	dev_geo->major_ver_id = id->mjr;
+	dev_geo->minor_ver_id = id->mnr;
+
+	if (!(dev_geo->major_ver_id == 2 && dev_geo->minor_ver_id == 0)) {
+		pr_err("nvm: OCSSD version not supported (v%d.%d)\n",
+				dev_geo->major_ver_id, dev_geo->minor_ver_id);
+		return -EINVAL;
+	}
 
 	dev_geo->nr_chnls = le16_to_cpu(id->num_grp);
 	dev_geo->nr_luns = le16_to_cpu(id->num_pu);
@@ -920,7 +929,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", dev_geo->ver_id);
+		if (dev_geo->major_ver_id == 1)
+			return scnprintf(page, PAGE_SIZE, "%u\n",
+						dev_geo->major_ver_id);
+		else
+			return scnprintf(page, PAGE_SIZE, "%u.%u\n",
+						dev_geo->major_ver_id,
+						dev_geo->minor_ver_id);
 	} else if (strcmp(attr->name, "capabilities") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.cap);
 	} else if (strcmp(attr->name, "read_typ") == 0) {
@@ -1174,7 +1189,7 @@ int nvme_nvm_register_sysfs(struct nvme_ns *ns)
 	if (!ndev)
 		return -EINVAL;
 
-	switch (dev_geo->ver_id) {
+	switch (dev_geo->major_ver_id) {
 	case 1:
 		return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
 					&nvm_dev_attr_group_12);
@@ -1191,7 +1206,7 @@ void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
 	struct nvm_dev *ndev = ns->ndev;
 	struct nvm_geo *dev_geo = &ndev->geo;
 
-	switch (dev_geo->ver_id) {
+	switch (dev_geo->major_ver_id) {
 	case 1:
 		sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
 					&nvm_dev_attr_group_12);
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 42704c4ca9af..ccaf8a30202d 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -309,7 +309,8 @@ struct nvm_common_geo {
 /* 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.7.4

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

* [PATCH 04/19] lightnvm: add shorten OCSSD version in geo
  2018-02-26 13:16 ` Javier González
  (?)
@ 2018-02-26 13:17   ` Javier González
  -1 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)
  To: mb; +Cc: linux-block, Javier González, linux-kernel, linux-nvme

Q3JlYXRlIGEgc2hvcnRlbiB2ZXJzaW9uIHRvIHVzZSBpbiB0aGUgZ2VuZXJpYyBnZW9tZXRyeS4K
ClNpZ25lZC1vZmYtYnk6IEphdmllciBHb256w6FsZXogPGphdmllckBjbmV4bGFicy5jb20+Ci0t
LQogZHJpdmVycy9udm1lL2hvc3QvbGlnaHRudm0uYyB8IDYgKysrKysrCiBpbmNsdWRlL2xpbnV4
L2xpZ2h0bnZtLmggICAgIHwgOCArKysrKysrKwogMiBmaWxlcyBjaGFuZ2VkLCAxNCBpbnNlcnRp
b25zKCspCgpkaWZmIC0tZ2l0IGEvZHJpdmVycy9udm1lL2hvc3QvbGlnaHRudm0uYyBiL2RyaXZl
cnMvbnZtZS9ob3N0L2xpZ2h0bnZtLmMKaW5kZXggOGJlZmI2MGVlYWNiLi5hNDg5NTBhMzdiOGQg
MTAwNjQ0Ci0tLSBhL2RyaXZlcnMvbnZtZS9ob3N0L2xpZ2h0bnZtLmMKKysrIGIvZHJpdmVycy9u
dm1lL2hvc3QvbGlnaHRudm0uYwpAQCAtMjk5LDYgKzI5OSw5IEBAIHN0YXRpYyBpbnQgbnZtZV9u
dm1fc2V0dXBfMTIoc3RydWN0IG52bWVfbnZtX2lkMTIgKmlkLAogCWRldl9nZW8tPm1ham9yX3Zl
cl9pZCA9IGlkLT52ZXJfaWQ7CiAJZGV2X2dlby0+bWlub3JfdmVyX2lkID0gMjsKIAorCS8qIFNl
dCBjb21wYWN0ZWQgdmVyc2lvbiBmb3IgdXBwZXIgbGF5ZXJzICovCisJZGV2X2dlby0+Yy52ZXJz
aW9uID0gTlZNX09DU1NEX1NQRUNfMTI7CisKIAlkZXZfZ2VvLT5ucl9jaG5scyA9IHNyYy0+bnVt
X2NoOwogCWRldl9nZW8tPm5yX2x1bnMgPSBzcmMtPm51bV9sdW47CiAJZGV2X2dlby0+YWxsX2x1
bnMgPSBkZXZfZ2VvLT5ucl9jaG5scyAqIGRldl9nZW8tPm5yX2x1bnM7CkBAIC0zODUsNiArMzg4
LDkgQEAgc3RhdGljIGludCBudm1lX252bV9zZXR1cF8yMChzdHJ1Y3QgbnZtZV9udm1faWQyMCAq
aWQsCiAJZGV2X2dlby0+bWFqb3JfdmVyX2lkID0gaWQtPm1qcjsKIAlkZXZfZ2VvLT5taW5vcl92
ZXJfaWQgPSBpZC0+bW5yOwogCisJLyogU2V0IGNvbXBhY3RlZCB2ZXJzaW9uIGZvciB1cHBlciBs
YXllcnMgKi8KKwlkZXZfZ2VvLT5jLnZlcnNpb24gPSBOVk1fT0NTU0RfU1BFQ18yMDsKKwogCWlm
ICghKGRldl9nZW8tPm1ham9yX3Zlcl9pZCA9PSAyICYmIGRldl9nZW8tPm1pbm9yX3Zlcl9pZCA9
PSAwKSkgewogCQlwcl9lcnIoIm52bTogT0NTU0QgdmVyc2lvbiBub3Qgc3VwcG9ydGVkICh2JWQu
JWQpXG4iLAogCQkJCWRldl9nZW8tPm1ham9yX3Zlcl9pZCwgZGV2X2dlby0+bWlub3JfdmVyX2lk
KTsKZGlmZiAtLWdpdCBhL2luY2x1ZGUvbGludXgvbGlnaHRudm0uaCBiL2luY2x1ZGUvbGludXgv
bGlnaHRudm0uaAppbmRleCBjY2FmOGEzMDIwMmQuLjU3ZDAwNjQ0YTFjNiAxMDA2NDQKLS0tIGEv
aW5jbHVkZS9saW51eC9saWdodG52bS5oCisrKyBiL2luY2x1ZGUvbGludXgvbGlnaHRudm0uaApA
QCAtMjMsNiArMjMsMTEgQEAgZW51bSB7CiAjZGVmaW5lIE5WTV9MVU5fQklUUyAoOCkKICNkZWZp
bmUgTlZNX0NIX0JJVFMgICg3KQogCitlbnVtIHsKKwlOVk1fT0NTU0RfU1BFQ18xMiA9IDEyLAor
CU5WTV9PQ1NTRF9TUEVDXzIwID0gMjAsCit9OworCiBzdHJ1Y3QgcHBhX2FkZHIgewogCS8qIEdl
bmVyaWMgc3RydWN0dXJlIGZvciBhbGwgYWRkcmVzc2VzICovCiAJdW5pb24gewpAQCAtMjYyLDYg
KzI2Nyw5IEBAIGVudW0gewogCiAvKiBEZXZpY2UgY29tbW9uIGdlb21ldHJ5ICovCiBzdHJ1Y3Qg
bnZtX2NvbW1vbl9nZW8geworCS8qIGtlcm5lbCBzaG9ydCB2ZXJzaW9uICovCisJdTgJdmVyc2lv
bjsKKwogCS8qIGNodW5rIGdlb21ldHJ5ICovCiAJdTMyCW51bV9jaGs7CS8qIGNodW5rcyBwZXIg
bHVuICovCiAJdTMyCWNsYmE7CQkvKiBzZWN0b3JzIHBlciBjaHVuayAqLwotLSAKMi43LjQKCgpf
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpMaW51eC1udm1l
IG1haWxpbmcgbGlzdApMaW51eC1udm1lQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3Rz
LmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1udm1lCg==

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

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

Create a shorten version to use in the generic geometry.

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

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 8befb60eeacb..a48950a37b8d 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -299,6 +299,9 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
 	dev_geo->major_ver_id = id->ver_id;
 	dev_geo->minor_ver_id = 2;
 
+	/* Set compacted version for upper layers */
+	dev_geo->c.version = NVM_OCSSD_SPEC_12;
+
 	dev_geo->nr_chnls = src->num_ch;
 	dev_geo->nr_luns = src->num_lun;
 	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
@@ -385,6 +388,9 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 	dev_geo->major_ver_id = id->mjr;
 	dev_geo->minor_ver_id = id->mnr;
 
+	/* Set compacted version for upper layers */
+	dev_geo->c.version = NVM_OCSSD_SPEC_20;
+
 	if (!(dev_geo->major_ver_id == 2 && dev_geo->minor_ver_id == 0)) {
 		pr_err("nvm: OCSSD version not supported (v%d.%d)\n",
 				dev_geo->major_ver_id, dev_geo->minor_ver_id);
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index ccaf8a30202d..57d00644a1c6 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 {
@@ -262,6 +267,9 @@ enum {
 
 /* Device common geometry */
 struct nvm_common_geo {
+	/* kernel short version */
+	u8	version;
+
 	/* chunk geometry */
 	u32	num_chk;	/* chunks per lun */
 	u32	clba;		/* sectors per chunk */
-- 
2.7.4

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

* [PATCH 04/19] lightnvm: add shorten OCSSD version in geo
@ 2018-02-26 13:17   ` Javier González
  0 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)


Create a shorten version to use in the generic geometry.

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

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 8befb60eeacb..a48950a37b8d 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -299,6 +299,9 @@ static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
 	dev_geo->major_ver_id = id->ver_id;
 	dev_geo->minor_ver_id = 2;
 
+	/* Set compacted version for upper layers */
+	dev_geo->c.version = NVM_OCSSD_SPEC_12;
+
 	dev_geo->nr_chnls = src->num_ch;
 	dev_geo->nr_luns = src->num_lun;
 	dev_geo->all_luns = dev_geo->nr_chnls * dev_geo->nr_luns;
@@ -385,6 +388,9 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 	dev_geo->major_ver_id = id->mjr;
 	dev_geo->minor_ver_id = id->mnr;
 
+	/* Set compacted version for upper layers */
+	dev_geo->c.version = NVM_OCSSD_SPEC_20;
+
 	if (!(dev_geo->major_ver_id == 2 && dev_geo->minor_ver_id == 0)) {
 		pr_err("nvm: OCSSD version not supported (v%d.%d)\n",
 				dev_geo->major_ver_id, dev_geo->minor_ver_id);
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index ccaf8a30202d..57d00644a1c6 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 {
@@ -262,6 +267,9 @@ enum {
 
 /* Device common geometry */
 struct nvm_common_geo {
+	/* kernel short version */
+	u8	version;
+
 	/* chunk geometry */
 	u32	num_chk;	/* chunks per lun */
 	u32	clba;		/* sectors per chunk */
-- 
2.7.4

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

* [PATCH 05/19] lightnvm: complete geo structure with maxoc*
  2018-02-26 13:16 ` Javier González
  (?)
@ 2018-02-26 13:17   ` Javier González
  -1 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)
  To: mb; +Cc: linux-block, Javier González, linux-kernel, linux-nvme

Q29tcGxldGUgdGhlIGdlbmVyaWMgZ2VvbWV0cnkgc3RydWN0dXJlIHdpdGggdGhlIG1heG9jIGFu
ZCBtYXhvY3B1CmZlbGRzLCBwcmVzZW50IGluIHRoZSAyLjAgc3BlYy4KClNpZ25lZC1vZmYtYnk6
IEphdmllciBHb256w6FsZXogPGphdmllckBjbmV4bGFicy5jb20+Ci0tLQogZHJpdmVycy9udm1l
L2hvc3QvbGlnaHRudm0uYyB8IDkgKysrKysrKysrCiBpbmNsdWRlL2xpbnV4L2xpZ2h0bnZtLmgg
ICAgIHwgMiArKwogMiBmaWxlcyBjaGFuZ2VkLCAxMSBpbnNlcnRpb25zKCspCgpkaWZmIC0tZ2l0
IGEvZHJpdmVycy9udm1lL2hvc3QvbGlnaHRudm0uYyBiL2RyaXZlcnMvbnZtZS9ob3N0L2xpZ2h0
bnZtLmMKaW5kZXggYTQ4OTUwYTM3YjhkLi5hOGYzNWU4Yjc5NTMgMTAwNjQ0Ci0tLSBhL2RyaXZl
cnMvbnZtZS9ob3N0L2xpZ2h0bnZtLmMKKysrIGIvZHJpdmVycy9udm1lL2hvc3QvbGlnaHRudm0u
YwpAQCAtMzIzLDYgKzMyMywxMyBAQCBzdGF0aWMgaW50IG52bWVfbnZtX3NldHVwXzEyKHN0cnVj
dCBudm1lX252bV9pZDEyICppZCwKIAlkZXZfZ2VvLT5jLndzX29wdCA9IHNlY19wZXJfcGc7CiAJ
ZGV2X2dlby0+Yy5td19jdW5pdHMgPSA4OwkJLyogZGVmYXVsdCB0byBNTEMgc2FmZSB2YWx1ZXMg
Ki8KIAorCS8qIERvIG5vdCBpbXBvc2UgdmFsdWVzIGZvciBtYXhpbXVtIG51bWJlciBvZiBvcGVu
IGJsb2NrcyBhcyBpdCBpcworCSAqIHVuc3BlY2lmaWVkIGluIDEuMi4gVXNlcnMgb2YgMS4yIG11
c3QgYmUgYXdhcmUgb2YgdGhpcyBhbmQgZXZlbnR1YWxseQorCSAqIHNwZWNpZnkgdGhlc2UgdmFs
dWVzIHRocm91Z2ggYSBxdWlyayBpZiByZXN0cmljdGlvbnMgYXBwbHkuCisJICovCisJZGV2X2dl
by0+Yy5tYXhvYyA9IGRldl9nZW8tPmFsbF9sdW5zICogZGV2X2dlby0+Yy5udW1fY2hrOworCWRl
dl9nZW8tPmMubWF4b2NwdSA9IGRldl9nZW8tPmMubnVtX2NoazsKKwogCWRldl9nZW8tPmMuY2Fw
ID0gbGUzMl90b19jcHUoc3JjLT5tY2NhcCk7CiAKIAlkZXZfZ2VvLT5jLnRyZHQgPSBsZTMyX3Rv
X2NwdShzcmMtPnRyZHQpOwpAQCAtNDEzLDYgKzQyMCw4IEBAIHN0YXRpYyBpbnQgbnZtZV9udm1f
c2V0dXBfMjAoc3RydWN0IG52bWVfbnZtX2lkMjAgKmlkLAogCWRldl9nZW8tPmMud3NfbWluID0g
bGUzMl90b19jcHUoaWQtPndzX21pbik7CiAJZGV2X2dlby0+Yy53c19vcHQgPSBsZTMyX3RvX2Nw
dShpZC0+d3Nfb3B0KTsKIAlkZXZfZ2VvLT5jLm13X2N1bml0cyA9IGxlMzJfdG9fY3B1KGlkLT5t
d19jdW5pdHMpOworCWRldl9nZW8tPmMubWF4b2MgPSBsZTMyX3RvX2NwdShpZC0+bWF4b2MpOwor
CWRldl9nZW8tPmMubWF4b2NwdSA9IGxlMzJfdG9fY3B1KGlkLT5tYXhvY3B1KTsKIAogCWRldl9n
ZW8tPmMuY2FwID0gbGUzMl90b19jcHUoaWQtPm1jY2FwKTsKIApkaWZmIC0tZ2l0IGEvaW5jbHVk
ZS9saW51eC9saWdodG52bS5oIGIvaW5jbHVkZS9saW51eC9saWdodG52bS5oCmluZGV4IDU3ZDAw
NjQ0YTFjNi4uZThlNmJmZDRkMGQ0IDEwMDY0NAotLS0gYS9pbmNsdWRlL2xpbnV4L2xpZ2h0bnZt
LmgKKysrIGIvaW5jbHVkZS9saW51eC9saWdodG52bS5oCkBAIC0yODAsNiArMjgwLDggQEAgc3Ry
dWN0IG52bV9jb21tb25fZ2VvIHsKIAl1MzIJd3NfbWluOwkJLyogbWluaW11bSB3cml0ZSBzaXpl
ICovCiAJdTMyCXdzX29wdDsJCS8qIG9wdGltYWwgd3JpdGUgc2l6ZSAqLwogCXUzMgltd19jdW5p
dHM7CS8qIGRpc3RhbmNlIHJlcXVpcmVkIGZvciBzdWNjZXNzZnVsIHJlYWQgKi8KKwl1MzIJbWF4
b2M7CQkvKiBtYXhpbXVtIG9wZW4gY2h1bmtzICovCisJdTMyCW1heG9jcHU7CS8qIG1heGltdW0g
b3BlbiBjaHVua3MgcGVyIHBhcmFsbGVsIHVuaXQgKi8KIAogCS8qIGRldmljZSBjYXBhYmlsaXRp
ZXMuIE5vdGUgdGhhdCB0aGlzIHJlcHJlc2VudHMgY2FwYWJpbGl0aWVzIGluIDEuMgogCSAqIGFu
ZCBtZWRpYSBhbmQgY29udHJvbGxlciBjYXBhYmlsaXRpZXMgaW4gMi4wCi0tIAoyLjcuNAoKCl9f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCkxpbnV4LW52bWUg
bWFpbGluZyBsaXN0CkxpbnV4LW52bWVAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMu
aW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LW52bWUK

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

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

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

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

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index a48950a37b8d..a8f35e8b7953 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,
 	dev_geo->c.ws_opt = sec_per_pg;
 	dev_geo->c.mw_cunits = 8;		/* 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.
+	 */
+	dev_geo->c.maxoc = dev_geo->all_luns * dev_geo->c.num_chk;
+	dev_geo->c.maxocpu = dev_geo->c.num_chk;
+
 	dev_geo->c.cap = le32_to_cpu(src->mccap);
 
 	dev_geo->c.trdt = le32_to_cpu(src->trdt);
@@ -413,6 +420,8 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 	dev_geo->c.ws_min = le32_to_cpu(id->ws_min);
 	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
 	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
+	dev_geo->c.maxoc = le32_to_cpu(id->maxoc);
+	dev_geo->c.maxocpu = le32_to_cpu(id->maxocpu);
 
 	dev_geo->c.cap = le32_to_cpu(id->mccap);
 
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 57d00644a1c6..e8e6bfd4d0d4 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -280,6 +280,8 @@ struct nvm_common_geo {
 	u32	ws_min;		/* minimum write size */
 	u32	ws_opt;		/* optimal write size */
 	u32	mw_cunits;	/* distance required for successful read */
+	u32	maxoc;		/* maximum open chunks */
+	u32	maxocpu;	/* maximum open chunks per parallel unit */
 
 	/* device capabilities. Note that this represents capabilities in 1.2
 	 * and media and controller capabilities in 2.0
-- 
2.7.4

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

* [PATCH 05/19] lightnvm: complete geo structure with maxoc*
@ 2018-02-26 13:17   ` Javier González
  0 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)


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

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

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index a48950a37b8d..a8f35e8b7953 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,
 	dev_geo->c.ws_opt = sec_per_pg;
 	dev_geo->c.mw_cunits = 8;		/* 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.
+	 */
+	dev_geo->c.maxoc = dev_geo->all_luns * dev_geo->c.num_chk;
+	dev_geo->c.maxocpu = dev_geo->c.num_chk;
+
 	dev_geo->c.cap = le32_to_cpu(src->mccap);
 
 	dev_geo->c.trdt = le32_to_cpu(src->trdt);
@@ -413,6 +420,8 @@ static int nvme_nvm_setup_20(struct nvme_nvm_id20 *id,
 	dev_geo->c.ws_min = le32_to_cpu(id->ws_min);
 	dev_geo->c.ws_opt = le32_to_cpu(id->ws_opt);
 	dev_geo->c.mw_cunits = le32_to_cpu(id->mw_cunits);
+	dev_geo->c.maxoc = le32_to_cpu(id->maxoc);
+	dev_geo->c.maxocpu = le32_to_cpu(id->maxocpu);
 
 	dev_geo->c.cap = le32_to_cpu(id->mccap);
 
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 57d00644a1c6..e8e6bfd4d0d4 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -280,6 +280,8 @@ struct nvm_common_geo {
 	u32	ws_min;		/* minimum write size */
 	u32	ws_opt;		/* optimal write size */
 	u32	mw_cunits;	/* distance required for successful read */
+	u32	maxoc;		/* maximum open chunks */
+	u32	maxocpu;	/* maximum open chunks per parallel unit */
 
 	/* device capabilities. Note that this represents capabilities in 1.2
 	 * and media and controller capabilities in 2.0
-- 
2.7.4

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

* [PATCH 06/19] lightnvm: pblk: check for supported version
  2018-02-26 13:16 ` Javier González
  (?)
@ 2018-02-26 13:17   ` Javier González
  -1 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)
  To: mb; +Cc: linux-block, Javier González, linux-kernel, linux-nvme

QXQgdGhpcyBwb2ludCwgb25seSAxLjIgc3BlYyBpcyBzdXBwb3J0ZWQsIHRodXMgY2hlY2sgZm9y
IGl0LiBBbHNvLApzaW5jZSBkZXZpY2Utc2lkZSBMMlAgaXMgb25seSBzdXBwb3J0ZWQgaW4gdGhl
IDEuMiBzcGVjLCBtYWtlIHN1cmUgdG8Kb25seSBjaGVjayBpdHMgdmFsdWUgdW5kZXIgMS4yLgoK
U2lnbmVkLW9mZi1ieTogSmF2aWVyIEdvbnrDoWxleiA8amF2aWVyQGNuZXhsYWJzLmNvbT4KLS0t
CiBkcml2ZXJzL2xpZ2h0bnZtL3BibGstaW5pdC5jIHwgMTAgKysrKysrKystLQogMSBmaWxlIGNo
YW5nZWQsIDggaW5zZXJ0aW9ucygrKSwgMiBkZWxldGlvbnMoLSkKCmRpZmYgLS1naXQgYS9kcml2
ZXJzL2xpZ2h0bnZtL3BibGstaW5pdC5jIGIvZHJpdmVycy9saWdodG52bS9wYmxrLWluaXQuYwpp
bmRleCA5NWVjYjBlYzczNmIuLjZlMDU2Nzk3MWNmNiAxMDA2NDQKLS0tIGEvZHJpdmVycy9saWdo
dG52bS9wYmxrLWluaXQuYworKysgYi9kcml2ZXJzL2xpZ2h0bnZtL3BibGstaW5pdC5jCkBAIC05
OTAsOSArOTkwLDE1IEBAIHN0YXRpYyB2b2lkICpwYmxrX2luaXQoc3RydWN0IG52bV90Z3RfZGV2
ICpkZXYsIHN0cnVjdCBnZW5kaXNrICp0ZGlzaywKIAlzdHJ1Y3QgcGJsayAqcGJsazsKIAlpbnQg
cmV0OwogCi0JaWYgKGRldi0+Z2VvLmMuZG9tICYgTlZNX1JTUF9MMlApIHsKKwlpZiAoZ2VvLT5j
LnZlcnNpb24gIT0gTlZNX09DU1NEX1NQRUNfMTIpIHsKKwkJcHJfZXJyKCJwYmxrOiBPQ1NTRCB2
ZXJzaW9uIG5vdCBzdXBwb3J0ZWQgKCV1KVxuIiwKKwkJCQkJCQlnZW8tPmMudmVyc2lvbik7CisJ
CXJldHVybiBFUlJfUFRSKC1FSU5WQUwpOworCX0KKworCWlmIChnZW8tPmMudmVyc2lvbiA9PSBO
Vk1fT0NTU0RfU1BFQ18xMiAmJiBnZW8tPmMuZG9tICYgTlZNX1JTUF9MMlApIHsKIAkJcHJfZXJy
KCJwYmxrOiBob3N0LXNpZGUgTDJQIHRhYmxlIG5vdCBzdXBwb3J0ZWQuICgleClcbiIsCi0JCQkJ
CQkJZGV2LT5nZW8uYy5kb20pOworCQkJCQkJCWdlby0+Yy5kb20pOwogCQlyZXR1cm4gRVJSX1BU
UigtRUlOVkFMKTsKIAl9CiAKLS0gCjIuNy40CgoKX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX18KTGludXgtbnZtZSBtYWlsaW5nIGxpc3QKTGludXgtbnZtZUBs
aXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlz
dGluZm8vbGludXgtbnZtZQo=

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

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

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

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

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

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

* [PATCH 06/19] lightnvm: pblk: check for supported version
@ 2018-02-26 13:17   ` Javier González
  0 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)


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

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

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

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

* [PATCH 07/19] lightnvm: complete 2.0 values in sysfs
  2018-02-26 13:16 ` Javier González
  (?)
@ 2018-02-26 13:17   ` Javier González
  -1 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)
  To: mb; +Cc: linux-block, Javier González, linux-kernel, linux-nvme

QWRkIG1pc3NpbmcgZ2VvbWV0cnkgdmFsdWVzIHRvIHN5c2ZzLiBOYW1lbHksIG1heG9jIGFuZCBt
YXhvY3B1LgoKU2lnbmVkLW9mZi1ieTogSmF2aWVyIEdvbnrDoWxleiA8amF2aWVyQGNuZXhsYWJz
LmNvbT4KLS0tCiBkcml2ZXJzL252bWUvaG9zdC9saWdodG52bS5jIHwgOCArKysrKysrKwogMSBm
aWxlIGNoYW5nZWQsIDggaW5zZXJ0aW9ucygrKQoKZGlmZiAtLWdpdCBhL2RyaXZlcnMvbnZtZS9o
b3N0L2xpZ2h0bnZtLmMgYi9kcml2ZXJzL252bWUvaG9zdC9saWdodG52bS5jCmluZGV4IGE4ZjM1
ZThiNzk1My4uNGVhNTUzYzkxNzU2IDEwMDY0NAotLS0gYS9kcml2ZXJzL252bWUvaG9zdC9saWdo
dG52bS5jCisrKyBiL2RyaXZlcnMvbnZtZS9ob3N0L2xpZ2h0bnZtLmMKQEAgLTEwNjYsNiArMTA2
NiwxMCBAQCBzdGF0aWMgc3NpemVfdCBudm1fZGV2X2F0dHJfc2hvd18yMChzdHJ1Y3QgZGV2aWNl
ICpkZXYsCiAJCXJldHVybiBzY25wcmludGYocGFnZSwgUEFHRV9TSVpFLCAiJXVcbiIsIGRldl9n
ZW8tPmMud3NfbWluKTsKIAl9IGVsc2UgaWYgKHN0cmNtcChhdHRyLT5uYW1lLCAid3Nfb3B0Iikg
PT0gMCkgewogCQlyZXR1cm4gc2NucHJpbnRmKHBhZ2UsIFBBR0VfU0laRSwgIiV1XG4iLCBkZXZf
Z2VvLT5jLndzX29wdCk7CisJfSBlbHNlIGlmIChzdHJjbXAoYXR0ci0+bmFtZSwgIm1heG9jIikg
PT0gMCkgeworCQlyZXR1cm4gc2NucHJpbnRmKHBhZ2UsIFBBR0VfU0laRSwgIiV1XG4iLCBkZXZf
Z2VvLT5jLm1heG9jKTsKKwl9IGVsc2UgaWYgKHN0cmNtcChhdHRyLT5uYW1lLCAibWF4b2NwdSIp
ID09IDApIHsKKwkJcmV0dXJuIHNjbnByaW50ZihwYWdlLCBQQUdFX1NJWkUsICIldVxuIiwgZGV2
X2dlby0+Yy5tYXhvY3B1KTsKIAl9IGVsc2UgaWYgKHN0cmNtcChhdHRyLT5uYW1lLCAibXdfY3Vu
aXRzIikgPT0gMCkgewogCQlyZXR1cm4gc2NucHJpbnRmKHBhZ2UsIFBBR0VfU0laRSwgIiV1XG4i
LCBkZXZfZ2VvLT5jLm13X2N1bml0cyk7CiAJfSBlbHNlIGlmIChzdHJjbXAoYXR0ci0+bmFtZSwg
IndyaXRlX3R5cCIpID09IDApIHsKQEAgLTExNjMsNiArMTE2Nyw4IEBAIHN0YXRpYyBOVk1fREVW
X0FUVFJfMjBfUk8oY2h1bmtzKTsKIHN0YXRpYyBOVk1fREVWX0FUVFJfMjBfUk8oY2xiYSk7CiBz
dGF0aWMgTlZNX0RFVl9BVFRSXzIwX1JPKHdzX21pbik7CiBzdGF0aWMgTlZNX0RFVl9BVFRSXzIw
X1JPKHdzX29wdCk7CitzdGF0aWMgTlZNX0RFVl9BVFRSXzIwX1JPKG1heG9jKTsKK3N0YXRpYyBO
Vk1fREVWX0FUVFJfMjBfUk8obWF4b2NwdSk7CiBzdGF0aWMgTlZNX0RFVl9BVFRSXzIwX1JPKG13
X2N1bml0cyk7CiBzdGF0aWMgTlZNX0RFVl9BVFRSXzIwX1JPKHdyaXRlX3R5cCk7CiBzdGF0aWMg
TlZNX0RFVl9BVFRSXzIwX1JPKHdyaXRlX21heCk7CkBAIC0xMTc5LDYgKzExODUsOCBAQCBzdGF0
aWMgc3RydWN0IGF0dHJpYnV0ZSAqbnZtX2Rldl9hdHRyc18yMFtdID0gewogCSZkZXZfYXR0cl9j
bGJhLmF0dHIsCiAJJmRldl9hdHRyX3dzX21pbi5hdHRyLAogCSZkZXZfYXR0cl93c19vcHQuYXR0
ciwKKwkmZGV2X2F0dHJfbWF4b2MuYXR0ciwKKwkmZGV2X2F0dHJfbWF4b2NwdS5hdHRyLAogCSZk
ZXZfYXR0cl9td19jdW5pdHMuYXR0ciwKIAogCSZkZXZfYXR0cl9yZWFkX3R5cC5hdHRyLAotLSAK
Mi43LjQKCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpM
aW51eC1udm1lIG1haWxpbmcgbGlzdApMaW51eC1udm1lQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0
cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1udm1lCg==

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

* [PATCH 07/19] lightnvm: complete 2.0 values in sysfs
@ 2018-02-26 13:17   ` Javier González
  0 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

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

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

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index a8f35e8b7953..4ea553c91756 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -1066,6 +1066,10 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_min);
 	} else if (strcmp(attr->name, "ws_opt") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_opt);
+	} else if (strcmp(attr->name, "maxoc") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.maxoc);
+	} else if (strcmp(attr->name, "maxocpu") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.maxocpu);
 	} else if (strcmp(attr->name, "mw_cunits") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mw_cunits);
 	} else if (strcmp(attr->name, "write_typ") == 0) {
@@ -1163,6 +1167,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);
@@ -1179,6 +1185,8 @@ static struct attribute *nvm_dev_attrs_20[] = {
 	&dev_attr_clba.attr,
 	&dev_attr_ws_min.attr,
 	&dev_attr_ws_opt.attr,
+	&dev_attr_maxoc.attr,
+	&dev_attr_maxocpu.attr,
 	&dev_attr_mw_cunits.attr,
 
 	&dev_attr_read_typ.attr,
-- 
2.7.4

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

* [PATCH 07/19] lightnvm: complete 2.0 values in sysfs
@ 2018-02-26 13:17   ` Javier González
  0 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)


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

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

diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index a8f35e8b7953..4ea553c91756 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -1066,6 +1066,10 @@ static ssize_t nvm_dev_attr_show_20(struct device *dev,
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_min);
 	} else if (strcmp(attr->name, "ws_opt") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.ws_opt);
+	} else if (strcmp(attr->name, "maxoc") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.maxoc);
+	} else if (strcmp(attr->name, "maxocpu") == 0) {
+		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.maxocpu);
 	} else if (strcmp(attr->name, "mw_cunits") == 0) {
 		return scnprintf(page, PAGE_SIZE, "%u\n", dev_geo->c.mw_cunits);
 	} else if (strcmp(attr->name, "write_typ") == 0) {
@@ -1163,6 +1167,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);
@@ -1179,6 +1185,8 @@ static struct attribute *nvm_dev_attrs_20[] = {
 	&dev_attr_clba.attr,
 	&dev_attr_ws_min.attr,
 	&dev_attr_ws_opt.attr,
+	&dev_attr_maxoc.attr,
+	&dev_attr_maxocpu.attr,
 	&dev_attr_mw_cunits.attr,
 
 	&dev_attr_read_typ.attr,
-- 
2.7.4

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

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

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

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

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

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

* [PATCH 08/19] lightnvm: rename number of channels and luns
@ 2018-02-26 13:17   ` Javier González
  0 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)


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

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

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

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

* [PATCH 09/19] lightnvm: rename sect_* to sec_*
  2018-02-26 13:16 ` Javier González
  (?)
@ 2018-02-26 13:17   ` Javier González
  -1 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)
  To: mb; +Cc: linux-block, Javier González, linux-kernel, linux-nvme

UmVuYW1lIGFiYnJldmlhdGlvbnMgZm9yIHNlY3RvciBmcm9tIHNlY3RfKiB0byBzZWNfKiBhcyBt
b3N0IG9mIHRoZSBjb2RlCnVzZXMgdGhpcyBmb3JtYXQgYW5kIGl0IGlzIGNvbmZ1c2luZyB3aGVu
IHVzaW5nIHRoZSBkaWZmZXJlbnQKc3RydWN0dXJlcy4KClNpZ25lZC1vZmYtYnk6IEphdmllciBH
b256w6FsZXogPGphdmllckBjbmV4bGFicy5jb20+Ci0tLQogZHJpdmVycy9saWdodG52bS9wYmxr
LWluaXQuYyAgfCA4ICsrKystLS0tCiBkcml2ZXJzL2xpZ2h0bnZtL3BibGstc3lzZnMuYyB8IDQg
KystLQogZHJpdmVycy9saWdodG52bS9wYmxrLmggICAgICAgfCA4ICsrKystLS0tCiBkcml2ZXJz
L252bWUvaG9zdC9saWdodG52bS5jICB8IDggKysrKy0tLS0KIGluY2x1ZGUvbGludXgvbGlnaHRu
dm0uaCAgICAgIHwgOCArKysrLS0tLQogNSBmaWxlcyBjaGFuZ2VkLCAxOCBpbnNlcnRpb25zKCsp
LCAxOCBkZWxldGlvbnMoLSkKCmRpZmYgLS1naXQgYS9kcml2ZXJzL2xpZ2h0bnZtL3BibGstaW5p
dC5jIGIvZHJpdmVycy9saWdodG52bS9wYmxrLWluaXQuYwppbmRleCA3ZTMyOTdiZTUxN2QuLjMw
YWVjODYzZjEzNiAxMDA2NDQKLS0tIGEvZHJpdmVycy9saWdodG52bS9wYmxrLWluaXQuYworKysg
Yi9kcml2ZXJzL2xpZ2h0bnZtL3BibGstaW5pdC5jCkBAIC0xNzksMTYgKzE3OSwxNiBAQCBzdGF0
aWMgaW50IHBibGtfc2V0X2FkZHJmXzEyKHN0cnVjdCBudm1fZ2VvICpnZW8sCiAJZHN0LT5ibGtf
bGVuID0gc3JjLT5ibGtfbGVuOwogCWRzdC0+cGdfbGVuID0gc3JjLT5wZ19sZW47CiAJZHN0LT5w
bG5fbGVuID0gc3JjLT5wbG5fbGVuOwotCWRzdC0+c2VjdF9sZW4gPSBzcmMtPnNlY3RfbGVuOwor
CWRzdC0+c2VjX2xlbiA9IHNyYy0+c2VjX2xlbjsKIAotCWRzdC0+c2VjdF9vZmZzZXQgPSAwOwot
CWRzdC0+cGxuX29mZnNldCA9IGRzdC0+c2VjdF9sZW47CisJZHN0LT5zZWNfb2Zmc2V0ID0gMDsK
Kwlkc3QtPnBsbl9vZmZzZXQgPSBkc3QtPnNlY19sZW47CiAJZHN0LT5jaF9vZmZzZXQgPSBkc3Qt
PnBsbl9vZmZzZXQgKyBkc3QtPnBsbl9sZW47CiAJZHN0LT5sdW5fb2Zmc2V0ID0gZHN0LT5jaF9v
ZmZzZXQgKyBkc3QtPmNoX2xlbjsKIAlkc3QtPnBnX29mZnNldCA9IGRzdC0+bHVuX29mZnNldCAr
IGRzdC0+bHVuX2xlbjsKIAlkc3QtPmJsa19vZmZzZXQgPSBkc3QtPnBnX29mZnNldCArIGRzdC0+
cGdfbGVuOwogCi0JZHN0LT5zZWNfbWFzayA9ICgoMVVMTCA8PCBkc3QtPnNlY3RfbGVuKSAtIDEp
IDw8IGRzdC0+c2VjdF9vZmZzZXQ7CisJZHN0LT5zZWNfbWFzayA9ICgoMVVMTCA8PCBkc3QtPnNl
Y19sZW4pIC0gMSkgPDwgZHN0LT5zZWNfb2Zmc2V0OwogCWRzdC0+cGxuX21hc2sgPSAoKDFVTEwg
PDwgZHN0LT5wbG5fbGVuKSAtIDEpIDw8IGRzdC0+cGxuX29mZnNldDsKIAlkc3QtPmNoX21hc2sg
PSAoKDFVTEwgPDwgZHN0LT5jaF9sZW4pIC0gMSkgPDwgZHN0LT5jaF9vZmZzZXQ7CiAJZHN0LT5s
dW5fbWFzayA9ICgoMVVMTCA8PCBkc3QtPmx1bl9sZW4pIC0gMSkgPDwgZHN0LT5sdW5fb2Zmc2V0
OwpkaWZmIC0tZ2l0IGEvZHJpdmVycy9saWdodG52bS9wYmxrLXN5c2ZzLmMgYi9kcml2ZXJzL2xp
Z2h0bnZtL3BibGstc3lzZnMuYwppbmRleCA1ZWIyMWEyNzkzNjEuLjgxMjg4YWE5MTYyYSAxMDA2
NDQKLS0tIGEvZHJpdmVycy9saWdodG52bS9wYmxrLXN5c2ZzLmMKKysrIGIvZHJpdmVycy9saWdo
dG52bS9wYmxrLXN5c2ZzLmMKQEAgLTEyOCw3ICsxMjgsNyBAQCBzdGF0aWMgc3NpemVfdCBwYmxr
X3N5c2ZzX3BwYWYoc3RydWN0IHBibGsgKnBibGssIGNoYXIgKnBhZ2UpCiAJCQlwcGFmLT5ibGtf
b2Zmc2V0LCBwcGFmLT5ibGtfbGVuLAogCQkJcHBhZi0+cGdfb2Zmc2V0LCBwcGFmLT5wZ19sZW4s
CiAJCQlwcGFmLT5wbG5fb2Zmc2V0LCBwcGFmLT5wbG5fbGVuLAotCQkJcHBhZi0+c2VjdF9vZmZz
ZXQsIHBwYWYtPnNlY3RfbGVuKTsKKwkJCXBwYWYtPnNlY19vZmZzZXQsIHBwYWYtPnNlY19sZW4p
OwogCiAJc3ogKz0gc25wcmludGYocGFnZSArIHN6LCBQQUdFX1NJWkUgLSBzeiwKIAkJImRldmlj
ZTpjaDolZC8lZCxsdW46JWQvJWQsYmxrOiVkLyVkLHBnOiVkLyVkLHBsOiVkLyVkLHNlYzolZC8l
ZFxuIiwKQEAgLTEzNyw3ICsxMzcsNyBAQCBzdGF0aWMgc3NpemVfdCBwYmxrX3N5c2ZzX3BwYWYo
c3RydWN0IHBibGsgKnBibGssIGNoYXIgKnBhZ2UpCiAJCQlnZW9fcHBhZi0+YmxrX29mZnNldCwg
Z2VvX3BwYWYtPmJsa19sZW4sCiAJCQlnZW9fcHBhZi0+cGdfb2Zmc2V0LCBnZW9fcHBhZi0+cGdf
bGVuLAogCQkJZ2VvX3BwYWYtPnBsbl9vZmZzZXQsIGdlb19wcGFmLT5wbG5fbGVuLAotCQkJZ2Vv
X3BwYWYtPnNlY3Rfb2Zmc2V0LCBnZW9fcHBhZi0+c2VjdF9sZW4pOworCQkJZ2VvX3BwYWYtPnNl
Y19vZmZzZXQsIGdlb19wcGFmLT5zZWNfbGVuKTsKIAogCXJldHVybiBzejsKIH0KZGlmZiAtLWdp
dCBhL2RyaXZlcnMvbGlnaHRudm0vcGJsay5oIGIvZHJpdmVycy9saWdodG52bS9wYmxrLmgKaW5k
ZXggMWYzMjI4NGIwYWVjLi40ZjdhMzY1NDM2ZjEgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvbGlnaHRu
dm0vcGJsay5oCisrKyBiL2RyaXZlcnMvbGlnaHRudm0vcGJsay5oCkBAIC05NTcsNyArOTU3LDcg
QEAgc3RhdGljIGlubGluZSBzdHJ1Y3QgcHBhX2FkZHIgYWRkcl90b19nZW5fcHBhKHN0cnVjdCBw
YmxrICpwYmxrLCB1NjQgcGFkZHIsCiAJcHBhLmcubHVuID0gKHBhZGRyICYgcHBhZi0+bHVuX21h
c2spID4+IHBwYWYtPmx1bl9vZmZzZXQ7CiAJcHBhLmcuY2ggPSAocGFkZHIgJiBwcGFmLT5jaF9t
YXNrKSA+PiBwcGFmLT5jaF9vZmZzZXQ7CiAJcHBhLmcucGwgPSAocGFkZHIgJiBwcGFmLT5wbG5f
bWFzaykgPj4gcHBhZi0+cGxuX29mZnNldDsKLQlwcGEuZy5zZWMgPSAocGFkZHIgJiBwcGFmLT5z
ZWNfbWFzaykgPj4gcHBhZi0+c2VjdF9vZmZzZXQ7CisJcHBhLmcuc2VjID0gKHBhZGRyICYgcHBh
Zi0+c2VjX21hc2spID4+IHBwYWYtPnNlY19vZmZzZXQ7CiAKIAlyZXR1cm4gcHBhOwogfQpAQCAt
OTczLDcgKzk3Myw3IEBAIHN0YXRpYyBpbmxpbmUgdTY0IHBibGtfZGV2X3BwYV90b19saW5lX2Fk
ZHIoc3RydWN0IHBibGsgKnBibGssCiAJcGFkZHIgfD0gKHU2NClwLmcubHVuIDw8IHBwYWYtPmx1
bl9vZmZzZXQ7CiAJcGFkZHIgfD0gKHU2NClwLmcucGcgPDwgcHBhZi0+cGdfb2Zmc2V0OwogCXBh
ZGRyIHw9ICh1NjQpcC5nLnBsIDw8IHBwYWYtPnBsbl9vZmZzZXQ7Ci0JcGFkZHIgfD0gKHU2NClw
Lmcuc2VjIDw8IHBwYWYtPnNlY3Rfb2Zmc2V0OworCXBhZGRyIHw9ICh1NjQpcC5nLnNlYyA8PCBw
cGFmLT5zZWNfb2Zmc2V0OwogCiAJcmV0dXJuIHBhZGRyOwogfQpAQCAtOTk4LDcgKzk5OCw3IEBA
IHN0YXRpYyBpbmxpbmUgc3RydWN0IHBwYV9hZGRyIHBibGtfcHBhMzJfdG9fcHBhNjQoc3RydWN0
IHBibGsgKnBibGssIHUzMiBwcGEzMikKIAkJcHBhNjQuZy5ibGsgPSAocHBhMzIgJiBwcGFmLT5i
bGtfbWFzaykgPj4gcHBhZi0+YmxrX29mZnNldDsKIAkJcHBhNjQuZy5wZyA9IChwcGEzMiAmIHBw
YWYtPnBnX21hc2spID4+IHBwYWYtPnBnX29mZnNldDsKIAkJcHBhNjQuZy5wbCA9IChwcGEzMiAm
IHBwYWYtPnBsbl9tYXNrKSA+PiBwcGFmLT5wbG5fb2Zmc2V0OwotCQlwcGE2NC5nLnNlYyA9IChw
cGEzMiAmIHBwYWYtPnNlY19tYXNrKSA+PiBwcGFmLT5zZWN0X29mZnNldDsKKwkJcHBhNjQuZy5z
ZWMgPSAocHBhMzIgJiBwcGFmLT5zZWNfbWFzaykgPj4gcHBhZi0+c2VjX29mZnNldDsKIAl9CiAK
IAlyZXR1cm4gcHBhNjQ7CkBAIC0xMDIyLDcgKzEwMjIsNyBAQCBzdGF0aWMgaW5saW5lIHUzMiBw
YmxrX3BwYTY0X3RvX3BwYTMyKHN0cnVjdCBwYmxrICpwYmxrLCBzdHJ1Y3QgcHBhX2FkZHIgcHBh
NjQpCiAJCXBwYTMyIHw9IHBwYTY0LmcuYmxrIDw8IHBwYWYtPmJsa19vZmZzZXQ7CiAJCXBwYTMy
IHw9IHBwYTY0LmcucGcgPDwgcHBhZi0+cGdfb2Zmc2V0OwogCQlwcGEzMiB8PSBwcGE2NC5nLnBs
IDw8IHBwYWYtPnBsbl9vZmZzZXQ7Ci0JCXBwYTMyIHw9IHBwYTY0Lmcuc2VjIDw8IHBwYWYtPnNl
Y3Rfb2Zmc2V0OworCQlwcGEzMiB8PSBwcGE2NC5nLnNlYyA8PCBwcGFmLT5zZWNfb2Zmc2V0Owog
CX0KIAogCXJldHVybiBwcGEzMjsKZGlmZiAtLWdpdCBhL2RyaXZlcnMvbnZtZS9ob3N0L2xpZ2h0
bnZtLmMgYi9kcml2ZXJzL252bWUvaG9zdC9saWdodG52bS5jCmluZGV4IGYzZjUyNGRjMTM4OS4u
Mzc3ZTY1MjVlNTNmIDEwMDY0NAotLS0gYS9kcml2ZXJzL252bWUvaG9zdC9saWdodG52bS5jCisr
KyBiL2RyaXZlcnMvbnZtZS9ob3N0L2xpZ2h0bnZtLmMKQEAgLTI2MiwyMSArMjYyLDIxIEBAIHN0
YXRpYyB2b2lkIG52bWVfbnZtX3NldF9hZGRyXzEyKHN0cnVjdCBudm1fYWRkcl9mb3JtYXRfMTIg
KmRzdCwKIAlkc3QtPmJsa19sZW4gPSBzcmMtPmJsa19sZW47CiAJZHN0LT5wZ19sZW4gPSBzcmMt
PnBnX2xlbjsKIAlkc3QtPnBsbl9sZW4gPSBzcmMtPnBsbl9sZW47Ci0JZHN0LT5zZWN0X2xlbiA9
IHNyYy0+c2VjX2xlbjsKKwlkc3QtPnNlY19sZW4gPSBzcmMtPnNlY19sZW47CiAKIAlkc3QtPmNo
X29mZnNldCA9IHNyYy0+Y2hfb2Zmc2V0OwogCWRzdC0+bHVuX29mZnNldCA9IHNyYy0+bHVuX29m
ZnNldDsKIAlkc3QtPmJsa19vZmZzZXQgPSBzcmMtPmJsa19vZmZzZXQ7CiAJZHN0LT5wZ19vZmZz
ZXQgPSBzcmMtPnBnX29mZnNldDsKIAlkc3QtPnBsbl9vZmZzZXQgPSBzcmMtPnBsbl9vZmZzZXQ7
Ci0JZHN0LT5zZWN0X29mZnNldCA9IHNyYy0+c2VjX29mZnNldDsKKwlkc3QtPnNlY19vZmZzZXQg
PSBzcmMtPnNlY19vZmZzZXQ7CiAKIAlkc3QtPmNoX21hc2sgPSAoKDFVTEwgPDwgZHN0LT5jaF9s
ZW4pIC0gMSkgPDwgZHN0LT5jaF9vZmZzZXQ7CiAJZHN0LT5sdW5fbWFzayA9ICgoMVVMTCA8PCBk
c3QtPmx1bl9sZW4pIC0gMSkgPDwgZHN0LT5sdW5fb2Zmc2V0OwogCWRzdC0+YmxrX21hc2sgPSAo
KDFVTEwgPDwgZHN0LT5ibGtfbGVuKSAtIDEpIDw8IGRzdC0+YmxrX29mZnNldDsKIAlkc3QtPnBn
X21hc2sgPSAoKDFVTEwgPDwgZHN0LT5wZ19sZW4pIC0gMSkgPDwgZHN0LT5wZ19vZmZzZXQ7CiAJ
ZHN0LT5wbG5fbWFzayA9ICgoMVVMTCA8PCBkc3QtPnBsbl9sZW4pIC0gMSkgPDwgZHN0LT5wbG5f
b2Zmc2V0OwotCWRzdC0+c2VjX21hc2sgPSAoKDFVTEwgPDwgZHN0LT5zZWN0X2xlbikgLSAxKSA8
PCBkc3QtPnNlY3Rfb2Zmc2V0OworCWRzdC0+c2VjX21hc2sgPSAoKDFVTEwgPDwgZHN0LT5zZWNf
bGVuKSAtIDEpIDw8IGRzdC0+c2VjX29mZnNldDsKIH0KIAogc3RhdGljIGludCBudm1lX252bV9z
ZXR1cF8xMihzdHJ1Y3QgbnZtZV9udm1faWQxMiAqaWQsCkBAIC05NzUsNyArOTc1LDcgQEAgc3Rh
dGljIHNzaXplX3QgbnZtX2Rldl9hdHRyX3Nob3dfcHBhZihzdHJ1Y3QgbnZtX2FkZHJfZm9ybWF0
XzEyICpwcGFmLAogCQkJCXBwYWYtPnBsbl9vZmZzZXQsIHBwYWYtPnBsbl9sZW4sCiAJCQkJcHBh
Zi0+YmxrX29mZnNldCwgcHBhZi0+YmxrX2xlbiwKIAkJCQlwcGFmLT5wZ19vZmZzZXQsIHBwYWYt
PnBnX2xlbiwKLQkJCQlwcGFmLT5zZWN0X29mZnNldCwgcHBhZi0+c2VjdF9sZW4pOworCQkJCXBw
YWYtPnNlY19vZmZzZXQsIHBwYWYtPnNlY19sZW4pOwogfQogCiBzdGF0aWMgc3NpemVfdCBudm1f
ZGV2X2F0dHJfc2hvd18xMihzdHJ1Y3QgZGV2aWNlICpkZXYsCmRpZmYgLS1naXQgYS9pbmNsdWRl
L2xpbnV4L2xpZ2h0bnZtLmggYi9pbmNsdWRlL2xpbnV4L2xpZ2h0bnZtLmgKaW5kZXggNzk3NTk0
ZDY1MTlmLi4xOGJiOWU5Nzc0ZDYgMTAwNjQ0Ci0tLSBhL2luY2x1ZGUvbGludXgvbGlnaHRudm0u
aAorKysgYi9pbmNsdWRlL2xpbnV4L2xpZ2h0bnZtLmgKQEAgLTE2MywxNCArMTYzLDE0IEBAIHN0
cnVjdCBudm1fYWRkcl9mb3JtYXRfMTIgewogCXU4CWJsa19sZW47CiAJdTgJcGdfbGVuOwogCXU4
CXBsbl9sZW47Ci0JdTgJc2VjdF9sZW47CisJdTgJc2VjX2xlbjsKIAogCXU4CWNoX29mZnNldDsK
IAl1OAlsdW5fb2Zmc2V0OwogCXU4CWJsa19vZmZzZXQ7CiAJdTgJcGdfb2Zmc2V0OwogCXU4CXBs
bl9vZmZzZXQ7Ci0JdTgJc2VjdF9vZmZzZXQ7CisJdTgJc2VjX29mZnNldDsKIAogCXU2NAljaF9t
YXNrOwogCXU2NAlsdW5fbWFzazsKQEAgLTM5MSw3ICszOTEsNyBAQCBzdGF0aWMgaW5saW5lIHN0
cnVjdCBwcGFfYWRkciBnZW5lcmljX3RvX2Rldl9hZGRyKHN0cnVjdCBudm1fdGd0X2RldiAqdGd0
X2RldiwKIAlsLnBwYSB8PSAoKHU2NClyLmcuYmxrKSA8PCBwcGFmLT5ibGtfb2Zmc2V0OwogCWwu
cHBhIHw9ICgodTY0KXIuZy5wZykgPDwgcHBhZi0+cGdfb2Zmc2V0OwogCWwucHBhIHw9ICgodTY0
KXIuZy5wbCkgPDwgcHBhZi0+cGxuX29mZnNldDsKLQlsLnBwYSB8PSAoKHU2NClyLmcuc2VjKSA8
PCBwcGFmLT5zZWN0X29mZnNldDsKKwlsLnBwYSB8PSAoKHU2NClyLmcuc2VjKSA8PCBwcGFmLT5z
ZWNfb2Zmc2V0OwogCiAJcmV0dXJuIGw7CiB9CkBAIC00MTEsNyArNDExLDcgQEAgc3RhdGljIGlu
bGluZSBzdHJ1Y3QgcHBhX2FkZHIgZGV2X3RvX2dlbmVyaWNfYWRkcihzdHJ1Y3QgbnZtX3RndF9k
ZXYgKnRndF9kZXYsCiAJbC5nLmJsayA9IChyLnBwYSAmIHBwYWYtPmJsa19tYXNrKSA+PiBwcGFm
LT5ibGtfb2Zmc2V0OwogCWwuZy5wZyA9IChyLnBwYSAmIHBwYWYtPnBnX21hc2spID4+IHBwYWYt
PnBnX29mZnNldDsKIAlsLmcucGwgPSAoci5wcGEgJiBwcGFmLT5wbG5fbWFzaykgPj4gcHBhZi0+
cGxuX29mZnNldDsKLQlsLmcuc2VjID0gKHIucHBhICYgcHBhZi0+c2VjX21hc2spID4+IHBwYWYt
PnNlY3Rfb2Zmc2V0OworCWwuZy5zZWMgPSAoci5wcGEgJiBwcGFmLT5zZWNfbWFzaykgPj4gcHBh
Zi0+c2VjX29mZnNldDsKIAogCXJldHVybiBsOwogfQotLSAKMi43LjQKCgpfX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpMaW51eC1udm1lIG1haWxpbmcgbGlz
dApMaW51eC1udm1lQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5v
cmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1udm1lCg==

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

* [PATCH 09/19] lightnvm: rename sect_* to sec_*
@ 2018-02-26 13:17   ` Javier González
  0 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

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

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

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 7e3297be517d..30aec863f136 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -179,16 +179,16 @@ static int pblk_set_addrf_12(struct nvm_geo *geo,
 	dst->blk_len = src->blk_len;
 	dst->pg_len = src->pg_len;
 	dst->pln_len = src->pln_len;
-	dst->sect_len = src->sect_len;
+	dst->sec_len = src->sec_len;
 
-	dst->sect_offset = 0;
-	dst->pln_offset = dst->sect_len;
+	dst->sec_offset = 0;
+	dst->pln_offset = dst->sec_len;
 	dst->ch_offset = dst->pln_offset + dst->pln_len;
 	dst->lun_offset = dst->ch_offset + dst->ch_len;
 	dst->pg_offset = dst->lun_offset + dst->lun_len;
 	dst->blk_offset = dst->pg_offset + dst->pg_len;
 
-	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
+	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
 	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
 	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
 	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index 5eb21a279361..81288aa9162a 100644
--- a/drivers/lightnvm/pblk-sysfs.c
+++ b/drivers/lightnvm/pblk-sysfs.c
@@ -128,7 +128,7 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
 			ppaf->blk_offset, ppaf->blk_len,
 			ppaf->pg_offset, ppaf->pg_len,
 			ppaf->pln_offset, ppaf->pln_len,
-			ppaf->sect_offset, ppaf->sect_len);
+			ppaf->sec_offset, ppaf->sec_len);
 
 	sz += snprintf(page + sz, PAGE_SIZE - sz,
 		"device:ch:%d/%d,lun:%d/%d,blk:%d/%d,pg:%d/%d,pl:%d/%d,sec:%d/%d\n",
@@ -137,7 +137,7 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
 			geo_ppaf->blk_offset, geo_ppaf->blk_len,
 			geo_ppaf->pg_offset, geo_ppaf->pg_len,
 			geo_ppaf->pln_offset, geo_ppaf->pln_len,
-			geo_ppaf->sect_offset, geo_ppaf->sect_len);
+			geo_ppaf->sec_offset, geo_ppaf->sec_len);
 
 	return sz;
 }
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 1f32284b0aec..4f7a365436f1 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -957,7 +957,7 @@ static inline struct ppa_addr addr_to_gen_ppa(struct pblk *pblk, u64 paddr,
 	ppa.g.lun = (paddr & ppaf->lun_mask) >> ppaf->lun_offset;
 	ppa.g.ch = (paddr & ppaf->ch_mask) >> ppaf->ch_offset;
 	ppa.g.pl = (paddr & ppaf->pln_mask) >> ppaf->pln_offset;
-	ppa.g.sec = (paddr & ppaf->sec_mask) >> ppaf->sect_offset;
+	ppa.g.sec = (paddr & ppaf->sec_mask) >> ppaf->sec_offset;
 
 	return ppa;
 }
@@ -973,7 +973,7 @@ static inline u64 pblk_dev_ppa_to_line_addr(struct pblk *pblk,
 	paddr |= (u64)p.g.lun << ppaf->lun_offset;
 	paddr |= (u64)p.g.pg << ppaf->pg_offset;
 	paddr |= (u64)p.g.pl << ppaf->pln_offset;
-	paddr |= (u64)p.g.sec << ppaf->sect_offset;
+	paddr |= (u64)p.g.sec << ppaf->sec_offset;
 
 	return paddr;
 }
@@ -998,7 +998,7 @@ static inline struct ppa_addr pblk_ppa32_to_ppa64(struct pblk *pblk, u32 ppa32)
 		ppa64.g.blk = (ppa32 & ppaf->blk_mask) >> ppaf->blk_offset;
 		ppa64.g.pg = (ppa32 & ppaf->pg_mask) >> ppaf->pg_offset;
 		ppa64.g.pl = (ppa32 & ppaf->pln_mask) >> ppaf->pln_offset;
-		ppa64.g.sec = (ppa32 & ppaf->sec_mask) >> ppaf->sect_offset;
+		ppa64.g.sec = (ppa32 & ppaf->sec_mask) >> ppaf->sec_offset;
 	}
 
 	return ppa64;
@@ -1022,7 +1022,7 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
 		ppa32 |= ppa64.g.blk << ppaf->blk_offset;
 		ppa32 |= ppa64.g.pg << ppaf->pg_offset;
 		ppa32 |= ppa64.g.pl << ppaf->pln_offset;
-		ppa32 |= ppa64.g.sec << ppaf->sect_offset;
+		ppa32 |= ppa64.g.sec << ppaf->sec_offset;
 	}
 
 	return ppa32;
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index f3f524dc1389..377e6525e53f 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -262,21 +262,21 @@ static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
 	dst->blk_len = src->blk_len;
 	dst->pg_len = src->pg_len;
 	dst->pln_len = src->pln_len;
-	dst->sect_len = src->sec_len;
+	dst->sec_len = src->sec_len;
 
 	dst->ch_offset = src->ch_offset;
 	dst->lun_offset = src->lun_offset;
 	dst->blk_offset = src->blk_offset;
 	dst->pg_offset = src->pg_offset;
 	dst->pln_offset = src->pln_offset;
-	dst->sect_offset = src->sec_offset;
+	dst->sec_offset = src->sec_offset;
 
 	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
 	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
 	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
 	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
 	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
-	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
+	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
 }
 
 static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
@@ -975,7 +975,7 @@ static ssize_t nvm_dev_attr_show_ppaf(struct nvm_addr_format_12 *ppaf,
 				ppaf->pln_offset, ppaf->pln_len,
 				ppaf->blk_offset, ppaf->blk_len,
 				ppaf->pg_offset, ppaf->pg_len,
-				ppaf->sect_offset, ppaf->sect_len);
+				ppaf->sec_offset, ppaf->sec_len);
 }
 
 static ssize_t nvm_dev_attr_show_12(struct device *dev,
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 797594d6519f..18bb9e9774d6 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -163,14 +163,14 @@ struct nvm_addr_format_12 {
 	u8	blk_len;
 	u8	pg_len;
 	u8	pln_len;
-	u8	sect_len;
+	u8	sec_len;
 
 	u8	ch_offset;
 	u8	lun_offset;
 	u8	blk_offset;
 	u8	pg_offset;
 	u8	pln_offset;
-	u8	sect_offset;
+	u8	sec_offset;
 
 	u64	ch_mask;
 	u64	lun_mask;
@@ -391,7 +391,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;
 }
@@ -411,7 +411,7 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
 	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
 	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
 	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
-	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sect_offset;
+	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
 
 	return l;
 }
-- 
2.7.4

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

* [PATCH 09/19] lightnvm: rename sect_* to sec_*
@ 2018-02-26 13:17   ` Javier González
  0 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)


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

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

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 7e3297be517d..30aec863f136 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -179,16 +179,16 @@ static int pblk_set_addrf_12(struct nvm_geo *geo,
 	dst->blk_len = src->blk_len;
 	dst->pg_len = src->pg_len;
 	dst->pln_len = src->pln_len;
-	dst->sect_len = src->sect_len;
+	dst->sec_len = src->sec_len;
 
-	dst->sect_offset = 0;
-	dst->pln_offset = dst->sect_len;
+	dst->sec_offset = 0;
+	dst->pln_offset = dst->sec_len;
 	dst->ch_offset = dst->pln_offset + dst->pln_len;
 	dst->lun_offset = dst->ch_offset + dst->ch_len;
 	dst->pg_offset = dst->lun_offset + dst->lun_len;
 	dst->blk_offset = dst->pg_offset + dst->pg_len;
 
-	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
+	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
 	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
 	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
 	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index 5eb21a279361..81288aa9162a 100644
--- a/drivers/lightnvm/pblk-sysfs.c
+++ b/drivers/lightnvm/pblk-sysfs.c
@@ -128,7 +128,7 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
 			ppaf->blk_offset, ppaf->blk_len,
 			ppaf->pg_offset, ppaf->pg_len,
 			ppaf->pln_offset, ppaf->pln_len,
-			ppaf->sect_offset, ppaf->sect_len);
+			ppaf->sec_offset, ppaf->sec_len);
 
 	sz += snprintf(page + sz, PAGE_SIZE - sz,
 		"device:ch:%d/%d,lun:%d/%d,blk:%d/%d,pg:%d/%d,pl:%d/%d,sec:%d/%d\n",
@@ -137,7 +137,7 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
 			geo_ppaf->blk_offset, geo_ppaf->blk_len,
 			geo_ppaf->pg_offset, geo_ppaf->pg_len,
 			geo_ppaf->pln_offset, geo_ppaf->pln_len,
-			geo_ppaf->sect_offset, geo_ppaf->sect_len);
+			geo_ppaf->sec_offset, geo_ppaf->sec_len);
 
 	return sz;
 }
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 1f32284b0aec..4f7a365436f1 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -957,7 +957,7 @@ static inline struct ppa_addr addr_to_gen_ppa(struct pblk *pblk, u64 paddr,
 	ppa.g.lun = (paddr & ppaf->lun_mask) >> ppaf->lun_offset;
 	ppa.g.ch = (paddr & ppaf->ch_mask) >> ppaf->ch_offset;
 	ppa.g.pl = (paddr & ppaf->pln_mask) >> ppaf->pln_offset;
-	ppa.g.sec = (paddr & ppaf->sec_mask) >> ppaf->sect_offset;
+	ppa.g.sec = (paddr & ppaf->sec_mask) >> ppaf->sec_offset;
 
 	return ppa;
 }
@@ -973,7 +973,7 @@ static inline u64 pblk_dev_ppa_to_line_addr(struct pblk *pblk,
 	paddr |= (u64)p.g.lun << ppaf->lun_offset;
 	paddr |= (u64)p.g.pg << ppaf->pg_offset;
 	paddr |= (u64)p.g.pl << ppaf->pln_offset;
-	paddr |= (u64)p.g.sec << ppaf->sect_offset;
+	paddr |= (u64)p.g.sec << ppaf->sec_offset;
 
 	return paddr;
 }
@@ -998,7 +998,7 @@ static inline struct ppa_addr pblk_ppa32_to_ppa64(struct pblk *pblk, u32 ppa32)
 		ppa64.g.blk = (ppa32 & ppaf->blk_mask) >> ppaf->blk_offset;
 		ppa64.g.pg = (ppa32 & ppaf->pg_mask) >> ppaf->pg_offset;
 		ppa64.g.pl = (ppa32 & ppaf->pln_mask) >> ppaf->pln_offset;
-		ppa64.g.sec = (ppa32 & ppaf->sec_mask) >> ppaf->sect_offset;
+		ppa64.g.sec = (ppa32 & ppaf->sec_mask) >> ppaf->sec_offset;
 	}
 
 	return ppa64;
@@ -1022,7 +1022,7 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
 		ppa32 |= ppa64.g.blk << ppaf->blk_offset;
 		ppa32 |= ppa64.g.pg << ppaf->pg_offset;
 		ppa32 |= ppa64.g.pl << ppaf->pln_offset;
-		ppa32 |= ppa64.g.sec << ppaf->sect_offset;
+		ppa32 |= ppa64.g.sec << ppaf->sec_offset;
 	}
 
 	return ppa32;
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index f3f524dc1389..377e6525e53f 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -262,21 +262,21 @@ static void nvme_nvm_set_addr_12(struct nvm_addr_format_12 *dst,
 	dst->blk_len = src->blk_len;
 	dst->pg_len = src->pg_len;
 	dst->pln_len = src->pln_len;
-	dst->sect_len = src->sec_len;
+	dst->sec_len = src->sec_len;
 
 	dst->ch_offset = src->ch_offset;
 	dst->lun_offset = src->lun_offset;
 	dst->blk_offset = src->blk_offset;
 	dst->pg_offset = src->pg_offset;
 	dst->pln_offset = src->pln_offset;
-	dst->sect_offset = src->sec_offset;
+	dst->sec_offset = src->sec_offset;
 
 	dst->ch_mask = ((1ULL << dst->ch_len) - 1) << dst->ch_offset;
 	dst->lun_mask = ((1ULL << dst->lun_len) - 1) << dst->lun_offset;
 	dst->blk_mask = ((1ULL << dst->blk_len) - 1) << dst->blk_offset;
 	dst->pg_mask = ((1ULL << dst->pg_len) - 1) << dst->pg_offset;
 	dst->pln_mask = ((1ULL << dst->pln_len) - 1) << dst->pln_offset;
-	dst->sec_mask = ((1ULL << dst->sect_len) - 1) << dst->sect_offset;
+	dst->sec_mask = ((1ULL << dst->sec_len) - 1) << dst->sec_offset;
 }
 
 static int nvme_nvm_setup_12(struct nvme_nvm_id12 *id,
@@ -975,7 +975,7 @@ static ssize_t nvm_dev_attr_show_ppaf(struct nvm_addr_format_12 *ppaf,
 				ppaf->pln_offset, ppaf->pln_len,
 				ppaf->blk_offset, ppaf->blk_len,
 				ppaf->pg_offset, ppaf->pg_len,
-				ppaf->sect_offset, ppaf->sect_len);
+				ppaf->sec_offset, ppaf->sec_len);
 }
 
 static ssize_t nvm_dev_attr_show_12(struct device *dev,
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 797594d6519f..18bb9e9774d6 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -163,14 +163,14 @@ struct nvm_addr_format_12 {
 	u8	blk_len;
 	u8	pg_len;
 	u8	pln_len;
-	u8	sect_len;
+	u8	sec_len;
 
 	u8	ch_offset;
 	u8	lun_offset;
 	u8	blk_offset;
 	u8	pg_offset;
 	u8	pln_offset;
-	u8	sect_offset;
+	u8	sec_offset;
 
 	u64	ch_mask;
 	u64	lun_mask;
@@ -391,7 +391,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;
 }
@@ -411,7 +411,7 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
 	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
 	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
 	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
-	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sect_offset;
+	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
 
 	return l;
 }
-- 
2.7.4

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

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

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

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

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 45bed54488f9..92ea6e39dd64 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -196,8 +196,8 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
 
 		for (j = 0; j < luns_in_chnl; j++) {
 			luns[lunid].ppa = 0;
-			luns[lunid].g.ch = i;
-			luns[lunid++].g.lun = j;
+			luns[lunid].a.ch = i;
+			luns[lunid++].a.lun = j;
 
 			lun_offs[j] = blun;
 			lun_roffs[j + blun] = blun;
@@ -563,22 +563,22 @@ static void nvm_unregister_map(struct nvm_dev *dev)
 static void nvm_map_to_dev(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
 {
 	struct nvm_dev_map *dev_map = tgt_dev->map;
-	struct nvm_ch_map *ch_map = &dev_map->chnls[p->g.ch];
-	int lun_off = ch_map->lun_offs[p->g.lun];
+	struct nvm_ch_map *ch_map = &dev_map->chnls[p->a.ch];
+	int lun_off = ch_map->lun_offs[p->a.lun];
 
-	p->g.ch += ch_map->ch_off;
-	p->g.lun += lun_off;
+	p->a.ch += ch_map->ch_off;
+	p->a.lun += lun_off;
 }
 
 static void nvm_map_to_tgt(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
 {
 	struct nvm_dev *dev = tgt_dev->parent;
 	struct nvm_dev_map *dev_rmap = dev->rmap;
-	struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[p->g.ch];
-	int lun_roff = ch_rmap->lun_offs[p->g.lun];
+	struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[p->a.ch];
+	int lun_roff = ch_rmap->lun_offs[p->a.lun];
 
-	p->g.ch -= ch_rmap->ch_off;
-	p->g.lun -= lun_roff;
+	p->a.ch -= ch_rmap->ch_off;
+	p->a.lun -= lun_roff;
 }
 
 static void nvm_ppa_tgt_to_dev(struct nvm_tgt_dev *tgt_dev,
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 18bb9e9774d6..8cda1125c34a 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;
@@ -382,16 +409,26 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
 						  struct ppa_addr r)
 {
 	struct nvm_geo *geo = &tgt_dev->geo;
-	struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&geo->c.addrf;
 	struct ppa_addr l;
 
-	l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
-	l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
-	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
-	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
-	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
-	l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
+	if (geo->c.version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&geo->c.addrf;
+
+		l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
+		l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
+		l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
+		l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
+		l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
+		l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
+	} else {
+		struct nvm_addr_format *lbaf = &geo->c.addrf;
+
+		l.ppa = ((u64)r.m.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;
 }
@@ -400,18 +437,28 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
 						  struct ppa_addr r)
 {
 	struct nvm_geo *geo = &tgt_dev->geo;
-	struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&geo->c.addrf;
 	struct ppa_addr l;
 
 	l.ppa = 0;
 
-	l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
-	l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
-	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
-	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
-	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
-	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
+	if (geo->c.version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&geo->c.addrf;
+
+		l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
+		l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
+		l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
+		l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
+		l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
+		l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
+	} else {
+		struct nvm_addr_format *lbaf = &geo->c.addrf;
+
+		l.m.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.7.4

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

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


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

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

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 45bed54488f9..92ea6e39dd64 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -196,8 +196,8 @@ static struct nvm_tgt_dev *nvm_create_tgt_dev(struct nvm_dev *dev,
 
 		for (j = 0; j < luns_in_chnl; j++) {
 			luns[lunid].ppa = 0;
-			luns[lunid].g.ch = i;
-			luns[lunid++].g.lun = j;
+			luns[lunid].a.ch = i;
+			luns[lunid++].a.lun = j;
 
 			lun_offs[j] = blun;
 			lun_roffs[j + blun] = blun;
@@ -563,22 +563,22 @@ static void nvm_unregister_map(struct nvm_dev *dev)
 static void nvm_map_to_dev(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
 {
 	struct nvm_dev_map *dev_map = tgt_dev->map;
-	struct nvm_ch_map *ch_map = &dev_map->chnls[p->g.ch];
-	int lun_off = ch_map->lun_offs[p->g.lun];
+	struct nvm_ch_map *ch_map = &dev_map->chnls[p->a.ch];
+	int lun_off = ch_map->lun_offs[p->a.lun];
 
-	p->g.ch += ch_map->ch_off;
-	p->g.lun += lun_off;
+	p->a.ch += ch_map->ch_off;
+	p->a.lun += lun_off;
 }
 
 static void nvm_map_to_tgt(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
 {
 	struct nvm_dev *dev = tgt_dev->parent;
 	struct nvm_dev_map *dev_rmap = dev->rmap;
-	struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[p->g.ch];
-	int lun_roff = ch_rmap->lun_offs[p->g.lun];
+	struct nvm_ch_map *ch_rmap = &dev_rmap->chnls[p->a.ch];
+	int lun_roff = ch_rmap->lun_offs[p->a.lun];
 
-	p->g.ch -= ch_rmap->ch_off;
-	p->g.lun -= lun_roff;
+	p->a.ch -= ch_rmap->ch_off;
+	p->a.lun -= lun_roff;
 }
 
 static void nvm_ppa_tgt_to_dev(struct nvm_tgt_dev *tgt_dev,
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 18bb9e9774d6..8cda1125c34a 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;
@@ -382,16 +409,26 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
 						  struct ppa_addr r)
 {
 	struct nvm_geo *geo = &tgt_dev->geo;
-	struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&geo->c.addrf;
 	struct ppa_addr l;
 
-	l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
-	l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
-	l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
-	l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
-	l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
-	l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
+	if (geo->c.version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&geo->c.addrf;
+
+		l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
+		l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
+		l.ppa |= ((u64)r.g.blk) << ppaf->blk_offset;
+		l.ppa |= ((u64)r.g.pg) << ppaf->pg_offset;
+		l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
+		l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
+	} else {
+		struct nvm_addr_format *lbaf = &geo->c.addrf;
+
+		l.ppa = ((u64)r.m.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;
 }
@@ -400,18 +437,28 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
 						  struct ppa_addr r)
 {
 	struct nvm_geo *geo = &tgt_dev->geo;
-	struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&geo->c.addrf;
 	struct ppa_addr l;
 
 	l.ppa = 0;
 
-	l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
-	l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
-	l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
-	l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
-	l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
-	l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
+	if (geo->c.version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&geo->c.addrf;
+
+		l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
+		l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
+		l.g.blk = (r.ppa & ppaf->blk_mask) >> ppaf->blk_offset;
+		l.g.pg = (r.ppa & ppaf->pg_mask) >> ppaf->pg_offset;
+		l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
+		l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
+	} else {
+		struct nvm_addr_format *lbaf = &geo->c.addrf;
+
+		l.m.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.7.4

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

* [PATCH 11/19] lightnvm: pblk: rename ppaf* to addrf*
  2018-02-26 13:16 ` Javier González
@ 2018-02-26 13:17   ` Javier González
  -1 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

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

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

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

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

* [PATCH 11/19] lightnvm: pblk: rename ppaf* to addrf*
@ 2018-02-26 13:17   ` Javier González
  0 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)


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

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

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

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

* [PATCH 12/19] lightnvn: pblk: use generic address format
  2018-02-26 13:16 ` Javier González
@ 2018-02-26 13:17   ` Javier González
  -1 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

Use the generic address format on common address manipulations.

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/lightnvm/pblk-core.c  | 10 +++++-----
 drivers/lightnvm/pblk-map.c   |  4 ++--
 drivers/lightnvm/pblk-sysfs.c |  4 ++--
 drivers/lightnvm/pblk.h       |  4 ++--
 4 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index 7c726003a8d2..1d7c6313f3d9 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));
@@ -1693,8 +1693,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));
@@ -1738,8 +1738,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 d3b50741b691..ccfb3abd2773 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 46b29a492f74..6e1fcd1a538a 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,
-- 
2.7.4

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

* [PATCH 12/19] lightnvn: pblk: use generic address format
@ 2018-02-26 13:17   ` Javier González
  0 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)


Use the generic address format on common address manipulations.

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/lightnvm/pblk-core.c  | 10 +++++-----
 drivers/lightnvm/pblk-map.c   |  4 ++--
 drivers/lightnvm/pblk-sysfs.c |  4 ++--
 drivers/lightnvm/pblk.h       |  4 ++--
 4 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index 7c726003a8d2..1d7c6313f3d9 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));
@@ -1693,8 +1693,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));
@@ -1738,8 +1738,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 d3b50741b691..ccfb3abd2773 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 46b29a492f74..6e1fcd1a538a 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,
-- 
2.7.4

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

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

T24gYWRkcmVzcyBjb252ZXJzaW9ucywgdXNlIHRoZSBnZW5lcmljIGRldmljZSwgaW5zdGVhZCBv
ZiB0aGUgdGFyZ2V0CmRldmljZS4gVGhpcyBhbGxvd3MgdG8gdXNlIGNvbnZlcnNpb25zIG91dHNp
ZGUgb2YgdGhlIHRhcmdldCdzIHJlYWxtLgoKU2lnbmVkLW9mZi1ieTogSmF2aWVyIEdvbnrDoWxl
eiA8amF2aWVyQGNuZXhsYWJzLmNvbT4KLS0tCiBkcml2ZXJzL2xpZ2h0bnZtL2NvcmUuYyAgfCAg
NCArKy0tCiBpbmNsdWRlL2xpbnV4L2xpZ2h0bnZtLmggfCAyMCArKysrKysrKysrLS0tLS0tLS0t
LQogMiBmaWxlcyBjaGFuZ2VkLCAxMiBpbnNlcnRpb25zKCspLCAxMiBkZWxldGlvbnMoLSkKCmRp
ZmYgLS1naXQgYS9kcml2ZXJzL2xpZ2h0bnZtL2NvcmUuYyBiL2RyaXZlcnMvbGlnaHRudm0vY29y
ZS5jCmluZGV4IDkyZWE2ZTM5ZGQ2NC4uZmFlNWU4YzZmY2QwIDEwMDY0NAotLS0gYS9kcml2ZXJz
L2xpZ2h0bnZtL2NvcmUuYworKysgYi9kcml2ZXJzL2xpZ2h0bnZtL2NvcmUuYwpAQCAtNTg4LDcg
KzU4OCw3IEBAIHN0YXRpYyB2b2lkIG52bV9wcGFfdGd0X3RvX2RldihzdHJ1Y3QgbnZtX3RndF9k
ZXYgKnRndF9kZXYsCiAKIAlmb3IgKGkgPSAwOyBpIDwgbnJfcHBhczsgaSsrKSB7CiAJCW52bV9t
YXBfdG9fZGV2KHRndF9kZXYsICZwcGFfbGlzdFtpXSk7Ci0JCXBwYV9saXN0W2ldID0gZ2VuZXJp
Y190b19kZXZfYWRkcih0Z3RfZGV2LCBwcGFfbGlzdFtpXSk7CisJCXBwYV9saXN0W2ldID0gZ2Vu
ZXJpY190b19kZXZfYWRkcih0Z3RfZGV2LT5wYXJlbnQsIHBwYV9saXN0W2ldKTsKIAl9CiB9CiAK
QEAgLTU5OCw3ICs1OTgsNyBAQCBzdGF0aWMgdm9pZCBudm1fcHBhX2Rldl90b190Z3Qoc3RydWN0
IG52bV90Z3RfZGV2ICp0Z3RfZGV2LAogCWludCBpOwogCiAJZm9yIChpID0gMDsgaSA8IG5yX3Bw
YXM7IGkrKykgewotCQlwcGFfbGlzdFtpXSA9IGRldl90b19nZW5lcmljX2FkZHIodGd0X2Rldiwg
cHBhX2xpc3RbaV0pOworCQlwcGFfbGlzdFtpXSA9IGRldl90b19nZW5lcmljX2FkZHIodGd0X2Rl
di0+cGFyZW50LCBwcGFfbGlzdFtpXSk7CiAJCW52bV9tYXBfdG9fdGd0KHRndF9kZXYsICZwcGFf
bGlzdFtpXSk7CiAJfQogfQpkaWZmIC0tZ2l0IGEvaW5jbHVkZS9saW51eC9saWdodG52bS5oIGIv
aW5jbHVkZS9saW51eC9saWdodG52bS5oCmluZGV4IDhjZGExMTI1YzM0YS4uMmI5MDk1OTI1Njhh
IDEwMDY0NAotLS0gYS9pbmNsdWRlL2xpbnV4L2xpZ2h0bnZtLmgKKysrIGIvaW5jbHVkZS9saW51
eC9saWdodG52bS5oCkBAIC00MDUsMTUgKzQwNSwxNSBAQCBzdHJ1Y3QgbnZtX2RldiB7CiAJc3Ry
dWN0IGxpc3RfaGVhZCB0YXJnZXRzOwogfTsKIAotc3RhdGljIGlubGluZSBzdHJ1Y3QgcHBhX2Fk
ZHIgZ2VuZXJpY190b19kZXZfYWRkcihzdHJ1Y3QgbnZtX3RndF9kZXYgKnRndF9kZXYsCitzdGF0
aWMgaW5saW5lIHN0cnVjdCBwcGFfYWRkciBnZW5lcmljX3RvX2Rldl9hZGRyKHN0cnVjdCBudm1f
ZGV2ICpkZXYsCiAJCQkJCQkgIHN0cnVjdCBwcGFfYWRkciByKQogewotCXN0cnVjdCBudm1fZ2Vv
ICpnZW8gPSAmdGd0X2Rldi0+Z2VvOworCXN0cnVjdCBudm1fZ2VvICpkZXZfZ2VvID0gJmRldi0+
Z2VvOwogCXN0cnVjdCBwcGFfYWRkciBsOwogCi0JaWYgKGdlby0+Yy52ZXJzaW9uID09IE5WTV9P
Q1NTRF9TUEVDXzEyKSB7CisJaWYgKGRldl9nZW8tPmMudmVyc2lvbiA9PSBOVk1fT0NTU0RfU1BF
Q18xMikgewogCQlzdHJ1Y3QgbnZtX2FkZHJfZm9ybWF0XzEyICpwcGFmID0KLQkJCQkoc3RydWN0
IG52bV9hZGRyX2Zvcm1hdF8xMiAqKSZnZW8tPmMuYWRkcmY7CisJCQkJKHN0cnVjdCBudm1fYWRk
cl9mb3JtYXRfMTIgKikmZGV2X2dlby0+Yy5hZGRyZjsKIAogCQlsLnBwYSA9ICgodTY0KXIuZy5j
aCkgPDwgcHBhZi0+Y2hfb2Zmc2V0OwogCQlsLnBwYSB8PSAoKHU2NClyLmcubHVuKSA8PCBwcGFm
LT5sdW5fb2Zmc2V0OwpAQCAtNDIyLDcgKzQyMiw3IEBAIHN0YXRpYyBpbmxpbmUgc3RydWN0IHBw
YV9hZGRyIGdlbmVyaWNfdG9fZGV2X2FkZHIoc3RydWN0IG52bV90Z3RfZGV2ICp0Z3RfZGV2LAog
CQlsLnBwYSB8PSAoKHU2NClyLmcucGwpIDw8IHBwYWYtPnBsbl9vZmZzZXQ7CiAJCWwucHBhIHw9
ICgodTY0KXIuZy5zZWMpIDw8IHBwYWYtPnNlY19vZmZzZXQ7CiAJfSBlbHNlIHsKLQkJc3RydWN0
IG52bV9hZGRyX2Zvcm1hdCAqbGJhZiA9ICZnZW8tPmMuYWRkcmY7CisJCXN0cnVjdCBudm1fYWRk
cl9mb3JtYXQgKmxiYWYgPSAmZGV2X2dlby0+Yy5hZGRyZjsKIAogCQlsLnBwYSA9ICgodTY0KXIu
bS5ncnApIDw8IGxiYWYtPmNoX29mZnNldDsKIAkJbC5wcGEgfD0gKCh1NjQpci5tLnB1KSA8PCBs
YmFmLT5sdW5fb2Zmc2V0OwpAQCAtNDMzLDE3ICs0MzMsMTcgQEAgc3RhdGljIGlubGluZSBzdHJ1
Y3QgcHBhX2FkZHIgZ2VuZXJpY190b19kZXZfYWRkcihzdHJ1Y3QgbnZtX3RndF9kZXYgKnRndF9k
ZXYsCiAJcmV0dXJuIGw7CiB9CiAKLXN0YXRpYyBpbmxpbmUgc3RydWN0IHBwYV9hZGRyIGRldl90
b19nZW5lcmljX2FkZHIoc3RydWN0IG52bV90Z3RfZGV2ICp0Z3RfZGV2LAorc3RhdGljIGlubGlu
ZSBzdHJ1Y3QgcHBhX2FkZHIgZGV2X3RvX2dlbmVyaWNfYWRkcihzdHJ1Y3QgbnZtX2RldiAqZGV2
LAogCQkJCQkJICBzdHJ1Y3QgcHBhX2FkZHIgcikKIHsKLQlzdHJ1Y3QgbnZtX2dlbyAqZ2VvID0g
JnRndF9kZXYtPmdlbzsKKwlzdHJ1Y3QgbnZtX2dlbyAqZGV2X2dlbyA9ICZkZXYtPmdlbzsKIAlz
dHJ1Y3QgcHBhX2FkZHIgbDsKIAogCWwucHBhID0gMDsKIAotCWlmIChnZW8tPmMudmVyc2lvbiA9
PSBOVk1fT0NTU0RfU1BFQ18xMikgeworCWlmIChkZXZfZ2VvLT5jLnZlcnNpb24gPT0gTlZNX09D
U1NEX1NQRUNfMTIpIHsKIAkJc3RydWN0IG52bV9hZGRyX2Zvcm1hdF8xMiAqcHBhZiA9Ci0JCQkJ
KHN0cnVjdCBudm1fYWRkcl9mb3JtYXRfMTIgKikmZ2VvLT5jLmFkZHJmOworCQkJCShzdHJ1Y3Qg
bnZtX2FkZHJfZm9ybWF0XzEyICopJmRldl9nZW8tPmMuYWRkcmY7CiAKIAkJbC5nLmNoID0gKHIu
cHBhICYgcHBhZi0+Y2hfbWFzaykgPj4gcHBhZi0+Y2hfb2Zmc2V0OwogCQlsLmcubHVuID0gKHIu
cHBhICYgcHBhZi0+bHVuX21hc2spID4+IHBwYWYtPmx1bl9vZmZzZXQ7CkBAIC00NTIsNyArNDUy
LDcgQEAgc3RhdGljIGlubGluZSBzdHJ1Y3QgcHBhX2FkZHIgZGV2X3RvX2dlbmVyaWNfYWRkcihz
dHJ1Y3QgbnZtX3RndF9kZXYgKnRndF9kZXYsCiAJCWwuZy5wbCA9IChyLnBwYSAmIHBwYWYtPnBs
bl9tYXNrKSA+PiBwcGFmLT5wbG5fb2Zmc2V0OwogCQlsLmcuc2VjID0gKHIucHBhICYgcHBhZi0+
c2VjX21hc2spID4+IHBwYWYtPnNlY19vZmZzZXQ7CiAJfSBlbHNlIHsKLQkJc3RydWN0IG52bV9h
ZGRyX2Zvcm1hdCAqbGJhZiA9ICZnZW8tPmMuYWRkcmY7CisJCXN0cnVjdCBudm1fYWRkcl9mb3Jt
YXQgKmxiYWYgPSAmZGV2X2dlby0+Yy5hZGRyZjsKIAogCQlsLm0uZ3JwID0gKHIucHBhICYgbGJh
Zi0+Y2hfbWFzaykgPj4gbGJhZi0+Y2hfb2Zmc2V0OwogCQlsLm0ucHUgPSAoci5wcGEgJiBsYmFm
LT5sdW5fbWFzaykgPj4gbGJhZi0+bHVuX29mZnNldDsKLS0gCjIuNy40CgoKX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KTGludXgtbnZtZSBtYWlsaW5nIGxp
c3QKTGludXgtbnZtZUBsaXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQu
b3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtbnZtZQo=

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

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

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

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

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 92ea6e39dd64..fae5e8c6fcd0 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -588,7 +588,7 @@ static void nvm_ppa_tgt_to_dev(struct nvm_tgt_dev *tgt_dev,
 
 	for (i = 0; i < nr_ppas; i++) {
 		nvm_map_to_dev(tgt_dev, &ppa_list[i]);
-		ppa_list[i] = generic_to_dev_addr(tgt_dev, ppa_list[i]);
+		ppa_list[i] = generic_to_dev_addr(tgt_dev->parent, ppa_list[i]);
 	}
 }
 
@@ -598,7 +598,7 @@ static void nvm_ppa_dev_to_tgt(struct nvm_tgt_dev *tgt_dev,
 	int i;
 
 	for (i = 0; i < nr_ppas; i++) {
-		ppa_list[i] = dev_to_generic_addr(tgt_dev, ppa_list[i]);
+		ppa_list[i] = dev_to_generic_addr(tgt_dev->parent, ppa_list[i]);
 		nvm_map_to_tgt(tgt_dev, &ppa_list[i]);
 	}
 }
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 8cda1125c34a..2b909592568a 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -405,15 +405,15 @@ 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 *dev_geo = &dev->geo;
 	struct ppa_addr l;
 
-	if (geo->c.version == NVM_OCSSD_SPEC_12) {
+	if (dev_geo->c.version == NVM_OCSSD_SPEC_12) {
 		struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&geo->c.addrf;
+				(struct nvm_addr_format_12 *)&dev_geo->c.addrf;
 
 		l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
 		l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
@@ -422,7 +422,7 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
 		l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
 		l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
 	} else {
-		struct nvm_addr_format *lbaf = &geo->c.addrf;
+		struct nvm_addr_format *lbaf = &dev_geo->c.addrf;
 
 		l.ppa = ((u64)r.m.grp) << lbaf->ch_offset;
 		l.ppa |= ((u64)r.m.pu) << lbaf->lun_offset;
@@ -433,17 +433,17 @@ 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 *dev_geo = &dev->geo;
 	struct ppa_addr l;
 
 	l.ppa = 0;
 
-	if (geo->c.version == NVM_OCSSD_SPEC_12) {
+	if (dev_geo->c.version == NVM_OCSSD_SPEC_12) {
 		struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&geo->c.addrf;
+				(struct nvm_addr_format_12 *)&dev_geo->c.addrf;
 
 		l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
 		l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
@@ -452,7 +452,7 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
 		l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
 		l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
 	} else {
-		struct nvm_addr_format *lbaf = &geo->c.addrf;
+		struct nvm_addr_format *lbaf = &dev_geo->c.addrf;
 
 		l.m.grp = (r.ppa & lbaf->ch_mask) >> lbaf->ch_offset;
 		l.m.pu = (r.ppa & lbaf->lun_mask) >> lbaf->lun_offset;
-- 
2.7.4

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

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


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

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

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 92ea6e39dd64..fae5e8c6fcd0 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -588,7 +588,7 @@ static void nvm_ppa_tgt_to_dev(struct nvm_tgt_dev *tgt_dev,
 
 	for (i = 0; i < nr_ppas; i++) {
 		nvm_map_to_dev(tgt_dev, &ppa_list[i]);
-		ppa_list[i] = generic_to_dev_addr(tgt_dev, ppa_list[i]);
+		ppa_list[i] = generic_to_dev_addr(tgt_dev->parent, ppa_list[i]);
 	}
 }
 
@@ -598,7 +598,7 @@ static void nvm_ppa_dev_to_tgt(struct nvm_tgt_dev *tgt_dev,
 	int i;
 
 	for (i = 0; i < nr_ppas; i++) {
-		ppa_list[i] = dev_to_generic_addr(tgt_dev, ppa_list[i]);
+		ppa_list[i] = dev_to_generic_addr(tgt_dev->parent, ppa_list[i]);
 		nvm_map_to_tgt(tgt_dev, &ppa_list[i]);
 	}
 }
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 8cda1125c34a..2b909592568a 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -405,15 +405,15 @@ 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 *dev_geo = &dev->geo;
 	struct ppa_addr l;
 
-	if (geo->c.version == NVM_OCSSD_SPEC_12) {
+	if (dev_geo->c.version == NVM_OCSSD_SPEC_12) {
 		struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&geo->c.addrf;
+				(struct nvm_addr_format_12 *)&dev_geo->c.addrf;
 
 		l.ppa = ((u64)r.g.ch) << ppaf->ch_offset;
 		l.ppa |= ((u64)r.g.lun) << ppaf->lun_offset;
@@ -422,7 +422,7 @@ static inline struct ppa_addr generic_to_dev_addr(struct nvm_tgt_dev *tgt_dev,
 		l.ppa |= ((u64)r.g.pl) << ppaf->pln_offset;
 		l.ppa |= ((u64)r.g.sec) << ppaf->sec_offset;
 	} else {
-		struct nvm_addr_format *lbaf = &geo->c.addrf;
+		struct nvm_addr_format *lbaf = &dev_geo->c.addrf;
 
 		l.ppa = ((u64)r.m.grp) << lbaf->ch_offset;
 		l.ppa |= ((u64)r.m.pu) << lbaf->lun_offset;
@@ -433,17 +433,17 @@ 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 *dev_geo = &dev->geo;
 	struct ppa_addr l;
 
 	l.ppa = 0;
 
-	if (geo->c.version == NVM_OCSSD_SPEC_12) {
+	if (dev_geo->c.version == NVM_OCSSD_SPEC_12) {
 		struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&geo->c.addrf;
+				(struct nvm_addr_format_12 *)&dev_geo->c.addrf;
 
 		l.g.ch = (r.ppa & ppaf->ch_mask) >> ppaf->ch_offset;
 		l.g.lun = (r.ppa & ppaf->lun_mask) >> ppaf->lun_offset;
@@ -452,7 +452,7 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_tgt_dev *tgt_dev,
 		l.g.pl = (r.ppa & ppaf->pln_mask) >> ppaf->pln_offset;
 		l.g.sec = (r.ppa & ppaf->sec_mask) >> ppaf->sec_offset;
 	} else {
-		struct nvm_addr_format *lbaf = &geo->c.addrf;
+		struct nvm_addr_format *lbaf = &dev_geo->c.addrf;
 
 		l.m.grp = (r.ppa & lbaf->ch_mask) >> lbaf->ch_offset;
 		l.m.pu = (r.ppa & lbaf->lun_mask) >> lbaf->lun_offset;
-- 
2.7.4

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

* [PATCH 14/19] nvme: make nvme_get_log_ext available
  2018-02-26 13:16 ` Javier González
  (?)
@ 2018-02-26 13:17   ` Javier González
  -1 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)
  To: mb; +Cc: linux-block, Javier González, linux-kernel, linux-nvme

TWFrZSBudm1lX2dldF9sb2dfZXh0IGF2YWlsYWJsZSBvdXRzaWRlIG9mIGNvcmUuYy4KClRoaXMg
aXMgaW4gcHJlcGFyYXRpb24gZm9yIHVzaW5nIGl0IGluIGxpZ2h0bnZtLmMKClNpZ25lZC1vZmYt
Ynk6IEphdmllciBHb256w6FsZXogPGphdmllckBjbmV4bGFicy4+Ci0tLQogZHJpdmVycy9udm1l
L2hvc3QvbnZtZS5oIHwgMyArKysKIDEgZmlsZSBjaGFuZ2VkLCAzIGluc2VydGlvbnMoKykKCmRp
ZmYgLS1naXQgYS9kcml2ZXJzL252bWUvaG9zdC9udm1lLmggYi9kcml2ZXJzL252bWUvaG9zdC9u
dm1lLmgKaW5kZXggMWNhMDhmNDk5M2JhLi41MDVmNzk3ZjhjNmMgMTAwNjQ0Ci0tLSBhL2RyaXZl
cnMvbnZtZS9ob3N0L252bWUuaAorKysgYi9kcml2ZXJzL252bWUvaG9zdC9udm1lLmgKQEAgLTM5
Niw2ICszOTYsOSBAQCBpbnQgbnZtZV9yZXNldF9jdHJsKHN0cnVjdCBudm1lX2N0cmwgKmN0cmwp
OwogaW50IG52bWVfZGVsZXRlX2N0cmwoc3RydWN0IG52bWVfY3RybCAqY3RybCk7CiBpbnQgbnZt
ZV9kZWxldGVfY3RybF9zeW5jKHN0cnVjdCBudm1lX2N0cmwgKmN0cmwpOwogCitpbnQgbnZtZV9n
ZXRfbG9nX2V4dChzdHJ1Y3QgbnZtZV9jdHJsICpjdHJsLCBzdHJ1Y3QgbnZtZV9ucyAqbnMsCisJ
CSAgICAgdTggbG9nX3BhZ2UsIHZvaWQgKmxvZywgc2l6ZV90IHNpemUsIHNpemVfdCBvZmZzZXQp
OworCiBleHRlcm4gY29uc3Qgc3RydWN0IGF0dHJpYnV0ZV9ncm91cCBudm1lX25zX2lkX2F0dHJf
Z3JvdXA7CiBleHRlcm4gY29uc3Qgc3RydWN0IGJsb2NrX2RldmljZV9vcGVyYXRpb25zIG52bWVf
bnNfaGVhZF9vcHM7CiAKLS0gCjIuNy40CgoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX18KTGludXgtbnZtZSBtYWlsaW5nIGxpc3QKTGludXgtbnZtZUBsaXN0
cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGlu
Zm8vbGludXgtbnZtZQo=

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

* [PATCH 14/19] nvme: make nvme_get_log_ext available
@ 2018-02-26 13:17   ` Javier González
  0 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)
  To: mb; +Cc: linux-block, linux-kernel, linux-nvme, Javier González

Make nvme_get_log_ext available outside of core.c.

This is in preparation for using it in lightnvm.c

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

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

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

* [PATCH 14/19] nvme: make nvme_get_log_ext available
@ 2018-02-26 13:17   ` Javier González
  0 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)


Make nvme_get_log_ext available outside of core.c.

This is in preparation for using it in lightnvm.c

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

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

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

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

RnJvbTogSmF2aWVyIEdvbnrDoWxleiA8amF2aWVyQGphdmlnb24uY29tPgoKVGhlIDIuMCBzcGVj
IHByb3ZpZGVzIGEgcmVwb3J0IGNodW5rIGxvZyBwYWdlIHRoYXQgY2FuIGJlIHJldHJpZXZlZAp1
c2luZyB0aGUgc3RhbmdhcmQgbnZtZSBnZXQgbG9nIHBhZ2UuIFRoaXMgcmVwbGFjZXMgdGhlIGRl
ZGljYXRlZApnZXQvcHV0IGJhZCBibG9jayB0YWJsZSBpbiAxLjIuCgpUaGlzIHBhdGNoIGltcGxl
bWVudHMgdGhlIGhlbHBlciBmdW5jdGlvbnMgdG8gYWxsb3cgdGFyZ2V0cyByZXRyaWV2ZSB0aGUK
Y2h1bmsgbWV0YWRhdGEgdXNpbmcgZ2V0IGxvZyBwYWdlCgpTaWduZWQtb2ZmLWJ5OiBKYXZpZXIg
R29uesOhbGV6IDxqYXZpZXJAY25leGxhYnMuY29tPgotLS0KIGRyaXZlcnMvbGlnaHRudm0vY29y
ZS5jICAgICAgfCAxMSArKysrKysrCiBkcml2ZXJzL252bWUvaG9zdC9saWdodG52bS5jIHwgNzQg
KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKIGluY2x1ZGUvbGlu
dXgvbGlnaHRudm0uaCAgICAgfCAyNCArKysrKysrKysrKysrKwogMyBmaWxlcyBjaGFuZ2VkLCAx
MDkgaW5zZXJ0aW9ucygrKQoKZGlmZiAtLWdpdCBhL2RyaXZlcnMvbGlnaHRudm0vY29yZS5jIGIv
ZHJpdmVycy9saWdodG52bS9jb3JlLmMKaW5kZXggZmFlNWU4YzZmY2QwLi4wZjQxMTRjYjQ4ZWUg
MTAwNjQ0Ci0tLSBhL2RyaXZlcnMvbGlnaHRudm0vY29yZS5jCisrKyBiL2RyaXZlcnMvbGlnaHRu
dm0vY29yZS5jCkBAIC03MTksNiArNzE5LDE3IEBAIHN0YXRpYyB2b2lkIG52bV9mcmVlX3JxZF9w
cGFsaXN0KHN0cnVjdCBudm1fdGd0X2RldiAqdGd0X2RldiwKIAludm1fZGV2X2RtYV9mcmVlKHRn
dF9kZXYtPnBhcmVudCwgcnFkLT5wcGFfbGlzdCwgcnFkLT5kbWFfcHBhX2xpc3QpOwogfQogCitp
bnQgbnZtX2dldF9jaHVua19tZXRhKHN0cnVjdCBudm1fdGd0X2RldiAqdGd0X2Rldiwgc3RydWN0
IG52bV9jaGtfbWV0YSAqbWV0YSwKKwkJc3RydWN0IHBwYV9hZGRyIHBwYSwgaW50IG5jaGtzKQor
eworCXN0cnVjdCBudm1fZGV2ICpkZXYgPSB0Z3RfZGV2LT5wYXJlbnQ7CisKKwludm1fcHBhX3Rn
dF90b19kZXYodGd0X2RldiwgJnBwYSwgMSk7CisKKwlyZXR1cm4gZGV2LT5vcHMtPmdldF9jaGtf
bWV0YSh0Z3RfZGV2LT5wYXJlbnQsIG1ldGEsCisJCQkJCQkoc2VjdG9yX3QpcHBhLnBwYSwgbmNo
a3MpOworfQorRVhQT1JUX1NZTUJPTChudm1fZ2V0X2NodW5rX21ldGEpOwogCiBpbnQgbnZtX3Nl
dF90Z3RfYmJfdGJsKHN0cnVjdCBudm1fdGd0X2RldiAqdGd0X2Rldiwgc3RydWN0IHBwYV9hZGRy
ICpwcGFzLAogCQkgICAgICAgaW50IG5yX3BwYXMsIGludCB0eXBlKQpkaWZmIC0tZ2l0IGEvZHJp
dmVycy9udm1lL2hvc3QvbGlnaHRudm0uYyBiL2RyaXZlcnMvbnZtZS9ob3N0L2xpZ2h0bnZtLmMK
aW5kZXggMzc3ZTY1MjVlNTNmLi43YzRhZjEzMmQwNzIgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvbnZt
ZS9ob3N0L2xpZ2h0bnZtLmMKKysrIGIvZHJpdmVycy9udm1lL2hvc3QvbGlnaHRudm0uYwpAQCAt
MzUsNiArMzUsMTAgQEAgZW51bSBudm1lX252bV9hZG1pbl9vcGNvZGUgewogCW52bWVfbnZtX2Fk
bWluX3NldF9iYl90YmwJPSAweGYxLAogfTsKIAorZW51bSBudm1lX252bV9sb2dfcGFnZSB7CisJ
TlZNRV9OVk1fTE9HX1JFUE9SVF9DSFVOSwk9IDB4Y2EsCit9OworCiBzdHJ1Y3QgbnZtZV9udm1f
cGhfcncgewogCV9fdTgJCQlvcGNvZGU7CiAJX191OAkJCWZsYWdzOwpAQCAtMjM2LDYgKzI0MCwx
NiBAQCBzdHJ1Y3QgbnZtZV9udm1faWQyMCB7CiAJX191OAkJCXZzWzEwMjRdOwogfTsKIAorc3Ry
dWN0IG52bWVfbnZtX2Noa19tZXRhIHsKKwlfX3U4CXN0YXRlOworCV9fdTgJdHlwZTsKKwlfX3U4
CXdpOworCV9fdTgJcnN2ZFs1XTsKKwlfX2xlNjQJc2xiYTsKKwlfX2xlNjQJY25sYjsKKwlfX2xl
NjQJd3A7Cit9OworCiAvKgogICogQ2hlY2sgd2UgZGlkbid0IGluYWR2ZXJ0ZW50bHkgZ3JvdyB0
aGUgY29tbWFuZCBzdHJ1Y3QKICAqLwpAQCAtMjUyLDYgKzI2Niw5IEBAIHN0YXRpYyBpbmxpbmUg
dm9pZCBfbnZtZV9udm1fY2hlY2tfc2l6ZSh2b2lkKQogCUJVSUxEX0JVR19PTihzaXplb2Yoc3Ry
dWN0IG52bWVfbnZtX2JiX3RibCkgIT0gNjQpOwogCUJVSUxEX0JVR19PTihzaXplb2Yoc3RydWN0
IG52bWVfbnZtX2lkMjBfYWRkcmYpICE9IDgpOwogCUJVSUxEX0JVR19PTihzaXplb2Yoc3RydWN0
IG52bWVfbnZtX2lkMjApICE9IE5WTUVfSURFTlRJRllfREFUQV9TSVpFKTsKKwlCVUlMRF9CVUdf
T04oc2l6ZW9mKHN0cnVjdCBudm1lX252bV9jaGtfbWV0YSkgIT0gMzIpOworCUJVSUxEX0JVR19P
TihzaXplb2Yoc3RydWN0IG52bWVfbnZtX2Noa19tZXRhKSAhPQorCQkJCQkJc2l6ZW9mKHN0cnVj
dCBudm1fY2hrX21ldGEpKTsKIH0KIAogc3RhdGljIHZvaWQgbnZtZV9udm1fc2V0X2FkZHJfMTIo
c3RydWN0IG52bV9hZGRyX2Zvcm1hdF8xMiAqZHN0LApAQCAtNTU4LDYgKzU3NSw2MSBAQCBzdGF0
aWMgaW50IG52bWVfbnZtX3NldF9iYl90Ymwoc3RydWN0IG52bV9kZXYgKm52bWRldiwgc3RydWN0
IHBwYV9hZGRyICpwcGFzLAogCXJldHVybiByZXQ7CiB9CiAKKy8qCisgKiBFeHBlY3QgdGhlIGxi
YSBpbiBkZXZpY2UgZm9ybWF0CisgKi8KK3N0YXRpYyBpbnQgbnZtZV9udm1fZ2V0X2Noa19tZXRh
KHN0cnVjdCBudm1fZGV2ICpuZGV2LAorCQkJCSBzdHJ1Y3QgbnZtX2Noa19tZXRhICptZXRhLAor
CQkJCSBzZWN0b3JfdCBzbGJhLCBpbnQgbmNoa3MpCit7CisJc3RydWN0IG52bV9nZW8gKmRldl9n
ZW8gPSAmbmRldi0+Z2VvOworCXN0cnVjdCBudm1lX25zICpucyA9IG5kZXYtPnEtPnF1ZXVlZGF0
YTsKKwlzdHJ1Y3QgbnZtZV9jdHJsICpjdHJsID0gbnMtPmN0cmw7CisJc3RydWN0IG52bWVfbnZt
X2Noa19tZXRhICpkZXZfbWV0YSA9IChzdHJ1Y3QgbnZtZV9udm1fY2hrX21ldGEgKiltZXRhOwor
CXN0cnVjdCBwcGFfYWRkciBwcGE7CisJc2l6ZV90IGxlZnQgPSBuY2hrcyAqIHNpemVvZihzdHJ1
Y3QgbnZtZV9udm1fY2hrX21ldGEpOworCXNpemVfdCBsb2dfcG9zLCBvZmZzZXQsIGxlbjsKKwlp
bnQgcmV0LCBpOworCisJLyogTm9ybWFsaXplIGxiYSBhZGRyZXNzIHNwYWNlIHRvIG9idGFpbiBs
b2cgb2Zmc2V0ICovCisJcHBhLnBwYSA9IHNsYmE7CisJcHBhID0gZGV2X3RvX2dlbmVyaWNfYWRk
cihuZGV2LCBwcGEpOworCisJbG9nX3BvcyA9IHBwYS5tLmNoazsKKwlsb2dfcG9zICs9IHBwYS5t
LnB1ICogZGV2X2dlby0+Yy5udW1fY2hrOworCWxvZ19wb3MgKz0gcHBhLm0uZ3JwICogZGV2X2dl
by0+bnVtX2x1biAqIGRldl9nZW8tPmMubnVtX2NoazsKKworCW9mZnNldCA9IGxvZ19wb3MgKiBz
aXplb2Yoc3RydWN0IG52bWVfbnZtX2Noa19tZXRhKTsKKworCXdoaWxlIChsZWZ0KSB7CisJCWxl
biA9IG1pbl90KHVuc2lnbmVkIGludCwgbGVmdCwgY3RybC0+bWF4X2h3X3NlY3RvcnMgPDwgOSk7
CisKKwkJcmV0ID0gbnZtZV9nZXRfbG9nX2V4dChjdHJsLCBucywgTlZNRV9OVk1fTE9HX1JFUE9S
VF9DSFVOSywKKwkJCQlkZXZfbWV0YSwgbGVuLCBvZmZzZXQpOworCQlpZiAocmV0KSB7CisJCQlk
ZXZfZXJyKGN0cmwtPmRldmljZSwgIkdldCBSRVBPUlQgQ0hVTksgbG9nIGVycm9yXG4iKTsKKwkJ
CWJyZWFrOworCQl9CisKKwkJZm9yIChpID0gMDsgaSA8IGxlbjsgaSArPSBzaXplb2Yoc3RydWN0
IG52bWVfbnZtX2Noa19tZXRhKSkgeworCQkJbWV0YS0+c3RhdGUgPSBkZXZfbWV0YS0+c3RhdGU7
CisJCQltZXRhLT50eXBlID0gZGV2X21ldGEtPnR5cGU7CisJCQltZXRhLT53aSA9IGRldl9tZXRh
LT53aTsKKwkJCW1ldGEtPnNsYmEgPSBsZTY0X3RvX2NwdShkZXZfbWV0YS0+c2xiYSk7CisJCQlt
ZXRhLT5jbmxiID0gbGU2NF90b19jcHUoZGV2X21ldGEtPmNubGIpOworCQkJbWV0YS0+d3AgPSBs
ZTY0X3RvX2NwdShkZXZfbWV0YS0+d3ApOworCisJCQltZXRhKys7CisJCQlkZXZfbWV0YSsrOwor
CQl9CisKKwkJb2Zmc2V0ICs9IGxlbjsKKwkJbGVmdCAtPSBsZW47CisJfQorCisJcmV0dXJuIHJl
dDsKK30KKwogc3RhdGljIGlubGluZSB2b2lkIG52bWVfbnZtX3JxdG9jbWQoc3RydWN0IG52bV9y
cSAqcnFkLCBzdHJ1Y3QgbnZtZV9ucyAqbnMsCiAJCQkJICAgIHN0cnVjdCBudm1lX252bV9jb21t
YW5kICpjKQogewpAQCAtNjg5LDYgKzc2MSw4IEBAIHN0YXRpYyBzdHJ1Y3QgbnZtX2Rldl9vcHMg
bnZtZV9udm1fZGV2X29wcyA9IHsKIAkuZ2V0X2JiX3RibAkJPSBudm1lX252bV9nZXRfYmJfdGJs
LAogCS5zZXRfYmJfdGJsCQk9IG52bWVfbnZtX3NldF9iYl90YmwsCiAKKwkuZ2V0X2Noa19tZXRh
CQk9IG52bWVfbnZtX2dldF9jaGtfbWV0YSwKKwogCS5zdWJtaXRfaW8JCT0gbnZtZV9udm1fc3Vi
bWl0X2lvLAogCS5zdWJtaXRfaW9fc3luYwkJPSBudm1lX252bV9zdWJtaXRfaW9fc3luYywKIApk
aWZmIC0tZ2l0IGEvaW5jbHVkZS9saW51eC9saWdodG52bS5oIGIvaW5jbHVkZS9saW51eC9saWdo
dG52bS5oCmluZGV4IDJiOTA5NTkyNTY4YS4uNzc2ZmZkYzJlMTM3IDEwMDY0NAotLS0gYS9pbmNs
dWRlL2xpbnV4L2xpZ2h0bnZtLmgKKysrIGIvaW5jbHVkZS9saW51eC9saWdodG52bS5oCkBAIC04
MSwxMCArODEsMTMgQEAgc3RydWN0IG52bV9ycTsKIHN0cnVjdCBudm1faWQ7CiBzdHJ1Y3QgbnZt
X2RldjsKIHN0cnVjdCBudm1fdGd0X2RldjsKK3N0cnVjdCBudm1fY2hrX21ldGE7CiAKIHR5cGVk
ZWYgaW50IChudm1faWRfZm4pKHN0cnVjdCBudm1fZGV2ICopOwogdHlwZWRlZiBpbnQgKG52bV9v
cF9iYl90YmxfZm4pKHN0cnVjdCBudm1fZGV2ICosIHN0cnVjdCBwcGFfYWRkciwgdTggKik7CiB0
eXBlZGVmIGludCAobnZtX29wX3NldF9iYl9mbikoc3RydWN0IG52bV9kZXYgKiwgc3RydWN0IHBw
YV9hZGRyICosIGludCwgaW50KTsKK3R5cGVkZWYgaW50IChudm1fZ2V0X2Noa19tZXRhX2ZuKShz
dHJ1Y3QgbnZtX2RldiAqLCBzdHJ1Y3QgbnZtX2Noa19tZXRhICosCisJCQkJCQkJCXNlY3Rvcl90
LCBpbnQpOwogdHlwZWRlZiBpbnQgKG52bV9zdWJtaXRfaW9fZm4pKHN0cnVjdCBudm1fZGV2ICos
IHN0cnVjdCBudm1fcnEgKik7CiB0eXBlZGVmIGludCAobnZtX3N1Ym1pdF9pb19zeW5jX2ZuKShz
dHJ1Y3QgbnZtX2RldiAqLCBzdHJ1Y3QgbnZtX3JxICopOwogdHlwZWRlZiB2b2lkICoobnZtX2Ny
ZWF0ZV9kbWFfcG9vbF9mbikoc3RydWN0IG52bV9kZXYgKiwgY2hhciAqKTsKQEAgLTk4LDYgKzEw
MSw4IEBAIHN0cnVjdCBudm1fZGV2X29wcyB7CiAJbnZtX29wX2JiX3RibF9mbgkqZ2V0X2JiX3Ri
bDsKIAludm1fb3Bfc2V0X2JiX2ZuCSpzZXRfYmJfdGJsOwogCisJbnZtX2dldF9jaGtfbWV0YV9m
bgkqZ2V0X2Noa19tZXRhOworCiAJbnZtX3N1Ym1pdF9pb19mbgkqc3VibWl0X2lvOwogCW52bV9z
dWJtaXRfaW9fc3luY19mbgkqc3VibWl0X2lvX3N5bmM7CiAKQEAgLTIyNyw2ICsyMzIsMjAgQEAg
c3RydWN0IG52bV9hZGRyX2Zvcm1hdCB7CiAJdTY0CXJzdl9tYXNrWzJdOwogfTsKIAorLyoKKyAq
IE5vdGU6IFRoZSBzdHJ1Y3R1cmUgc2l6ZSBpcyBsaW5rZWQgdG8gbnZtZV9udm1fY2hrX21ldGEg
c3VjaCB0aGF0IHRoZSBzYW1lCisgKiBidWZmZXIgY2FuIGJlIHVzZWQgd2hlbiBjb252ZXJ0aW5n
IGZyb20gbGl0dGxlIGVuZGlhbiB0byBjcHUgYWRkcmVzc2luZy4KKyAqLworc3RydWN0IG52bV9j
aGtfbWV0YSB7CisJdTgJc3RhdGU7CisJdTgJdHlwZTsKKwl1OAl3aTsKKwl1OAlyc3ZkWzVdOwor
CXU2NAlzbGJhOworCXU2NAljbmxiOworCXU2NAl3cDsKK307CisKIHN0cnVjdCBudm1fdGFyZ2V0
IHsKIAlzdHJ1Y3QgbGlzdF9oZWFkIGxpc3Q7CiAJc3RydWN0IG52bV90Z3RfZGV2ICpkZXY7CkBA
IC01MDIsNiArNTIxLDExIEBAIGV4dGVybiBzdHJ1Y3QgbnZtX2RldiAqbnZtX2FsbG9jX2Rldihp
bnQpOwogZXh0ZXJuIGludCBudm1fcmVnaXN0ZXIoc3RydWN0IG52bV9kZXYgKik7CiBleHRlcm4g
dm9pZCBudm1fdW5yZWdpc3RlcihzdHJ1Y3QgbnZtX2RldiAqKTsKIAorCitleHRlcm4gaW50IG52
bV9nZXRfY2h1bmtfbWV0YShzdHJ1Y3QgbnZtX3RndF9kZXYgKnRndF9kZXYsCisJCQkgICAgICBz
dHJ1Y3QgbnZtX2Noa19tZXRhICptZXRhLCBzdHJ1Y3QgcHBhX2FkZHIgcHBhLAorCQkJICAgICAg
aW50IG5jaGtzKTsKKwogZXh0ZXJuIGludCBudm1fc2V0X3RndF9iYl90Ymwoc3RydWN0IG52bV90
Z3RfZGV2ICosIHN0cnVjdCBwcGFfYWRkciAqLAogCQkJICAgICAgaW50LCBpbnQpOwogZXh0ZXJu
IGludCBudm1fc3VibWl0X2lvKHN0cnVjdCBudm1fdGd0X2RldiAqLCBzdHJ1Y3QgbnZtX3JxICop
OwotLSAKMi43LjQKCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fXwpMaW51eC1udm1lIG1haWxpbmcgbGlzdApMaW51eC1udm1lQGxpc3RzLmluZnJhZGVhZC5v
cmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1udm1l
Cg==

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

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

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

The 2.0 spec provides a report chunk log page that can be retrieved
using the stangard nvme get log page. This replaces the dedicated
get/put bad block table in 1.2.

This patch implements the helper functions to allow targets retrieve the
chunk metadata using get log page

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

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index fae5e8c6fcd0..0f4114cb48ee 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -719,6 +719,17 @@ static void nvm_free_rqd_ppalist(struct nvm_tgt_dev *tgt_dev,
 	nvm_dev_dma_free(tgt_dev->parent, rqd->ppa_list, rqd->dma_ppa_list);
 }
 
+int nvm_get_chunk_meta(struct nvm_tgt_dev *tgt_dev, struct nvm_chk_meta *meta,
+		struct ppa_addr ppa, int nchks)
+{
+	struct nvm_dev *dev = tgt_dev->parent;
+
+	nvm_ppa_tgt_to_dev(tgt_dev, &ppa, 1);
+
+	return dev->ops->get_chk_meta(tgt_dev->parent, meta,
+						(sector_t)ppa.ppa, nchks);
+}
+EXPORT_SYMBOL(nvm_get_chunk_meta);
 
 int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *ppas,
 		       int nr_ppas, int type)
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 377e6525e53f..7c4af132d072 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_addr_format_12 *dst,
@@ -558,6 +575,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 *dev_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 * dev_geo->c.num_chk;
+	log_pos += ppa.m.grp * dev_geo->num_lun * dev_geo->c.num_chk;
+
+	offset = log_pos * sizeof(struct nvme_nvm_chk_meta);
+
+	while (left) {
+		len = min_t(unsigned int, left, ctrl->max_hw_sectors << 9);
+
+		ret = nvme_get_log_ext(ctrl, ns, NVME_NVM_LOG_REPORT_CHUNK,
+				dev_meta, len, offset);
+		if (ret) {
+			dev_err(ctrl->device, "Get REPORT CHUNK log error\n");
+			break;
+		}
+
+		for (i = 0; i < len; i += sizeof(struct nvme_nvm_chk_meta)) {
+			meta->state = dev_meta->state;
+			meta->type = dev_meta->type;
+			meta->wi = dev_meta->wi;
+			meta->slba = le64_to_cpu(dev_meta->slba);
+			meta->cnlb = le64_to_cpu(dev_meta->cnlb);
+			meta->wp = le64_to_cpu(dev_meta->wp);
+
+			meta++;
+			dev_meta++;
+		}
+
+		offset += len;
+		left -= len;
+	}
+
+	return ret;
+}
+
 static inline void nvme_nvm_rqtocmd(struct nvm_rq *rqd, struct nvme_ns *ns,
 				    struct nvme_nvm_command *c)
 {
@@ -689,6 +761,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 2b909592568a..776ffdc2e137 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_addr_format {
 	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;
@@ -502,6 +521,11 @@ extern struct nvm_dev *nvm_alloc_dev(int);
 extern int nvm_register(struct nvm_dev *);
 extern void nvm_unregister(struct nvm_dev *);
 
+
+extern int nvm_get_chunk_meta(struct nvm_tgt_dev *tgt_dev,
+			      struct nvm_chk_meta *meta, struct ppa_addr ppa,
+			      int nchks);
+
 extern int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *, struct ppa_addr *,
 			      int, int);
 extern int nvm_submit_io(struct nvm_tgt_dev *, struct nvm_rq *);
-- 
2.7.4

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

* [PATCH 15/19] lightnvm: implement get log report chunk helpers
@ 2018-02-26 13:17   ` Javier González
  0 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-26 13:17 UTC (permalink / raw)


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

The 2.0 spec provides a report chunk log page that can be retrieved
using the stangard nvme get log page. This replaces the dedicated
get/put bad block table in 1.2.

This patch implements the helper functions to allow targets retrieve the
chunk metadata using get log page

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

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index fae5e8c6fcd0..0f4114cb48ee 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -719,6 +719,17 @@ static void nvm_free_rqd_ppalist(struct nvm_tgt_dev *tgt_dev,
 	nvm_dev_dma_free(tgt_dev->parent, rqd->ppa_list, rqd->dma_ppa_list);
 }
 
+int nvm_get_chunk_meta(struct nvm_tgt_dev *tgt_dev, struct nvm_chk_meta *meta,
+		struct ppa_addr ppa, int nchks)
+{
+	struct nvm_dev *dev = tgt_dev->parent;
+
+	nvm_ppa_tgt_to_dev(tgt_dev, &ppa, 1);
+
+	return dev->ops->get_chk_meta(tgt_dev->parent, meta,
+						(sector_t)ppa.ppa, nchks);
+}
+EXPORT_SYMBOL(nvm_get_chunk_meta);
 
 int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *ppas,
 		       int nr_ppas, int type)
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 377e6525e53f..7c4af132d072 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_addr_format_12 *dst,
@@ -558,6 +575,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 *dev_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 * dev_geo->c.num_chk;
+	log_pos += ppa.m.grp * dev_geo->num_lun * dev_geo->c.num_chk;
+
+	offset = log_pos * sizeof(struct nvme_nvm_chk_meta);
+
+	while (left) {
+		len = min_t(unsigned int, left, ctrl->max_hw_sectors << 9);
+
+		ret = nvme_get_log_ext(ctrl, ns, NVME_NVM_LOG_REPORT_CHUNK,
+				dev_meta, len, offset);
+		if (ret) {
+			dev_err(ctrl->device, "Get REPORT CHUNK log error\n");
+			break;
+		}
+
+		for (i = 0; i < len; i += sizeof(struct nvme_nvm_chk_meta)) {
+			meta->state = dev_meta->state;
+			meta->type = dev_meta->type;
+			meta->wi = dev_meta->wi;
+			meta->slba = le64_to_cpu(dev_meta->slba);
+			meta->cnlb = le64_to_cpu(dev_meta->cnlb);
+			meta->wp = le64_to_cpu(dev_meta->wp);
+
+			meta++;
+			dev_meta++;
+		}
+
+		offset += len;
+		left -= len;
+	}
+
+	return ret;
+}
+
 static inline void nvme_nvm_rqtocmd(struct nvm_rq *rqd, struct nvme_ns *ns,
 				    struct nvme_nvm_command *c)
 {
@@ -689,6 +761,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 2b909592568a..776ffdc2e137 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_addr_format {
 	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;
@@ -502,6 +521,11 @@ extern struct nvm_dev *nvm_alloc_dev(int);
 extern int nvm_register(struct nvm_dev *);
 extern void nvm_unregister(struct nvm_dev *);
 
+
+extern int nvm_get_chunk_meta(struct nvm_tgt_dev *tgt_dev,
+			      struct nvm_chk_meta *meta, struct ppa_addr ppa,
+			      int nchks);
+
 extern int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *, struct ppa_addr *,
 			      int, int);
 extern int nvm_submit_io(struct nvm_tgt_dev *, struct nvm_rq *);
-- 
2.7.4

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

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

RGVmaW5lIGNodW5rIHN0YXRlcyBhcyBnaXZlbiBpbiB0aGUgMi4wIHNwZWMuIEFsc28sIGFkZCBh
biBleHRyYSBjaHVuawpzdGF0ZSB0aGF0IHNpZ25hbHMgdGhhdCB0aGUgY2h1bmsgaXMgaW4gdXNl
IGJ5IHRoZSBob3N0LiBUaGlzIGFsbG93cyBmb3IKdGhlIGNodW5rIG1ldGFkYXRhIHRvIGJlICJv
d25lZCIgYnkgYSB0YXJnZXQgd2hlbiBhY3RpdmUsIHRodXMKY29tcGxldGluZyB0aGUgY2h1bmsg
c3RhdGUgbWFjaGluZSBmcm9tIHRoZSBob3N0IHBlcnNwZWN0aXZlIGFuZApmYWNpbGl0YXRpbmcg
c2FuaXR5IGNoZWNrcy4gVGhpcyBzdGF0ZSBpcyB0cmFuc3BhcmVudCBmb3IgdGhlIGRldmljZS4K
ClNpZ25lZC1vZmYtYnk6IEphdmllciBHb256w6FsZXogPGphdmllckBjbmV4bGFicy5jb20+Ci0t
LQogaW5jbHVkZS9saW51eC9saWdodG52bS5oIHwgMTQgKysrKysrKysrKysrKysKIDEgZmlsZSBj
aGFuZ2VkLCAxNCBpbnNlcnRpb25zKCspCgpkaWZmIC0tZ2l0IGEvaW5jbHVkZS9saW51eC9saWdo
dG52bS5oIGIvaW5jbHVkZS9saW51eC9saWdodG52bS5oCmluZGV4IDc3NmZmZGMyZTEzNy4uNzQ4
MzBkNWRiZDZlIDEwMDY0NAotLS0gYS9pbmNsdWRlL2xpbnV4L2xpZ2h0bnZtLmgKKysrIGIvaW5j
bHVkZS9saW51eC9saWdodG52bS5oCkBAIC0yMzIsNiArMjMyLDIwIEBAIHN0cnVjdCBudm1fYWRk
cl9mb3JtYXQgewogCXU2NAlyc3ZfbWFza1syXTsKIH07CiAKK2VudW0geworCS8qIENodW5rIHN0
YXRlcyAqLworCU5WTV9DSEtfU1RfRlJFRSA9CTEgPDwgMCwKKwlOVk1fQ0hLX1NUX0NMT1NFRCA9
CTEgPDwgMSwKKwlOVk1fQ0hLX1NUX09QRU4gPQkxIDw8IDIsCisJTlZNX0NIS19TVF9PRkZMSU5F
ID0JMSA8PCAzLAorCU5WTV9DSEtfU1RfSE9TVF9VU0UgPQkxIDw8IDcsCisKKwkvKiBDaHVuayB0
eXBlcyAqLworCU5WTV9DSEtfVFBfV19TRVEgPQkxIDw8IDAsCisJTlZNX0NIS19UUF9XX1JBTiA9
CTEgPDwgMSwKKwlOVk1fQ0hLX1RQX1NaX1NQRUMgPQkxIDw8IDQsCit9OworCiAvKgogICogTm90
ZTogVGhlIHN0cnVjdHVyZSBzaXplIGlzIGxpbmtlZCB0byBudm1lX252bV9jaGtfbWV0YSBzdWNo
IHRoYXQgdGhlIHNhbWUKICAqIGJ1ZmZlciBjYW4gYmUgdXNlZCB3aGVuIGNvbnZlcnRpbmcgZnJv
bSBsaXR0bGUgZW5kaWFuIHRvIGNwdSBhZGRyZXNzaW5nLgotLSAKMi43LjQKCgpfX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpMaW51eC1udm1lIG1haWxpbmcg
bGlzdApMaW51eC1udm1lQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVh
ZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1udm1lCg==

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

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

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

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

diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 776ffdc2e137..74830d5dbd6e 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -232,6 +232,20 @@ struct nvm_addr_format {
 	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,
+	NVM_CHK_ST_HOST_USE =	1 << 7,
+
+	/* Chunk types */
+	NVM_CHK_TP_W_SEQ =	1 << 0,
+	NVM_CHK_TP_W_RAN =	1 << 1,
+	NVM_CHK_TP_SZ_SPEC =	1 << 4,
+};
+
 /*
  * Note: The structure size is linked to nvme_nvm_chk_meta such that the same
  * buffer can be used when converting from little endian to cpu addressing.
-- 
2.7.4

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

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


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

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

diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index 776ffdc2e137..74830d5dbd6e 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -232,6 +232,20 @@ struct nvm_addr_format {
 	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,
+	NVM_CHK_ST_HOST_USE =	1 << 7,
+
+	/* Chunk types */
+	NVM_CHK_TP_W_SEQ =	1 << 0,
+	NVM_CHK_TP_W_RAN =	1 << 1,
+	NVM_CHK_TP_SZ_SPEC =	1 << 4,
+};
+
 /*
  * Note: The structure size is linked to nvme_nvm_chk_meta such that the same
  * buffer can be used when converting from little endian to cpu addressing.
-- 
2.7.4

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

Signed-off-by: Javier González <javier@cnexlabs.com>
---
 drivers/lightnvm/pblk-init.c  |  57 ++++++++++--
 drivers/lightnvm/pblk-sysfs.c |  36 ++++++--
 drivers/lightnvm/pblk.h       | 198 ++++++++++++++++++++++++++++++++----------
 3 files changed, 233 insertions(+), 58 deletions(-)

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 7f88fb937440..fe04996cd3ba 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -231,20 +231,63 @@ static int pblk_set_addrf_12(struct nvm_geo *geo,
 	return dst->blk_offset + src->blk_len;
 }
 
+static int pblk_set_addrf_20(struct nvm_geo *geo,
+			     struct nvm_addr_format *adst,
+			     struct pblk_addr_format *udst)
+{
+	struct nvm_addr_format *src = &geo->c.addrf;
+
+	adst->ch_len = get_count_order(geo->num_ch);
+	adst->lun_len = get_count_order(geo->num_lun);
+	adst->chk_len = src->chk_len;
+	adst->sec_len = src->sec_len;
+
+	adst->sec_offset = 0;
+	adst->ch_offset = adst->sec_len;
+	adst->lun_offset = adst->ch_offset + adst->ch_len;
+	adst->chk_offset = adst->lun_offset + adst->lun_len;
+
+	adst->sec_mask = ((1ULL << adst->sec_len) - 1) << adst->sec_offset;
+	adst->chk_mask = ((1ULL << adst->chk_len) - 1) << adst->chk_offset;
+	adst->lun_mask = ((1ULL << adst->lun_len) - 1) << adst->lun_offset;
+	adst->ch_mask = ((1ULL << adst->ch_len) - 1) << adst->ch_offset;
+
+	udst->sec_stripe = geo->c.ws_opt;
+	udst->ch_stripe = geo->num_ch;
+	udst->lun_stripe = geo->num_lun;
+
+	udst->sec_lun_stripe = udst->sec_stripe * udst->ch_stripe;
+	udst->sec_ws_stripe = udst->sec_lun_stripe * udst->lun_stripe;
+
+	return adst->chk_offset + adst->chk_len;
+}
+
 static int pblk_set_addrf(struct pblk *pblk)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
 	int mod;
 
-	div_u64_rem(geo->c.clba, pblk->min_write_pgs, &mod);
-	if (mod) {
-		pr_err("pblk: bad configuration of sectors/pages\n");
+	switch (geo->c.version) {
+	case NVM_OCSSD_SPEC_12:
+		div_u64_rem(geo->c.clba, pblk->min_write_pgs, &mod);
+		if (mod) {
+			pr_err("pblk: bad configuration of sectors/pages\n");
+			return -EINVAL;
+		}
+
+		pblk->addrf_len = pblk_set_addrf_12(geo, (void *)&pblk->addrf);
+		break;
+	case NVM_OCSSD_SPEC_20:
+		pblk->addrf_len = pblk_set_addrf_20(geo, (void *)&pblk->addrf,
+								&pblk->uaddrf);
+		break;
+	default:
+		pr_err("pblk: OCSSD revision not supported (%d)\n",
+								geo->c.version);
 		return -EINVAL;
 	}
 
-	pblk->addrf_len = pblk_set_addrf_12(geo, (void *)&pblk->addrf);
-
 	return 0;
 }
 
@@ -1113,7 +1156,9 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 	struct pblk *pblk;
 	int ret;
 
-	if (geo->c.version != NVM_OCSSD_SPEC_12) {
+	/* pblk supports 1.2 and 2.0 versions */
+	if (!(geo->c.version == NVM_OCSSD_SPEC_12 ||
+					geo->c.version == NVM_OCSSD_SPEC_20)) {
 		pr_err("pblk: OCSSD version not supported (%u)\n",
 							geo->c.version);
 		return ERR_PTR(-EINVAL);
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index 1ce5b956c622..42ec00e8d393 100644
--- a/drivers/lightnvm/pblk-sysfs.c
+++ b/drivers/lightnvm/pblk-sysfs.c
@@ -113,15 +113,16 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
-	struct nvm_addr_format_12 *ppaf;
-	struct nvm_addr_format_12 *geo_ppaf;
 	ssize_t sz = 0;
 
-	ppaf = (struct nvm_addr_format_12 *)&pblk->addrf;
-	geo_ppaf = (struct nvm_addr_format_12 *)&geo->c.addrf;
+	if (geo->c.version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&pblk->addrf;
+		struct nvm_addr_format_12 *geo_ppaf =
+				(struct nvm_addr_format_12 *)&geo->c.addrf;
 
-	sz = snprintf(page, PAGE_SIZE,
-		"pblk:(s:%d)ch:%d/%d,lun:%d/%d,blk:%d/%d,pg:%d/%d,pl:%d/%d,sec:%d/%d\n",
+		sz = snprintf(page, PAGE_SIZE,
+			"pblk:(s:%d)ch:%d/%d,lun:%d/%d,blk:%d/%d,pg:%d/%d,pl:%d/%d,sec:%d/%d\n",
 			pblk->addrf_len,
 			ppaf->ch_offset, ppaf->ch_len,
 			ppaf->lun_offset, ppaf->lun_len,
@@ -130,14 +131,33 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
 			ppaf->pln_offset, ppaf->pln_len,
 			ppaf->sec_offset, ppaf->sec_len);
 
-	sz += snprintf(page + sz, PAGE_SIZE - sz,
-		"device:ch:%d/%d,lun:%d/%d,blk:%d/%d,pg:%d/%d,pl:%d/%d,sec:%d/%d\n",
+		sz += snprintf(page + sz, PAGE_SIZE - sz,
+			"device:ch:%d/%d,lun:%d/%d,blk:%d/%d,pg:%d/%d,pl:%d/%d,sec:%d/%d\n",
 			geo_ppaf->ch_offset, geo_ppaf->ch_len,
 			geo_ppaf->lun_offset, geo_ppaf->lun_len,
 			geo_ppaf->blk_offset, geo_ppaf->blk_len,
 			geo_ppaf->pg_offset, geo_ppaf->pg_len,
 			geo_ppaf->pln_offset, geo_ppaf->pln_len,
 			geo_ppaf->sec_offset, geo_ppaf->sec_len);
+	} else {
+		struct nvm_addr_format *ppaf = &pblk->addrf;
+		struct nvm_addr_format *geo_ppaf = &geo->c.addrf;
+
+		sz = snprintf(page, PAGE_SIZE,
+			"pblk:(s:%d)ch:%d/%d,lun:%d/%d,chk:%d/%d/sec:%d/%d\n",
+			pblk->addrf_len,
+			ppaf->ch_offset, ppaf->ch_len,
+			ppaf->lun_offset, ppaf->lun_len,
+			ppaf->chk_offset, ppaf->chk_len,
+			ppaf->sec_offset, ppaf->sec_len);
+
+		sz += snprintf(page + sz, PAGE_SIZE - sz,
+			"device:ch:%d/%d,lun:%d/%d,chk:%d/%d,sec:%d/%d\n",
+			geo_ppaf->ch_offset, geo_ppaf->ch_len,
+			geo_ppaf->lun_offset, geo_ppaf->lun_len,
+			geo_ppaf->chk_offset, geo_ppaf->chk_len,
+			geo_ppaf->sec_offset, geo_ppaf->sec_len);
+	}
 
 	return sz;
 }
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index bc31c67b725f..d8f71a9371b1 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -574,6 +574,18 @@ enum {
 	PBLK_STATE_STOPPED = 3,
 };
 
+/* Internal format to support not power-of-2 device formats (for now) */
+struct pblk_addr_format {
+	/* gen to dev */
+	int sec_stripe;
+	int ch_stripe;
+	int lun_stripe;
+
+	/* dev to gen */
+	int sec_lun_stripe;
+	int sec_ws_stripe;
+};
+
 struct pblk {
 	struct nvm_tgt_dev *dev;
 	struct gendisk *disk;
@@ -586,7 +598,8 @@ struct pblk {
 	struct pblk_line_mgmt l_mg;		/* Line management */
 	struct pblk_line_meta lm;		/* Line metadata */
 
-	struct nvm_addr_format addrf;
+	struct nvm_addr_format addrf;	/* Aligned address format */
+	struct pblk_addr_format uaddrf;	/* Unaligned address format */
 	int addrf_len;
 
 	struct pblk_rb rwb;
@@ -967,17 +980,43 @@ static inline int pblk_ppa_to_pos(struct nvm_geo *geo, struct ppa_addr p)
 static inline struct ppa_addr addr_to_gen_ppa(struct pblk *pblk, u64 paddr,
 					      u64 line_id)
 {
-	struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&pblk->addrf;
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
 	struct ppa_addr ppa;
 
-	ppa.ppa = 0;
-	ppa.g.blk = line_id;
-	ppa.g.pg = (paddr & ppaf->pg_mask) >> ppaf->pg_offset;
-	ppa.g.lun = (paddr & ppaf->lun_mask) >> ppaf->lun_offset;
-	ppa.g.ch = (paddr & ppaf->ch_mask) >> ppaf->ch_offset;
-	ppa.g.pl = (paddr & ppaf->pln_mask) >> ppaf->pln_offset;
-	ppa.g.sec = (paddr & ppaf->sec_mask) >> ppaf->sec_offset;
+	if (geo->c.version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&pblk->addrf;
+
+		ppa.ppa = 0;
+		ppa.g.blk = line_id;
+		ppa.g.pg = (paddr & ppaf->pg_mask) >> ppaf->pg_offset;
+		ppa.g.lun = (paddr & ppaf->lun_mask) >> ppaf->lun_offset;
+		ppa.g.ch = (paddr & ppaf->ch_mask) >> ppaf->ch_offset;
+		ppa.g.pl = (paddr & ppaf->pln_mask) >> ppaf->pln_offset;
+		ppa.g.sec = (paddr & ppaf->sec_mask) >> ppaf->sec_offset;
+	} else {
+		struct pblk_addr_format *uaddrf = &pblk->uaddrf;
+		int secs, chnls, luns;
+
+		ppa.ppa = 0;
+
+		ppa.m.chk = line_id;
+
+		div_u64_rem(paddr, uaddrf->sec_stripe, &secs);
+		ppa.m.sec = secs;
+
+		sector_div(paddr, uaddrf->sec_stripe);
+		div_u64_rem(paddr, uaddrf->ch_stripe, &chnls);
+		ppa.m.grp = chnls;
+
+		sector_div(paddr, uaddrf->ch_stripe);
+		div_u64_rem(paddr, uaddrf->lun_stripe, &luns);
+		ppa.m.pu = luns;
+
+		sector_div(paddr, uaddrf->lun_stripe);
+		ppa.m.sec += uaddrf->sec_stripe * paddr;
+	}
 
 	return ppa;
 }
@@ -985,15 +1024,32 @@ static inline struct ppa_addr addr_to_gen_ppa(struct pblk *pblk, u64 paddr,
 static inline u64 pblk_dev_ppa_to_line_addr(struct pblk *pblk,
 							struct ppa_addr p)
 {
-	struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&pblk->addrf;
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
 	u64 paddr;
 
-	paddr = (u64)p.g.ch << ppaf->ch_offset;
-	paddr |= (u64)p.g.lun << ppaf->lun_offset;
-	paddr |= (u64)p.g.pg << ppaf->pg_offset;
-	paddr |= (u64)p.g.pl << ppaf->pln_offset;
-	paddr |= (u64)p.g.sec << ppaf->sec_offset;
+	if (geo->c.version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&pblk->addrf;
+
+		paddr = (u64)p.g.ch << ppaf->ch_offset;
+		paddr |= (u64)p.g.lun << ppaf->lun_offset;
+		paddr |= (u64)p.g.pg << ppaf->pg_offset;
+		paddr |= (u64)p.g.pl << ppaf->pln_offset;
+		paddr |= (u64)p.g.sec << ppaf->sec_offset;
+	} else {
+		struct pblk_addr_format *uaddrf = &pblk->uaddrf;
+		u64 secs = (u64)p.m.sec;
+		int sec_stripe;
+
+		paddr = (u64)p.m.grp * uaddrf->sec_stripe;
+		paddr += (u64)p.m.pu * uaddrf->sec_lun_stripe;
+
+		div_u64_rem(secs, uaddrf->sec_stripe, &sec_stripe);
+		sector_div(secs, uaddrf->sec_stripe);
+		paddr += secs * uaddrf->sec_ws_stripe;
+		paddr += sec_stripe;
+	}
 
 	return paddr;
 }
@@ -1010,15 +1066,37 @@ static inline struct ppa_addr pblk_ppa32_to_ppa64(struct pblk *pblk, u32 ppa32)
 		ppa64.c.line = ppa32 & ((~0U) >> 1);
 		ppa64.c.is_cached = 1;
 	} else {
-		struct nvm_addr_format_12 *ppaf =
+		struct nvm_tgt_dev *dev = pblk->dev;
+		struct nvm_geo *geo = &dev->geo;
+
+		if (geo->c.version == NVM_OCSSD_SPEC_12) {
+			struct nvm_addr_format_12 *ppaf =
 				(struct nvm_addr_format_12 *)&pblk->addrf;
 
-		ppa64.g.ch = (ppa32 & ppaf->ch_mask) >> ppaf->ch_offset;
-		ppa64.g.lun = (ppa32 & ppaf->lun_mask) >> ppaf->lun_offset;
-		ppa64.g.blk = (ppa32 & ppaf->blk_mask) >> ppaf->blk_offset;
-		ppa64.g.pg = (ppa32 & ppaf->pg_mask) >> ppaf->pg_offset;
-		ppa64.g.pl = (ppa32 & ppaf->pln_mask) >> ppaf->pln_offset;
-		ppa64.g.sec = (ppa32 & ppaf->sec_mask) >> ppaf->sec_offset;
+			ppa64.g.ch = (ppa32 & ppaf->ch_mask) >>
+							ppaf->ch_offset;
+			ppa64.g.lun = (ppa32 & ppaf->lun_mask) >>
+							ppaf->lun_offset;
+			ppa64.g.blk = (ppa32 & ppaf->blk_mask) >>
+							ppaf->blk_offset;
+			ppa64.g.pg = (ppa32 & ppaf->pg_mask) >>
+							ppaf->pg_offset;
+			ppa64.g.pl = (ppa32 & ppaf->pln_mask) >>
+							ppaf->pln_offset;
+			ppa64.g.sec = (ppa32 & ppaf->sec_mask) >>
+							ppaf->sec_offset;
+		} else {
+			struct nvm_addr_format *lbaf = &pblk->addrf;
+
+			ppa64.m.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;
@@ -1034,15 +1112,27 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
 		ppa32 |= ppa64.c.line;
 		ppa32 |= 1U << 31;
 	} else {
-		struct nvm_addr_format_12 *ppaf =
+		struct nvm_tgt_dev *dev = pblk->dev;
+		struct nvm_geo *geo = &dev->geo;
+
+		if (geo->c.version == NVM_OCSSD_SPEC_12) {
+			struct nvm_addr_format_12 *ppaf =
 				(struct nvm_addr_format_12 *)&pblk->addrf;
 
-		ppa32 |= ppa64.g.ch << ppaf->ch_offset;
-		ppa32 |= ppa64.g.lun << ppaf->lun_offset;
-		ppa32 |= ppa64.g.blk << ppaf->blk_offset;
-		ppa32 |= ppa64.g.pg << ppaf->pg_offset;
-		ppa32 |= ppa64.g.pl << ppaf->pln_offset;
-		ppa32 |= ppa64.g.sec << ppaf->sec_offset;
+			ppa32 |= ppa64.g.ch << ppaf->ch_offset;
+			ppa32 |= ppa64.g.lun << ppaf->lun_offset;
+			ppa32 |= ppa64.g.blk << ppaf->blk_offset;
+			ppa32 |= ppa64.g.pg << ppaf->pg_offset;
+			ppa32 |= ppa64.g.pl << ppaf->pln_offset;
+			ppa32 |= ppa64.g.sec << ppaf->sec_offset;
+		} else {
+			struct nvm_addr_format *lbaf = &pblk->addrf;
+
+			ppa32 |= ppa64.m.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;
@@ -1160,6 +1250,9 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type)
 	struct nvm_geo *geo = &dev->geo;
 	int flags;
 
+	if (geo->c.version == NVM_OCSSD_SPEC_20)
+		return 0;
+
 	flags = geo->c.pln_mode >> 1;
 
 	if (type == PBLK_WRITE)
@@ -1179,6 +1272,9 @@ static inline int pblk_set_read_mode(struct pblk *pblk, int type)
 	struct nvm_geo *geo = &dev->geo;
 	int flags;
 
+	if (geo->c.version == NVM_OCSSD_SPEC_20)
+		return 0;
+
 	flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
 	if (type == PBLK_READ_SEQUENTIAL)
 		flags |= geo->c.pln_mode >> 1;
@@ -1192,16 +1288,21 @@ static inline int pblk_io_aligned(struct pblk *pblk, int nr_secs)
 }
 
 #ifdef CONFIG_NVM_DEBUG
-static inline void print_ppa(struct ppa_addr *p, char *msg, int error)
+static inline void print_ppa(struct nvm_geo *geo, struct ppa_addr *p,
+			     char *msg, int error)
 {
 	if (p->c.is_cached) {
 		pr_err("ppa: (%s: %x) cache line: %llu\n",
 				msg, error, (u64)p->c.line);
-	} else {
+	} else if (geo->c.version == NVM_OCSSD_SPEC_12) {
 		pr_err("ppa: (%s: %x):ch:%d,lun:%d,blk:%d,pg:%d,pl:%d,sec:%d\n",
 			msg, error,
 			p->g.ch, p->g.lun, p->g.blk,
 			p->g.pg, p->g.pl, p->g.sec);
+	} else {
+		pr_err("ppa: (%s: %x):ch:%d,lun:%d,chk:%d,sec:%d\n",
+			msg, error,
+			p->m.grp, p->m.pu, p->m.chk, p->m.sec);
 	}
 }
 
@@ -1211,13 +1312,13 @@ static inline void pblk_print_failed_rqd(struct pblk *pblk, struct nvm_rq *rqd,
 	int bit = -1;
 
 	if (rqd->nr_ppas ==  1) {
-		print_ppa(&rqd->ppa_addr, "rqd", error);
+		print_ppa(&pblk->dev->geo, &rqd->ppa_addr, "rqd", error);
 		return;
 	}
 
 	while ((bit = find_next_bit((void *)&rqd->ppa_status, rqd->nr_ppas,
 						bit + 1)) < rqd->nr_ppas) {
-		print_ppa(&rqd->ppa_list[bit], "rqd", error);
+		print_ppa(&pblk->dev->geo, &rqd->ppa_list[bit], "rqd", error);
 	}
 
 	pr_err("error:%d, ppa_status:%llx\n", error, rqd->ppa_status);
@@ -1233,16 +1334,25 @@ static inline int pblk_boundary_ppa_checks(struct nvm_tgt_dev *tgt_dev,
 	for (i = 0; i < nr_ppas; i++) {
 		ppa = &ppas[i];
 
-		if (!ppa->c.is_cached &&
-				ppa->g.ch < geo->num_ch &&
-				ppa->g.lun < geo->num_lun &&
-				ppa->g.pl < geo->c.num_pln &&
-				ppa->g.blk < geo->c.num_chk &&
-				ppa->g.pg < geo->c.num_pg &&
-				ppa->g.sec < geo->c.ws_min)
-			continue;
+		if (geo->c.version == NVM_OCSSD_SPEC_12) {
+			if (!ppa->c.is_cached &&
+					ppa->g.ch < geo->num_ch &&
+					ppa->g.lun < geo->num_lun &&
+					ppa->g.pl < geo->c.num_pln &&
+					ppa->g.blk < geo->c.num_chk &&
+					ppa->g.pg < geo->c.num_pg &&
+					ppa->g.sec < geo->c.ws_min)
+				continue;
+		} else {
+			if (!ppa->c.is_cached &&
+					ppa->m.grp < geo->num_ch &&
+					ppa->m.pu < geo->num_lun &&
+					ppa->m.chk < geo->c.num_chk &&
+					ppa->m.sec < geo->c.clba)
+				continue;
+		}
 
-		print_ppa(ppa, "boundary", i);
+		print_ppa(geo, ppa, "boundary", i);
 
 		return 1;
 	}
-- 
2.7.4

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

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


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

Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
---
 drivers/lightnvm/pblk-init.c  |  57 ++++++++++--
 drivers/lightnvm/pblk-sysfs.c |  36 ++++++--
 drivers/lightnvm/pblk.h       | 198 ++++++++++++++++++++++++++++++++----------
 3 files changed, 233 insertions(+), 58 deletions(-)

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 7f88fb937440..fe04996cd3ba 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -231,20 +231,63 @@ static int pblk_set_addrf_12(struct nvm_geo *geo,
 	return dst->blk_offset + src->blk_len;
 }
 
+static int pblk_set_addrf_20(struct nvm_geo *geo,
+			     struct nvm_addr_format *adst,
+			     struct pblk_addr_format *udst)
+{
+	struct nvm_addr_format *src = &geo->c.addrf;
+
+	adst->ch_len = get_count_order(geo->num_ch);
+	adst->lun_len = get_count_order(geo->num_lun);
+	adst->chk_len = src->chk_len;
+	adst->sec_len = src->sec_len;
+
+	adst->sec_offset = 0;
+	adst->ch_offset = adst->sec_len;
+	adst->lun_offset = adst->ch_offset + adst->ch_len;
+	adst->chk_offset = adst->lun_offset + adst->lun_len;
+
+	adst->sec_mask = ((1ULL << adst->sec_len) - 1) << adst->sec_offset;
+	adst->chk_mask = ((1ULL << adst->chk_len) - 1) << adst->chk_offset;
+	adst->lun_mask = ((1ULL << adst->lun_len) - 1) << adst->lun_offset;
+	adst->ch_mask = ((1ULL << adst->ch_len) - 1) << adst->ch_offset;
+
+	udst->sec_stripe = geo->c.ws_opt;
+	udst->ch_stripe = geo->num_ch;
+	udst->lun_stripe = geo->num_lun;
+
+	udst->sec_lun_stripe = udst->sec_stripe * udst->ch_stripe;
+	udst->sec_ws_stripe = udst->sec_lun_stripe * udst->lun_stripe;
+
+	return adst->chk_offset + adst->chk_len;
+}
+
 static int pblk_set_addrf(struct pblk *pblk)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
 	int mod;
 
-	div_u64_rem(geo->c.clba, pblk->min_write_pgs, &mod);
-	if (mod) {
-		pr_err("pblk: bad configuration of sectors/pages\n");
+	switch (geo->c.version) {
+	case NVM_OCSSD_SPEC_12:
+		div_u64_rem(geo->c.clba, pblk->min_write_pgs, &mod);
+		if (mod) {
+			pr_err("pblk: bad configuration of sectors/pages\n");
+			return -EINVAL;
+		}
+
+		pblk->addrf_len = pblk_set_addrf_12(geo, (void *)&pblk->addrf);
+		break;
+	case NVM_OCSSD_SPEC_20:
+		pblk->addrf_len = pblk_set_addrf_20(geo, (void *)&pblk->addrf,
+								&pblk->uaddrf);
+		break;
+	default:
+		pr_err("pblk: OCSSD revision not supported (%d)\n",
+								geo->c.version);
 		return -EINVAL;
 	}
 
-	pblk->addrf_len = pblk_set_addrf_12(geo, (void *)&pblk->addrf);
-
 	return 0;
 }
 
@@ -1113,7 +1156,9 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 	struct pblk *pblk;
 	int ret;
 
-	if (geo->c.version != NVM_OCSSD_SPEC_12) {
+	/* pblk supports 1.2 and 2.0 versions */
+	if (!(geo->c.version == NVM_OCSSD_SPEC_12 ||
+					geo->c.version == NVM_OCSSD_SPEC_20)) {
 		pr_err("pblk: OCSSD version not supported (%u)\n",
 							geo->c.version);
 		return ERR_PTR(-EINVAL);
diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
index 1ce5b956c622..42ec00e8d393 100644
--- a/drivers/lightnvm/pblk-sysfs.c
+++ b/drivers/lightnvm/pblk-sysfs.c
@@ -113,15 +113,16 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
 {
 	struct nvm_tgt_dev *dev = pblk->dev;
 	struct nvm_geo *geo = &dev->geo;
-	struct nvm_addr_format_12 *ppaf;
-	struct nvm_addr_format_12 *geo_ppaf;
 	ssize_t sz = 0;
 
-	ppaf = (struct nvm_addr_format_12 *)&pblk->addrf;
-	geo_ppaf = (struct nvm_addr_format_12 *)&geo->c.addrf;
+	if (geo->c.version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&pblk->addrf;
+		struct nvm_addr_format_12 *geo_ppaf =
+				(struct nvm_addr_format_12 *)&geo->c.addrf;
 
-	sz = snprintf(page, PAGE_SIZE,
-		"pblk:(s:%d)ch:%d/%d,lun:%d/%d,blk:%d/%d,pg:%d/%d,pl:%d/%d,sec:%d/%d\n",
+		sz = snprintf(page, PAGE_SIZE,
+			"pblk:(s:%d)ch:%d/%d,lun:%d/%d,blk:%d/%d,pg:%d/%d,pl:%d/%d,sec:%d/%d\n",
 			pblk->addrf_len,
 			ppaf->ch_offset, ppaf->ch_len,
 			ppaf->lun_offset, ppaf->lun_len,
@@ -130,14 +131,33 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
 			ppaf->pln_offset, ppaf->pln_len,
 			ppaf->sec_offset, ppaf->sec_len);
 
-	sz += snprintf(page + sz, PAGE_SIZE - sz,
-		"device:ch:%d/%d,lun:%d/%d,blk:%d/%d,pg:%d/%d,pl:%d/%d,sec:%d/%d\n",
+		sz += snprintf(page + sz, PAGE_SIZE - sz,
+			"device:ch:%d/%d,lun:%d/%d,blk:%d/%d,pg:%d/%d,pl:%d/%d,sec:%d/%d\n",
 			geo_ppaf->ch_offset, geo_ppaf->ch_len,
 			geo_ppaf->lun_offset, geo_ppaf->lun_len,
 			geo_ppaf->blk_offset, geo_ppaf->blk_len,
 			geo_ppaf->pg_offset, geo_ppaf->pg_len,
 			geo_ppaf->pln_offset, geo_ppaf->pln_len,
 			geo_ppaf->sec_offset, geo_ppaf->sec_len);
+	} else {
+		struct nvm_addr_format *ppaf = &pblk->addrf;
+		struct nvm_addr_format *geo_ppaf = &geo->c.addrf;
+
+		sz = snprintf(page, PAGE_SIZE,
+			"pblk:(s:%d)ch:%d/%d,lun:%d/%d,chk:%d/%d/sec:%d/%d\n",
+			pblk->addrf_len,
+			ppaf->ch_offset, ppaf->ch_len,
+			ppaf->lun_offset, ppaf->lun_len,
+			ppaf->chk_offset, ppaf->chk_len,
+			ppaf->sec_offset, ppaf->sec_len);
+
+		sz += snprintf(page + sz, PAGE_SIZE - sz,
+			"device:ch:%d/%d,lun:%d/%d,chk:%d/%d,sec:%d/%d\n",
+			geo_ppaf->ch_offset, geo_ppaf->ch_len,
+			geo_ppaf->lun_offset, geo_ppaf->lun_len,
+			geo_ppaf->chk_offset, geo_ppaf->chk_len,
+			geo_ppaf->sec_offset, geo_ppaf->sec_len);
+	}
 
 	return sz;
 }
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index bc31c67b725f..d8f71a9371b1 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -574,6 +574,18 @@ enum {
 	PBLK_STATE_STOPPED = 3,
 };
 
+/* Internal format to support not power-of-2 device formats (for now) */
+struct pblk_addr_format {
+	/* gen to dev */
+	int sec_stripe;
+	int ch_stripe;
+	int lun_stripe;
+
+	/* dev to gen */
+	int sec_lun_stripe;
+	int sec_ws_stripe;
+};
+
 struct pblk {
 	struct nvm_tgt_dev *dev;
 	struct gendisk *disk;
@@ -586,7 +598,8 @@ struct pblk {
 	struct pblk_line_mgmt l_mg;		/* Line management */
 	struct pblk_line_meta lm;		/* Line metadata */
 
-	struct nvm_addr_format addrf;
+	struct nvm_addr_format addrf;	/* Aligned address format */
+	struct pblk_addr_format uaddrf;	/* Unaligned address format */
 	int addrf_len;
 
 	struct pblk_rb rwb;
@@ -967,17 +980,43 @@ static inline int pblk_ppa_to_pos(struct nvm_geo *geo, struct ppa_addr p)
 static inline struct ppa_addr addr_to_gen_ppa(struct pblk *pblk, u64 paddr,
 					      u64 line_id)
 {
-	struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&pblk->addrf;
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
 	struct ppa_addr ppa;
 
-	ppa.ppa = 0;
-	ppa.g.blk = line_id;
-	ppa.g.pg = (paddr & ppaf->pg_mask) >> ppaf->pg_offset;
-	ppa.g.lun = (paddr & ppaf->lun_mask) >> ppaf->lun_offset;
-	ppa.g.ch = (paddr & ppaf->ch_mask) >> ppaf->ch_offset;
-	ppa.g.pl = (paddr & ppaf->pln_mask) >> ppaf->pln_offset;
-	ppa.g.sec = (paddr & ppaf->sec_mask) >> ppaf->sec_offset;
+	if (geo->c.version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&pblk->addrf;
+
+		ppa.ppa = 0;
+		ppa.g.blk = line_id;
+		ppa.g.pg = (paddr & ppaf->pg_mask) >> ppaf->pg_offset;
+		ppa.g.lun = (paddr & ppaf->lun_mask) >> ppaf->lun_offset;
+		ppa.g.ch = (paddr & ppaf->ch_mask) >> ppaf->ch_offset;
+		ppa.g.pl = (paddr & ppaf->pln_mask) >> ppaf->pln_offset;
+		ppa.g.sec = (paddr & ppaf->sec_mask) >> ppaf->sec_offset;
+	} else {
+		struct pblk_addr_format *uaddrf = &pblk->uaddrf;
+		int secs, chnls, luns;
+
+		ppa.ppa = 0;
+
+		ppa.m.chk = line_id;
+
+		div_u64_rem(paddr, uaddrf->sec_stripe, &secs);
+		ppa.m.sec = secs;
+
+		sector_div(paddr, uaddrf->sec_stripe);
+		div_u64_rem(paddr, uaddrf->ch_stripe, &chnls);
+		ppa.m.grp = chnls;
+
+		sector_div(paddr, uaddrf->ch_stripe);
+		div_u64_rem(paddr, uaddrf->lun_stripe, &luns);
+		ppa.m.pu = luns;
+
+		sector_div(paddr, uaddrf->lun_stripe);
+		ppa.m.sec += uaddrf->sec_stripe * paddr;
+	}
 
 	return ppa;
 }
@@ -985,15 +1024,32 @@ static inline struct ppa_addr addr_to_gen_ppa(struct pblk *pblk, u64 paddr,
 static inline u64 pblk_dev_ppa_to_line_addr(struct pblk *pblk,
 							struct ppa_addr p)
 {
-	struct nvm_addr_format_12 *ppaf =
-				(struct nvm_addr_format_12 *)&pblk->addrf;
+	struct nvm_tgt_dev *dev = pblk->dev;
+	struct nvm_geo *geo = &dev->geo;
 	u64 paddr;
 
-	paddr = (u64)p.g.ch << ppaf->ch_offset;
-	paddr |= (u64)p.g.lun << ppaf->lun_offset;
-	paddr |= (u64)p.g.pg << ppaf->pg_offset;
-	paddr |= (u64)p.g.pl << ppaf->pln_offset;
-	paddr |= (u64)p.g.sec << ppaf->sec_offset;
+	if (geo->c.version == NVM_OCSSD_SPEC_12) {
+		struct nvm_addr_format_12 *ppaf =
+				(struct nvm_addr_format_12 *)&pblk->addrf;
+
+		paddr = (u64)p.g.ch << ppaf->ch_offset;
+		paddr |= (u64)p.g.lun << ppaf->lun_offset;
+		paddr |= (u64)p.g.pg << ppaf->pg_offset;
+		paddr |= (u64)p.g.pl << ppaf->pln_offset;
+		paddr |= (u64)p.g.sec << ppaf->sec_offset;
+	} else {
+		struct pblk_addr_format *uaddrf = &pblk->uaddrf;
+		u64 secs = (u64)p.m.sec;
+		int sec_stripe;
+
+		paddr = (u64)p.m.grp * uaddrf->sec_stripe;
+		paddr += (u64)p.m.pu * uaddrf->sec_lun_stripe;
+
+		div_u64_rem(secs, uaddrf->sec_stripe, &sec_stripe);
+		sector_div(secs, uaddrf->sec_stripe);
+		paddr += secs * uaddrf->sec_ws_stripe;
+		paddr += sec_stripe;
+	}
 
 	return paddr;
 }
@@ -1010,15 +1066,37 @@ static inline struct ppa_addr pblk_ppa32_to_ppa64(struct pblk *pblk, u32 ppa32)
 		ppa64.c.line = ppa32 & ((~0U) >> 1);
 		ppa64.c.is_cached = 1;
 	} else {
-		struct nvm_addr_format_12 *ppaf =
+		struct nvm_tgt_dev *dev = pblk->dev;
+		struct nvm_geo *geo = &dev->geo;
+
+		if (geo->c.version == NVM_OCSSD_SPEC_12) {
+			struct nvm_addr_format_12 *ppaf =
 				(struct nvm_addr_format_12 *)&pblk->addrf;
 
-		ppa64.g.ch = (ppa32 & ppaf->ch_mask) >> ppaf->ch_offset;
-		ppa64.g.lun = (ppa32 & ppaf->lun_mask) >> ppaf->lun_offset;
-		ppa64.g.blk = (ppa32 & ppaf->blk_mask) >> ppaf->blk_offset;
-		ppa64.g.pg = (ppa32 & ppaf->pg_mask) >> ppaf->pg_offset;
-		ppa64.g.pl = (ppa32 & ppaf->pln_mask) >> ppaf->pln_offset;
-		ppa64.g.sec = (ppa32 & ppaf->sec_mask) >> ppaf->sec_offset;
+			ppa64.g.ch = (ppa32 & ppaf->ch_mask) >>
+							ppaf->ch_offset;
+			ppa64.g.lun = (ppa32 & ppaf->lun_mask) >>
+							ppaf->lun_offset;
+			ppa64.g.blk = (ppa32 & ppaf->blk_mask) >>
+							ppaf->blk_offset;
+			ppa64.g.pg = (ppa32 & ppaf->pg_mask) >>
+							ppaf->pg_offset;
+			ppa64.g.pl = (ppa32 & ppaf->pln_mask) >>
+							ppaf->pln_offset;
+			ppa64.g.sec = (ppa32 & ppaf->sec_mask) >>
+							ppaf->sec_offset;
+		} else {
+			struct nvm_addr_format *lbaf = &pblk->addrf;
+
+			ppa64.m.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;
@@ -1034,15 +1112,27 @@ static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)
 		ppa32 |= ppa64.c.line;
 		ppa32 |= 1U << 31;
 	} else {
-		struct nvm_addr_format_12 *ppaf =
+		struct nvm_tgt_dev *dev = pblk->dev;
+		struct nvm_geo *geo = &dev->geo;
+
+		if (geo->c.version == NVM_OCSSD_SPEC_12) {
+			struct nvm_addr_format_12 *ppaf =
 				(struct nvm_addr_format_12 *)&pblk->addrf;
 
-		ppa32 |= ppa64.g.ch << ppaf->ch_offset;
-		ppa32 |= ppa64.g.lun << ppaf->lun_offset;
-		ppa32 |= ppa64.g.blk << ppaf->blk_offset;
-		ppa32 |= ppa64.g.pg << ppaf->pg_offset;
-		ppa32 |= ppa64.g.pl << ppaf->pln_offset;
-		ppa32 |= ppa64.g.sec << ppaf->sec_offset;
+			ppa32 |= ppa64.g.ch << ppaf->ch_offset;
+			ppa32 |= ppa64.g.lun << ppaf->lun_offset;
+			ppa32 |= ppa64.g.blk << ppaf->blk_offset;
+			ppa32 |= ppa64.g.pg << ppaf->pg_offset;
+			ppa32 |= ppa64.g.pl << ppaf->pln_offset;
+			ppa32 |= ppa64.g.sec << ppaf->sec_offset;
+		} else {
+			struct nvm_addr_format *lbaf = &pblk->addrf;
+
+			ppa32 |= ppa64.m.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;
@@ -1160,6 +1250,9 @@ static inline int pblk_set_progr_mode(struct pblk *pblk, int type)
 	struct nvm_geo *geo = &dev->geo;
 	int flags;
 
+	if (geo->c.version == NVM_OCSSD_SPEC_20)
+		return 0;
+
 	flags = geo->c.pln_mode >> 1;
 
 	if (type == PBLK_WRITE)
@@ -1179,6 +1272,9 @@ static inline int pblk_set_read_mode(struct pblk *pblk, int type)
 	struct nvm_geo *geo = &dev->geo;
 	int flags;
 
+	if (geo->c.version == NVM_OCSSD_SPEC_20)
+		return 0;
+
 	flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE;
 	if (type == PBLK_READ_SEQUENTIAL)
 		flags |= geo->c.pln_mode >> 1;
@@ -1192,16 +1288,21 @@ static inline int pblk_io_aligned(struct pblk *pblk, int nr_secs)
 }
 
 #ifdef CONFIG_NVM_DEBUG
-static inline void print_ppa(struct ppa_addr *p, char *msg, int error)
+static inline void print_ppa(struct nvm_geo *geo, struct ppa_addr *p,
+			     char *msg, int error)
 {
 	if (p->c.is_cached) {
 		pr_err("ppa: (%s: %x) cache line: %llu\n",
 				msg, error, (u64)p->c.line);
-	} else {
+	} else if (geo->c.version == NVM_OCSSD_SPEC_12) {
 		pr_err("ppa: (%s: %x):ch:%d,lun:%d,blk:%d,pg:%d,pl:%d,sec:%d\n",
 			msg, error,
 			p->g.ch, p->g.lun, p->g.blk,
 			p->g.pg, p->g.pl, p->g.sec);
+	} else {
+		pr_err("ppa: (%s: %x):ch:%d,lun:%d,chk:%d,sec:%d\n",
+			msg, error,
+			p->m.grp, p->m.pu, p->m.chk, p->m.sec);
 	}
 }
 
@@ -1211,13 +1312,13 @@ static inline void pblk_print_failed_rqd(struct pblk *pblk, struct nvm_rq *rqd,
 	int bit = -1;
 
 	if (rqd->nr_ppas ==  1) {
-		print_ppa(&rqd->ppa_addr, "rqd", error);
+		print_ppa(&pblk->dev->geo, &rqd->ppa_addr, "rqd", error);
 		return;
 	}
 
 	while ((bit = find_next_bit((void *)&rqd->ppa_status, rqd->nr_ppas,
 						bit + 1)) < rqd->nr_ppas) {
-		print_ppa(&rqd->ppa_list[bit], "rqd", error);
+		print_ppa(&pblk->dev->geo, &rqd->ppa_list[bit], "rqd", error);
 	}
 
 	pr_err("error:%d, ppa_status:%llx\n", error, rqd->ppa_status);
@@ -1233,16 +1334,25 @@ static inline int pblk_boundary_ppa_checks(struct nvm_tgt_dev *tgt_dev,
 	for (i = 0; i < nr_ppas; i++) {
 		ppa = &ppas[i];
 
-		if (!ppa->c.is_cached &&
-				ppa->g.ch < geo->num_ch &&
-				ppa->g.lun < geo->num_lun &&
-				ppa->g.pl < geo->c.num_pln &&
-				ppa->g.blk < geo->c.num_chk &&
-				ppa->g.pg < geo->c.num_pg &&
-				ppa->g.sec < geo->c.ws_min)
-			continue;
+		if (geo->c.version == NVM_OCSSD_SPEC_12) {
+			if (!ppa->c.is_cached &&
+					ppa->g.ch < geo->num_ch &&
+					ppa->g.lun < geo->num_lun &&
+					ppa->g.pl < geo->c.num_pln &&
+					ppa->g.blk < geo->c.num_chk &&
+					ppa->g.pg < geo->c.num_pg &&
+					ppa->g.sec < geo->c.ws_min)
+				continue;
+		} else {
+			if (!ppa->c.is_cached &&
+					ppa->m.grp < geo->num_ch &&
+					ppa->m.pu < geo->num_lun &&
+					ppa->m.chk < geo->c.num_chk &&
+					ppa->m.sec < geo->c.clba)
+				continue;
+		}
 
-		print_ppa(ppa, "boundary", i);
+		print_ppa(geo, ppa, "boundary", i);
 
 		return 1;
 	}
-- 
2.7.4

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

* Re: [PATCH V3 00/19] lightnvm: pblk: implement 2.0 support
  2018-02-26 13:16 ` Javier González
@ 2018-02-26 18:19   ` Matias Bjørling
  -1 siblings, 0 replies; 70+ messages in thread
From: Matias Bjørling @ 2018-02-26 18:19 UTC (permalink / raw)
  To: Javier González
  Cc: linux-block, linux-kernel, linux-nvme, Javier González

On 02/26/2018 02:16 PM, Javier González wrote:
> # Changes since V2:
> 
> Apply Matias' feedback:
>   - Remove generic nvm_id identify structure.
>   - Do not remap capabilities (cap) to media and controlled capabilities
>     (mccap). Instead, add a comment to prevent confusion when
>     crosschecking with 2.0 spec.
>   - Change maxoc and maxocpu defaults from 1 block to the max number of
>     blocks.
>   - Re-implement the generic geometry to use nvm_geo on both device and
>     targets. Maintain nvm_common_geo to make it easier to copy the common
>     part of the geometry (without having to overwrite target-specific
>     fields, which is ugly and error prone). Matias, if you still want to
>     get rid of this, we can do it.

I do, the variables should go directly in nvm_geo. Thanks.

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

* [PATCH V3 00/19] lightnvm: pblk: implement 2.0 support
@ 2018-02-26 18:19   ` Matias Bjørling
  0 siblings, 0 replies; 70+ messages in thread
From: Matias Bjørling @ 2018-02-26 18:19 UTC (permalink / raw)


On 02/26/2018 02:16 PM, Javier Gonz?lez wrote:
> # Changes since V2:
> 
> Apply Matias' feedback:
>   - Remove generic nvm_id identify structure.
>   - Do not remap capabilities (cap) to media and controlled capabilities
>     (mccap). Instead, add a comment to prevent confusion when
>     crosschecking with 2.0 spec.
>   - Change maxoc and maxocpu defaults from 1 block to the max number of
>     blocks.
>   - Re-implement the generic geometry to use nvm_geo on both device and
>     targets. Maintain nvm_common_geo to make it easier to copy the common
>     part of the geometry (without having to overwrite target-specific
>     fields, which is ugly and error prone). Matias, if you still want to
>     get rid of this, we can do it.

I do, the variables should go directly in nvm_geo. Thanks.

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

* Re: [PATCH V3 00/19] lightnvm: pblk: implement 2.0 support
  2018-02-26 18:19   ` Matias Bjørling
@ 2018-02-26 18:21     ` Javier Gonzalez
  -1 siblings, 0 replies; 70+ messages in thread
From: Javier Gonzalez @ 2018-02-26 18:21 UTC (permalink / raw)
  To: Matias Bjørling; +Cc: linux-block, linux-kernel, linux-nvme

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

> On 26 Feb 2018, at 19.19, Matias Bjørling <mb@lightnvm.io> wrote:
> 
> On 02/26/2018 02:16 PM, Javier González wrote:
>> # Changes since V2:
>> Apply Matias' feedback:
>>  - Remove generic nvm_id identify structure.
>>  - Do not remap capabilities (cap) to media and controlled capabilities
>>    (mccap). Instead, add a comment to prevent confusion when
>>    crosschecking with 2.0 spec.
>>  - Change maxoc and maxocpu defaults from 1 block to the max number of
>>    blocks.
>>  - Re-implement the generic geometry to use nvm_geo on both device and
>>    targets. Maintain nvm_common_geo to make it easier to copy the common
>>    part of the geometry (without having to overwrite target-specific
>>    fields, which is ugly and error prone). Matias, if you still want to
>>    get rid of this, we can do it.
> 
> I do, the variables should go directly in nvm_geo. Thanks.

Ok. Is the rest ok with you?

Javier

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

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

* [PATCH V3 00/19] lightnvm: pblk: implement 2.0 support
@ 2018-02-26 18:21     ` Javier Gonzalez
  0 siblings, 0 replies; 70+ messages in thread
From: Javier Gonzalez @ 2018-02-26 18:21 UTC (permalink / raw)


> On 26 Feb 2018,@19.19, Matias Bj?rling <mb@lightnvm.io> wrote:
> 
> On 02/26/2018 02:16 PM, Javier Gonz?lez wrote:
>> # Changes since V2:
>> Apply Matias' feedback:
>>  - Remove generic nvm_id identify structure.
>>  - Do not remap capabilities (cap) to media and controlled capabilities
>>    (mccap). Instead, add a comment to prevent confusion when
>>    crosschecking with 2.0 spec.
>>  - Change maxoc and maxocpu defaults from 1 block to the max number of
>>    blocks.
>>  - Re-implement the generic geometry to use nvm_geo on both device and
>>    targets. Maintain nvm_common_geo to make it easier to copy the common
>>    part of the geometry (without having to overwrite target-specific
>>    fields, which is ugly and error prone). Matias, if you still want to
>>    get rid of this, we can do it.
> 
> I do, the variables should go directly in nvm_geo. Thanks.

Ok. Is the rest ok with you?

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

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

* Re: [PATCH V3 00/19] lightnvm: pblk: implement 2.0 support
  2018-02-26 18:21     ` Javier Gonzalez
@ 2018-02-26 18:24       ` Matias Bjørling
  -1 siblings, 0 replies; 70+ messages in thread
From: Matias Bjørling @ 2018-02-26 18:24 UTC (permalink / raw)
  To: Javier Gonzalez; +Cc: linux-block, linux-kernel, linux-nvme

On 02/26/2018 07:21 PM, Javier Gonzalez wrote:
>> On 26 Feb 2018, at 19.19, Matias Bjørling <mb@lightnvm.io> wrote:
>>
>> On 02/26/2018 02:16 PM, Javier González wrote:
>>> # Changes since V2:
>>> Apply Matias' feedback:
>>>   - Remove generic nvm_id identify structure.
>>>   - Do not remap capabilities (cap) to media and controlled capabilities
>>>     (mccap). Instead, add a comment to prevent confusion when
>>>     crosschecking with 2.0 spec.
>>>   - Change maxoc and maxocpu defaults from 1 block to the max number of
>>>     blocks.
>>>   - Re-implement the generic geometry to use nvm_geo on both device and
>>>     targets. Maintain nvm_common_geo to make it easier to copy the common
>>>     part of the geometry (without having to overwrite target-specific
>>>     fields, which is ugly and error prone). Matias, if you still want to
>>>     get rid of this, we can do it.
>>
>> I do, the variables should go directly in nvm_geo. Thanks.
> 
> Ok. Is the rest ok with you?
>
I'll go through it when the rebase is posted. Most of the patches is 
dependent on the first patch.

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

* [PATCH V3 00/19] lightnvm: pblk: implement 2.0 support
@ 2018-02-26 18:24       ` Matias Bjørling
  0 siblings, 0 replies; 70+ messages in thread
From: Matias Bjørling @ 2018-02-26 18:24 UTC (permalink / raw)


On 02/26/2018 07:21 PM, Javier Gonzalez wrote:
>> On 26 Feb 2018,@19.19, Matias Bj?rling <mb@lightnvm.io> wrote:
>>
>> On 02/26/2018 02:16 PM, Javier Gonz?lez wrote:
>>> # Changes since V2:
>>> Apply Matias' feedback:
>>>   - Remove generic nvm_id identify structure.
>>>   - Do not remap capabilities (cap) to media and controlled capabilities
>>>     (mccap). Instead, add a comment to prevent confusion when
>>>     crosschecking with 2.0 spec.
>>>   - Change maxoc and maxocpu defaults from 1 block to the max number of
>>>     blocks.
>>>   - Re-implement the generic geometry to use nvm_geo on both device and
>>>     targets. Maintain nvm_common_geo to make it easier to copy the common
>>>     part of the geometry (without having to overwrite target-specific
>>>     fields, which is ugly and error prone). Matias, if you still want to
>>>     get rid of this, we can do it.
>>
>> I do, the variables should go directly in nvm_geo. Thanks.
> 
> Ok. Is the rest ok with you?
>
I'll go through it when the rebase is posted. Most of the patches is 
dependent on the first patch.

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

* Re: [PATCH V3 00/19] lightnvm: pblk: implement 2.0 support
  2018-02-26 18:24       ` Matias Bjørling
@ 2018-02-26 18:27         ` Javier Gonzalez
  -1 siblings, 0 replies; 70+ messages in thread
From: Javier Gonzalez @ 2018-02-26 18:27 UTC (permalink / raw)
  To: Matias Bjørling; +Cc: linux-block, linux-kernel, linux-nvme

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

> On 26 Feb 2018, at 19.24, Matias Bjørling <mb@lightnvm.io> wrote:
> 
> On 02/26/2018 07:21 PM, Javier Gonzalez wrote:
>>> On 26 Feb 2018, at 19.19, Matias Bjørling <mb@lightnvm.io> wrote:
>>> 
>>> On 02/26/2018 02:16 PM, Javier González wrote:
>>>> # Changes since V2:
>>>> Apply Matias' feedback:
>>>>  - Remove generic nvm_id identify structure.
>>>>  - Do not remap capabilities (cap) to media and controlled capabilities
>>>>    (mccap). Instead, add a comment to prevent confusion when
>>>>    crosschecking with 2.0 spec.
>>>>  - Change maxoc and maxocpu defaults from 1 block to the max number of
>>>>    blocks.
>>>>  - Re-implement the generic geometry to use nvm_geo on both device and
>>>>    targets. Maintain nvm_common_geo to make it easier to copy the common
>>>>    part of the geometry (without having to overwrite target-specific
>>>>    fields, which is ugly and error prone). Matias, if you still want to
>>>>    get rid of this, we can do it.
>>> 
>>> I do, the variables should go directly in nvm_geo. Thanks.
>> Ok. Is the rest ok with you?
> I'll go through it when the rebase is posted. Most of the patches is
> dependent on the first patch.

As it is now, it will be basically %s/geo->c.X/geo->X/g. If you can look
at the first patch now, I can put all comments in a single version more,
instead of going through one extra cycle...



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

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

* [PATCH V3 00/19] lightnvm: pblk: implement 2.0 support
@ 2018-02-26 18:27         ` Javier Gonzalez
  0 siblings, 0 replies; 70+ messages in thread
From: Javier Gonzalez @ 2018-02-26 18:27 UTC (permalink / raw)


> On 26 Feb 2018,@19.24, Matias Bj?rling <mb@lightnvm.io> wrote:
> 
> On 02/26/2018 07:21 PM, Javier Gonzalez wrote:
>>> On 26 Feb 2018,@19.19, Matias Bj?rling <mb@lightnvm.io> wrote:
>>> 
>>> On 02/26/2018 02:16 PM, Javier Gonz?lez wrote:
>>>> # Changes since V2:
>>>> Apply Matias' feedback:
>>>>  - Remove generic nvm_id identify structure.
>>>>  - Do not remap capabilities (cap) to media and controlled capabilities
>>>>    (mccap). Instead, add a comment to prevent confusion when
>>>>    crosschecking with 2.0 spec.
>>>>  - Change maxoc and maxocpu defaults from 1 block to the max number of
>>>>    blocks.
>>>>  - Re-implement the generic geometry to use nvm_geo on both device and
>>>>    targets. Maintain nvm_common_geo to make it easier to copy the common
>>>>    part of the geometry (without having to overwrite target-specific
>>>>    fields, which is ugly and error prone). Matias, if you still want to
>>>>    get rid of this, we can do it.
>>> 
>>> I do, the variables should go directly in nvm_geo. Thanks.
>> Ok. Is the rest ok with you?
> I'll go through it when the rebase is posted. Most of the patches is
> dependent on the first patch.

As it is now, it will be basically %s/geo->c.X/geo->X/g. If you can look
at the first patch now, I can put all comments in a single version more,
instead of going through one extra cycle...


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

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

* Re: [PATCH V3 00/19] lightnvm: pblk: implement 2.0 support
  2018-02-26 18:27         ` Javier Gonzalez
@ 2018-02-26 18:33           ` Matias Bjørling
  -1 siblings, 0 replies; 70+ messages in thread
From: Matias Bjørling @ 2018-02-26 18:33 UTC (permalink / raw)
  To: Javier Gonzalez; +Cc: linux-block, linux-kernel, linux-nvme

On 02/26/2018 07:27 PM, Javier Gonzalez wrote:
>> On 26 Feb 2018, at 19.24, Matias Bjørling <mb@lightnvm.io> wrote:
>>
>> On 02/26/2018 07:21 PM, Javier Gonzalez wrote:
>>>> On 26 Feb 2018, at 19.19, Matias Bjørling <mb@lightnvm.io> wrote:
>>>>
>>>> On 02/26/2018 02:16 PM, Javier González wrote:
>>>>> # Changes since V2:
>>>>> Apply Matias' feedback:
>>>>>   - Remove generic nvm_id identify structure.
>>>>>   - Do not remap capabilities (cap) to media and controlled capabilities
>>>>>     (mccap). Instead, add a comment to prevent confusion when
>>>>>     crosschecking with 2.0 spec.
>>>>>   - Change maxoc and maxocpu defaults from 1 block to the max number of
>>>>>     blocks.
>>>>>   - Re-implement the generic geometry to use nvm_geo on both device and
>>>>>     targets. Maintain nvm_common_geo to make it easier to copy the common
>>>>>     part of the geometry (without having to overwrite target-specific
>>>>>     fields, which is ugly and error prone). Matias, if you still want to
>>>>>     get rid of this, we can do it.
>>>>
>>>> I do, the variables should go directly in nvm_geo. Thanks.
>>> Ok. Is the rest ok with you?
>> I'll go through it when the rebase is posted. Most of the patches is
>> dependent on the first patch.
> 
> As it is now, it will be basically %s/geo->c.X/geo->X/g. If you can look
> at the first patch now, I can put all comments in a single version more,
> instead of going through one extra cycle...
> 
> 

Also the variable dev_geo -> geo. I'm good with just getting the updated 
version before posting the full patch set again.

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

* [PATCH V3 00/19] lightnvm: pblk: implement 2.0 support
@ 2018-02-26 18:33           ` Matias Bjørling
  0 siblings, 0 replies; 70+ messages in thread
From: Matias Bjørling @ 2018-02-26 18:33 UTC (permalink / raw)


On 02/26/2018 07:27 PM, Javier Gonzalez wrote:
>> On 26 Feb 2018,@19.24, Matias Bj?rling <mb@lightnvm.io> wrote:
>>
>> On 02/26/2018 07:21 PM, Javier Gonzalez wrote:
>>>> On 26 Feb 2018,@19.19, Matias Bj?rling <mb@lightnvm.io> wrote:
>>>>
>>>> On 02/26/2018 02:16 PM, Javier Gonz?lez wrote:
>>>>> # Changes since V2:
>>>>> Apply Matias' feedback:
>>>>>   - Remove generic nvm_id identify structure.
>>>>>   - Do not remap capabilities (cap) to media and controlled capabilities
>>>>>     (mccap). Instead, add a comment to prevent confusion when
>>>>>     crosschecking with 2.0 spec.
>>>>>   - Change maxoc and maxocpu defaults from 1 block to the max number of
>>>>>     blocks.
>>>>>   - Re-implement the generic geometry to use nvm_geo on both device and
>>>>>     targets. Maintain nvm_common_geo to make it easier to copy the common
>>>>>     part of the geometry (without having to overwrite target-specific
>>>>>     fields, which is ugly and error prone). Matias, if you still want to
>>>>>     get rid of this, we can do it.
>>>>
>>>> I do, the variables should go directly in nvm_geo. Thanks.
>>> Ok. Is the rest ok with you?
>> I'll go through it when the rebase is posted. Most of the patches is
>> dependent on the first patch.
> 
> As it is now, it will be basically %s/geo->c.X/geo->X/g. If you can look
> at the first patch now, I can put all comments in a single version more,
> instead of going through one extra cycle...
> 
> 

Also the variable dev_geo -> geo. I'm good with just getting the updated 
version before posting the full patch set again.

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

* Re: [PATCH 17/19] lightnvm: pblk: implement get log report chunk
  2018-02-26 13:17   ` Javier González
@ 2018-02-26 19:04     ` Matias Bjørling
  -1 siblings, 0 replies; 70+ messages in thread
From: Matias Bjørling @ 2018-02-26 19:04 UTC (permalink / raw)
  To: Javier González
  Cc: linux-block, linux-kernel, linux-nvme, Javier González,
	Javier González

On 02/26/2018 02:17 PM, Javier González wrote:
> From: Javier González <javier@javigon.com>
> 
> In preparation of pblk supporting 2.0, implement the get log report
> chunk in pblk.
> 
> This patch only replicates de bad block functionality as the rest of the
> metadata requires new pblk functionality (e.g., wear-index to implement
> wear-leveling). 


"This functionality will come in future patches."

I think the  above belongs in the cover letter, not in the patch 
description.

> 
> Signed-off-by: Javier González <javier@cnexlabs.com>
> ---
>   drivers/lightnvm/pblk-core.c  | 121 +++++++++++++++++++----
>   drivers/lightnvm/pblk-init.c  | 218 ++++++++++++++++++++++++++++++------------
>   drivers/lightnvm/pblk-sysfs.c |  67 +++++++++++++
>   drivers/lightnvm/pblk.h       |  20 ++++
>   4 files changed, 346 insertions(+), 80 deletions(-)
> 
> diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
> index 1d7c6313f3d9..ce6a7cfdba66 100644
> --- a/drivers/lightnvm/pblk-core.c
> +++ b/drivers/lightnvm/pblk-core.c
> @@ -44,11 +44,12 @@ static void pblk_line_mark_bb(struct work_struct *work)
>   }
>   
>   static void pblk_mark_bb(struct pblk *pblk, struct pblk_line *line,
> -			 struct ppa_addr *ppa)
> +			 struct ppa_addr ppa_addr)
>   {
>   	struct nvm_tgt_dev *dev = pblk->dev;
>   	struct nvm_geo *geo = &dev->geo;
> -	int pos = pblk_ppa_to_pos(geo, *ppa);
> +	struct ppa_addr *ppa;
> +	int pos = pblk_ppa_to_pos(geo, ppa_addr);
>   
>   	pr_debug("pblk: erase failed: line:%d, pos:%d\n", line->id, pos);
>   	atomic_long_inc(&pblk->erase_failed);
> @@ -58,6 +59,15 @@ static void pblk_mark_bb(struct pblk *pblk, struct pblk_line *line,
>   		pr_err("pblk: attempted to erase bb: line:%d, pos:%d\n",
>   							line->id, pos);
>   
> +	/* Not necessary to mark bad blocks on 2.0 spec. */
> +	if (geo->c.version == NVM_OCSSD_SPEC_20)
> +		return;
> +
> +	ppa = kmalloc(sizeof(struct ppa_addr), GFP_ATOMIC);
> +	if (!ppa)
> +		return;
> +
> +	*ppa = ppa_addr;
>   	pblk_gen_run_ws(pblk, NULL, ppa, pblk_line_mark_bb,
>   						GFP_ATOMIC, pblk->bb_wq);
>   }
> @@ -69,16 +79,8 @@ static void __pblk_end_io_erase(struct pblk *pblk, struct nvm_rq *rqd)
>   	line = &pblk->lines[pblk_ppa_to_line(rqd->ppa_addr)];
>   	atomic_dec(&line->left_seblks);
>   
> -	if (rqd->error) {
> -		struct ppa_addr *ppa;
> -
> -		ppa = kmalloc(sizeof(struct ppa_addr), GFP_ATOMIC);
> -		if (!ppa)
> -			return;
> -
> -		*ppa = rqd->ppa_addr;
> -		pblk_mark_bb(pblk, line, ppa);
> -	}
> +	if (rqd->error)
> +		pblk_mark_bb(pblk, line, rqd->ppa_addr);
>   
>   	atomic_dec(&pblk->inflight_io);
>   }
> @@ -92,6 +94,50 @@ static void pblk_end_io_erase(struct nvm_rq *rqd)
>   	mempool_free(rqd, pblk->e_rq_pool);
>   }
>   
> +/*
> + * Get information for all chunks from the device.
> + *
> + * The caller is responsible for freeing the returned structure
> + */
> +struct nvm_chk_meta *pblk_chunk_get_info(struct pblk *pblk)
> +{
> +	struct nvm_tgt_dev *dev = pblk->dev;
> +	struct nvm_geo *geo = &dev->geo;
> +	struct nvm_chk_meta *meta;
> +	struct ppa_addr ppa;
> +	unsigned long len;
> +	int ret;
> +
> +	ppa.ppa = 0;
> +
> +	len = geo->all_chunks * sizeof(*meta);
> +	meta = kzalloc(len, GFP_KERNEL);
> +	if (!meta)
> +		return ERR_PTR(-ENOMEM);
> +
> +	ret = nvm_get_chunk_meta(dev, meta, ppa, geo->all_chunks);
> +	if (ret) {
> +		pr_err("pblk: could not get chunk metadata (%d)\n", ret);
> +		kfree(meta);
> +		return ERR_PTR(-EIO);
> +	}
> +
> +	return meta;
> +}
> +
> +struct nvm_chk_meta *pblk_chunk_get_off(struct pblk *pblk,
> +					      struct nvm_chk_meta *meta,
> +					      struct ppa_addr ppa)
> +{
> +	struct nvm_tgt_dev *dev = pblk->dev;
> +	struct nvm_geo *geo = &dev->geo;
> +	int ch_off = ppa.m.grp * geo->c.num_chk * geo->num_lun;
> +	int lun_off = ppa.m.pu * geo->c.num_chk;
> +	int chk_off = ppa.m.chk;
> +
> +	return meta + ch_off + lun_off + chk_off;
> +}
> +
>   void __pblk_map_invalidate(struct pblk *pblk, struct pblk_line *line,
>   			   u64 paddr)
>   {
> @@ -1094,10 +1140,38 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>   	return 1;
>   }
>   
> +static int pblk_prepare_new_line(struct pblk *pblk, struct pblk_line *line)
> +{
> +	struct pblk_line_meta *lm = &pblk->lm;
> +	struct nvm_tgt_dev *dev = pblk->dev;
> +	struct nvm_geo *geo = &dev->geo;
> +	int blk_to_erase = atomic_read(&line->blk_in_line);
> +	int i;
> +
> +	for (i = 0; i < lm->blk_per_line; i++) {
> +		int state = line->chks[i].state;
> +		struct pblk_lun *rlun = &pblk->luns[i];
> +
> +		/* Free chunks should not be erased */
> +		if (state & NVM_CHK_ST_FREE) {
> +			set_bit(pblk_ppa_to_pos(geo, rlun->chunk_bppa),
> +					line->erase_bitmap);
> +			blk_to_erase--;
> +			line->chks[i].state = NVM_CHK_ST_HOST_USE;


Can you help me understand why you want to use The NVM_CHK_ST_HOST_USE? 
Why would I care if the chunk state is HOST_USE? A target instance 
should not be able to see states from other chunks it doesn't own. and 
in that case, why have a separate state?


> +		}
> +
> +		WARN_ONCE(state & NVM_CHK_ST_OPEN,
> +				"pblk: open chunk in new line: %d\n",
> +				line->id);
> +	}
> +
> +	return blk_to_erase;
> +}
> +
>   static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>   {
>   	struct pblk_line_meta *lm = &pblk->lm;
> -	int blk_in_line = atomic_read(&line->blk_in_line);
> +	int blk_to_erase;
>   
>   	line->map_bitmap = kzalloc(lm->sec_bitmap_len, GFP_ATOMIC);
>   	if (!line->map_bitmap)
> @@ -1110,7 +1184,21 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>   		return -ENOMEM;
>   	}
>   
> +	/* Bad blocks do not need to be erased */
> +	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
> +
>   	spin_lock(&line->lock);
> +
> +	/* If we have not written to this line, we need to mark up free chunks
> +	 * as already erased
> +	 */
> +	if (line->state == PBLK_LINESTATE_NEW) {
> +		blk_to_erase = pblk_prepare_new_line(pblk, line);
> +		line->state = PBLK_LINESTATE_FREE;
> +	} else {
> +		blk_to_erase = atomic_read(&line->blk_in_line);
> +	}
> +
>   	if (line->state != PBLK_LINESTATE_FREE) {
>   		kfree(line->map_bitmap);
>   		kfree(line->invalid_bitmap);
> @@ -1122,15 +1210,12 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>   
>   	line->state = PBLK_LINESTATE_OPEN;
>   
> -	atomic_set(&line->left_eblks, blk_in_line);
> -	atomic_set(&line->left_seblks, blk_in_line);
> +	atomic_set(&line->left_eblks, blk_to_erase);
> +	atomic_set(&line->left_seblks, blk_to_erase);
>   
>   	line->meta_distance = lm->meta_distance;
>   	spin_unlock(&line->lock);
>   
> -	/* Bad blocks do not need to be erased */
> -	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
> -
>   	kref_init(&line->ref);
>   
>   	return 0;
> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
> index ec39800eea42..cf4f49d48aed 100644
> --- a/drivers/lightnvm/pblk-init.c
> +++ b/drivers/lightnvm/pblk-init.c
> @@ -401,6 +401,7 @@ static void pblk_line_meta_free(struct pblk_line *line)
>   {
>   	kfree(line->blk_bitmap);
>   	kfree(line->erase_bitmap);
> +	kfree(line->chks);
>   }
>   
>   static void pblk_lines_free(struct pblk *pblk)
> @@ -440,54 +441,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->c.num_chk * geo->c.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;
>   
> -	for (i = 0; i < blk_per_line; i++) {
> -		struct pblk_lun *rlun = &pblk->luns[i];
> -		u8 *lun_bb_log = bb_log + i * blk_per_line;
> -
> -		if (lun_bb_log[line->id] == NVM_BLK_T_FREE)
> -			continue;
> -
> -		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
> -		bb_cnt++;
> -	}
> -
> -	return bb_cnt;
> +	if (geo->c.version == NVM_OCSSD_SPEC_12)
> +		return pblk_bb_get_meta(pblk);
> +	else
> +		return pblk_chunk_get_info(pblk);

This 1.2 or 2.0 would be nice to have inside the lightnvm core. A target 
should not care weather it is a 1.2 or 2.0 device.

>   }
>   
>   static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
> @@ -516,6 +507,7 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
>   
>   		rlun = &pblk->luns[i];
>   		rlun->bppa = luns[lunid];
> +		rlun->chunk_bppa = luns[i];
>   
>   		sema_init(&rlun->wr_sem, 1);
>   	}
> @@ -695,8 +687,125 @@ static int pblk_lines_alloc_metadata(struct pblk *pblk)
>   	return -ENOMEM;
>   }
>   
> -static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
> -				void *chunk_log, long *nr_bad_blks)
> +static int pblk_setup_line_meta_12(struct pblk *pblk, struct pblk_line *line,
> +				   void *chunk_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->c.num_chk * geo->c.pln_mode;
> +
> +	for (i = 0; i < lm->blk_per_line; i++) {
> +		struct pblk_chunk *chunk = &line->chks[i];
> +		struct pblk_lun *rlun = &pblk->luns[i];
> +		u8 *lun_bb_meta = chunk_meta + i * chk_per_lun;
> +
> +		/*
> +		 * In 1.2 spec. chunk state is not persisted by the device. Thus
> +		 * some of the values are reset each time pblk is instantiated.
> +		 */
> +		if (lun_bb_meta[line->id] == NVM_BLK_T_FREE)
> +			chunk->state =  NVM_CHK_ST_HOST_USE;
> +		else
> +			chunk->state = NVM_CHK_ST_OFFLINE;
> +
> +		chunk->type = NVM_CHK_TP_W_SEQ;
> +		chunk->wi = 0;
> +		chunk->slba = -1;
> +		chunk->cnlb = geo->c.clba;
> +		chunk->wp = 0;
> +
> +		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
> +			continue;
> +
> +		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
> +		nr_bad_chks++;
> +	}
> +
> +	return nr_bad_chks;
> +}
> +
> +static int pblk_setup_line_meta_20(struct pblk *pblk, struct pblk_line *line,
> +				   struct nvm_chk_meta *meta)
> +{
> +	struct nvm_tgt_dev *dev = pblk->dev;
> +	struct nvm_geo *geo = &dev->geo;
> +	struct pblk_line_meta *lm = &pblk->lm;
> +	int i, nr_bad_chks = 0;
> +
> +	for (i = 0; i < lm->blk_per_line; i++) {
> +		struct pblk_chunk *chunk = &line->chks[i];
> +		struct pblk_lun *rlun = &pblk->luns[i];
> +		struct nvm_chk_meta *chunk_meta;
> +		struct ppa_addr ppa;
> +
> +		ppa = rlun->chunk_bppa;
> +		ppa.m.chk = line->id;
> +		chunk_meta = pblk_chunk_get_off(pblk, meta, ppa);
> +
> +		chunk->state = chunk_meta->state;
> +		chunk->type = chunk_meta->type;
> +		chunk->wi = chunk_meta->wi;
> +		chunk->slba = chunk_meta->slba;
> +		chunk->cnlb = chunk_meta->cnlb;
> +		chunk->wp = chunk_meta->wp;
> +
> +		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
> +			continue;
> +
> +		if (chunk->type & NVM_CHK_TP_SZ_SPEC) {
> +			WARN_ONCE(1, "pblk: custom-sized chunks unsupported\n");
> +			continue;
> +		}
> +
> +		set_bit(pblk_ppa_to_pos(geo, rlun->chunk_bppa),
> +							line->blk_bitmap);
> +		nr_bad_chks++;
> +	}
> +
> +	return nr_bad_chks;
> +}
> +
> +static long pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
> +				 void *chunk_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->c.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;
>   
> @@ -710,7 +819,13 @@ static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>   		return -ENOMEM;
>   	}
>   
> -	*nr_bad_blks = pblk_bb_line(pblk, line, chunk_log, lm->blk_per_line);
> +	line->chks = kmalloc(lm->blk_per_line * sizeof(struct pblk_chunk),
> +								GFP_KERNEL);
> +	if (!line->chks) {
> +		kfree(line->erase_bitmap);
> +		kfree(line->blk_bitmap);
> +		return -ENOMEM;
> +	}
>   
>   	return 0;
>   }
> @@ -722,9 +837,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;
> +	void *chunk_meta;
>   	unsigned int smeta_len, emeta_len;
> -	long nr_bad_blks = 0, nr_free_blks = 0;
> +	long nr_free_chks = 0;
>   	int bb_distance, max_write_ppas;
>   	int i, ret;
>   
> @@ -743,6 +858,7 @@ static int pblk_lines_init(struct pblk *pblk)
>   	l_mg->log_line = l_mg->data_line = NULL;
>   	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
>   	l_mg->nr_free_lines = 0;
> +	atomic_set(&l_mg->sysfs_line_state, -1);
>   	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
>   
>   	lm->sec_per_line = geo->c.clba * geo->all_luns;
> @@ -841,53 +957,31 @@ static int pblk_lines_init(struct pblk *pblk)
>   		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);
> +	chunk_meta = pblk_chunk_get_meta(pblk);
> +	if (IS_ERR(chunk_meta)) {
> +		pr_err("pblk: could not get chunk log (%lu)\n",
> +							PTR_ERR(chunk_meta));
> +		ret = PTR_ERR(chunk_meta);
>   		goto fail_free_lines;
>   	}
>   
>   	for (i = 0; i < l_mg->nr_lines; i++) {
> -		int chk_in_line;
> -
>   		line = &pblk->lines[i];
>   
> -		line->pblk = pblk;
> -		line->id = i;
> -		line->type = PBLK_LINETYPE_FREE;
> -		line->state = PBLK_LINESTATE_FREE;
> -		line->gc_group = PBLK_LINEGC_NONE;
> -		line->vsc = &l_mg->vsc_list[i];
> -		spin_lock_init(&line->lock);
> -
> -		ret = pblk_setup_line_meta(pblk, line, chunk_log, &nr_bad_blks);
> +		ret = pblk_alloc_line_meta(pblk, line);
>   		if (ret)
> -			goto fail_free_chunk_log;
> +			goto fail_free_chunk_meta;
>   
> -		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_chunk_log:
> -	kfree(chunk_log);
> +fail_free_chunk_meta:
> +	kfree(chunk_meta);
>   	while (--i >= 0)
>   		pblk_line_meta_free(&pblk->lines[i]);
>   fail_free_lines:
> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
> index ccfb3abd2773..1ce5b956c622 100644
> --- a/drivers/lightnvm/pblk-sysfs.c
> +++ b/drivers/lightnvm/pblk-sysfs.c
> @@ -142,6 +142,40 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
>   	return sz;
>   }
>   
> +static ssize_t pblk_sysfs_line_state_show(struct pblk *pblk, char *page)
> +{
> +	struct pblk_line_meta *lm = &pblk->lm;
> +	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
> +	struct pblk_line *line;
> +	int line_id = atomic_read(&l_mg->sysfs_line_state);
> +	ssize_t sz = 0;
> +	int i;
> +
> +	if (line_id < 0 || line_id >= l_mg->nr_lines)
> +		return 0;
> +
> +	sz = snprintf(page, PAGE_SIZE,
> +		"line\tchunk\tstate\ttype\twear-index\tslba\t\tcnlb\twp\n");
> +
> +	line = &pblk->lines[line_id];
> +
> +	for (i = 0; i < lm->blk_per_line; i++) {
> +		struct pblk_chunk *chunk = &line->chks[i];
> +
> +		sz += snprintf(page + sz, PAGE_SIZE - sz,
> +				"%d\t%d\t%d\t%d\t%d\t\t%llu\t\t%llu\t%llu\n",
> +				line->id, i,
> +				chunk->state,
> +				chunk->type,
> +				chunk->wi,
> +				chunk->slba,
> +				chunk->cnlb,
> +				chunk->wp);
> +	}
> +
> +	return sz;
> +}
> +
>   static ssize_t pblk_sysfs_lines(struct pblk *pblk, char *page)
>   {
>   	struct nvm_tgt_dev *dev = pblk->dev;
> @@ -398,6 +432,29 @@ static ssize_t pblk_sysfs_stats_debug(struct pblk *pblk, char *page)
>   }
>   #endif
>   
> +
> +static ssize_t pblk_sysfs_line_state_store(struct pblk *pblk, const char *page,
> +					   size_t len)
> +{
> +	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
> +	size_t c_len;
> +	int line_id;
> +
> +	c_len = strcspn(page, "\n");
> +	if (c_len >= len)
> +		return -EINVAL;
> +
> +	if (kstrtouint(page, 0, &line_id))
> +		return -EINVAL;
> +
> +	if (line_id < 0 || line_id >= l_mg->nr_lines)
> +		return -EINVAL;
> +
> +	atomic_set(&l_mg->sysfs_line_state, line_id);
> +
> +	return len;
> +}
> +
>   static ssize_t pblk_sysfs_gc_force(struct pblk *pblk, const char *page,
>   				   size_t len)
>   {
> @@ -529,6 +586,11 @@ static struct attribute sys_lines_info_attr = {
>   	.mode = 0444,
>   };
>   
> +static struct attribute sys_line_state_attr = {
> +	.name = "line_state",
> +	.mode = 0644,
> +};
> +
>   static struct attribute sys_gc_force = {
>   	.name = "gc_force",
>   	.mode = 0200,
> @@ -572,6 +634,7 @@ static struct attribute *pblk_attrs[] = {
>   	&sys_stats_ppaf_attr,
>   	&sys_lines_attr,
>   	&sys_lines_info_attr,
> +	&sys_line_state_attr,
>   	&sys_write_amp_mileage,
>   	&sys_write_amp_trip,
>   	&sys_padding_dist,
> @@ -602,6 +665,8 @@ static ssize_t pblk_sysfs_show(struct kobject *kobj, struct attribute *attr,
>   		return pblk_sysfs_lines(pblk, buf);
>   	else if (strcmp(attr->name, "lines_info") == 0)
>   		return pblk_sysfs_lines_info(pblk, buf);
> +	else if (strcmp(attr->name, "line_state") == 0)
> +		return pblk_sysfs_line_state_show(pblk, buf);
>   	else if (strcmp(attr->name, "max_sec_per_write") == 0)
>   		return pblk_sysfs_get_sec_per_write(pblk, buf);
>   	else if (strcmp(attr->name, "write_amp_mileage") == 0)
> @@ -628,6 +693,8 @@ static ssize_t pblk_sysfs_store(struct kobject *kobj, struct attribute *attr,
>   		return pblk_sysfs_set_sec_per_write(pblk, buf, len);
>   	else if (strcmp(attr->name, "write_amp_trip") == 0)
>   		return pblk_sysfs_set_write_amp_trip(pblk, buf, len);
> +	else if (strcmp(attr->name, "line_state") == 0)
> +		return pblk_sysfs_line_state_store(pblk, buf, len);
>   	else if (strcmp(attr->name, "padding_dist") == 0)
>   		return pblk_sysfs_set_padding_dist(pblk, buf, len);
>   	return 0;
> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
> index 6e1fcd1a538a..bc31c67b725f 100644
> --- a/drivers/lightnvm/pblk.h
> +++ b/drivers/lightnvm/pblk.h
> @@ -201,6 +201,8 @@ struct pblk_rb {
>   
>   struct pblk_lun {
>   	struct ppa_addr bppa;
> +	struct ppa_addr chunk_bppa;
> +
>   	struct semaphore wr_sem;
>   };
>   
> @@ -297,6 +299,7 @@ enum {
>   	PBLK_LINETYPE_DATA = 2,
>   
>   	/* Line state */
> +	PBLK_LINESTATE_NEW = 9,
>   	PBLK_LINESTATE_FREE = 10,
>   	PBLK_LINESTATE_OPEN = 11,
>   	PBLK_LINESTATE_CLOSED = 12,
> @@ -412,6 +415,15 @@ struct pblk_smeta {
>   	struct line_smeta *buf;		/* smeta buffer in persistent format */
>   };
>   
> +struct pblk_chunk {
> +	int state;
> +	int type;
> +	int wi;
> +	u64 slba;
> +	u64 cnlb;
> +	u64 wp;
> +};
> +

How come the code replicate the nvm_chk_meta data structure?

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

* [PATCH 17/19] lightnvm: pblk: implement get log report chunk
@ 2018-02-26 19:04     ` Matias Bjørling
  0 siblings, 0 replies; 70+ messages in thread
From: Matias Bjørling @ 2018-02-26 19:04 UTC (permalink / raw)


On 02/26/2018 02:17 PM, Javier Gonz?lez wrote:
> From: Javier Gonz?lez <javier at javigon.com>
> 
> In preparation of pblk supporting 2.0, implement the get log report
> chunk in pblk.
> 
> This patch only replicates de bad block functionality as the rest of the
> metadata requires new pblk functionality (e.g., wear-index to implement
> wear-leveling). 


"This functionality will come in future patches."

I think the  above belongs in the cover letter, not in the patch 
description.

> 
> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
> ---
>   drivers/lightnvm/pblk-core.c  | 121 +++++++++++++++++++----
>   drivers/lightnvm/pblk-init.c  | 218 ++++++++++++++++++++++++++++++------------
>   drivers/lightnvm/pblk-sysfs.c |  67 +++++++++++++
>   drivers/lightnvm/pblk.h       |  20 ++++
>   4 files changed, 346 insertions(+), 80 deletions(-)
> 
> diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
> index 1d7c6313f3d9..ce6a7cfdba66 100644
> --- a/drivers/lightnvm/pblk-core.c
> +++ b/drivers/lightnvm/pblk-core.c
> @@ -44,11 +44,12 @@ static void pblk_line_mark_bb(struct work_struct *work)
>   }
>   
>   static void pblk_mark_bb(struct pblk *pblk, struct pblk_line *line,
> -			 struct ppa_addr *ppa)
> +			 struct ppa_addr ppa_addr)
>   {
>   	struct nvm_tgt_dev *dev = pblk->dev;
>   	struct nvm_geo *geo = &dev->geo;
> -	int pos = pblk_ppa_to_pos(geo, *ppa);
> +	struct ppa_addr *ppa;
> +	int pos = pblk_ppa_to_pos(geo, ppa_addr);
>   
>   	pr_debug("pblk: erase failed: line:%d, pos:%d\n", line->id, pos);
>   	atomic_long_inc(&pblk->erase_failed);
> @@ -58,6 +59,15 @@ static void pblk_mark_bb(struct pblk *pblk, struct pblk_line *line,
>   		pr_err("pblk: attempted to erase bb: line:%d, pos:%d\n",
>   							line->id, pos);
>   
> +	/* Not necessary to mark bad blocks on 2.0 spec. */
> +	if (geo->c.version == NVM_OCSSD_SPEC_20)
> +		return;
> +
> +	ppa = kmalloc(sizeof(struct ppa_addr), GFP_ATOMIC);
> +	if (!ppa)
> +		return;
> +
> +	*ppa = ppa_addr;
>   	pblk_gen_run_ws(pblk, NULL, ppa, pblk_line_mark_bb,
>   						GFP_ATOMIC, pblk->bb_wq);
>   }
> @@ -69,16 +79,8 @@ static void __pblk_end_io_erase(struct pblk *pblk, struct nvm_rq *rqd)
>   	line = &pblk->lines[pblk_ppa_to_line(rqd->ppa_addr)];
>   	atomic_dec(&line->left_seblks);
>   
> -	if (rqd->error) {
> -		struct ppa_addr *ppa;
> -
> -		ppa = kmalloc(sizeof(struct ppa_addr), GFP_ATOMIC);
> -		if (!ppa)
> -			return;
> -
> -		*ppa = rqd->ppa_addr;
> -		pblk_mark_bb(pblk, line, ppa);
> -	}
> +	if (rqd->error)
> +		pblk_mark_bb(pblk, line, rqd->ppa_addr);
>   
>   	atomic_dec(&pblk->inflight_io);
>   }
> @@ -92,6 +94,50 @@ static void pblk_end_io_erase(struct nvm_rq *rqd)
>   	mempool_free(rqd, pblk->e_rq_pool);
>   }
>   
> +/*
> + * Get information for all chunks from the device.
> + *
> + * The caller is responsible for freeing the returned structure
> + */
> +struct nvm_chk_meta *pblk_chunk_get_info(struct pblk *pblk)
> +{
> +	struct nvm_tgt_dev *dev = pblk->dev;
> +	struct nvm_geo *geo = &dev->geo;
> +	struct nvm_chk_meta *meta;
> +	struct ppa_addr ppa;
> +	unsigned long len;
> +	int ret;
> +
> +	ppa.ppa = 0;
> +
> +	len = geo->all_chunks * sizeof(*meta);
> +	meta = kzalloc(len, GFP_KERNEL);
> +	if (!meta)
> +		return ERR_PTR(-ENOMEM);
> +
> +	ret = nvm_get_chunk_meta(dev, meta, ppa, geo->all_chunks);
> +	if (ret) {
> +		pr_err("pblk: could not get chunk metadata (%d)\n", ret);
> +		kfree(meta);
> +		return ERR_PTR(-EIO);
> +	}
> +
> +	return meta;
> +}
> +
> +struct nvm_chk_meta *pblk_chunk_get_off(struct pblk *pblk,
> +					      struct nvm_chk_meta *meta,
> +					      struct ppa_addr ppa)
> +{
> +	struct nvm_tgt_dev *dev = pblk->dev;
> +	struct nvm_geo *geo = &dev->geo;
> +	int ch_off = ppa.m.grp * geo->c.num_chk * geo->num_lun;
> +	int lun_off = ppa.m.pu * geo->c.num_chk;
> +	int chk_off = ppa.m.chk;
> +
> +	return meta + ch_off + lun_off + chk_off;
> +}
> +
>   void __pblk_map_invalidate(struct pblk *pblk, struct pblk_line *line,
>   			   u64 paddr)
>   {
> @@ -1094,10 +1140,38 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>   	return 1;
>   }
>   
> +static int pblk_prepare_new_line(struct pblk *pblk, struct pblk_line *line)
> +{
> +	struct pblk_line_meta *lm = &pblk->lm;
> +	struct nvm_tgt_dev *dev = pblk->dev;
> +	struct nvm_geo *geo = &dev->geo;
> +	int blk_to_erase = atomic_read(&line->blk_in_line);
> +	int i;
> +
> +	for (i = 0; i < lm->blk_per_line; i++) {
> +		int state = line->chks[i].state;
> +		struct pblk_lun *rlun = &pblk->luns[i];
> +
> +		/* Free chunks should not be erased */
> +		if (state & NVM_CHK_ST_FREE) {
> +			set_bit(pblk_ppa_to_pos(geo, rlun->chunk_bppa),
> +					line->erase_bitmap);
> +			blk_to_erase--;
> +			line->chks[i].state = NVM_CHK_ST_HOST_USE;


Can you help me understand why you want to use The NVM_CHK_ST_HOST_USE? 
Why would I care if the chunk state is HOST_USE? A target instance 
should not be able to see states from other chunks it doesn't own. and 
in that case, why have a separate state?


> +		}
> +
> +		WARN_ONCE(state & NVM_CHK_ST_OPEN,
> +				"pblk: open chunk in new line: %d\n",
> +				line->id);
> +	}
> +
> +	return blk_to_erase;
> +}
> +
>   static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>   {
>   	struct pblk_line_meta *lm = &pblk->lm;
> -	int blk_in_line = atomic_read(&line->blk_in_line);
> +	int blk_to_erase;
>   
>   	line->map_bitmap = kzalloc(lm->sec_bitmap_len, GFP_ATOMIC);
>   	if (!line->map_bitmap)
> @@ -1110,7 +1184,21 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>   		return -ENOMEM;
>   	}
>   
> +	/* Bad blocks do not need to be erased */
> +	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
> +
>   	spin_lock(&line->lock);
> +
> +	/* If we have not written to this line, we need to mark up free chunks
> +	 * as already erased
> +	 */
> +	if (line->state == PBLK_LINESTATE_NEW) {
> +		blk_to_erase = pblk_prepare_new_line(pblk, line);
> +		line->state = PBLK_LINESTATE_FREE;
> +	} else {
> +		blk_to_erase = atomic_read(&line->blk_in_line);
> +	}
> +
>   	if (line->state != PBLK_LINESTATE_FREE) {
>   		kfree(line->map_bitmap);
>   		kfree(line->invalid_bitmap);
> @@ -1122,15 +1210,12 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>   
>   	line->state = PBLK_LINESTATE_OPEN;
>   
> -	atomic_set(&line->left_eblks, blk_in_line);
> -	atomic_set(&line->left_seblks, blk_in_line);
> +	atomic_set(&line->left_eblks, blk_to_erase);
> +	atomic_set(&line->left_seblks, blk_to_erase);
>   
>   	line->meta_distance = lm->meta_distance;
>   	spin_unlock(&line->lock);
>   
> -	/* Bad blocks do not need to be erased */
> -	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
> -
>   	kref_init(&line->ref);
>   
>   	return 0;
> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
> index ec39800eea42..cf4f49d48aed 100644
> --- a/drivers/lightnvm/pblk-init.c
> +++ b/drivers/lightnvm/pblk-init.c
> @@ -401,6 +401,7 @@ static void pblk_line_meta_free(struct pblk_line *line)
>   {
>   	kfree(line->blk_bitmap);
>   	kfree(line->erase_bitmap);
> +	kfree(line->chks);
>   }
>   
>   static void pblk_lines_free(struct pblk *pblk)
> @@ -440,54 +441,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->c.num_chk * geo->c.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;
>   
> -	for (i = 0; i < blk_per_line; i++) {
> -		struct pblk_lun *rlun = &pblk->luns[i];
> -		u8 *lun_bb_log = bb_log + i * blk_per_line;
> -
> -		if (lun_bb_log[line->id] == NVM_BLK_T_FREE)
> -			continue;
> -
> -		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
> -		bb_cnt++;
> -	}
> -
> -	return bb_cnt;
> +	if (geo->c.version == NVM_OCSSD_SPEC_12)
> +		return pblk_bb_get_meta(pblk);
> +	else
> +		return pblk_chunk_get_info(pblk);

This 1.2 or 2.0 would be nice to have inside the lightnvm core. A target 
should not care weather it is a 1.2 or 2.0 device.

>   }
>   
>   static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
> @@ -516,6 +507,7 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
>   
>   		rlun = &pblk->luns[i];
>   		rlun->bppa = luns[lunid];
> +		rlun->chunk_bppa = luns[i];
>   
>   		sema_init(&rlun->wr_sem, 1);
>   	}
> @@ -695,8 +687,125 @@ static int pblk_lines_alloc_metadata(struct pblk *pblk)
>   	return -ENOMEM;
>   }
>   
> -static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
> -				void *chunk_log, long *nr_bad_blks)
> +static int pblk_setup_line_meta_12(struct pblk *pblk, struct pblk_line *line,
> +				   void *chunk_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->c.num_chk * geo->c.pln_mode;
> +
> +	for (i = 0; i < lm->blk_per_line; i++) {
> +		struct pblk_chunk *chunk = &line->chks[i];
> +		struct pblk_lun *rlun = &pblk->luns[i];
> +		u8 *lun_bb_meta = chunk_meta + i * chk_per_lun;
> +
> +		/*
> +		 * In 1.2 spec. chunk state is not persisted by the device. Thus
> +		 * some of the values are reset each time pblk is instantiated.
> +		 */
> +		if (lun_bb_meta[line->id] == NVM_BLK_T_FREE)
> +			chunk->state =  NVM_CHK_ST_HOST_USE;
> +		else
> +			chunk->state = NVM_CHK_ST_OFFLINE;
> +
> +		chunk->type = NVM_CHK_TP_W_SEQ;
> +		chunk->wi = 0;
> +		chunk->slba = -1;
> +		chunk->cnlb = geo->c.clba;
> +		chunk->wp = 0;
> +
> +		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
> +			continue;
> +
> +		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
> +		nr_bad_chks++;
> +	}
> +
> +	return nr_bad_chks;
> +}
> +
> +static int pblk_setup_line_meta_20(struct pblk *pblk, struct pblk_line *line,
> +				   struct nvm_chk_meta *meta)
> +{
> +	struct nvm_tgt_dev *dev = pblk->dev;
> +	struct nvm_geo *geo = &dev->geo;
> +	struct pblk_line_meta *lm = &pblk->lm;
> +	int i, nr_bad_chks = 0;
> +
> +	for (i = 0; i < lm->blk_per_line; i++) {
> +		struct pblk_chunk *chunk = &line->chks[i];
> +		struct pblk_lun *rlun = &pblk->luns[i];
> +		struct nvm_chk_meta *chunk_meta;
> +		struct ppa_addr ppa;
> +
> +		ppa = rlun->chunk_bppa;
> +		ppa.m.chk = line->id;
> +		chunk_meta = pblk_chunk_get_off(pblk, meta, ppa);
> +
> +		chunk->state = chunk_meta->state;
> +		chunk->type = chunk_meta->type;
> +		chunk->wi = chunk_meta->wi;
> +		chunk->slba = chunk_meta->slba;
> +		chunk->cnlb = chunk_meta->cnlb;
> +		chunk->wp = chunk_meta->wp;
> +
> +		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
> +			continue;
> +
> +		if (chunk->type & NVM_CHK_TP_SZ_SPEC) {
> +			WARN_ONCE(1, "pblk: custom-sized chunks unsupported\n");
> +			continue;
> +		}
> +
> +		set_bit(pblk_ppa_to_pos(geo, rlun->chunk_bppa),
> +							line->blk_bitmap);
> +		nr_bad_chks++;
> +	}
> +
> +	return nr_bad_chks;
> +}
> +
> +static long pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
> +				 void *chunk_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->c.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;
>   
> @@ -710,7 +819,13 @@ static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>   		return -ENOMEM;
>   	}
>   
> -	*nr_bad_blks = pblk_bb_line(pblk, line, chunk_log, lm->blk_per_line);
> +	line->chks = kmalloc(lm->blk_per_line * sizeof(struct pblk_chunk),
> +								GFP_KERNEL);
> +	if (!line->chks) {
> +		kfree(line->erase_bitmap);
> +		kfree(line->blk_bitmap);
> +		return -ENOMEM;
> +	}
>   
>   	return 0;
>   }
> @@ -722,9 +837,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;
> +	void *chunk_meta;
>   	unsigned int smeta_len, emeta_len;
> -	long nr_bad_blks = 0, nr_free_blks = 0;
> +	long nr_free_chks = 0;
>   	int bb_distance, max_write_ppas;
>   	int i, ret;
>   
> @@ -743,6 +858,7 @@ static int pblk_lines_init(struct pblk *pblk)
>   	l_mg->log_line = l_mg->data_line = NULL;
>   	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
>   	l_mg->nr_free_lines = 0;
> +	atomic_set(&l_mg->sysfs_line_state, -1);
>   	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
>   
>   	lm->sec_per_line = geo->c.clba * geo->all_luns;
> @@ -841,53 +957,31 @@ static int pblk_lines_init(struct pblk *pblk)
>   		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);
> +	chunk_meta = pblk_chunk_get_meta(pblk);
> +	if (IS_ERR(chunk_meta)) {
> +		pr_err("pblk: could not get chunk log (%lu)\n",
> +							PTR_ERR(chunk_meta));
> +		ret = PTR_ERR(chunk_meta);
>   		goto fail_free_lines;
>   	}
>   
>   	for (i = 0; i < l_mg->nr_lines; i++) {
> -		int chk_in_line;
> -
>   		line = &pblk->lines[i];
>   
> -		line->pblk = pblk;
> -		line->id = i;
> -		line->type = PBLK_LINETYPE_FREE;
> -		line->state = PBLK_LINESTATE_FREE;
> -		line->gc_group = PBLK_LINEGC_NONE;
> -		line->vsc = &l_mg->vsc_list[i];
> -		spin_lock_init(&line->lock);
> -
> -		ret = pblk_setup_line_meta(pblk, line, chunk_log, &nr_bad_blks);
> +		ret = pblk_alloc_line_meta(pblk, line);
>   		if (ret)
> -			goto fail_free_chunk_log;
> +			goto fail_free_chunk_meta;
>   
> -		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_chunk_log:
> -	kfree(chunk_log);
> +fail_free_chunk_meta:
> +	kfree(chunk_meta);
>   	while (--i >= 0)
>   		pblk_line_meta_free(&pblk->lines[i]);
>   fail_free_lines:
> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
> index ccfb3abd2773..1ce5b956c622 100644
> --- a/drivers/lightnvm/pblk-sysfs.c
> +++ b/drivers/lightnvm/pblk-sysfs.c
> @@ -142,6 +142,40 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
>   	return sz;
>   }
>   
> +static ssize_t pblk_sysfs_line_state_show(struct pblk *pblk, char *page)
> +{
> +	struct pblk_line_meta *lm = &pblk->lm;
> +	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
> +	struct pblk_line *line;
> +	int line_id = atomic_read(&l_mg->sysfs_line_state);
> +	ssize_t sz = 0;
> +	int i;
> +
> +	if (line_id < 0 || line_id >= l_mg->nr_lines)
> +		return 0;
> +
> +	sz = snprintf(page, PAGE_SIZE,
> +		"line\tchunk\tstate\ttype\twear-index\tslba\t\tcnlb\twp\n");
> +
> +	line = &pblk->lines[line_id];
> +
> +	for (i = 0; i < lm->blk_per_line; i++) {
> +		struct pblk_chunk *chunk = &line->chks[i];
> +
> +		sz += snprintf(page + sz, PAGE_SIZE - sz,
> +				"%d\t%d\t%d\t%d\t%d\t\t%llu\t\t%llu\t%llu\n",
> +				line->id, i,
> +				chunk->state,
> +				chunk->type,
> +				chunk->wi,
> +				chunk->slba,
> +				chunk->cnlb,
> +				chunk->wp);
> +	}
> +
> +	return sz;
> +}
> +
>   static ssize_t pblk_sysfs_lines(struct pblk *pblk, char *page)
>   {
>   	struct nvm_tgt_dev *dev = pblk->dev;
> @@ -398,6 +432,29 @@ static ssize_t pblk_sysfs_stats_debug(struct pblk *pblk, char *page)
>   }
>   #endif
>   
> +
> +static ssize_t pblk_sysfs_line_state_store(struct pblk *pblk, const char *page,
> +					   size_t len)
> +{
> +	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
> +	size_t c_len;
> +	int line_id;
> +
> +	c_len = strcspn(page, "\n");
> +	if (c_len >= len)
> +		return -EINVAL;
> +
> +	if (kstrtouint(page, 0, &line_id))
> +		return -EINVAL;
> +
> +	if (line_id < 0 || line_id >= l_mg->nr_lines)
> +		return -EINVAL;
> +
> +	atomic_set(&l_mg->sysfs_line_state, line_id);
> +
> +	return len;
> +}
> +
>   static ssize_t pblk_sysfs_gc_force(struct pblk *pblk, const char *page,
>   				   size_t len)
>   {
> @@ -529,6 +586,11 @@ static struct attribute sys_lines_info_attr = {
>   	.mode = 0444,
>   };
>   
> +static struct attribute sys_line_state_attr = {
> +	.name = "line_state",
> +	.mode = 0644,
> +};
> +
>   static struct attribute sys_gc_force = {
>   	.name = "gc_force",
>   	.mode = 0200,
> @@ -572,6 +634,7 @@ static struct attribute *pblk_attrs[] = {
>   	&sys_stats_ppaf_attr,
>   	&sys_lines_attr,
>   	&sys_lines_info_attr,
> +	&sys_line_state_attr,
>   	&sys_write_amp_mileage,
>   	&sys_write_amp_trip,
>   	&sys_padding_dist,
> @@ -602,6 +665,8 @@ static ssize_t pblk_sysfs_show(struct kobject *kobj, struct attribute *attr,
>   		return pblk_sysfs_lines(pblk, buf);
>   	else if (strcmp(attr->name, "lines_info") == 0)
>   		return pblk_sysfs_lines_info(pblk, buf);
> +	else if (strcmp(attr->name, "line_state") == 0)
> +		return pblk_sysfs_line_state_show(pblk, buf);
>   	else if (strcmp(attr->name, "max_sec_per_write") == 0)
>   		return pblk_sysfs_get_sec_per_write(pblk, buf);
>   	else if (strcmp(attr->name, "write_amp_mileage") == 0)
> @@ -628,6 +693,8 @@ static ssize_t pblk_sysfs_store(struct kobject *kobj, struct attribute *attr,
>   		return pblk_sysfs_set_sec_per_write(pblk, buf, len);
>   	else if (strcmp(attr->name, "write_amp_trip") == 0)
>   		return pblk_sysfs_set_write_amp_trip(pblk, buf, len);
> +	else if (strcmp(attr->name, "line_state") == 0)
> +		return pblk_sysfs_line_state_store(pblk, buf, len);
>   	else if (strcmp(attr->name, "padding_dist") == 0)
>   		return pblk_sysfs_set_padding_dist(pblk, buf, len);
>   	return 0;
> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
> index 6e1fcd1a538a..bc31c67b725f 100644
> --- a/drivers/lightnvm/pblk.h
> +++ b/drivers/lightnvm/pblk.h
> @@ -201,6 +201,8 @@ struct pblk_rb {
>   
>   struct pblk_lun {
>   	struct ppa_addr bppa;
> +	struct ppa_addr chunk_bppa;
> +
>   	struct semaphore wr_sem;
>   };
>   
> @@ -297,6 +299,7 @@ enum {
>   	PBLK_LINETYPE_DATA = 2,
>   
>   	/* Line state */
> +	PBLK_LINESTATE_NEW = 9,
>   	PBLK_LINESTATE_FREE = 10,
>   	PBLK_LINESTATE_OPEN = 11,
>   	PBLK_LINESTATE_CLOSED = 12,
> @@ -412,6 +415,15 @@ struct pblk_smeta {
>   	struct line_smeta *buf;		/* smeta buffer in persistent format */
>   };
>   
> +struct pblk_chunk {
> +	int state;
> +	int type;
> +	int wi;
> +	u64 slba;
> +	u64 cnlb;
> +	u64 wp;
> +};
> +

How come the code replicate the nvm_chk_meta data structure?

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

* Re: [PATCH 17/19] lightnvm: pblk: implement get log report chunk
  2018-02-26 19:04     ` Matias Bjørling
@ 2018-02-27 14:40       ` Javier González
  -1 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-27 14:40 UTC (permalink / raw)
  To: Matias Bjørling; +Cc: linux-block, linux-kernel, linux-nvme

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

> On 26 Feb 2018, at 20.04, Matias Bjørling <mb@lightnvm.io> wrote:
> 
> On 02/26/2018 02:17 PM, Javier González wrote:
>> From: Javier González <javier@javigon.com>
>> In preparation of pblk supporting 2.0, implement the get log report
>> chunk in pblk.
>> This patch only replicates de bad block functionality as the rest of the
>> metadata requires new pblk functionality (e.g., wear-index to implement
>> wear-leveling).
> 
> 
> "This functionality will come in future patches."
> 
> I think the above belongs in the cover letter, not in the patch
> description.
> 

Ok.

>> Signed-off-by: Javier González <javier@cnexlabs.com>
>> ---
>>  drivers/lightnvm/pblk-core.c  | 121 +++++++++++++++++++----
>>  drivers/lightnvm/pblk-init.c  | 218 ++++++++++++++++++++++++++++++------------
>>  drivers/lightnvm/pblk-sysfs.c |  67 +++++++++++++
>>  drivers/lightnvm/pblk.h       |  20 ++++
>>  4 files changed, 346 insertions(+), 80 deletions(-)
>> diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
>> index 1d7c6313f3d9..ce6a7cfdba66 100644
>> --- a/drivers/lightnvm/pblk-core.c
>> +++ b/drivers/lightnvm/pblk-core.c
>> @@ -44,11 +44,12 @@ static void pblk_line_mark_bb(struct work_struct *work)
>>  }
>>    static void pblk_mark_bb(struct pblk *pblk, struct pblk_line *line,
>> -			 struct ppa_addr *ppa)
>> +			 struct ppa_addr ppa_addr)
>>  {
>>  	struct nvm_tgt_dev *dev = pblk->dev;
>>  	struct nvm_geo *geo = &dev->geo;
>> -	int pos = pblk_ppa_to_pos(geo, *ppa);
>> +	struct ppa_addr *ppa;
>> +	int pos = pblk_ppa_to_pos(geo, ppa_addr);
>>    	pr_debug("pblk: erase failed: line:%d, pos:%d\n", line->id, pos);
>>  	atomic_long_inc(&pblk->erase_failed);
>> @@ -58,6 +59,15 @@ static void pblk_mark_bb(struct pblk *pblk, struct pblk_line *line,
>>  		pr_err("pblk: attempted to erase bb: line:%d, pos:%d\n",
>>  							line->id, pos);
>>  +	/* Not necessary to mark bad blocks on 2.0 spec. */
>> +	if (geo->c.version == NVM_OCSSD_SPEC_20)
>> +		return;
>> +
>> +	ppa = kmalloc(sizeof(struct ppa_addr), GFP_ATOMIC);
>> +	if (!ppa)
>> +		return;
>> +
>> +	*ppa = ppa_addr;
>>  	pblk_gen_run_ws(pblk, NULL, ppa, pblk_line_mark_bb,
>>  						GFP_ATOMIC, pblk->bb_wq);
>>  }
>> @@ -69,16 +79,8 @@ static void __pblk_end_io_erase(struct pblk *pblk, struct nvm_rq *rqd)
>>  	line = &pblk->lines[pblk_ppa_to_line(rqd->ppa_addr)];
>>  	atomic_dec(&line->left_seblks);
>>  -	if (rqd->error) {
>> -		struct ppa_addr *ppa;
>> -
>> -		ppa = kmalloc(sizeof(struct ppa_addr), GFP_ATOMIC);
>> -		if (!ppa)
>> -			return;
>> -
>> -		*ppa = rqd->ppa_addr;
>> -		pblk_mark_bb(pblk, line, ppa);
>> -	}
>> +	if (rqd->error)
>> +		pblk_mark_bb(pblk, line, rqd->ppa_addr);
>>    	atomic_dec(&pblk->inflight_io);
>>  }
>> @@ -92,6 +94,50 @@ static void pblk_end_io_erase(struct nvm_rq *rqd)
>>  	mempool_free(rqd, pblk->e_rq_pool);
>>  }
>>  +/*
>> + * Get information for all chunks from the device.
>> + *
>> + * The caller is responsible for freeing the returned structure
>> + */
>> +struct nvm_chk_meta *pblk_chunk_get_info(struct pblk *pblk)
>> +{
>> +	struct nvm_tgt_dev *dev = pblk->dev;
>> +	struct nvm_geo *geo = &dev->geo;
>> +	struct nvm_chk_meta *meta;
>> +	struct ppa_addr ppa;
>> +	unsigned long len;
>> +	int ret;
>> +
>> +	ppa.ppa = 0;
>> +
>> +	len = geo->all_chunks * sizeof(*meta);
>> +	meta = kzalloc(len, GFP_KERNEL);
>> +	if (!meta)
>> +		return ERR_PTR(-ENOMEM);
>> +
>> +	ret = nvm_get_chunk_meta(dev, meta, ppa, geo->all_chunks);
>> +	if (ret) {
>> +		pr_err("pblk: could not get chunk metadata (%d)\n", ret);
>> +		kfree(meta);
>> +		return ERR_PTR(-EIO);
>> +	}
>> +
>> +	return meta;
>> +}
>> +
>> +struct nvm_chk_meta *pblk_chunk_get_off(struct pblk *pblk,
>> +					      struct nvm_chk_meta *meta,
>> +					      struct ppa_addr ppa)
>> +{
>> +	struct nvm_tgt_dev *dev = pblk->dev;
>> +	struct nvm_geo *geo = &dev->geo;
>> +	int ch_off = ppa.m.grp * geo->c.num_chk * geo->num_lun;
>> +	int lun_off = ppa.m.pu * geo->c.num_chk;
>> +	int chk_off = ppa.m.chk;
>> +
>> +	return meta + ch_off + lun_off + chk_off;
>> +}
>> +
>>  void __pblk_map_invalidate(struct pblk *pblk, struct pblk_line *line,
>>  			   u64 paddr)
>>  {
>> @@ -1094,10 +1140,38 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>>  	return 1;
>>  }
>>  +static int pblk_prepare_new_line(struct pblk *pblk, struct pblk_line *line)
>> +{
>> +	struct pblk_line_meta *lm = &pblk->lm;
>> +	struct nvm_tgt_dev *dev = pblk->dev;
>> +	struct nvm_geo *geo = &dev->geo;
>> +	int blk_to_erase = atomic_read(&line->blk_in_line);
>> +	int i;
>> +
>> +	for (i = 0; i < lm->blk_per_line; i++) {
>> +		int state = line->chks[i].state;
>> +		struct pblk_lun *rlun = &pblk->luns[i];
>> +
>> +		/* Free chunks should not be erased */
>> +		if (state & NVM_CHK_ST_FREE) {
>> +			set_bit(pblk_ppa_to_pos(geo, rlun->chunk_bppa),
>> +					line->erase_bitmap);
>> +			blk_to_erase--;
>> +			line->chks[i].state = NVM_CHK_ST_HOST_USE;
> 
> 
> Can you help me understand why you want to use The
> NVM_CHK_ST_HOST_USE? Why would I care if the chunk state is HOST_USE?
> A target instance should not be able to see states from other chunks
> it doesn't own. and in that case, why have a separate state?
> 

The motivation for this state is that pblk does not maintain a per
block/chunk state. On the first disk pass however, the state of the
chunks is unknown, thus we need to check for each one individually;
after that, we know that good chunks need to be erased. Having this
extra chunk state, frees us from maintaining this unnecessary intra-line
state. Also, at the point I wrote this code, we did not have the report
chunk on the erase path, so updating the chunk metadata would be
something periodic.

I have taken a look at this again and I solved it in a different way -
basically, only maintaining free/closed states, which is not much more
expensive. It is included in the next version.

> 
>> +		}
>> +
>> +		WARN_ONCE(state & NVM_CHK_ST_OPEN,
>> +				"pblk: open chunk in new line: %d\n",
>> +				line->id);
>> +	}
>> +
>> +	return blk_to_erase;
>> +}
>> +
>>  static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>>  {
>>  	struct pblk_line_meta *lm = &pblk->lm;
>> -	int blk_in_line = atomic_read(&line->blk_in_line);
>> +	int blk_to_erase;
>>    	line->map_bitmap = kzalloc(lm->sec_bitmap_len, GFP_ATOMIC);
>>  	if (!line->map_bitmap)
>> @@ -1110,7 +1184,21 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>>  		return -ENOMEM;
>>  	}
>>  +	/* Bad blocks do not need to be erased */
>> +	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
>> +
>>  	spin_lock(&line->lock);
>> +
>> +	/* If we have not written to this line, we need to mark up free chunks
>> +	 * as already erased
>> +	 */
>> +	if (line->state == PBLK_LINESTATE_NEW) {
>> +		blk_to_erase = pblk_prepare_new_line(pblk, line);
>> +		line->state = PBLK_LINESTATE_FREE;
>> +	} else {
>> +		blk_to_erase = atomic_read(&line->blk_in_line);
>> +	}
>> +
>>  	if (line->state != PBLK_LINESTATE_FREE) {
>>  		kfree(line->map_bitmap);
>>  		kfree(line->invalid_bitmap);
>> @@ -1122,15 +1210,12 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>>    	line->state = PBLK_LINESTATE_OPEN;
>>  -	atomic_set(&line->left_eblks, blk_in_line);
>> -	atomic_set(&line->left_seblks, blk_in_line);
>> +	atomic_set(&line->left_eblks, blk_to_erase);
>> +	atomic_set(&line->left_seblks, blk_to_erase);
>>    	line->meta_distance = lm->meta_distance;
>>  	spin_unlock(&line->lock);
>>  -	/* Bad blocks do not need to be erased */
>> -	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
>> -
>>  	kref_init(&line->ref);
>>    	return 0;
>> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
>> index ec39800eea42..cf4f49d48aed 100644
>> --- a/drivers/lightnvm/pblk-init.c
>> +++ b/drivers/lightnvm/pblk-init.c
>> @@ -401,6 +401,7 @@ static void pblk_line_meta_free(struct pblk_line *line)
>>  {
>>  	kfree(line->blk_bitmap);
>>  	kfree(line->erase_bitmap);
>> +	kfree(line->chks);
>>  }
>>    static void pblk_lines_free(struct pblk *pblk)
>> @@ -440,54 +441,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->c.num_chk * geo->c.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;
>>  -	for (i = 0; i < blk_per_line; i++) {
>> -		struct pblk_lun *rlun = &pblk->luns[i];
>> -		u8 *lun_bb_log = bb_log + i * blk_per_line;
>> -
>> -		if (lun_bb_log[line->id] == NVM_BLK_T_FREE)
>> -			continue;
>> -
>> -		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
>> -		bb_cnt++;
>> -	}
>> -
>> -	return bb_cnt;
>> +	if (geo->c.version == NVM_OCSSD_SPEC_12)
>> +		return pblk_bb_get_meta(pblk);
>> +	else
>> +		return pblk_chunk_get_info(pblk);
> 
> This 1.2 or 2.0 would be nice to have inside the lightnvm core. A
> target should not care weather it is a 1.2 or 2.0 device.
> 

It is not an easy thing to do since the bad block format and chunk
report return completely different formats. As I explained in a
different thread, doing this in core would force 1.2 to understand fake
chunk formats, which are not meaningful. It is better to leave the logic
at the target level, where we know what to do with the format.

>>  }
>>    static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
>> @@ -516,6 +507,7 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
>>    		rlun = &pblk->luns[i];
>>  		rlun->bppa = luns[lunid];
>> +		rlun->chunk_bppa = luns[i];
>>    		sema_init(&rlun->wr_sem, 1);
>>  	}
>> @@ -695,8 +687,125 @@ static int pblk_lines_alloc_metadata(struct pblk *pblk)
>>  	return -ENOMEM;
>>  }
>>  -static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>> -				void *chunk_log, long *nr_bad_blks)
>> +static int pblk_setup_line_meta_12(struct pblk *pblk, struct pblk_line *line,
>> +				   void *chunk_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->c.num_chk * geo->c.pln_mode;
>> +
>> +	for (i = 0; i < lm->blk_per_line; i++) {
>> +		struct pblk_chunk *chunk = &line->chks[i];
>> +		struct pblk_lun *rlun = &pblk->luns[i];
>> +		u8 *lun_bb_meta = chunk_meta + i * chk_per_lun;
>> +
>> +		/*
>> +		 * In 1.2 spec. chunk state is not persisted by the device. Thus
>> +		 * some of the values are reset each time pblk is instantiated.
>> +		 */
>> +		if (lun_bb_meta[line->id] == NVM_BLK_T_FREE)
>> +			chunk->state =  NVM_CHK_ST_HOST_USE;
>> +		else
>> +			chunk->state = NVM_CHK_ST_OFFLINE;
>> +
>> +		chunk->type = NVM_CHK_TP_W_SEQ;
>> +		chunk->wi = 0;
>> +		chunk->slba = -1;
>> +		chunk->cnlb = geo->c.clba;
>> +		chunk->wp = 0;
>> +
>> +		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
>> +			continue;
>> +
>> +		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
>> +		nr_bad_chks++;
>> +	}
>> +
>> +	return nr_bad_chks;
>> +}
>> +
>> +static int pblk_setup_line_meta_20(struct pblk *pblk, struct pblk_line *line,
>> +				   struct nvm_chk_meta *meta)
>> +{
>> +	struct nvm_tgt_dev *dev = pblk->dev;
>> +	struct nvm_geo *geo = &dev->geo;
>> +	struct pblk_line_meta *lm = &pblk->lm;
>> +	int i, nr_bad_chks = 0;
>> +
>> +	for (i = 0; i < lm->blk_per_line; i++) {
>> +		struct pblk_chunk *chunk = &line->chks[i];
>> +		struct pblk_lun *rlun = &pblk->luns[i];
>> +		struct nvm_chk_meta *chunk_meta;
>> +		struct ppa_addr ppa;
>> +
>> +		ppa = rlun->chunk_bppa;
>> +		ppa.m.chk = line->id;
>> +		chunk_meta = pblk_chunk_get_off(pblk, meta, ppa);
>> +
>> +		chunk->state = chunk_meta->state;
>> +		chunk->type = chunk_meta->type;
>> +		chunk->wi = chunk_meta->wi;
>> +		chunk->slba = chunk_meta->slba;
>> +		chunk->cnlb = chunk_meta->cnlb;
>> +		chunk->wp = chunk_meta->wp;
>> +
>> +		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
>> +			continue;
>> +
>> +		if (chunk->type & NVM_CHK_TP_SZ_SPEC) {
>> +			WARN_ONCE(1, "pblk: custom-sized chunks unsupported\n");
>> +			continue;
>> +		}
>> +
>> +		set_bit(pblk_ppa_to_pos(geo, rlun->chunk_bppa),
>> +							line->blk_bitmap);
>> +		nr_bad_chks++;
>> +	}
>> +
>> +	return nr_bad_chks;
>> +}
>> +
>> +static long pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>> +				 void *chunk_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->c.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;
>>  @@ -710,7 +819,13 @@ static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>>  		return -ENOMEM;
>>  	}
>>  -	*nr_bad_blks = pblk_bb_line(pblk, line, chunk_log, lm->blk_per_line);
>> +	line->chks = kmalloc(lm->blk_per_line * sizeof(struct pblk_chunk),
>> +								GFP_KERNEL);
>> +	if (!line->chks) {
>> +		kfree(line->erase_bitmap);
>> +		kfree(line->blk_bitmap);
>> +		return -ENOMEM;
>> +	}
>>    	return 0;
>>  }
>> @@ -722,9 +837,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;
>> +	void *chunk_meta;
>>  	unsigned int smeta_len, emeta_len;
>> -	long nr_bad_blks = 0, nr_free_blks = 0;
>> +	long nr_free_chks = 0;
>>  	int bb_distance, max_write_ppas;
>>  	int i, ret;
>>  @@ -743,6 +858,7 @@ static int pblk_lines_init(struct pblk *pblk)
>>  	l_mg->log_line = l_mg->data_line = NULL;
>>  	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
>>  	l_mg->nr_free_lines = 0;
>> +	atomic_set(&l_mg->sysfs_line_state, -1);
>>  	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
>>    	lm->sec_per_line = geo->c.clba * geo->all_luns;
>> @@ -841,53 +957,31 @@ static int pblk_lines_init(struct pblk *pblk)
>>  		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);
>> +	chunk_meta = pblk_chunk_get_meta(pblk);
>> +	if (IS_ERR(chunk_meta)) {
>> +		pr_err("pblk: could not get chunk log (%lu)\n",
>> +							PTR_ERR(chunk_meta));
>> +		ret = PTR_ERR(chunk_meta);
>>  		goto fail_free_lines;
>>  	}
>>    	for (i = 0; i < l_mg->nr_lines; i++) {
>> -		int chk_in_line;
>> -
>>  		line = &pblk->lines[i];
>>  -		line->pblk = pblk;
>> -		line->id = i;
>> -		line->type = PBLK_LINETYPE_FREE;
>> -		line->state = PBLK_LINESTATE_FREE;
>> -		line->gc_group = PBLK_LINEGC_NONE;
>> -		line->vsc = &l_mg->vsc_list[i];
>> -		spin_lock_init(&line->lock);
>> -
>> -		ret = pblk_setup_line_meta(pblk, line, chunk_log, &nr_bad_blks);
>> +		ret = pblk_alloc_line_meta(pblk, line);
>>  		if (ret)
>> -			goto fail_free_chunk_log;
>> +			goto fail_free_chunk_meta;
>>  -		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_chunk_log:
>> -	kfree(chunk_log);
>> +fail_free_chunk_meta:
>> +	kfree(chunk_meta);
>>  	while (--i >= 0)
>>  		pblk_line_meta_free(&pblk->lines[i]);
>>  fail_free_lines:
>> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
>> index ccfb3abd2773..1ce5b956c622 100644
>> --- a/drivers/lightnvm/pblk-sysfs.c
>> +++ b/drivers/lightnvm/pblk-sysfs.c
>> @@ -142,6 +142,40 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
>>  	return sz;
>>  }
>>  +static ssize_t pblk_sysfs_line_state_show(struct pblk *pblk, char *page)
>> +{
>> +	struct pblk_line_meta *lm = &pblk->lm;
>> +	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
>> +	struct pblk_line *line;
>> +	int line_id = atomic_read(&l_mg->sysfs_line_state);
>> +	ssize_t sz = 0;
>> +	int i;
>> +
>> +	if (line_id < 0 || line_id >= l_mg->nr_lines)
>> +		return 0;
>> +
>> +	sz = snprintf(page, PAGE_SIZE,
>> +		"line\tchunk\tstate\ttype\twear-index\tslba\t\tcnlb\twp\n");
>> +
>> +	line = &pblk->lines[line_id];
>> +
>> +	for (i = 0; i < lm->blk_per_line; i++) {
>> +		struct pblk_chunk *chunk = &line->chks[i];
>> +
>> +		sz += snprintf(page + sz, PAGE_SIZE - sz,
>> +				"%d\t%d\t%d\t%d\t%d\t\t%llu\t\t%llu\t%llu\n",
>> +				line->id, i,
>> +				chunk->state,
>> +				chunk->type,
>> +				chunk->wi,
>> +				chunk->slba,
>> +				chunk->cnlb,
>> +				chunk->wp);
>> +	}
>> +
>> +	return sz;
>> +}
>> +
>>  static ssize_t pblk_sysfs_lines(struct pblk *pblk, char *page)
>>  {
>>  	struct nvm_tgt_dev *dev = pblk->dev;
>> @@ -398,6 +432,29 @@ static ssize_t pblk_sysfs_stats_debug(struct pblk *pblk, char *page)
>>  }
>>  #endif
>>  +
>> +static ssize_t pblk_sysfs_line_state_store(struct pblk *pblk, const char *page,
>> +					   size_t len)
>> +{
>> +	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
>> +	size_t c_len;
>> +	int line_id;
>> +
>> +	c_len = strcspn(page, "\n");
>> +	if (c_len >= len)
>> +		return -EINVAL;
>> +
>> +	if (kstrtouint(page, 0, &line_id))
>> +		return -EINVAL;
>> +
>> +	if (line_id < 0 || line_id >= l_mg->nr_lines)
>> +		return -EINVAL;
>> +
>> +	atomic_set(&l_mg->sysfs_line_state, line_id);
>> +
>> +	return len;
>> +}
>> +
>>  static ssize_t pblk_sysfs_gc_force(struct pblk *pblk, const char *page,
>>  				   size_t len)
>>  {
>> @@ -529,6 +586,11 @@ static struct attribute sys_lines_info_attr = {
>>  	.mode = 0444,
>>  };
>>  +static struct attribute sys_line_state_attr = {
>> +	.name = "line_state",
>> +	.mode = 0644,
>> +};
>> +
>>  static struct attribute sys_gc_force = {
>>  	.name = "gc_force",
>>  	.mode = 0200,
>> @@ -572,6 +634,7 @@ static struct attribute *pblk_attrs[] = {
>>  	&sys_stats_ppaf_attr,
>>  	&sys_lines_attr,
>>  	&sys_lines_info_attr,
>> +	&sys_line_state_attr,
>>  	&sys_write_amp_mileage,
>>  	&sys_write_amp_trip,
>>  	&sys_padding_dist,
>> @@ -602,6 +665,8 @@ static ssize_t pblk_sysfs_show(struct kobject *kobj, struct attribute *attr,
>>  		return pblk_sysfs_lines(pblk, buf);
>>  	else if (strcmp(attr->name, "lines_info") == 0)
>>  		return pblk_sysfs_lines_info(pblk, buf);
>> +	else if (strcmp(attr->name, "line_state") == 0)
>> +		return pblk_sysfs_line_state_show(pblk, buf);
>>  	else if (strcmp(attr->name, "max_sec_per_write") == 0)
>>  		return pblk_sysfs_get_sec_per_write(pblk, buf);
>>  	else if (strcmp(attr->name, "write_amp_mileage") == 0)
>> @@ -628,6 +693,8 @@ static ssize_t pblk_sysfs_store(struct kobject *kobj, struct attribute *attr,
>>  		return pblk_sysfs_set_sec_per_write(pblk, buf, len);
>>  	else if (strcmp(attr->name, "write_amp_trip") == 0)
>>  		return pblk_sysfs_set_write_amp_trip(pblk, buf, len);
>> +	else if (strcmp(attr->name, "line_state") == 0)
>> +		return pblk_sysfs_line_state_store(pblk, buf, len);
>>  	else if (strcmp(attr->name, "padding_dist") == 0)
>>  		return pblk_sysfs_set_padding_dist(pblk, buf, len);
>>  	return 0;
>> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
>> index 6e1fcd1a538a..bc31c67b725f 100644
>> --- a/drivers/lightnvm/pblk.h
>> +++ b/drivers/lightnvm/pblk.h
>> @@ -201,6 +201,8 @@ struct pblk_rb {
>>    struct pblk_lun {
>>  	struct ppa_addr bppa;
>> +	struct ppa_addr chunk_bppa;
>> +
>>  	struct semaphore wr_sem;
>>  };
>>  @@ -297,6 +299,7 @@ enum {
>>  	PBLK_LINETYPE_DATA = 2,
>>    	/* Line state */
>> +	PBLK_LINESTATE_NEW = 9,
>>  	PBLK_LINESTATE_FREE = 10,
>>  	PBLK_LINESTATE_OPEN = 11,
>>  	PBLK_LINESTATE_CLOSED = 12,
>> @@ -412,6 +415,15 @@ struct pblk_smeta {
>>  	struct line_smeta *buf;		/* smeta buffer in persistent format */
>>  };
>>  +struct pblk_chunk {
>> +	int state;
>> +	int type;
>> +	int wi;
>> +	u64 slba;
>> +	u64 cnlb;
>> +	u64 wp;
>> +};
>> +
> 
> How come the code replicate the nvm_chk_meta data structure?

There is no need to maintain the chunk reserved bits in nvm_chk_meta and
waste memory in the process, as these are alive for the whole life of
the pblk instance. This structure only maintains the necessary bits.

Javier

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

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

* [PATCH 17/19] lightnvm: pblk: implement get log report chunk
@ 2018-02-27 14:40       ` Javier González
  0 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-27 14:40 UTC (permalink / raw)


> On 26 Feb 2018,@20.04, Matias Bj?rling <mb@lightnvm.io> wrote:
> 
> On 02/26/2018 02:17 PM, Javier Gonz?lez wrote:
>> From: Javier Gonz?lez <javier at javigon.com>
>> In preparation of pblk supporting 2.0, implement the get log report
>> chunk in pblk.
>> This patch only replicates de bad block functionality as the rest of the
>> metadata requires new pblk functionality (e.g., wear-index to implement
>> wear-leveling).
> 
> 
> "This functionality will come in future patches."
> 
> I think the above belongs in the cover letter, not in the patch
> description.
> 

Ok.

>> Signed-off-by: Javier Gonz?lez <javier at cnexlabs.com>
>> ---
>>  drivers/lightnvm/pblk-core.c  | 121 +++++++++++++++++++----
>>  drivers/lightnvm/pblk-init.c  | 218 ++++++++++++++++++++++++++++++------------
>>  drivers/lightnvm/pblk-sysfs.c |  67 +++++++++++++
>>  drivers/lightnvm/pblk.h       |  20 ++++
>>  4 files changed, 346 insertions(+), 80 deletions(-)
>> diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
>> index 1d7c6313f3d9..ce6a7cfdba66 100644
>> --- a/drivers/lightnvm/pblk-core.c
>> +++ b/drivers/lightnvm/pblk-core.c
>> @@ -44,11 +44,12 @@ static void pblk_line_mark_bb(struct work_struct *work)
>>  }
>>    static void pblk_mark_bb(struct pblk *pblk, struct pblk_line *line,
>> -			 struct ppa_addr *ppa)
>> +			 struct ppa_addr ppa_addr)
>>  {
>>  	struct nvm_tgt_dev *dev = pblk->dev;
>>  	struct nvm_geo *geo = &dev->geo;
>> -	int pos = pblk_ppa_to_pos(geo, *ppa);
>> +	struct ppa_addr *ppa;
>> +	int pos = pblk_ppa_to_pos(geo, ppa_addr);
>>    	pr_debug("pblk: erase failed: line:%d, pos:%d\n", line->id, pos);
>>  	atomic_long_inc(&pblk->erase_failed);
>> @@ -58,6 +59,15 @@ static void pblk_mark_bb(struct pblk *pblk, struct pblk_line *line,
>>  		pr_err("pblk: attempted to erase bb: line:%d, pos:%d\n",
>>  							line->id, pos);
>>  +	/* Not necessary to mark bad blocks on 2.0 spec. */
>> +	if (geo->c.version == NVM_OCSSD_SPEC_20)
>> +		return;
>> +
>> +	ppa = kmalloc(sizeof(struct ppa_addr), GFP_ATOMIC);
>> +	if (!ppa)
>> +		return;
>> +
>> +	*ppa = ppa_addr;
>>  	pblk_gen_run_ws(pblk, NULL, ppa, pblk_line_mark_bb,
>>  						GFP_ATOMIC, pblk->bb_wq);
>>  }
>> @@ -69,16 +79,8 @@ static void __pblk_end_io_erase(struct pblk *pblk, struct nvm_rq *rqd)
>>  	line = &pblk->lines[pblk_ppa_to_line(rqd->ppa_addr)];
>>  	atomic_dec(&line->left_seblks);
>>  -	if (rqd->error) {
>> -		struct ppa_addr *ppa;
>> -
>> -		ppa = kmalloc(sizeof(struct ppa_addr), GFP_ATOMIC);
>> -		if (!ppa)
>> -			return;
>> -
>> -		*ppa = rqd->ppa_addr;
>> -		pblk_mark_bb(pblk, line, ppa);
>> -	}
>> +	if (rqd->error)
>> +		pblk_mark_bb(pblk, line, rqd->ppa_addr);
>>    	atomic_dec(&pblk->inflight_io);
>>  }
>> @@ -92,6 +94,50 @@ static void pblk_end_io_erase(struct nvm_rq *rqd)
>>  	mempool_free(rqd, pblk->e_rq_pool);
>>  }
>>  +/*
>> + * Get information for all chunks from the device.
>> + *
>> + * The caller is responsible for freeing the returned structure
>> + */
>> +struct nvm_chk_meta *pblk_chunk_get_info(struct pblk *pblk)
>> +{
>> +	struct nvm_tgt_dev *dev = pblk->dev;
>> +	struct nvm_geo *geo = &dev->geo;
>> +	struct nvm_chk_meta *meta;
>> +	struct ppa_addr ppa;
>> +	unsigned long len;
>> +	int ret;
>> +
>> +	ppa.ppa = 0;
>> +
>> +	len = geo->all_chunks * sizeof(*meta);
>> +	meta = kzalloc(len, GFP_KERNEL);
>> +	if (!meta)
>> +		return ERR_PTR(-ENOMEM);
>> +
>> +	ret = nvm_get_chunk_meta(dev, meta, ppa, geo->all_chunks);
>> +	if (ret) {
>> +		pr_err("pblk: could not get chunk metadata (%d)\n", ret);
>> +		kfree(meta);
>> +		return ERR_PTR(-EIO);
>> +	}
>> +
>> +	return meta;
>> +}
>> +
>> +struct nvm_chk_meta *pblk_chunk_get_off(struct pblk *pblk,
>> +					      struct nvm_chk_meta *meta,
>> +					      struct ppa_addr ppa)
>> +{
>> +	struct nvm_tgt_dev *dev = pblk->dev;
>> +	struct nvm_geo *geo = &dev->geo;
>> +	int ch_off = ppa.m.grp * geo->c.num_chk * geo->num_lun;
>> +	int lun_off = ppa.m.pu * geo->c.num_chk;
>> +	int chk_off = ppa.m.chk;
>> +
>> +	return meta + ch_off + lun_off + chk_off;
>> +}
>> +
>>  void __pblk_map_invalidate(struct pblk *pblk, struct pblk_line *line,
>>  			   u64 paddr)
>>  {
>> @@ -1094,10 +1140,38 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
>>  	return 1;
>>  }
>>  +static int pblk_prepare_new_line(struct pblk *pblk, struct pblk_line *line)
>> +{
>> +	struct pblk_line_meta *lm = &pblk->lm;
>> +	struct nvm_tgt_dev *dev = pblk->dev;
>> +	struct nvm_geo *geo = &dev->geo;
>> +	int blk_to_erase = atomic_read(&line->blk_in_line);
>> +	int i;
>> +
>> +	for (i = 0; i < lm->blk_per_line; i++) {
>> +		int state = line->chks[i].state;
>> +		struct pblk_lun *rlun = &pblk->luns[i];
>> +
>> +		/* Free chunks should not be erased */
>> +		if (state & NVM_CHK_ST_FREE) {
>> +			set_bit(pblk_ppa_to_pos(geo, rlun->chunk_bppa),
>> +					line->erase_bitmap);
>> +			blk_to_erase--;
>> +			line->chks[i].state = NVM_CHK_ST_HOST_USE;
> 
> 
> Can you help me understand why you want to use The
> NVM_CHK_ST_HOST_USE? Why would I care if the chunk state is HOST_USE?
> A target instance should not be able to see states from other chunks
> it doesn't own. and in that case, why have a separate state?
> 

The motivation for this state is that pblk does not maintain a per
block/chunk state. On the first disk pass however, the state of the
chunks is unknown, thus we need to check for each one individually;
after that, we know that good chunks need to be erased. Having this
extra chunk state, frees us from maintaining this unnecessary intra-line
state. Also, at the point I wrote this code, we did not have the report
chunk on the erase path, so updating the chunk metadata would be
something periodic.

I have taken a look at this again and I solved it in a different way -
basically, only maintaining free/closed states, which is not much more
expensive. It is included in the next version.

> 
>> +		}
>> +
>> +		WARN_ONCE(state & NVM_CHK_ST_OPEN,
>> +				"pblk: open chunk in new line: %d\n",
>> +				line->id);
>> +	}
>> +
>> +	return blk_to_erase;
>> +}
>> +
>>  static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>>  {
>>  	struct pblk_line_meta *lm = &pblk->lm;
>> -	int blk_in_line = atomic_read(&line->blk_in_line);
>> +	int blk_to_erase;
>>    	line->map_bitmap = kzalloc(lm->sec_bitmap_len, GFP_ATOMIC);
>>  	if (!line->map_bitmap)
>> @@ -1110,7 +1184,21 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>>  		return -ENOMEM;
>>  	}
>>  +	/* Bad blocks do not need to be erased */
>> +	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
>> +
>>  	spin_lock(&line->lock);
>> +
>> +	/* If we have not written to this line, we need to mark up free chunks
>> +	 * as already erased
>> +	 */
>> +	if (line->state == PBLK_LINESTATE_NEW) {
>> +		blk_to_erase = pblk_prepare_new_line(pblk, line);
>> +		line->state = PBLK_LINESTATE_FREE;
>> +	} else {
>> +		blk_to_erase = atomic_read(&line->blk_in_line);
>> +	}
>> +
>>  	if (line->state != PBLK_LINESTATE_FREE) {
>>  		kfree(line->map_bitmap);
>>  		kfree(line->invalid_bitmap);
>> @@ -1122,15 +1210,12 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>>    	line->state = PBLK_LINESTATE_OPEN;
>>  -	atomic_set(&line->left_eblks, blk_in_line);
>> -	atomic_set(&line->left_seblks, blk_in_line);
>> +	atomic_set(&line->left_eblks, blk_to_erase);
>> +	atomic_set(&line->left_seblks, blk_to_erase);
>>    	line->meta_distance = lm->meta_distance;
>>  	spin_unlock(&line->lock);
>>  -	/* Bad blocks do not need to be erased */
>> -	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
>> -
>>  	kref_init(&line->ref);
>>    	return 0;
>> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
>> index ec39800eea42..cf4f49d48aed 100644
>> --- a/drivers/lightnvm/pblk-init.c
>> +++ b/drivers/lightnvm/pblk-init.c
>> @@ -401,6 +401,7 @@ static void pblk_line_meta_free(struct pblk_line *line)
>>  {
>>  	kfree(line->blk_bitmap);
>>  	kfree(line->erase_bitmap);
>> +	kfree(line->chks);
>>  }
>>    static void pblk_lines_free(struct pblk *pblk)
>> @@ -440,54 +441,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->c.num_chk * geo->c.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;
>>  -	for (i = 0; i < blk_per_line; i++) {
>> -		struct pblk_lun *rlun = &pblk->luns[i];
>> -		u8 *lun_bb_log = bb_log + i * blk_per_line;
>> -
>> -		if (lun_bb_log[line->id] == NVM_BLK_T_FREE)
>> -			continue;
>> -
>> -		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
>> -		bb_cnt++;
>> -	}
>> -
>> -	return bb_cnt;
>> +	if (geo->c.version == NVM_OCSSD_SPEC_12)
>> +		return pblk_bb_get_meta(pblk);
>> +	else
>> +		return pblk_chunk_get_info(pblk);
> 
> This 1.2 or 2.0 would be nice to have inside the lightnvm core. A
> target should not care weather it is a 1.2 or 2.0 device.
> 

It is not an easy thing to do since the bad block format and chunk
report return completely different formats. As I explained in a
different thread, doing this in core would force 1.2 to understand fake
chunk formats, which are not meaningful. It is better to leave the logic
at the target level, where we know what to do with the format.

>>  }
>>    static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
>> @@ -516,6 +507,7 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
>>    		rlun = &pblk->luns[i];
>>  		rlun->bppa = luns[lunid];
>> +		rlun->chunk_bppa = luns[i];
>>    		sema_init(&rlun->wr_sem, 1);
>>  	}
>> @@ -695,8 +687,125 @@ static int pblk_lines_alloc_metadata(struct pblk *pblk)
>>  	return -ENOMEM;
>>  }
>>  -static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>> -				void *chunk_log, long *nr_bad_blks)
>> +static int pblk_setup_line_meta_12(struct pblk *pblk, struct pblk_line *line,
>> +				   void *chunk_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->c.num_chk * geo->c.pln_mode;
>> +
>> +	for (i = 0; i < lm->blk_per_line; i++) {
>> +		struct pblk_chunk *chunk = &line->chks[i];
>> +		struct pblk_lun *rlun = &pblk->luns[i];
>> +		u8 *lun_bb_meta = chunk_meta + i * chk_per_lun;
>> +
>> +		/*
>> +		 * In 1.2 spec. chunk state is not persisted by the device. Thus
>> +		 * some of the values are reset each time pblk is instantiated.
>> +		 */
>> +		if (lun_bb_meta[line->id] == NVM_BLK_T_FREE)
>> +			chunk->state =  NVM_CHK_ST_HOST_USE;
>> +		else
>> +			chunk->state = NVM_CHK_ST_OFFLINE;
>> +
>> +		chunk->type = NVM_CHK_TP_W_SEQ;
>> +		chunk->wi = 0;
>> +		chunk->slba = -1;
>> +		chunk->cnlb = geo->c.clba;
>> +		chunk->wp = 0;
>> +
>> +		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
>> +			continue;
>> +
>> +		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
>> +		nr_bad_chks++;
>> +	}
>> +
>> +	return nr_bad_chks;
>> +}
>> +
>> +static int pblk_setup_line_meta_20(struct pblk *pblk, struct pblk_line *line,
>> +				   struct nvm_chk_meta *meta)
>> +{
>> +	struct nvm_tgt_dev *dev = pblk->dev;
>> +	struct nvm_geo *geo = &dev->geo;
>> +	struct pblk_line_meta *lm = &pblk->lm;
>> +	int i, nr_bad_chks = 0;
>> +
>> +	for (i = 0; i < lm->blk_per_line; i++) {
>> +		struct pblk_chunk *chunk = &line->chks[i];
>> +		struct pblk_lun *rlun = &pblk->luns[i];
>> +		struct nvm_chk_meta *chunk_meta;
>> +		struct ppa_addr ppa;
>> +
>> +		ppa = rlun->chunk_bppa;
>> +		ppa.m.chk = line->id;
>> +		chunk_meta = pblk_chunk_get_off(pblk, meta, ppa);
>> +
>> +		chunk->state = chunk_meta->state;
>> +		chunk->type = chunk_meta->type;
>> +		chunk->wi = chunk_meta->wi;
>> +		chunk->slba = chunk_meta->slba;
>> +		chunk->cnlb = chunk_meta->cnlb;
>> +		chunk->wp = chunk_meta->wp;
>> +
>> +		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
>> +			continue;
>> +
>> +		if (chunk->type & NVM_CHK_TP_SZ_SPEC) {
>> +			WARN_ONCE(1, "pblk: custom-sized chunks unsupported\n");
>> +			continue;
>> +		}
>> +
>> +		set_bit(pblk_ppa_to_pos(geo, rlun->chunk_bppa),
>> +							line->blk_bitmap);
>> +		nr_bad_chks++;
>> +	}
>> +
>> +	return nr_bad_chks;
>> +}
>> +
>> +static long pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>> +				 void *chunk_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->c.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;
>>  @@ -710,7 +819,13 @@ static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>>  		return -ENOMEM;
>>  	}
>>  -	*nr_bad_blks = pblk_bb_line(pblk, line, chunk_log, lm->blk_per_line);
>> +	line->chks = kmalloc(lm->blk_per_line * sizeof(struct pblk_chunk),
>> +								GFP_KERNEL);
>> +	if (!line->chks) {
>> +		kfree(line->erase_bitmap);
>> +		kfree(line->blk_bitmap);
>> +		return -ENOMEM;
>> +	}
>>    	return 0;
>>  }
>> @@ -722,9 +837,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;
>> +	void *chunk_meta;
>>  	unsigned int smeta_len, emeta_len;
>> -	long nr_bad_blks = 0, nr_free_blks = 0;
>> +	long nr_free_chks = 0;
>>  	int bb_distance, max_write_ppas;
>>  	int i, ret;
>>  @@ -743,6 +858,7 @@ static int pblk_lines_init(struct pblk *pblk)
>>  	l_mg->log_line = l_mg->data_line = NULL;
>>  	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
>>  	l_mg->nr_free_lines = 0;
>> +	atomic_set(&l_mg->sysfs_line_state, -1);
>>  	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
>>    	lm->sec_per_line = geo->c.clba * geo->all_luns;
>> @@ -841,53 +957,31 @@ static int pblk_lines_init(struct pblk *pblk)
>>  		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);
>> +	chunk_meta = pblk_chunk_get_meta(pblk);
>> +	if (IS_ERR(chunk_meta)) {
>> +		pr_err("pblk: could not get chunk log (%lu)\n",
>> +							PTR_ERR(chunk_meta));
>> +		ret = PTR_ERR(chunk_meta);
>>  		goto fail_free_lines;
>>  	}
>>    	for (i = 0; i < l_mg->nr_lines; i++) {
>> -		int chk_in_line;
>> -
>>  		line = &pblk->lines[i];
>>  -		line->pblk = pblk;
>> -		line->id = i;
>> -		line->type = PBLK_LINETYPE_FREE;
>> -		line->state = PBLK_LINESTATE_FREE;
>> -		line->gc_group = PBLK_LINEGC_NONE;
>> -		line->vsc = &l_mg->vsc_list[i];
>> -		spin_lock_init(&line->lock);
>> -
>> -		ret = pblk_setup_line_meta(pblk, line, chunk_log, &nr_bad_blks);
>> +		ret = pblk_alloc_line_meta(pblk, line);
>>  		if (ret)
>> -			goto fail_free_chunk_log;
>> +			goto fail_free_chunk_meta;
>>  -		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_chunk_log:
>> -	kfree(chunk_log);
>> +fail_free_chunk_meta:
>> +	kfree(chunk_meta);
>>  	while (--i >= 0)
>>  		pblk_line_meta_free(&pblk->lines[i]);
>>  fail_free_lines:
>> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
>> index ccfb3abd2773..1ce5b956c622 100644
>> --- a/drivers/lightnvm/pblk-sysfs.c
>> +++ b/drivers/lightnvm/pblk-sysfs.c
>> @@ -142,6 +142,40 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
>>  	return sz;
>>  }
>>  +static ssize_t pblk_sysfs_line_state_show(struct pblk *pblk, char *page)
>> +{
>> +	struct pblk_line_meta *lm = &pblk->lm;
>> +	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
>> +	struct pblk_line *line;
>> +	int line_id = atomic_read(&l_mg->sysfs_line_state);
>> +	ssize_t sz = 0;
>> +	int i;
>> +
>> +	if (line_id < 0 || line_id >= l_mg->nr_lines)
>> +		return 0;
>> +
>> +	sz = snprintf(page, PAGE_SIZE,
>> +		"line\tchunk\tstate\ttype\twear-index\tslba\t\tcnlb\twp\n");
>> +
>> +	line = &pblk->lines[line_id];
>> +
>> +	for (i = 0; i < lm->blk_per_line; i++) {
>> +		struct pblk_chunk *chunk = &line->chks[i];
>> +
>> +		sz += snprintf(page + sz, PAGE_SIZE - sz,
>> +				"%d\t%d\t%d\t%d\t%d\t\t%llu\t\t%llu\t%llu\n",
>> +				line->id, i,
>> +				chunk->state,
>> +				chunk->type,
>> +				chunk->wi,
>> +				chunk->slba,
>> +				chunk->cnlb,
>> +				chunk->wp);
>> +	}
>> +
>> +	return sz;
>> +}
>> +
>>  static ssize_t pblk_sysfs_lines(struct pblk *pblk, char *page)
>>  {
>>  	struct nvm_tgt_dev *dev = pblk->dev;
>> @@ -398,6 +432,29 @@ static ssize_t pblk_sysfs_stats_debug(struct pblk *pblk, char *page)
>>  }
>>  #endif
>>  +
>> +static ssize_t pblk_sysfs_line_state_store(struct pblk *pblk, const char *page,
>> +					   size_t len)
>> +{
>> +	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
>> +	size_t c_len;
>> +	int line_id;
>> +
>> +	c_len = strcspn(page, "\n");
>> +	if (c_len >= len)
>> +		return -EINVAL;
>> +
>> +	if (kstrtouint(page, 0, &line_id))
>> +		return -EINVAL;
>> +
>> +	if (line_id < 0 || line_id >= l_mg->nr_lines)
>> +		return -EINVAL;
>> +
>> +	atomic_set(&l_mg->sysfs_line_state, line_id);
>> +
>> +	return len;
>> +}
>> +
>>  static ssize_t pblk_sysfs_gc_force(struct pblk *pblk, const char *page,
>>  				   size_t len)
>>  {
>> @@ -529,6 +586,11 @@ static struct attribute sys_lines_info_attr = {
>>  	.mode = 0444,
>>  };
>>  +static struct attribute sys_line_state_attr = {
>> +	.name = "line_state",
>> +	.mode = 0644,
>> +};
>> +
>>  static struct attribute sys_gc_force = {
>>  	.name = "gc_force",
>>  	.mode = 0200,
>> @@ -572,6 +634,7 @@ static struct attribute *pblk_attrs[] = {
>>  	&sys_stats_ppaf_attr,
>>  	&sys_lines_attr,
>>  	&sys_lines_info_attr,
>> +	&sys_line_state_attr,
>>  	&sys_write_amp_mileage,
>>  	&sys_write_amp_trip,
>>  	&sys_padding_dist,
>> @@ -602,6 +665,8 @@ static ssize_t pblk_sysfs_show(struct kobject *kobj, struct attribute *attr,
>>  		return pblk_sysfs_lines(pblk, buf);
>>  	else if (strcmp(attr->name, "lines_info") == 0)
>>  		return pblk_sysfs_lines_info(pblk, buf);
>> +	else if (strcmp(attr->name, "line_state") == 0)
>> +		return pblk_sysfs_line_state_show(pblk, buf);
>>  	else if (strcmp(attr->name, "max_sec_per_write") == 0)
>>  		return pblk_sysfs_get_sec_per_write(pblk, buf);
>>  	else if (strcmp(attr->name, "write_amp_mileage") == 0)
>> @@ -628,6 +693,8 @@ static ssize_t pblk_sysfs_store(struct kobject *kobj, struct attribute *attr,
>>  		return pblk_sysfs_set_sec_per_write(pblk, buf, len);
>>  	else if (strcmp(attr->name, "write_amp_trip") == 0)
>>  		return pblk_sysfs_set_write_amp_trip(pblk, buf, len);
>> +	else if (strcmp(attr->name, "line_state") == 0)
>> +		return pblk_sysfs_line_state_store(pblk, buf, len);
>>  	else if (strcmp(attr->name, "padding_dist") == 0)
>>  		return pblk_sysfs_set_padding_dist(pblk, buf, len);
>>  	return 0;
>> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
>> index 6e1fcd1a538a..bc31c67b725f 100644
>> --- a/drivers/lightnvm/pblk.h
>> +++ b/drivers/lightnvm/pblk.h
>> @@ -201,6 +201,8 @@ struct pblk_rb {
>>    struct pblk_lun {
>>  	struct ppa_addr bppa;
>> +	struct ppa_addr chunk_bppa;
>> +
>>  	struct semaphore wr_sem;
>>  };
>>  @@ -297,6 +299,7 @@ enum {
>>  	PBLK_LINETYPE_DATA = 2,
>>    	/* Line state */
>> +	PBLK_LINESTATE_NEW = 9,
>>  	PBLK_LINESTATE_FREE = 10,
>>  	PBLK_LINESTATE_OPEN = 11,
>>  	PBLK_LINESTATE_CLOSED = 12,
>> @@ -412,6 +415,15 @@ struct pblk_smeta {
>>  	struct line_smeta *buf;		/* smeta buffer in persistent format */
>>  };
>>  +struct pblk_chunk {
>> +	int state;
>> +	int type;
>> +	int wi;
>> +	u64 slba;
>> +	u64 cnlb;
>> +	u64 wp;
>> +};
>> +
> 
> How come the code replicate the nvm_chk_meta data structure?

There is no need to maintain the chunk reserved bits in nvm_chk_meta and
waste memory in the process, as these are alive for the whole life of
the pblk instance. This structure only maintains the necessary bits.

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

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

* Re: [PATCH 17/19] lightnvm: pblk: implement get log report chunk
  2018-02-27 14:40       ` Javier González
@ 2018-02-27 18:46         ` Matias Bjørling
  -1 siblings, 0 replies; 70+ messages in thread
From: Matias Bjørling @ 2018-02-27 18:46 UTC (permalink / raw)
  To: Javier González; +Cc: linux-block, linux-kernel, linux-nvme

On 02/27/2018 03:40 PM, Javier González wrote:
>> On 26 Feb 2018, at 20.04, Matias Bjørling <mb@lightnvm.io> wrote:
>>
<snip>
>>
>>
>> Can you help me understand why you want to use The
>> NVM_CHK_ST_HOST_USE? Why would I care if the chunk state is HOST_USE?
>> A target instance should not be able to see states from other chunks
>> it doesn't own. and in that case, why have a separate state?
>>
> 
> The motivation for this state is that pblk does not maintain a per
> block/chunk state. On the first disk pass however, the state of the
> chunks is unknown, 

I don't understand this. Why is the state unknown? If assuming 1.2 
drive, one can do a scan of first page of each block. If the block 
returns success (it is in use), if 0x42ff, the block is empty, and if 
reading and it returns 0x4281, it is open.

thus we need to check for each one individually;
> after that, we know that good chunks need to be erased. Having this
> extra chunk state, frees us from maintaining this unnecessary intra-line
> state. Also, at the point I wrote this code, we did not have the report
> chunk on the erase path, so updating the chunk metadata would be
> something periodic.
> 
> I have taken a look at this again and I solved it in a different way -
> basically, only maintaining free/closed states, which is not much more
> expensive. It is included in the next version.
> 
>>
>>> +		}
>>> +
>>> +		WARN_ONCE(state & NVM_CHK_ST_OPEN,
>>> +				"pblk: open chunk in new line: %d\n",
>>> +				line->id);
>>> +	}
>>> +
>>> +	return blk_to_erase;
>>> +}
>>> +
>>>   static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>>>   {
>>>   	struct pblk_line_meta *lm = &pblk->lm;
>>> -	int blk_in_line = atomic_read(&line->blk_in_line);
>>> +	int blk_to_erase;
>>>     	line->map_bitmap = kzalloc(lm->sec_bitmap_len, GFP_ATOMIC);
>>>   	if (!line->map_bitmap)
>>> @@ -1110,7 +1184,21 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>>>   		return -ENOMEM;
>>>   	}
>>>   +	/* Bad blocks do not need to be erased */
>>> +	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
>>> +
>>>   	spin_lock(&line->lock);
>>> +
>>> +	/* If we have not written to this line, we need to mark up free chunks
>>> +	 * as already erased
>>> +	 */
>>> +	if (line->state == PBLK_LINESTATE_NEW) {
>>> +		blk_to_erase = pblk_prepare_new_line(pblk, line);
>>> +		line->state = PBLK_LINESTATE_FREE;
>>> +	} else {
>>> +		blk_to_erase = atomic_read(&line->blk_in_line);
>>> +	}
>>> +
>>>   	if (line->state != PBLK_LINESTATE_FREE) {
>>>   		kfree(line->map_bitmap);
>>>   		kfree(line->invalid_bitmap);
>>> @@ -1122,15 +1210,12 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>>>     	line->state = PBLK_LINESTATE_OPEN;
>>>   -	atomic_set(&line->left_eblks, blk_in_line);
>>> -	atomic_set(&line->left_seblks, blk_in_line);
>>> +	atomic_set(&line->left_eblks, blk_to_erase);
>>> +	atomic_set(&line->left_seblks, blk_to_erase);
>>>     	line->meta_distance = lm->meta_distance;
>>>   	spin_unlock(&line->lock);
>>>   -	/* Bad blocks do not need to be erased */
>>> -	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
>>> -
>>>   	kref_init(&line->ref);
>>>     	return 0;
>>> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
>>> index ec39800eea42..cf4f49d48aed 100644
>>> --- a/drivers/lightnvm/pblk-init.c
>>> +++ b/drivers/lightnvm/pblk-init.c
>>> @@ -401,6 +401,7 @@ static void pblk_line_meta_free(struct pblk_line *line)
>>>   {
>>>   	kfree(line->blk_bitmap);
>>>   	kfree(line->erase_bitmap);
>>> +	kfree(line->chks);
>>>   }
>>>     static void pblk_lines_free(struct pblk *pblk)
>>> @@ -440,54 +441,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->c.num_chk * geo->c.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;
>>>   -	for (i = 0; i < blk_per_line; i++) {
>>> -		struct pblk_lun *rlun = &pblk->luns[i];
>>> -		u8 *lun_bb_log = bb_log + i * blk_per_line;
>>> -
>>> -		if (lun_bb_log[line->id] == NVM_BLK_T_FREE)
>>> -			continue;
>>> -
>>> -		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
>>> -		bb_cnt++;
>>> -	}
>>> -
>>> -	return bb_cnt;
>>> +	if (geo->c.version == NVM_OCSSD_SPEC_12)
>>> +		return pblk_bb_get_meta(pblk);
>>> +	else
>>> +		return pblk_chunk_get_info(pblk);
>>
>> This 1.2 or 2.0 would be nice to have inside the lightnvm core. A
>> target should not care weather it is a 1.2 or 2.0 device.
>>
> 
> It is not an easy thing to do since the bad block format and chunk
> report return completely different formats. As I explained in a
> different thread, doing this in core would force 1.2 to understand fake
> chunk formats, which are not meaningful. It is better to leave the logic
> at the target level, where we know what to do with the format.

What if the core layer exported a generic "chunk meta" interface, and 
then filled it as is done in pblk. In the core, it will then fill out 
what it can fill out, and leave the rest of the fields untouched. The 
pblk code can then if () in certain places if for example wp attribute 
can,'t be used?

In the interest of time, and to get this moving, we can ignore it for now.

> 
>>>   }
>>>     static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
>>> @@ -516,6 +507,7 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
>>>     		rlun = &pblk->luns[i];
>>>   		rlun->bppa = luns[lunid];
>>> +		rlun->chunk_bppa = luns[i];
>>>     		sema_init(&rlun->wr_sem, 1);
>>>   	}
>>> @@ -695,8 +687,125 @@ static int pblk_lines_alloc_metadata(struct pblk *pblk)
>>>   	return -ENOMEM;
>>>   }
>>>   -static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>>> -				void *chunk_log, long *nr_bad_blks)
>>> +static int pblk_setup_line_meta_12(struct pblk *pblk, struct pblk_line *line,
>>> +				   void *chunk_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->c.num_chk * geo->c.pln_mode;
>>> +
>>> +	for (i = 0; i < lm->blk_per_line; i++) {
>>> +		struct pblk_chunk *chunk = &line->chks[i];
>>> +		struct pblk_lun *rlun = &pblk->luns[i];
>>> +		u8 *lun_bb_meta = chunk_meta + i * chk_per_lun;
>>> +
>>> +		/*
>>> +		 * In 1.2 spec. chunk state is not persisted by the device. Thus
>>> +		 * some of the values are reset each time pblk is instantiated.
>>> +		 */
>>> +		if (lun_bb_meta[line->id] == NVM_BLK_T_FREE)
>>> +			chunk->state =  NVM_CHK_ST_HOST_USE;
>>> +		else
>>> +			chunk->state = NVM_CHK_ST_OFFLINE;
>>> +
>>> +		chunk->type = NVM_CHK_TP_W_SEQ;
>>> +		chunk->wi = 0;
>>> +		chunk->slba = -1;
>>> +		chunk->cnlb = geo->c.clba;
>>> +		chunk->wp = 0;
>>> +
>>> +		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
>>> +			continue;
>>> +
>>> +		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
>>> +		nr_bad_chks++;
>>> +	}
>>> +
>>> +	return nr_bad_chks;
>>> +}
>>> +
>>> +static int pblk_setup_line_meta_20(struct pblk *pblk, struct pblk_line *line,
>>> +				   struct nvm_chk_meta *meta)
>>> +{
>>> +	struct nvm_tgt_dev *dev = pblk->dev;
>>> +	struct nvm_geo *geo = &dev->geo;
>>> +	struct pblk_line_meta *lm = &pblk->lm;
>>> +	int i, nr_bad_chks = 0;
>>> +
>>> +	for (i = 0; i < lm->blk_per_line; i++) {
>>> +		struct pblk_chunk *chunk = &line->chks[i];
>>> +		struct pblk_lun *rlun = &pblk->luns[i];
>>> +		struct nvm_chk_meta *chunk_meta;
>>> +		struct ppa_addr ppa;
>>> +
>>> +		ppa = rlun->chunk_bppa;
>>> +		ppa.m.chk = line->id;
>>> +		chunk_meta = pblk_chunk_get_off(pblk, meta, ppa);
>>> +
>>> +		chunk->state = chunk_meta->state;
>>> +		chunk->type = chunk_meta->type;
>>> +		chunk->wi = chunk_meta->wi;
>>> +		chunk->slba = chunk_meta->slba;
>>> +		chunk->cnlb = chunk_meta->cnlb;
>>> +		chunk->wp = chunk_meta->wp;
>>> +
>>> +		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
>>> +			continue;
>>> +
>>> +		if (chunk->type & NVM_CHK_TP_SZ_SPEC) {
>>> +			WARN_ONCE(1, "pblk: custom-sized chunks unsupported\n");
>>> +			continue;
>>> +		}
>>> +
>>> +		set_bit(pblk_ppa_to_pos(geo, rlun->chunk_bppa),
>>> +							line->blk_bitmap);
>>> +		nr_bad_chks++;
>>> +	}
>>> +
>>> +	return nr_bad_chks;
>>> +}
>>> +
>>> +static long pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>>> +				 void *chunk_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->c.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;
>>>   @@ -710,7 +819,13 @@ static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>>>   		return -ENOMEM;
>>>   	}
>>>   -	*nr_bad_blks = pblk_bb_line(pblk, line, chunk_log, lm->blk_per_line);
>>> +	line->chks = kmalloc(lm->blk_per_line * sizeof(struct pblk_chunk),
>>> +								GFP_KERNEL);
>>> +	if (!line->chks) {
>>> +		kfree(line->erase_bitmap);
>>> +		kfree(line->blk_bitmap);
>>> +		return -ENOMEM;
>>> +	}
>>>     	return 0;
>>>   }
>>> @@ -722,9 +837,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;
>>> +	void *chunk_meta;
>>>   	unsigned int smeta_len, emeta_len;
>>> -	long nr_bad_blks = 0, nr_free_blks = 0;
>>> +	long nr_free_chks = 0;
>>>   	int bb_distance, max_write_ppas;
>>>   	int i, ret;
>>>   @@ -743,6 +858,7 @@ static int pblk_lines_init(struct pblk *pblk)
>>>   	l_mg->log_line = l_mg->data_line = NULL;
>>>   	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
>>>   	l_mg->nr_free_lines = 0;
>>> +	atomic_set(&l_mg->sysfs_line_state, -1);
>>>   	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
>>>     	lm->sec_per_line = geo->c.clba * geo->all_luns;
>>> @@ -841,53 +957,31 @@ static int pblk_lines_init(struct pblk *pblk)
>>>   		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);
>>> +	chunk_meta = pblk_chunk_get_meta(pblk);
>>> +	if (IS_ERR(chunk_meta)) {
>>> +		pr_err("pblk: could not get chunk log (%lu)\n",
>>> +							PTR_ERR(chunk_meta));
>>> +		ret = PTR_ERR(chunk_meta);
>>>   		goto fail_free_lines;
>>>   	}
>>>     	for (i = 0; i < l_mg->nr_lines; i++) {
>>> -		int chk_in_line;
>>> -
>>>   		line = &pblk->lines[i];
>>>   -		line->pblk = pblk;
>>> -		line->id = i;
>>> -		line->type = PBLK_LINETYPE_FREE;
>>> -		line->state = PBLK_LINESTATE_FREE;
>>> -		line->gc_group = PBLK_LINEGC_NONE;
>>> -		line->vsc = &l_mg->vsc_list[i];
>>> -		spin_lock_init(&line->lock);
>>> -
>>> -		ret = pblk_setup_line_meta(pblk, line, chunk_log, &nr_bad_blks);
>>> +		ret = pblk_alloc_line_meta(pblk, line);
>>>   		if (ret)
>>> -			goto fail_free_chunk_log;
>>> +			goto fail_free_chunk_meta;
>>>   -		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_chunk_log:
>>> -	kfree(chunk_log);
>>> +fail_free_chunk_meta:
>>> +	kfree(chunk_meta);
>>>   	while (--i >= 0)
>>>   		pblk_line_meta_free(&pblk->lines[i]);
>>>   fail_free_lines:
>>> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
>>> index ccfb3abd2773..1ce5b956c622 100644
>>> --- a/drivers/lightnvm/pblk-sysfs.c
>>> +++ b/drivers/lightnvm/pblk-sysfs.c
>>> @@ -142,6 +142,40 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
>>>   	return sz;
>>>   }
>>>   +static ssize_t pblk_sysfs_line_state_show(struct pblk *pblk, char *page)
>>> +{
>>> +	struct pblk_line_meta *lm = &pblk->lm;
>>> +	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
>>> +	struct pblk_line *line;
>>> +	int line_id = atomic_read(&l_mg->sysfs_line_state);
>>> +	ssize_t sz = 0;
>>> +	int i;
>>> +
>>> +	if (line_id < 0 || line_id >= l_mg->nr_lines)
>>> +		return 0;
>>> +
>>> +	sz = snprintf(page, PAGE_SIZE,
>>> +		"line\tchunk\tstate\ttype\twear-index\tslba\t\tcnlb\twp\n");
>>> +
>>> +	line = &pblk->lines[line_id];
>>> +
>>> +	for (i = 0; i < lm->blk_per_line; i++) {
>>> +		struct pblk_chunk *chunk = &line->chks[i];
>>> +
>>> +		sz += snprintf(page + sz, PAGE_SIZE - sz,
>>> +				"%d\t%d\t%d\t%d\t%d\t\t%llu\t\t%llu\t%llu\n",
>>> +				line->id, i,
>>> +				chunk->state,
>>> +				chunk->type,
>>> +				chunk->wi,
>>> +				chunk->slba,
>>> +				chunk->cnlb,
>>> +				chunk->wp);
>>> +	}
>>> +
>>> +	return sz;
>>> +}
>>> +
>>>   static ssize_t pblk_sysfs_lines(struct pblk *pblk, char *page)
>>>   {
>>>   	struct nvm_tgt_dev *dev = pblk->dev;
>>> @@ -398,6 +432,29 @@ static ssize_t pblk_sysfs_stats_debug(struct pblk *pblk, char *page)
>>>   }
>>>   #endif
>>>   +
>>> +static ssize_t pblk_sysfs_line_state_store(struct pblk *pblk, const char *page,
>>> +					   size_t len)
>>> +{
>>> +	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
>>> +	size_t c_len;
>>> +	int line_id;
>>> +
>>> +	c_len = strcspn(page, "\n");
>>> +	if (c_len >= len)
>>> +		return -EINVAL;
>>> +
>>> +	if (kstrtouint(page, 0, &line_id))
>>> +		return -EINVAL;
>>> +
>>> +	if (line_id < 0 || line_id >= l_mg->nr_lines)
>>> +		return -EINVAL;
>>> +
>>> +	atomic_set(&l_mg->sysfs_line_state, line_id);
>>> +
>>> +	return len;
>>> +}
>>> +
>>>   static ssize_t pblk_sysfs_gc_force(struct pblk *pblk, const char *page,
>>>   				   size_t len)
>>>   {
>>> @@ -529,6 +586,11 @@ static struct attribute sys_lines_info_attr = {
>>>   	.mode = 0444,
>>>   };
>>>   +static struct attribute sys_line_state_attr = {
>>> +	.name = "line_state",
>>> +	.mode = 0644,
>>> +};
>>> +
>>>   static struct attribute sys_gc_force = {
>>>   	.name = "gc_force",
>>>   	.mode = 0200,
>>> @@ -572,6 +634,7 @@ static struct attribute *pblk_attrs[] = {
>>>   	&sys_stats_ppaf_attr,
>>>   	&sys_lines_attr,
>>>   	&sys_lines_info_attr,
>>> +	&sys_line_state_attr,
>>>   	&sys_write_amp_mileage,
>>>   	&sys_write_amp_trip,
>>>   	&sys_padding_dist,
>>> @@ -602,6 +665,8 @@ static ssize_t pblk_sysfs_show(struct kobject *kobj, struct attribute *attr,
>>>   		return pblk_sysfs_lines(pblk, buf);
>>>   	else if (strcmp(attr->name, "lines_info") == 0)
>>>   		return pblk_sysfs_lines_info(pblk, buf);
>>> +	else if (strcmp(attr->name, "line_state") == 0)
>>> +		return pblk_sysfs_line_state_show(pblk, buf);
>>>   	else if (strcmp(attr->name, "max_sec_per_write") == 0)
>>>   		return pblk_sysfs_get_sec_per_write(pblk, buf);
>>>   	else if (strcmp(attr->name, "write_amp_mileage") == 0)
>>> @@ -628,6 +693,8 @@ static ssize_t pblk_sysfs_store(struct kobject *kobj, struct attribute *attr,
>>>   		return pblk_sysfs_set_sec_per_write(pblk, buf, len);
>>>   	else if (strcmp(attr->name, "write_amp_trip") == 0)
>>>   		return pblk_sysfs_set_write_amp_trip(pblk, buf, len);
>>> +	else if (strcmp(attr->name, "line_state") == 0)
>>> +		return pblk_sysfs_line_state_store(pblk, buf, len);
>>>   	else if (strcmp(attr->name, "padding_dist") == 0)
>>>   		return pblk_sysfs_set_padding_dist(pblk, buf, len);
>>>   	return 0;
>>> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
>>> index 6e1fcd1a538a..bc31c67b725f 100644
>>> --- a/drivers/lightnvm/pblk.h
>>> +++ b/drivers/lightnvm/pblk.h
>>> @@ -201,6 +201,8 @@ struct pblk_rb {
>>>     struct pblk_lun {
>>>   	struct ppa_addr bppa;
>>> +	struct ppa_addr chunk_bppa;
>>> +
>>>   	struct semaphore wr_sem;
>>>   };
>>>   @@ -297,6 +299,7 @@ enum {
>>>   	PBLK_LINETYPE_DATA = 2,
>>>     	/* Line state */
>>> +	PBLK_LINESTATE_NEW = 9,
>>>   	PBLK_LINESTATE_FREE = 10,
>>>   	PBLK_LINESTATE_OPEN = 11,
>>>   	PBLK_LINESTATE_CLOSED = 12,
>>> @@ -412,6 +415,15 @@ struct pblk_smeta {
>>>   	struct line_smeta *buf;		/* smeta buffer in persistent format */
>>>   };
>>>   +struct pblk_chunk {
>>> +	int state;
>>> +	int type;
>>> +	int wi;
>>> +	u64 slba;
>>> +	u64 cnlb;
>>> +	u64 wp;
>>> +};
>>> +
>>
>> How come the code replicate the nvm_chk_meta data structure?
> 
> There is no need to maintain the chunk reserved bits in nvm_chk_meta and
> waste memory in the process, as these are alive for the whole life of
> the pblk instance. This structure only maintains the necessary bits.
>

nvm_chk_meta is 32 bytes:

struct nvm_chk_meta {
	u8                         state;                /* 0     1 */
	u8                         type;                 /* 1     1 */
	u8                         wli;                  /* 2     1 */
	u8                         rsvd[5];              /* 3     5 */
	u64                        slba;                 /* 8     8 */
	u64                        cnlb;                 /* 16     8 */
	u64                        wp;                   /* 24     8 */

	/* size: 32, cachelines: 1, members: 7 */
	/* last cacheline: 32 bytes */
};

pblk_chunk is 40 bytes:

struct pblk_chunk {
	int                        state;                /*  0     4 */
	int                        type;                 /*  4     4 */
	int                        wi;                   /*  8     4 */

	/* XXX 4 bytes hole, try to pack */

	u64                        slba;                 /*  16     8 */
	u64                        cnlb;                 /*  24     8 */
	u64                        wp;                   /*  32     8 */

	/* size: 40, cachelines: 1, members: 6 */
	/* sum members: 36, holes: 1, sum holes: 4 */
	/* last cacheline: 40 bytes */
};

If assuming 64K chunks, pblk chunk uses 2560KB (and requires an extra 
traversal when the chunk meta information is returned to copy over the 
data to the new data structure), while nvm_chk_meta uses 2048KB. 
Granted, the nvm_chk_meta state/type/wli fields will be slightly slower 
to access due to the bit shifting, but I think it is worth it. One can 
measure and see if there is any performance difference.

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

* [PATCH 17/19] lightnvm: pblk: implement get log report chunk
@ 2018-02-27 18:46         ` Matias Bjørling
  0 siblings, 0 replies; 70+ messages in thread
From: Matias Bjørling @ 2018-02-27 18:46 UTC (permalink / raw)


On 02/27/2018 03:40 PM, Javier Gonz?lez wrote:
>> On 26 Feb 2018,@20.04, Matias Bj?rling <mb@lightnvm.io> wrote:
>>
<snip>
>>
>>
>> Can you help me understand why you want to use The
>> NVM_CHK_ST_HOST_USE? Why would I care if the chunk state is HOST_USE?
>> A target instance should not be able to see states from other chunks
>> it doesn't own. and in that case, why have a separate state?
>>
> 
> The motivation for this state is that pblk does not maintain a per
> block/chunk state. On the first disk pass however, the state of the
> chunks is unknown, 

I don't understand this. Why is the state unknown? If assuming 1.2 
drive, one can do a scan of first page of each block. If the block 
returns success (it is in use), if 0x42ff, the block is empty, and if 
reading and it returns 0x4281, it is open.

thus we need to check for each one individually;
> after that, we know that good chunks need to be erased. Having this
> extra chunk state, frees us from maintaining this unnecessary intra-line
> state. Also, at the point I wrote this code, we did not have the report
> chunk on the erase path, so updating the chunk metadata would be
> something periodic.
> 
> I have taken a look at this again and I solved it in a different way -
> basically, only maintaining free/closed states, which is not much more
> expensive. It is included in the next version.
> 
>>
>>> +		}
>>> +
>>> +		WARN_ONCE(state & NVM_CHK_ST_OPEN,
>>> +				"pblk: open chunk in new line: %d\n",
>>> +				line->id);
>>> +	}
>>> +
>>> +	return blk_to_erase;
>>> +}
>>> +
>>>   static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>>>   {
>>>   	struct pblk_line_meta *lm = &pblk->lm;
>>> -	int blk_in_line = atomic_read(&line->blk_in_line);
>>> +	int blk_to_erase;
>>>     	line->map_bitmap = kzalloc(lm->sec_bitmap_len, GFP_ATOMIC);
>>>   	if (!line->map_bitmap)
>>> @@ -1110,7 +1184,21 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>>>   		return -ENOMEM;
>>>   	}
>>>   +	/* Bad blocks do not need to be erased */
>>> +	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
>>> +
>>>   	spin_lock(&line->lock);
>>> +
>>> +	/* If we have not written to this line, we need to mark up free chunks
>>> +	 * as already erased
>>> +	 */
>>> +	if (line->state == PBLK_LINESTATE_NEW) {
>>> +		blk_to_erase = pblk_prepare_new_line(pblk, line);
>>> +		line->state = PBLK_LINESTATE_FREE;
>>> +	} else {
>>> +		blk_to_erase = atomic_read(&line->blk_in_line);
>>> +	}
>>> +
>>>   	if (line->state != PBLK_LINESTATE_FREE) {
>>>   		kfree(line->map_bitmap);
>>>   		kfree(line->invalid_bitmap);
>>> @@ -1122,15 +1210,12 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>>>     	line->state = PBLK_LINESTATE_OPEN;
>>>   -	atomic_set(&line->left_eblks, blk_in_line);
>>> -	atomic_set(&line->left_seblks, blk_in_line);
>>> +	atomic_set(&line->left_eblks, blk_to_erase);
>>> +	atomic_set(&line->left_seblks, blk_to_erase);
>>>     	line->meta_distance = lm->meta_distance;
>>>   	spin_unlock(&line->lock);
>>>   -	/* Bad blocks do not need to be erased */
>>> -	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
>>> -
>>>   	kref_init(&line->ref);
>>>     	return 0;
>>> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
>>> index ec39800eea42..cf4f49d48aed 100644
>>> --- a/drivers/lightnvm/pblk-init.c
>>> +++ b/drivers/lightnvm/pblk-init.c
>>> @@ -401,6 +401,7 @@ static void pblk_line_meta_free(struct pblk_line *line)
>>>   {
>>>   	kfree(line->blk_bitmap);
>>>   	kfree(line->erase_bitmap);
>>> +	kfree(line->chks);
>>>   }
>>>     static void pblk_lines_free(struct pblk *pblk)
>>> @@ -440,54 +441,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->c.num_chk * geo->c.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;
>>>   -	for (i = 0; i < blk_per_line; i++) {
>>> -		struct pblk_lun *rlun = &pblk->luns[i];
>>> -		u8 *lun_bb_log = bb_log + i * blk_per_line;
>>> -
>>> -		if (lun_bb_log[line->id] == NVM_BLK_T_FREE)
>>> -			continue;
>>> -
>>> -		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
>>> -		bb_cnt++;
>>> -	}
>>> -
>>> -	return bb_cnt;
>>> +	if (geo->c.version == NVM_OCSSD_SPEC_12)
>>> +		return pblk_bb_get_meta(pblk);
>>> +	else
>>> +		return pblk_chunk_get_info(pblk);
>>
>> This 1.2 or 2.0 would be nice to have inside the lightnvm core. A
>> target should not care weather it is a 1.2 or 2.0 device.
>>
> 
> It is not an easy thing to do since the bad block format and chunk
> report return completely different formats. As I explained in a
> different thread, doing this in core would force 1.2 to understand fake
> chunk formats, which are not meaningful. It is better to leave the logic
> at the target level, where we know what to do with the format.

What if the core layer exported a generic "chunk meta" interface, and 
then filled it as is done in pblk. In the core, it will then fill out 
what it can fill out, and leave the rest of the fields untouched. The 
pblk code can then if () in certain places if for example wp attribute 
can,'t be used?

In the interest of time, and to get this moving, we can ignore it for now.

> 
>>>   }
>>>     static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
>>> @@ -516,6 +507,7 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
>>>     		rlun = &pblk->luns[i];
>>>   		rlun->bppa = luns[lunid];
>>> +		rlun->chunk_bppa = luns[i];
>>>     		sema_init(&rlun->wr_sem, 1);
>>>   	}
>>> @@ -695,8 +687,125 @@ static int pblk_lines_alloc_metadata(struct pblk *pblk)
>>>   	return -ENOMEM;
>>>   }
>>>   -static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>>> -				void *chunk_log, long *nr_bad_blks)
>>> +static int pblk_setup_line_meta_12(struct pblk *pblk, struct pblk_line *line,
>>> +				   void *chunk_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->c.num_chk * geo->c.pln_mode;
>>> +
>>> +	for (i = 0; i < lm->blk_per_line; i++) {
>>> +		struct pblk_chunk *chunk = &line->chks[i];
>>> +		struct pblk_lun *rlun = &pblk->luns[i];
>>> +		u8 *lun_bb_meta = chunk_meta + i * chk_per_lun;
>>> +
>>> +		/*
>>> +		 * In 1.2 spec. chunk state is not persisted by the device. Thus
>>> +		 * some of the values are reset each time pblk is instantiated.
>>> +		 */
>>> +		if (lun_bb_meta[line->id] == NVM_BLK_T_FREE)
>>> +			chunk->state =  NVM_CHK_ST_HOST_USE;
>>> +		else
>>> +			chunk->state = NVM_CHK_ST_OFFLINE;
>>> +
>>> +		chunk->type = NVM_CHK_TP_W_SEQ;
>>> +		chunk->wi = 0;
>>> +		chunk->slba = -1;
>>> +		chunk->cnlb = geo->c.clba;
>>> +		chunk->wp = 0;
>>> +
>>> +		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
>>> +			continue;
>>> +
>>> +		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
>>> +		nr_bad_chks++;
>>> +	}
>>> +
>>> +	return nr_bad_chks;
>>> +}
>>> +
>>> +static int pblk_setup_line_meta_20(struct pblk *pblk, struct pblk_line *line,
>>> +				   struct nvm_chk_meta *meta)
>>> +{
>>> +	struct nvm_tgt_dev *dev = pblk->dev;
>>> +	struct nvm_geo *geo = &dev->geo;
>>> +	struct pblk_line_meta *lm = &pblk->lm;
>>> +	int i, nr_bad_chks = 0;
>>> +
>>> +	for (i = 0; i < lm->blk_per_line; i++) {
>>> +		struct pblk_chunk *chunk = &line->chks[i];
>>> +		struct pblk_lun *rlun = &pblk->luns[i];
>>> +		struct nvm_chk_meta *chunk_meta;
>>> +		struct ppa_addr ppa;
>>> +
>>> +		ppa = rlun->chunk_bppa;
>>> +		ppa.m.chk = line->id;
>>> +		chunk_meta = pblk_chunk_get_off(pblk, meta, ppa);
>>> +
>>> +		chunk->state = chunk_meta->state;
>>> +		chunk->type = chunk_meta->type;
>>> +		chunk->wi = chunk_meta->wi;
>>> +		chunk->slba = chunk_meta->slba;
>>> +		chunk->cnlb = chunk_meta->cnlb;
>>> +		chunk->wp = chunk_meta->wp;
>>> +
>>> +		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
>>> +			continue;
>>> +
>>> +		if (chunk->type & NVM_CHK_TP_SZ_SPEC) {
>>> +			WARN_ONCE(1, "pblk: custom-sized chunks unsupported\n");
>>> +			continue;
>>> +		}
>>> +
>>> +		set_bit(pblk_ppa_to_pos(geo, rlun->chunk_bppa),
>>> +							line->blk_bitmap);
>>> +		nr_bad_chks++;
>>> +	}
>>> +
>>> +	return nr_bad_chks;
>>> +}
>>> +
>>> +static long pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>>> +				 void *chunk_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->c.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;
>>>   @@ -710,7 +819,13 @@ static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>>>   		return -ENOMEM;
>>>   	}
>>>   -	*nr_bad_blks = pblk_bb_line(pblk, line, chunk_log, lm->blk_per_line);
>>> +	line->chks = kmalloc(lm->blk_per_line * sizeof(struct pblk_chunk),
>>> +								GFP_KERNEL);
>>> +	if (!line->chks) {
>>> +		kfree(line->erase_bitmap);
>>> +		kfree(line->blk_bitmap);
>>> +		return -ENOMEM;
>>> +	}
>>>     	return 0;
>>>   }
>>> @@ -722,9 +837,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;
>>> +	void *chunk_meta;
>>>   	unsigned int smeta_len, emeta_len;
>>> -	long nr_bad_blks = 0, nr_free_blks = 0;
>>> +	long nr_free_chks = 0;
>>>   	int bb_distance, max_write_ppas;
>>>   	int i, ret;
>>>   @@ -743,6 +858,7 @@ static int pblk_lines_init(struct pblk *pblk)
>>>   	l_mg->log_line = l_mg->data_line = NULL;
>>>   	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
>>>   	l_mg->nr_free_lines = 0;
>>> +	atomic_set(&l_mg->sysfs_line_state, -1);
>>>   	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
>>>     	lm->sec_per_line = geo->c.clba * geo->all_luns;
>>> @@ -841,53 +957,31 @@ static int pblk_lines_init(struct pblk *pblk)
>>>   		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);
>>> +	chunk_meta = pblk_chunk_get_meta(pblk);
>>> +	if (IS_ERR(chunk_meta)) {
>>> +		pr_err("pblk: could not get chunk log (%lu)\n",
>>> +							PTR_ERR(chunk_meta));
>>> +		ret = PTR_ERR(chunk_meta);
>>>   		goto fail_free_lines;
>>>   	}
>>>     	for (i = 0; i < l_mg->nr_lines; i++) {
>>> -		int chk_in_line;
>>> -
>>>   		line = &pblk->lines[i];
>>>   -		line->pblk = pblk;
>>> -		line->id = i;
>>> -		line->type = PBLK_LINETYPE_FREE;
>>> -		line->state = PBLK_LINESTATE_FREE;
>>> -		line->gc_group = PBLK_LINEGC_NONE;
>>> -		line->vsc = &l_mg->vsc_list[i];
>>> -		spin_lock_init(&line->lock);
>>> -
>>> -		ret = pblk_setup_line_meta(pblk, line, chunk_log, &nr_bad_blks);
>>> +		ret = pblk_alloc_line_meta(pblk, line);
>>>   		if (ret)
>>> -			goto fail_free_chunk_log;
>>> +			goto fail_free_chunk_meta;
>>>   -		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_chunk_log:
>>> -	kfree(chunk_log);
>>> +fail_free_chunk_meta:
>>> +	kfree(chunk_meta);
>>>   	while (--i >= 0)
>>>   		pblk_line_meta_free(&pblk->lines[i]);
>>>   fail_free_lines:
>>> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
>>> index ccfb3abd2773..1ce5b956c622 100644
>>> --- a/drivers/lightnvm/pblk-sysfs.c
>>> +++ b/drivers/lightnvm/pblk-sysfs.c
>>> @@ -142,6 +142,40 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
>>>   	return sz;
>>>   }
>>>   +static ssize_t pblk_sysfs_line_state_show(struct pblk *pblk, char *page)
>>> +{
>>> +	struct pblk_line_meta *lm = &pblk->lm;
>>> +	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
>>> +	struct pblk_line *line;
>>> +	int line_id = atomic_read(&l_mg->sysfs_line_state);
>>> +	ssize_t sz = 0;
>>> +	int i;
>>> +
>>> +	if (line_id < 0 || line_id >= l_mg->nr_lines)
>>> +		return 0;
>>> +
>>> +	sz = snprintf(page, PAGE_SIZE,
>>> +		"line\tchunk\tstate\ttype\twear-index\tslba\t\tcnlb\twp\n");
>>> +
>>> +	line = &pblk->lines[line_id];
>>> +
>>> +	for (i = 0; i < lm->blk_per_line; i++) {
>>> +		struct pblk_chunk *chunk = &line->chks[i];
>>> +
>>> +		sz += snprintf(page + sz, PAGE_SIZE - sz,
>>> +				"%d\t%d\t%d\t%d\t%d\t\t%llu\t\t%llu\t%llu\n",
>>> +				line->id, i,
>>> +				chunk->state,
>>> +				chunk->type,
>>> +				chunk->wi,
>>> +				chunk->slba,
>>> +				chunk->cnlb,
>>> +				chunk->wp);
>>> +	}
>>> +
>>> +	return sz;
>>> +}
>>> +
>>>   static ssize_t pblk_sysfs_lines(struct pblk *pblk, char *page)
>>>   {
>>>   	struct nvm_tgt_dev *dev = pblk->dev;
>>> @@ -398,6 +432,29 @@ static ssize_t pblk_sysfs_stats_debug(struct pblk *pblk, char *page)
>>>   }
>>>   #endif
>>>   +
>>> +static ssize_t pblk_sysfs_line_state_store(struct pblk *pblk, const char *page,
>>> +					   size_t len)
>>> +{
>>> +	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
>>> +	size_t c_len;
>>> +	int line_id;
>>> +
>>> +	c_len = strcspn(page, "\n");
>>> +	if (c_len >= len)
>>> +		return -EINVAL;
>>> +
>>> +	if (kstrtouint(page, 0, &line_id))
>>> +		return -EINVAL;
>>> +
>>> +	if (line_id < 0 || line_id >= l_mg->nr_lines)
>>> +		return -EINVAL;
>>> +
>>> +	atomic_set(&l_mg->sysfs_line_state, line_id);
>>> +
>>> +	return len;
>>> +}
>>> +
>>>   static ssize_t pblk_sysfs_gc_force(struct pblk *pblk, const char *page,
>>>   				   size_t len)
>>>   {
>>> @@ -529,6 +586,11 @@ static struct attribute sys_lines_info_attr = {
>>>   	.mode = 0444,
>>>   };
>>>   +static struct attribute sys_line_state_attr = {
>>> +	.name = "line_state",
>>> +	.mode = 0644,
>>> +};
>>> +
>>>   static struct attribute sys_gc_force = {
>>>   	.name = "gc_force",
>>>   	.mode = 0200,
>>> @@ -572,6 +634,7 @@ static struct attribute *pblk_attrs[] = {
>>>   	&sys_stats_ppaf_attr,
>>>   	&sys_lines_attr,
>>>   	&sys_lines_info_attr,
>>> +	&sys_line_state_attr,
>>>   	&sys_write_amp_mileage,
>>>   	&sys_write_amp_trip,
>>>   	&sys_padding_dist,
>>> @@ -602,6 +665,8 @@ static ssize_t pblk_sysfs_show(struct kobject *kobj, struct attribute *attr,
>>>   		return pblk_sysfs_lines(pblk, buf);
>>>   	else if (strcmp(attr->name, "lines_info") == 0)
>>>   		return pblk_sysfs_lines_info(pblk, buf);
>>> +	else if (strcmp(attr->name, "line_state") == 0)
>>> +		return pblk_sysfs_line_state_show(pblk, buf);
>>>   	else if (strcmp(attr->name, "max_sec_per_write") == 0)
>>>   		return pblk_sysfs_get_sec_per_write(pblk, buf);
>>>   	else if (strcmp(attr->name, "write_amp_mileage") == 0)
>>> @@ -628,6 +693,8 @@ static ssize_t pblk_sysfs_store(struct kobject *kobj, struct attribute *attr,
>>>   		return pblk_sysfs_set_sec_per_write(pblk, buf, len);
>>>   	else if (strcmp(attr->name, "write_amp_trip") == 0)
>>>   		return pblk_sysfs_set_write_amp_trip(pblk, buf, len);
>>> +	else if (strcmp(attr->name, "line_state") == 0)
>>> +		return pblk_sysfs_line_state_store(pblk, buf, len);
>>>   	else if (strcmp(attr->name, "padding_dist") == 0)
>>>   		return pblk_sysfs_set_padding_dist(pblk, buf, len);
>>>   	return 0;
>>> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
>>> index 6e1fcd1a538a..bc31c67b725f 100644
>>> --- a/drivers/lightnvm/pblk.h
>>> +++ b/drivers/lightnvm/pblk.h
>>> @@ -201,6 +201,8 @@ struct pblk_rb {
>>>     struct pblk_lun {
>>>   	struct ppa_addr bppa;
>>> +	struct ppa_addr chunk_bppa;
>>> +
>>>   	struct semaphore wr_sem;
>>>   };
>>>   @@ -297,6 +299,7 @@ enum {
>>>   	PBLK_LINETYPE_DATA = 2,
>>>     	/* Line state */
>>> +	PBLK_LINESTATE_NEW = 9,
>>>   	PBLK_LINESTATE_FREE = 10,
>>>   	PBLK_LINESTATE_OPEN = 11,
>>>   	PBLK_LINESTATE_CLOSED = 12,
>>> @@ -412,6 +415,15 @@ struct pblk_smeta {
>>>   	struct line_smeta *buf;		/* smeta buffer in persistent format */
>>>   };
>>>   +struct pblk_chunk {
>>> +	int state;
>>> +	int type;
>>> +	int wi;
>>> +	u64 slba;
>>> +	u64 cnlb;
>>> +	u64 wp;
>>> +};
>>> +
>>
>> How come the code replicate the nvm_chk_meta data structure?
> 
> There is no need to maintain the chunk reserved bits in nvm_chk_meta and
> waste memory in the process, as these are alive for the whole life of
> the pblk instance. This structure only maintains the necessary bits.
>

nvm_chk_meta is 32 bytes:

struct nvm_chk_meta {
	u8                         state;                /* 0     1 */
	u8                         type;                 /* 1     1 */
	u8                         wli;                  /* 2     1 */
	u8                         rsvd[5];              /* 3     5 */
	u64                        slba;                 /* 8     8 */
	u64                        cnlb;                 /* 16     8 */
	u64                        wp;                   /* 24     8 */

	/* size: 32, cachelines: 1, members: 7 */
	/* last cacheline: 32 bytes */
};

pblk_chunk is 40 bytes:

struct pblk_chunk {
	int                        state;                /*  0     4 */
	int                        type;                 /*  4     4 */
	int                        wi;                   /*  8     4 */

	/* XXX 4 bytes hole, try to pack */

	u64                        slba;                 /*  16     8 */
	u64                        cnlb;                 /*  24     8 */
	u64                        wp;                   /*  32     8 */

	/* size: 40, cachelines: 1, members: 6 */
	/* sum members: 36, holes: 1, sum holes: 4 */
	/* last cacheline: 40 bytes */
};

If assuming 64K chunks, pblk chunk uses 2560KB (and requires an extra 
traversal when the chunk meta information is returned to copy over the 
data to the new data structure), while nvm_chk_meta uses 2048KB. 
Granted, the nvm_chk_meta state/type/wli fields will be slightly slower 
to access due to the bit shifting, but I think it is worth it. One can 
measure and see if there is any performance difference.

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

* Re: [PATCH 17/19] lightnvm: pblk: implement get log report chunk
  2018-02-27 18:46         ` Matias Bjørling
@ 2018-02-27 19:50           ` Javier González
  -1 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-27 19:50 UTC (permalink / raw)
  To: Matias Bjørling; +Cc: linux-block, linux-kernel, linux-nvme

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


> On 27 Feb 2018, at 19.46, Matias Bjørling <mb@lightnvm.io> wrote:
> 
> On 02/27/2018 03:40 PM, Javier González wrote:
>>> On 26 Feb 2018, at 20.04, Matias Bjørling <mb@lightnvm.io> wrote:
> <snip>
>>> Can you help me understand why you want to use The
>>> NVM_CHK_ST_HOST_USE? Why would I care if the chunk state is HOST_USE?
>>> A target instance should not be able to see states from other chunks
>>> it doesn't own. and in that case, why have a separate state?
>> The motivation for this state is that pblk does not maintain a per
>> block/chunk state. On the first disk pass however, the state of the
>> chunks is unknown,
> 
> I don't understand this. Why is the state unknown? If assuming 1.2
> drive, one can do a scan of first page of each block. If the block
> returns success (it is in use), if 0x42ff, the block is empty, and if
> reading and it returns 0x4281, it is open.
> 
> thus we need to check for each one individually;

Yes, we could do this on init - this is actually how we do recovery
after all..

>> after that, we know that good chunks need to be erased. Having this
>> extra chunk state, frees us from maintaining this unnecessary intra-line
>> state. Also, at the point I wrote this code, we did not have the report
>> chunk on the erase path, so updating the chunk metadata would be
>> something periodic.
>> I have taken a look at this again and I solved it in a different way -
>> basically, only maintaining free/closed states, which is not much more
>> expensive. It is included in the next version.
>>>> +		}
>>>> +
>>>> +		WARN_ONCE(state & NVM_CHK_ST_OPEN,
>>>> +				"pblk: open chunk in new line: %d\n",
>>>> +				line->id);
>>>> +	}
>>>> +
>>>> +	return blk_to_erase;
>>>> +}
>>>> +
>>>>  static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>>>>  {
>>>>  	struct pblk_line_meta *lm = &pblk->lm;
>>>> -	int blk_in_line = atomic_read(&line->blk_in_line);
>>>> +	int blk_to_erase;
>>>>    	line->map_bitmap = kzalloc(lm->sec_bitmap_len, GFP_ATOMIC);
>>>>  	if (!line->map_bitmap)
>>>> @@ -1110,7 +1184,21 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>>>>  		return -ENOMEM;
>>>>  	}
>>>>  +	/* Bad blocks do not need to be erased */
>>>> +	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
>>>> +
>>>>  	spin_lock(&line->lock);
>>>> +
>>>> +	/* If we have not written to this line, we need to mark up free chunks
>>>> +	 * as already erased
>>>> +	 */
>>>> +	if (line->state == PBLK_LINESTATE_NEW) {
>>>> +		blk_to_erase = pblk_prepare_new_line(pblk, line);
>>>> +		line->state = PBLK_LINESTATE_FREE;
>>>> +	} else {
>>>> +		blk_to_erase = atomic_read(&line->blk_in_line);
>>>> +	}
>>>> +
>>>>  	if (line->state != PBLK_LINESTATE_FREE) {
>>>>  		kfree(line->map_bitmap);
>>>>  		kfree(line->invalid_bitmap);
>>>> @@ -1122,15 +1210,12 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>>>>    	line->state = PBLK_LINESTATE_OPEN;
>>>>  -	atomic_set(&line->left_eblks, blk_in_line);
>>>> -	atomic_set(&line->left_seblks, blk_in_line);
>>>> +	atomic_set(&line->left_eblks, blk_to_erase);
>>>> +	atomic_set(&line->left_seblks, blk_to_erase);
>>>>    	line->meta_distance = lm->meta_distance;
>>>>  	spin_unlock(&line->lock);
>>>>  -	/* Bad blocks do not need to be erased */
>>>> -	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
>>>> -
>>>>  	kref_init(&line->ref);
>>>>    	return 0;
>>>> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
>>>> index ec39800eea42..cf4f49d48aed 100644
>>>> --- a/drivers/lightnvm/pblk-init.c
>>>> +++ b/drivers/lightnvm/pblk-init.c
>>>> @@ -401,6 +401,7 @@ static void pblk_line_meta_free(struct pblk_line *line)
>>>>  {
>>>>  	kfree(line->blk_bitmap);
>>>>  	kfree(line->erase_bitmap);
>>>> +	kfree(line->chks);
>>>>  }
>>>>    static void pblk_lines_free(struct pblk *pblk)
>>>> @@ -440,54 +441,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->c.num_chk * geo->c.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;
>>>>  -	for (i = 0; i < blk_per_line; i++) {
>>>> -		struct pblk_lun *rlun = &pblk->luns[i];
>>>> -		u8 *lun_bb_log = bb_log + i * blk_per_line;
>>>> -
>>>> -		if (lun_bb_log[line->id] == NVM_BLK_T_FREE)
>>>> -			continue;
>>>> -
>>>> -		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
>>>> -		bb_cnt++;
>>>> -	}
>>>> -
>>>> -	return bb_cnt;
>>>> +	if (geo->c.version == NVM_OCSSD_SPEC_12)
>>>> +		return pblk_bb_get_meta(pblk);
>>>> +	else
>>>> +		return pblk_chunk_get_info(pblk);
>>> 
>>> This 1.2 or 2.0 would be nice to have inside the lightnvm core. A
>>> target should not care weather it is a 1.2 or 2.0 device.
>> It is not an easy thing to do since the bad block format and chunk
>> report return completely different formats. As I explained in a
>> different thread, doing this in core would force 1.2 to understand fake
>> chunk formats, which are not meaningful. It is better to leave the logic
>> at the target level, where we know what to do with the format.
> 
> What if the core layer exported a generic "chunk meta" interface, and
> then filled it as is done in pblk. In the core, it will then fill out
> what it can fill out, and leave the rest of the fields untouched. The
> pblk code can then if () in certain places if for example wp attribute
> can,'t be used?
> 

It is basically what we do in pblk now.

It is easy to abstract in core; I'm just concerned that hiding the chunk
metadata will end up making the pblk code more complex - in the end
doing a check on the version is meaningful for the reader.


> In the interest of time, and to get this moving, we can ignore it for now.

Ok. Let's do it this way now and we can see how to abstract it when we
start implementing features based on these fields. The first one will be
wear levelling, which I expect to have for next window.

>>>>  }
>>>>    static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
>>>> @@ -516,6 +507,7 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
>>>>    		rlun = &pblk->luns[i];
>>>>  		rlun->bppa = luns[lunid];
>>>> +		rlun->chunk_bppa = luns[i];
>>>>    		sema_init(&rlun->wr_sem, 1);
>>>>  	}
>>>> @@ -695,8 +687,125 @@ static int pblk_lines_alloc_metadata(struct pblk *pblk)
>>>>  	return -ENOMEM;
>>>>  }
>>>>  -static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>>>> -				void *chunk_log, long *nr_bad_blks)
>>>> +static int pblk_setup_line_meta_12(struct pblk *pblk, struct pblk_line *line,
>>>> +				   void *chunk_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->c.num_chk * geo->c.pln_mode;
>>>> +
>>>> +	for (i = 0; i < lm->blk_per_line; i++) {
>>>> +		struct pblk_chunk *chunk = &line->chks[i];
>>>> +		struct pblk_lun *rlun = &pblk->luns[i];
>>>> +		u8 *lun_bb_meta = chunk_meta + i * chk_per_lun;
>>>> +
>>>> +		/*
>>>> +		 * In 1.2 spec. chunk state is not persisted by the device. Thus
>>>> +		 * some of the values are reset each time pblk is instantiated.
>>>> +		 */
>>>> +		if (lun_bb_meta[line->id] == NVM_BLK_T_FREE)
>>>> +			chunk->state =  NVM_CHK_ST_HOST_USE;
>>>> +		else
>>>> +			chunk->state = NVM_CHK_ST_OFFLINE;
>>>> +
>>>> +		chunk->type = NVM_CHK_TP_W_SEQ;
>>>> +		chunk->wi = 0;
>>>> +		chunk->slba = -1;
>>>> +		chunk->cnlb = geo->c.clba;
>>>> +		chunk->wp = 0;
>>>> +
>>>> +		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
>>>> +			continue;
>>>> +
>>>> +		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
>>>> +		nr_bad_chks++;
>>>> +	}
>>>> +
>>>> +	return nr_bad_chks;
>>>> +}
>>>> +
>>>> +static int pblk_setup_line_meta_20(struct pblk *pblk, struct pblk_line *line,
>>>> +				   struct nvm_chk_meta *meta)
>>>> +{
>>>> +	struct nvm_tgt_dev *dev = pblk->dev;
>>>> +	struct nvm_geo *geo = &dev->geo;
>>>> +	struct pblk_line_meta *lm = &pblk->lm;
>>>> +	int i, nr_bad_chks = 0;
>>>> +
>>>> +	for (i = 0; i < lm->blk_per_line; i++) {
>>>> +		struct pblk_chunk *chunk = &line->chks[i];
>>>> +		struct pblk_lun *rlun = &pblk->luns[i];
>>>> +		struct nvm_chk_meta *chunk_meta;
>>>> +		struct ppa_addr ppa;
>>>> +
>>>> +		ppa = rlun->chunk_bppa;
>>>> +		ppa.m.chk = line->id;
>>>> +		chunk_meta = pblk_chunk_get_off(pblk, meta, ppa);
>>>> +
>>>> +		chunk->state = chunk_meta->state;
>>>> +		chunk->type = chunk_meta->type;
>>>> +		chunk->wi = chunk_meta->wi;
>>>> +		chunk->slba = chunk_meta->slba;
>>>> +		chunk->cnlb = chunk_meta->cnlb;
>>>> +		chunk->wp = chunk_meta->wp;
>>>> +
>>>> +		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
>>>> +			continue;
>>>> +
>>>> +		if (chunk->type & NVM_CHK_TP_SZ_SPEC) {
>>>> +			WARN_ONCE(1, "pblk: custom-sized chunks unsupported\n");
>>>> +			continue;
>>>> +		}
>>>> +
>>>> +		set_bit(pblk_ppa_to_pos(geo, rlun->chunk_bppa),
>>>> +							line->blk_bitmap);
>>>> +		nr_bad_chks++;
>>>> +	}
>>>> +
>>>> +	return nr_bad_chks;
>>>> +}
>>>> +
>>>> +static long pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>>>> +				 void *chunk_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->c.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;
>>>>  @@ -710,7 +819,13 @@ static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>>>>  		return -ENOMEM;
>>>>  	}
>>>>  -	*nr_bad_blks = pblk_bb_line(pblk, line, chunk_log, lm->blk_per_line);
>>>> +	line->chks = kmalloc(lm->blk_per_line * sizeof(struct pblk_chunk),
>>>> +								GFP_KERNEL);
>>>> +	if (!line->chks) {
>>>> +		kfree(line->erase_bitmap);
>>>> +		kfree(line->blk_bitmap);
>>>> +		return -ENOMEM;
>>>> +	}
>>>>    	return 0;
>>>>  }
>>>> @@ -722,9 +837,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;
>>>> +	void *chunk_meta;
>>>>  	unsigned int smeta_len, emeta_len;
>>>> -	long nr_bad_blks = 0, nr_free_blks = 0;
>>>> +	long nr_free_chks = 0;
>>>>  	int bb_distance, max_write_ppas;
>>>>  	int i, ret;
>>>>  @@ -743,6 +858,7 @@ static int pblk_lines_init(struct pblk *pblk)
>>>>  	l_mg->log_line = l_mg->data_line = NULL;
>>>>  	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
>>>>  	l_mg->nr_free_lines = 0;
>>>> +	atomic_set(&l_mg->sysfs_line_state, -1);
>>>>  	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
>>>>    	lm->sec_per_line = geo->c.clba * geo->all_luns;
>>>> @@ -841,53 +957,31 @@ static int pblk_lines_init(struct pblk *pblk)
>>>>  		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);
>>>> +	chunk_meta = pblk_chunk_get_meta(pblk);
>>>> +	if (IS_ERR(chunk_meta)) {
>>>> +		pr_err("pblk: could not get chunk log (%lu)\n",
>>>> +							PTR_ERR(chunk_meta));
>>>> +		ret = PTR_ERR(chunk_meta);
>>>>  		goto fail_free_lines;
>>>>  	}
>>>>    	for (i = 0; i < l_mg->nr_lines; i++) {
>>>> -		int chk_in_line;
>>>> -
>>>>  		line = &pblk->lines[i];
>>>>  -		line->pblk = pblk;
>>>> -		line->id = i;
>>>> -		line->type = PBLK_LINETYPE_FREE;
>>>> -		line->state = PBLK_LINESTATE_FREE;
>>>> -		line->gc_group = PBLK_LINEGC_NONE;
>>>> -		line->vsc = &l_mg->vsc_list[i];
>>>> -		spin_lock_init(&line->lock);
>>>> -
>>>> -		ret = pblk_setup_line_meta(pblk, line, chunk_log, &nr_bad_blks);
>>>> +		ret = pblk_alloc_line_meta(pblk, line);
>>>>  		if (ret)
>>>> -			goto fail_free_chunk_log;
>>>> +			goto fail_free_chunk_meta;
>>>>  -		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_chunk_log:
>>>> -	kfree(chunk_log);
>>>> +fail_free_chunk_meta:
>>>> +	kfree(chunk_meta);
>>>>  	while (--i >= 0)
>>>>  		pblk_line_meta_free(&pblk->lines[i]);
>>>>  fail_free_lines:
>>>> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
>>>> index ccfb3abd2773..1ce5b956c622 100644
>>>> --- a/drivers/lightnvm/pblk-sysfs.c
>>>> +++ b/drivers/lightnvm/pblk-sysfs.c
>>>> @@ -142,6 +142,40 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
>>>>  	return sz;
>>>>  }
>>>>  +static ssize_t pblk_sysfs_line_state_show(struct pblk *pblk, char *page)
>>>> +{
>>>> +	struct pblk_line_meta *lm = &pblk->lm;
>>>> +	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
>>>> +	struct pblk_line *line;
>>>> +	int line_id = atomic_read(&l_mg->sysfs_line_state);
>>>> +	ssize_t sz = 0;
>>>> +	int i;
>>>> +
>>>> +	if (line_id < 0 || line_id >= l_mg->nr_lines)
>>>> +		return 0;
>>>> +
>>>> +	sz = snprintf(page, PAGE_SIZE,
>>>> +		"line\tchunk\tstate\ttype\twear-index\tslba\t\tcnlb\twp\n");
>>>> +
>>>> +	line = &pblk->lines[line_id];
>>>> +
>>>> +	for (i = 0; i < lm->blk_per_line; i++) {
>>>> +		struct pblk_chunk *chunk = &line->chks[i];
>>>> +
>>>> +		sz += snprintf(page + sz, PAGE_SIZE - sz,
>>>> +				"%d\t%d\t%d\t%d\t%d\t\t%llu\t\t%llu\t%llu\n",
>>>> +				line->id, i,
>>>> +				chunk->state,
>>>> +				chunk->type,
>>>> +				chunk->wi,
>>>> +				chunk->slba,
>>>> +				chunk->cnlb,
>>>> +				chunk->wp);
>>>> +	}
>>>> +
>>>> +	return sz;
>>>> +}
>>>> +
>>>>  static ssize_t pblk_sysfs_lines(struct pblk *pblk, char *page)
>>>>  {
>>>>  	struct nvm_tgt_dev *dev = pblk->dev;
>>>> @@ -398,6 +432,29 @@ static ssize_t pblk_sysfs_stats_debug(struct pblk *pblk, char *page)
>>>>  }
>>>>  #endif
>>>>  +
>>>> +static ssize_t pblk_sysfs_line_state_store(struct pblk *pblk, const char *page,
>>>> +					   size_t len)
>>>> +{
>>>> +	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
>>>> +	size_t c_len;
>>>> +	int line_id;
>>>> +
>>>> +	c_len = strcspn(page, "\n");
>>>> +	if (c_len >= len)
>>>> +		return -EINVAL;
>>>> +
>>>> +	if (kstrtouint(page, 0, &line_id))
>>>> +		return -EINVAL;
>>>> +
>>>> +	if (line_id < 0 || line_id >= l_mg->nr_lines)
>>>> +		return -EINVAL;
>>>> +
>>>> +	atomic_set(&l_mg->sysfs_line_state, line_id);
>>>> +
>>>> +	return len;
>>>> +}
>>>> +
>>>>  static ssize_t pblk_sysfs_gc_force(struct pblk *pblk, const char *page,
>>>>  				   size_t len)
>>>>  {
>>>> @@ -529,6 +586,11 @@ static struct attribute sys_lines_info_attr = {
>>>>  	.mode = 0444,
>>>>  };
>>>>  +static struct attribute sys_line_state_attr = {
>>>> +	.name = "line_state",
>>>> +	.mode = 0644,
>>>> +};
>>>> +
>>>>  static struct attribute sys_gc_force = {
>>>>  	.name = "gc_force",
>>>>  	.mode = 0200,
>>>> @@ -572,6 +634,7 @@ static struct attribute *pblk_attrs[] = {
>>>>  	&sys_stats_ppaf_attr,
>>>>  	&sys_lines_attr,
>>>>  	&sys_lines_info_attr,
>>>> +	&sys_line_state_attr,
>>>>  	&sys_write_amp_mileage,
>>>>  	&sys_write_amp_trip,
>>>>  	&sys_padding_dist,
>>>> @@ -602,6 +665,8 @@ static ssize_t pblk_sysfs_show(struct kobject *kobj, struct attribute *attr,
>>>>  		return pblk_sysfs_lines(pblk, buf);
>>>>  	else if (strcmp(attr->name, "lines_info") == 0)
>>>>  		return pblk_sysfs_lines_info(pblk, buf);
>>>> +	else if (strcmp(attr->name, "line_state") == 0)
>>>> +		return pblk_sysfs_line_state_show(pblk, buf);
>>>>  	else if (strcmp(attr->name, "max_sec_per_write") == 0)
>>>>  		return pblk_sysfs_get_sec_per_write(pblk, buf);
>>>>  	else if (strcmp(attr->name, "write_amp_mileage") == 0)
>>>> @@ -628,6 +693,8 @@ static ssize_t pblk_sysfs_store(struct kobject *kobj, struct attribute *attr,
>>>>  		return pblk_sysfs_set_sec_per_write(pblk, buf, len);
>>>>  	else if (strcmp(attr->name, "write_amp_trip") == 0)
>>>>  		return pblk_sysfs_set_write_amp_trip(pblk, buf, len);
>>>> +	else if (strcmp(attr->name, "line_state") == 0)
>>>> +		return pblk_sysfs_line_state_store(pblk, buf, len);
>>>>  	else if (strcmp(attr->name, "padding_dist") == 0)
>>>>  		return pblk_sysfs_set_padding_dist(pblk, buf, len);
>>>>  	return 0;
>>>> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
>>>> index 6e1fcd1a538a..bc31c67b725f 100644
>>>> --- a/drivers/lightnvm/pblk.h
>>>> +++ b/drivers/lightnvm/pblk.h
>>>> @@ -201,6 +201,8 @@ struct pblk_rb {
>>>>    struct pblk_lun {
>>>>  	struct ppa_addr bppa;
>>>> +	struct ppa_addr chunk_bppa;
>>>> +
>>>>  	struct semaphore wr_sem;
>>>>  };
>>>>  @@ -297,6 +299,7 @@ enum {
>>>>  	PBLK_LINETYPE_DATA = 2,
>>>>    	/* Line state */
>>>> +	PBLK_LINESTATE_NEW = 9,
>>>>  	PBLK_LINESTATE_FREE = 10,
>>>>  	PBLK_LINESTATE_OPEN = 11,
>>>>  	PBLK_LINESTATE_CLOSED = 12,
>>>> @@ -412,6 +415,15 @@ struct pblk_smeta {
>>>>  	struct line_smeta *buf;		/* smeta buffer in persistent format */
>>>>  };
>>>>  +struct pblk_chunk {
>>>> +	int state;
>>>> +	int type;
>>>> +	int wi;
>>>> +	u64 slba;
>>>> +	u64 cnlb;
>>>> +	u64 wp;
>>>> +};
>>>> +
>>> 
>>> How come the code replicate the nvm_chk_meta data structure?
>> There is no need to maintain the chunk reserved bits in nvm_chk_meta and
>> waste memory in the process, as these are alive for the whole life of
>> the pblk instance. This structure only maintains the necessary bits.
> 
> nvm_chk_meta is 32 bytes:
> 
> struct nvm_chk_meta {
> 	u8                         state;                /* 0     1 */
> 	u8                         type;                 /* 1     1 */
> 	u8                         wli;                  /* 2     1 */
> 	u8                         rsvd[5];              /* 3     5 */
> 	u64                        slba;                 /* 8     8 */
> 	u64                        cnlb;                 /* 16     8 */
> 	u64                        wp;                   /* 24     8 */
> 
> 	/* size: 32, cachelines: 1, members: 7 */
> 	/* last cacheline: 32 bytes */
> };
> 
> pblk_chunk is 40 bytes:
> 
> struct pblk_chunk {
> 	int                        state;                /*  0     4 */
> 	int                        type;                 /*  4     4 */
> 	int                        wi;                   /*  8     4 */
> 
> 	/* XXX 4 bytes hole, try to pack */
> 
> 	u64                        slba;                 /*  16     8 */
> 	u64                        cnlb;                 /*  24     8 */
> 	u64                        wp;                   /*  32     8 */
> 
> 	/* size: 40, cachelines: 1, members: 6 */
> 	/* sum members: 36, holes: 1, sum holes: 4 */
> 	/* last cacheline: 40 bytes */
> };
> 
> If assuming 64K chunks, pblk chunk uses 2560KB (and requires an extra
> traversal when the chunk meta information is returned to copy over the
> data to the new data structure), while nvm_chk_meta uses 2048KB.
> Granted, the nvm_chk_meta state/type/wli fields will be slightly
> slower to access due to the bit shifting, but I think it is worth it.
> One can measure and see if there is any performance difference.
> 

Ok. This is not in the fast path now. We can look into it if it gets
there at some point.

I'll fix in the next version.

Javier

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

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

* [PATCH 17/19] lightnvm: pblk: implement get log report chunk
@ 2018-02-27 19:50           ` Javier González
  0 siblings, 0 replies; 70+ messages in thread
From: Javier González @ 2018-02-27 19:50 UTC (permalink / raw)



> On 27 Feb 2018,@19.46, Matias Bj?rling <mb@lightnvm.io> wrote:
> 
> On 02/27/2018 03:40 PM, Javier Gonz?lez wrote:
>>> On 26 Feb 2018,@20.04, Matias Bj?rling <mb@lightnvm.io> wrote:
> <snip>
>>> Can you help me understand why you want to use The
>>> NVM_CHK_ST_HOST_USE? Why would I care if the chunk state is HOST_USE?
>>> A target instance should not be able to see states from other chunks
>>> it doesn't own. and in that case, why have a separate state?
>> The motivation for this state is that pblk does not maintain a per
>> block/chunk state. On the first disk pass however, the state of the
>> chunks is unknown,
> 
> I don't understand this. Why is the state unknown? If assuming 1.2
> drive, one can do a scan of first page of each block. If the block
> returns success (it is in use), if 0x42ff, the block is empty, and if
> reading and it returns 0x4281, it is open.
> 
> thus we need to check for each one individually;

Yes, we could do this on init - this is actually how we do recovery
after all..

>> after that, we know that good chunks need to be erased. Having this
>> extra chunk state, frees us from maintaining this unnecessary intra-line
>> state. Also, at the point I wrote this code, we did not have the report
>> chunk on the erase path, so updating the chunk metadata would be
>> something periodic.
>> I have taken a look at this again and I solved it in a different way -
>> basically, only maintaining free/closed states, which is not much more
>> expensive. It is included in the next version.
>>>> +		}
>>>> +
>>>> +		WARN_ONCE(state & NVM_CHK_ST_OPEN,
>>>> +				"pblk: open chunk in new line: %d\n",
>>>> +				line->id);
>>>> +	}
>>>> +
>>>> +	return blk_to_erase;
>>>> +}
>>>> +
>>>>  static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>>>>  {
>>>>  	struct pblk_line_meta *lm = &pblk->lm;
>>>> -	int blk_in_line = atomic_read(&line->blk_in_line);
>>>> +	int blk_to_erase;
>>>>    	line->map_bitmap = kzalloc(lm->sec_bitmap_len, GFP_ATOMIC);
>>>>  	if (!line->map_bitmap)
>>>> @@ -1110,7 +1184,21 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>>>>  		return -ENOMEM;
>>>>  	}
>>>>  +	/* Bad blocks do not need to be erased */
>>>> +	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
>>>> +
>>>>  	spin_lock(&line->lock);
>>>> +
>>>> +	/* If we have not written to this line, we need to mark up free chunks
>>>> +	 * as already erased
>>>> +	 */
>>>> +	if (line->state == PBLK_LINESTATE_NEW) {
>>>> +		blk_to_erase = pblk_prepare_new_line(pblk, line);
>>>> +		line->state = PBLK_LINESTATE_FREE;
>>>> +	} else {
>>>> +		blk_to_erase = atomic_read(&line->blk_in_line);
>>>> +	}
>>>> +
>>>>  	if (line->state != PBLK_LINESTATE_FREE) {
>>>>  		kfree(line->map_bitmap);
>>>>  		kfree(line->invalid_bitmap);
>>>> @@ -1122,15 +1210,12 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>>>>    	line->state = PBLK_LINESTATE_OPEN;
>>>>  -	atomic_set(&line->left_eblks, blk_in_line);
>>>> -	atomic_set(&line->left_seblks, blk_in_line);
>>>> +	atomic_set(&line->left_eblks, blk_to_erase);
>>>> +	atomic_set(&line->left_seblks, blk_to_erase);
>>>>    	line->meta_distance = lm->meta_distance;
>>>>  	spin_unlock(&line->lock);
>>>>  -	/* Bad blocks do not need to be erased */
>>>> -	bitmap_copy(line->erase_bitmap, line->blk_bitmap, lm->blk_per_line);
>>>> -
>>>>  	kref_init(&line->ref);
>>>>    	return 0;
>>>> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
>>>> index ec39800eea42..cf4f49d48aed 100644
>>>> --- a/drivers/lightnvm/pblk-init.c
>>>> +++ b/drivers/lightnvm/pblk-init.c
>>>> @@ -401,6 +401,7 @@ static void pblk_line_meta_free(struct pblk_line *line)
>>>>  {
>>>>  	kfree(line->blk_bitmap);
>>>>  	kfree(line->erase_bitmap);
>>>> +	kfree(line->chks);
>>>>  }
>>>>    static void pblk_lines_free(struct pblk *pblk)
>>>> @@ -440,54 +441,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->c.num_chk * geo->c.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;
>>>>  -	for (i = 0; i < blk_per_line; i++) {
>>>> -		struct pblk_lun *rlun = &pblk->luns[i];
>>>> -		u8 *lun_bb_log = bb_log + i * blk_per_line;
>>>> -
>>>> -		if (lun_bb_log[line->id] == NVM_BLK_T_FREE)
>>>> -			continue;
>>>> -
>>>> -		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
>>>> -		bb_cnt++;
>>>> -	}
>>>> -
>>>> -	return bb_cnt;
>>>> +	if (geo->c.version == NVM_OCSSD_SPEC_12)
>>>> +		return pblk_bb_get_meta(pblk);
>>>> +	else
>>>> +		return pblk_chunk_get_info(pblk);
>>> 
>>> This 1.2 or 2.0 would be nice to have inside the lightnvm core. A
>>> target should not care weather it is a 1.2 or 2.0 device.
>> It is not an easy thing to do since the bad block format and chunk
>> report return completely different formats. As I explained in a
>> different thread, doing this in core would force 1.2 to understand fake
>> chunk formats, which are not meaningful. It is better to leave the logic
>> at the target level, where we know what to do with the format.
> 
> What if the core layer exported a generic "chunk meta" interface, and
> then filled it as is done in pblk. In the core, it will then fill out
> what it can fill out, and leave the rest of the fields untouched. The
> pblk code can then if () in certain places if for example wp attribute
> can,'t be used?
> 

It is basically what we do in pblk now.

It is easy to abstract in core; I'm just concerned that hiding the chunk
metadata will end up making the pblk code more complex - in the end
doing a check on the version is meaningful for the reader.


> In the interest of time, and to get this moving, we can ignore it for now.

Ok. Let's do it this way now and we can see how to abstract it when we
start implementing features based on these fields. The first one will be
wear levelling, which I expect to have for next window.

>>>>  }
>>>>    static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
>>>> @@ -516,6 +507,7 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
>>>>    		rlun = &pblk->luns[i];
>>>>  		rlun->bppa = luns[lunid];
>>>> +		rlun->chunk_bppa = luns[i];
>>>>    		sema_init(&rlun->wr_sem, 1);
>>>>  	}
>>>> @@ -695,8 +687,125 @@ static int pblk_lines_alloc_metadata(struct pblk *pblk)
>>>>  	return -ENOMEM;
>>>>  }
>>>>  -static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>>>> -				void *chunk_log, long *nr_bad_blks)
>>>> +static int pblk_setup_line_meta_12(struct pblk *pblk, struct pblk_line *line,
>>>> +				   void *chunk_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->c.num_chk * geo->c.pln_mode;
>>>> +
>>>> +	for (i = 0; i < lm->blk_per_line; i++) {
>>>> +		struct pblk_chunk *chunk = &line->chks[i];
>>>> +		struct pblk_lun *rlun = &pblk->luns[i];
>>>> +		u8 *lun_bb_meta = chunk_meta + i * chk_per_lun;
>>>> +
>>>> +		/*
>>>> +		 * In 1.2 spec. chunk state is not persisted by the device. Thus
>>>> +		 * some of the values are reset each time pblk is instantiated.
>>>> +		 */
>>>> +		if (lun_bb_meta[line->id] == NVM_BLK_T_FREE)
>>>> +			chunk->state =  NVM_CHK_ST_HOST_USE;
>>>> +		else
>>>> +			chunk->state = NVM_CHK_ST_OFFLINE;
>>>> +
>>>> +		chunk->type = NVM_CHK_TP_W_SEQ;
>>>> +		chunk->wi = 0;
>>>> +		chunk->slba = -1;
>>>> +		chunk->cnlb = geo->c.clba;
>>>> +		chunk->wp = 0;
>>>> +
>>>> +		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
>>>> +			continue;
>>>> +
>>>> +		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
>>>> +		nr_bad_chks++;
>>>> +	}
>>>> +
>>>> +	return nr_bad_chks;
>>>> +}
>>>> +
>>>> +static int pblk_setup_line_meta_20(struct pblk *pblk, struct pblk_line *line,
>>>> +				   struct nvm_chk_meta *meta)
>>>> +{
>>>> +	struct nvm_tgt_dev *dev = pblk->dev;
>>>> +	struct nvm_geo *geo = &dev->geo;
>>>> +	struct pblk_line_meta *lm = &pblk->lm;
>>>> +	int i, nr_bad_chks = 0;
>>>> +
>>>> +	for (i = 0; i < lm->blk_per_line; i++) {
>>>> +		struct pblk_chunk *chunk = &line->chks[i];
>>>> +		struct pblk_lun *rlun = &pblk->luns[i];
>>>> +		struct nvm_chk_meta *chunk_meta;
>>>> +		struct ppa_addr ppa;
>>>> +
>>>> +		ppa = rlun->chunk_bppa;
>>>> +		ppa.m.chk = line->id;
>>>> +		chunk_meta = pblk_chunk_get_off(pblk, meta, ppa);
>>>> +
>>>> +		chunk->state = chunk_meta->state;
>>>> +		chunk->type = chunk_meta->type;
>>>> +		chunk->wi = chunk_meta->wi;
>>>> +		chunk->slba = chunk_meta->slba;
>>>> +		chunk->cnlb = chunk_meta->cnlb;
>>>> +		chunk->wp = chunk_meta->wp;
>>>> +
>>>> +		if (!(chunk->state & NVM_CHK_ST_OFFLINE))
>>>> +			continue;
>>>> +
>>>> +		if (chunk->type & NVM_CHK_TP_SZ_SPEC) {
>>>> +			WARN_ONCE(1, "pblk: custom-sized chunks unsupported\n");
>>>> +			continue;
>>>> +		}
>>>> +
>>>> +		set_bit(pblk_ppa_to_pos(geo, rlun->chunk_bppa),
>>>> +							line->blk_bitmap);
>>>> +		nr_bad_chks++;
>>>> +	}
>>>> +
>>>> +	return nr_bad_chks;
>>>> +}
>>>> +
>>>> +static long pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>>>> +				 void *chunk_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->c.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;
>>>>  @@ -710,7 +819,13 @@ static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
>>>>  		return -ENOMEM;
>>>>  	}
>>>>  -	*nr_bad_blks = pblk_bb_line(pblk, line, chunk_log, lm->blk_per_line);
>>>> +	line->chks = kmalloc(lm->blk_per_line * sizeof(struct pblk_chunk),
>>>> +								GFP_KERNEL);
>>>> +	if (!line->chks) {
>>>> +		kfree(line->erase_bitmap);
>>>> +		kfree(line->blk_bitmap);
>>>> +		return -ENOMEM;
>>>> +	}
>>>>    	return 0;
>>>>  }
>>>> @@ -722,9 +837,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;
>>>> +	void *chunk_meta;
>>>>  	unsigned int smeta_len, emeta_len;
>>>> -	long nr_bad_blks = 0, nr_free_blks = 0;
>>>> +	long nr_free_chks = 0;
>>>>  	int bb_distance, max_write_ppas;
>>>>  	int i, ret;
>>>>  @@ -743,6 +858,7 @@ static int pblk_lines_init(struct pblk *pblk)
>>>>  	l_mg->log_line = l_mg->data_line = NULL;
>>>>  	l_mg->l_seq_nr = l_mg->d_seq_nr = 0;
>>>>  	l_mg->nr_free_lines = 0;
>>>> +	atomic_set(&l_mg->sysfs_line_state, -1);
>>>>  	bitmap_zero(&l_mg->meta_bitmap, PBLK_DATA_LINES);
>>>>    	lm->sec_per_line = geo->c.clba * geo->all_luns;
>>>> @@ -841,53 +957,31 @@ static int pblk_lines_init(struct pblk *pblk)
>>>>  		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);
>>>> +	chunk_meta = pblk_chunk_get_meta(pblk);
>>>> +	if (IS_ERR(chunk_meta)) {
>>>> +		pr_err("pblk: could not get chunk log (%lu)\n",
>>>> +							PTR_ERR(chunk_meta));
>>>> +		ret = PTR_ERR(chunk_meta);
>>>>  		goto fail_free_lines;
>>>>  	}
>>>>    	for (i = 0; i < l_mg->nr_lines; i++) {
>>>> -		int chk_in_line;
>>>> -
>>>>  		line = &pblk->lines[i];
>>>>  -		line->pblk = pblk;
>>>> -		line->id = i;
>>>> -		line->type = PBLK_LINETYPE_FREE;
>>>> -		line->state = PBLK_LINESTATE_FREE;
>>>> -		line->gc_group = PBLK_LINEGC_NONE;
>>>> -		line->vsc = &l_mg->vsc_list[i];
>>>> -		spin_lock_init(&line->lock);
>>>> -
>>>> -		ret = pblk_setup_line_meta(pblk, line, chunk_log, &nr_bad_blks);
>>>> +		ret = pblk_alloc_line_meta(pblk, line);
>>>>  		if (ret)
>>>> -			goto fail_free_chunk_log;
>>>> +			goto fail_free_chunk_meta;
>>>>  -		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_chunk_log:
>>>> -	kfree(chunk_log);
>>>> +fail_free_chunk_meta:
>>>> +	kfree(chunk_meta);
>>>>  	while (--i >= 0)
>>>>  		pblk_line_meta_free(&pblk->lines[i]);
>>>>  fail_free_lines:
>>>> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
>>>> index ccfb3abd2773..1ce5b956c622 100644
>>>> --- a/drivers/lightnvm/pblk-sysfs.c
>>>> +++ b/drivers/lightnvm/pblk-sysfs.c
>>>> @@ -142,6 +142,40 @@ static ssize_t pblk_sysfs_ppaf(struct pblk *pblk, char *page)
>>>>  	return sz;
>>>>  }
>>>>  +static ssize_t pblk_sysfs_line_state_show(struct pblk *pblk, char *page)
>>>> +{
>>>> +	struct pblk_line_meta *lm = &pblk->lm;
>>>> +	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
>>>> +	struct pblk_line *line;
>>>> +	int line_id = atomic_read(&l_mg->sysfs_line_state);
>>>> +	ssize_t sz = 0;
>>>> +	int i;
>>>> +
>>>> +	if (line_id < 0 || line_id >= l_mg->nr_lines)
>>>> +		return 0;
>>>> +
>>>> +	sz = snprintf(page, PAGE_SIZE,
>>>> +		"line\tchunk\tstate\ttype\twear-index\tslba\t\tcnlb\twp\n");
>>>> +
>>>> +	line = &pblk->lines[line_id];
>>>> +
>>>> +	for (i = 0; i < lm->blk_per_line; i++) {
>>>> +		struct pblk_chunk *chunk = &line->chks[i];
>>>> +
>>>> +		sz += snprintf(page + sz, PAGE_SIZE - sz,
>>>> +				"%d\t%d\t%d\t%d\t%d\t\t%llu\t\t%llu\t%llu\n",
>>>> +				line->id, i,
>>>> +				chunk->state,
>>>> +				chunk->type,
>>>> +				chunk->wi,
>>>> +				chunk->slba,
>>>> +				chunk->cnlb,
>>>> +				chunk->wp);
>>>> +	}
>>>> +
>>>> +	return sz;
>>>> +}
>>>> +
>>>>  static ssize_t pblk_sysfs_lines(struct pblk *pblk, char *page)
>>>>  {
>>>>  	struct nvm_tgt_dev *dev = pblk->dev;
>>>> @@ -398,6 +432,29 @@ static ssize_t pblk_sysfs_stats_debug(struct pblk *pblk, char *page)
>>>>  }
>>>>  #endif
>>>>  +
>>>> +static ssize_t pblk_sysfs_line_state_store(struct pblk *pblk, const char *page,
>>>> +					   size_t len)
>>>> +{
>>>> +	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
>>>> +	size_t c_len;
>>>> +	int line_id;
>>>> +
>>>> +	c_len = strcspn(page, "\n");
>>>> +	if (c_len >= len)
>>>> +		return -EINVAL;
>>>> +
>>>> +	if (kstrtouint(page, 0, &line_id))
>>>> +		return -EINVAL;
>>>> +
>>>> +	if (line_id < 0 || line_id >= l_mg->nr_lines)
>>>> +		return -EINVAL;
>>>> +
>>>> +	atomic_set(&l_mg->sysfs_line_state, line_id);
>>>> +
>>>> +	return len;
>>>> +}
>>>> +
>>>>  static ssize_t pblk_sysfs_gc_force(struct pblk *pblk, const char *page,
>>>>  				   size_t len)
>>>>  {
>>>> @@ -529,6 +586,11 @@ static struct attribute sys_lines_info_attr = {
>>>>  	.mode = 0444,
>>>>  };
>>>>  +static struct attribute sys_line_state_attr = {
>>>> +	.name = "line_state",
>>>> +	.mode = 0644,
>>>> +};
>>>> +
>>>>  static struct attribute sys_gc_force = {
>>>>  	.name = "gc_force",
>>>>  	.mode = 0200,
>>>> @@ -572,6 +634,7 @@ static struct attribute *pblk_attrs[] = {
>>>>  	&sys_stats_ppaf_attr,
>>>>  	&sys_lines_attr,
>>>>  	&sys_lines_info_attr,
>>>> +	&sys_line_state_attr,
>>>>  	&sys_write_amp_mileage,
>>>>  	&sys_write_amp_trip,
>>>>  	&sys_padding_dist,
>>>> @@ -602,6 +665,8 @@ static ssize_t pblk_sysfs_show(struct kobject *kobj, struct attribute *attr,
>>>>  		return pblk_sysfs_lines(pblk, buf);
>>>>  	else if (strcmp(attr->name, "lines_info") == 0)
>>>>  		return pblk_sysfs_lines_info(pblk, buf);
>>>> +	else if (strcmp(attr->name, "line_state") == 0)
>>>> +		return pblk_sysfs_line_state_show(pblk, buf);
>>>>  	else if (strcmp(attr->name, "max_sec_per_write") == 0)
>>>>  		return pblk_sysfs_get_sec_per_write(pblk, buf);
>>>>  	else if (strcmp(attr->name, "write_amp_mileage") == 0)
>>>> @@ -628,6 +693,8 @@ static ssize_t pblk_sysfs_store(struct kobject *kobj, struct attribute *attr,
>>>>  		return pblk_sysfs_set_sec_per_write(pblk, buf, len);
>>>>  	else if (strcmp(attr->name, "write_amp_trip") == 0)
>>>>  		return pblk_sysfs_set_write_amp_trip(pblk, buf, len);
>>>> +	else if (strcmp(attr->name, "line_state") == 0)
>>>> +		return pblk_sysfs_line_state_store(pblk, buf, len);
>>>>  	else if (strcmp(attr->name, "padding_dist") == 0)
>>>>  		return pblk_sysfs_set_padding_dist(pblk, buf, len);
>>>>  	return 0;
>>>> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
>>>> index 6e1fcd1a538a..bc31c67b725f 100644
>>>> --- a/drivers/lightnvm/pblk.h
>>>> +++ b/drivers/lightnvm/pblk.h
>>>> @@ -201,6 +201,8 @@ struct pblk_rb {
>>>>    struct pblk_lun {
>>>>  	struct ppa_addr bppa;
>>>> +	struct ppa_addr chunk_bppa;
>>>> +
>>>>  	struct semaphore wr_sem;
>>>>  };
>>>>  @@ -297,6 +299,7 @@ enum {
>>>>  	PBLK_LINETYPE_DATA = 2,
>>>>    	/* Line state */
>>>> +	PBLK_LINESTATE_NEW = 9,
>>>>  	PBLK_LINESTATE_FREE = 10,
>>>>  	PBLK_LINESTATE_OPEN = 11,
>>>>  	PBLK_LINESTATE_CLOSED = 12,
>>>> @@ -412,6 +415,15 @@ struct pblk_smeta {
>>>>  	struct line_smeta *buf;		/* smeta buffer in persistent format */
>>>>  };
>>>>  +struct pblk_chunk {
>>>> +	int state;
>>>> +	int type;
>>>> +	int wi;
>>>> +	u64 slba;
>>>> +	u64 cnlb;
>>>> +	u64 wp;
>>>> +};
>>>> +
>>> 
>>> How come the code replicate the nvm_chk_meta data structure?
>> There is no need to maintain the chunk reserved bits in nvm_chk_meta and
>> waste memory in the process, as these are alive for the whole life of
>> the pblk instance. This structure only maintains the necessary bits.
> 
> nvm_chk_meta is 32 bytes:
> 
> struct nvm_chk_meta {
> 	u8                         state;                /* 0     1 */
> 	u8                         type;                 /* 1     1 */
> 	u8                         wli;                  /* 2     1 */
> 	u8                         rsvd[5];              /* 3     5 */
> 	u64                        slba;                 /* 8     8 */
> 	u64                        cnlb;                 /* 16     8 */
> 	u64                        wp;                   /* 24     8 */
> 
> 	/* size: 32, cachelines: 1, members: 7 */
> 	/* last cacheline: 32 bytes */
> };
> 
> pblk_chunk is 40 bytes:
> 
> struct pblk_chunk {
> 	int                        state;                /*  0     4 */
> 	int                        type;                 /*  4     4 */
> 	int                        wi;                   /*  8     4 */
> 
> 	/* XXX 4 bytes hole, try to pack */
> 
> 	u64                        slba;                 /*  16     8 */
> 	u64                        cnlb;                 /*  24     8 */
> 	u64                        wp;                   /*  32     8 */
> 
> 	/* size: 40, cachelines: 1, members: 6 */
> 	/* sum members: 36, holes: 1, sum holes: 4 */
> 	/* last cacheline: 40 bytes */
> };
> 
> If assuming 64K chunks, pblk chunk uses 2560KB (and requires an extra
> traversal when the chunk meta information is returned to copy over the
> data to the new data structure), while nvm_chk_meta uses 2048KB.
> Granted, the nvm_chk_meta state/type/wli fields will be slightly
> slower to access due to the bit shifting, but I think it is worth it.
> One can measure and see if there is any performance difference.
> 

Ok. This is not in the fast path now. We can look into it if it gets
there at some point.

I'll fix in the next version.

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

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

end of thread, other threads:[~2018-02-27 19:50 UTC | newest]

Thread overview: 70+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-26 13:16 [PATCH V3 00/19] lightnvm: pblk: implement 2.0 support Javier González
2018-02-26 13:16 ` Javier González
2018-02-26 13:16 ` Javier González
2018-02-26 13:17 ` [PATCH 01/19] lightnvm: simplify geometry structure Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17 ` [PATCH 02/19] lightnvm: add controller capabilities to 2.0 Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17 ` [PATCH 03/19] lightnvm: add minor version to generic geometry Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17 ` [PATCH 04/19] lightnvm: add shorten OCSSD version in geo Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17 ` [PATCH 05/19] lightnvm: complete geo structure with maxoc* Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17 ` [PATCH 06/19] lightnvm: pblk: check for supported version Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17 ` [PATCH 07/19] lightnvm: complete 2.0 values in sysfs Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17 ` [PATCH 08/19] lightnvm: rename number of channels and luns Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17 ` [PATCH 09/19] lightnvm: rename sect_* to sec_* Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17 ` [PATCH 10/19] lightnvm: add support for 2.0 address format Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17 ` [PATCH 11/19] lightnvm: pblk: rename ppaf* to addrf* Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17 ` [PATCH 12/19] lightnvn: pblk: use generic address format Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17 ` [PATCH 13/19] lightnvm: make address conversions depend on generic device Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17 ` [PATCH 14/19] nvme: make nvme_get_log_ext available Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17 ` [PATCH 15/19] lightnvm: implement get log report chunk helpers Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17 ` [PATCH 16/19] lightnvm: define chunk states Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17 ` [PATCH 17/19] lightnvm: pblk: implement get log report chunk Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 19:04   ` Matias Bjørling
2018-02-26 19:04     ` Matias Bjørling
2018-02-27 14:40     ` Javier González
2018-02-27 14:40       ` Javier González
2018-02-27 18:46       ` Matias Bjørling
2018-02-27 18:46         ` Matias Bjørling
2018-02-27 19:50         ` Javier González
2018-02-27 19:50           ` Javier González
2018-02-26 13:17 ` [PATCH 18/19] lightnvm: pblk: refactor init/exit sequences Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 13:17 ` [PATCH 19/19] lightnvm: pblk: implement 2.0 support Javier González
2018-02-26 13:17   ` Javier González
2018-02-26 18:19 ` [PATCH V3 00/19] " Matias Bjørling
2018-02-26 18:19   ` Matias Bjørling
2018-02-26 18:21   ` Javier Gonzalez
2018-02-26 18:21     ` Javier Gonzalez
2018-02-26 18:24     ` Matias Bjørling
2018-02-26 18:24       ` Matias Bjørling
2018-02-26 18:27       ` Javier Gonzalez
2018-02-26 18:27         ` Javier Gonzalez
2018-02-26 18:33         ` Matias Bjørling
2018-02-26 18:33           ` Matias Bjørling

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