[PATCH V2 3/4] lightnvm: add 2.0 geometry identification

2018-02-09 Thread Matias Bjørling
Implement the geometry data structures for 2.0 and enable a drive
to be identified as one, including exposing the appropriate 2.0
sysfs entries.

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

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index c72863b36439..9b1255b3e05e 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -931,11 +931,9 @@ static int nvm_init(struct nvm_dev *dev)
goto err;
}
 
-   pr_debug("nvm: ver:%x nvm_vendor:%x\n",
-   dev->identity.ver_id, dev->identity.vmnt);
-
-   if (dev->identity.ver_id != 1) {
-   pr_err("nvm: device not supported by kernel.");
+   if (dev->identity.ver_id != 1 && dev->identity.ver_id != 2) {
+   pr_err("nvm: device ver_id %d not supported by kernel.\n",
+   dev->identity.ver_id);
goto err;
}
 
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 6412551ecc65..8b243af8a949 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -184,6 +184,58 @@ struct nvme_nvm_bb_tbl {
__u8blk[0];
 };
 
+struct nvme_nvm_id20_addrf {
+   __u8grp_len;
+   __u8pu_len;
+   __u8chk_len;
+   __u8lba_len;
+   __u8resv[4];
+};
+
+struct nvme_nvm_id20 {
+   __u8mjr;
+   __u8mnr;
+   __u8resv[6];
+
+   struct nvme_nvm_id20_addrf lbaf;
+
+   __le32  mccap;
+   __u8resv2[12];
+
+   __u8wit;
+   __u8resv3[31];
+
+   /* Geometry */
+   __le16  num_grp;
+   __le16  num_pu;
+   __le32  num_chk;
+   __le32  clba;
+   __u8resv4[52];
+
+   /* Write data requirements */
+   __le32  ws_min;
+   __le32  ws_opt;
+   __le32  mw_cunits;
+   __le32  maxoc;
+   __le32  maxocpu;
+   __u8resv5[44];
+
+   /* Performance related metrics */
+   __le32  trdt;
+   __le32  trdm;
+   __le32  twrt;
+   __le32  twrm;
+   __le32  tcrst;
+   __le32  tcrsm;
+   __u8resv6[40];
+
+   /* Reserved area */
+   __u8resv7[2816];
+
+   /* Vendor specific */
+   __u8vs[1024];
+};
+
 /*
  * Check we didn't inadvertently grow the command struct
  */
@@ -198,6 +250,8 @@ static inline void _nvme_nvm_check_size(void)
BUILD_BUG_ON(sizeof(struct nvme_nvm_id12_addrf) != 16);
BUILD_BUG_ON(sizeof(struct nvme_nvm_id12) != NVME_IDENTIFY_DATA_SIZE);
BUILD_BUG_ON(sizeof(struct nvme_nvm_bb_tbl) != 64);
+   BUILD_BUG_ON(sizeof(struct nvme_nvm_id20_addrf) != 8);
+   BUILD_BUG_ON(sizeof(struct nvme_nvm_id20) != NVME_IDENTIFY_DATA_SIZE);
 }
 
 static int init_grp(struct nvm_id *nvm_id, struct nvme_nvm_id12 *id12)
@@ -256,6 +310,49 @@ static int init_grp(struct nvm_id *nvm_id, struct 
nvme_nvm_id12 *id12)
return 0;
 }
 
+static int nvme_nvm_setup_12(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
+   struct nvme_nvm_id12 *id)
+{
+   nvm_id->ver_id = id->ver_id;
+   nvm_id->vmnt = id->vmnt;
+   nvm_id->cap = le32_to_cpu(id->cap);
+   nvm_id->dom = le32_to_cpu(id->dom);
+   memcpy(_id->ppaf, >ppaf,
+   sizeof(struct nvm_addr_format));
+
+   return init_grp(nvm_id, id);
+}
+
+static int nvme_nvm_setup_20(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
+   struct nvme_nvm_id20 *id)
+{
+   nvm_id->ver_id = id->mjr;
+
+   nvm_id->num_ch = le16_to_cpu(id->num_grp);
+   nvm_id->num_lun = le16_to_cpu(id->num_pu);
+   nvm_id->num_chk = le32_to_cpu(id->num_chk);
+   nvm_id->clba = le32_to_cpu(id->clba);
+
+   nvm_id->ws_min = le32_to_cpu(id->ws_min);
+   nvm_id->ws_opt = le32_to_cpu(id->ws_opt);
+   nvm_id->mw_cunits = le32_to_cpu(id->mw_cunits);
+
+   nvm_id->trdt = le32_to_cpu(id->trdt);
+   nvm_id->trdm = le32_to_cpu(id->trdm);
+   nvm_id->tprt = le32_to_cpu(id->twrt);
+   nvm_id->tprm = le32_to_cpu(id->twrm);
+   nvm_id->tbet = le32_to_cpu(id->tcrst);
+   nvm_id->tbem = le32_to_cpu(id->tcrsm);
+
+   /* calculated values */
+   nvm_id->ws_per_chk = nvm_id->clba / nvm_id->ws_min;
+
+   /* 1.2 compatibility */
+ 

[PATCH V2 3/4] lightnvm: add 2.0 geometry identification

2018-02-09 Thread Matias Bjørling
Implement the geometry data structures for 2.0 and enable a drive
to be identified as one, including exposing the appropriate 2.0
sysfs entries.

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

diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index c72863b36439..9b1255b3e05e 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -931,11 +931,9 @@ static int nvm_init(struct nvm_dev *dev)
goto err;
}
 
-   pr_debug("nvm: ver:%x nvm_vendor:%x\n",
-   dev->identity.ver_id, dev->identity.vmnt);
-
-   if (dev->identity.ver_id != 1) {
-   pr_err("nvm: device not supported by kernel.");
+   if (dev->identity.ver_id != 1 && dev->identity.ver_id != 2) {
+   pr_err("nvm: device ver_id %d not supported by kernel.\n",
+   dev->identity.ver_id);
goto err;
}
 
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 6412551ecc65..8b243af8a949 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -184,6 +184,58 @@ struct nvme_nvm_bb_tbl {
__u8blk[0];
 };
 
+struct nvme_nvm_id20_addrf {
+   __u8grp_len;
+   __u8pu_len;
+   __u8chk_len;
+   __u8lba_len;
+   __u8resv[4];
+};
+
+struct nvme_nvm_id20 {
+   __u8mjr;
+   __u8mnr;
+   __u8resv[6];
+
+   struct nvme_nvm_id20_addrf lbaf;
+
+   __le32  mccap;
+   __u8resv2[12];
+
+   __u8wit;
+   __u8resv3[31];
+
+   /* Geometry */
+   __le16  num_grp;
+   __le16  num_pu;
+   __le32  num_chk;
+   __le32  clba;
+   __u8resv4[52];
+
+   /* Write data requirements */
+   __le32  ws_min;
+   __le32  ws_opt;
+   __le32  mw_cunits;
+   __le32  maxoc;
+   __le32  maxocpu;
+   __u8resv5[44];
+
+   /* Performance related metrics */
+   __le32  trdt;
+   __le32  trdm;
+   __le32  twrt;
+   __le32  twrm;
+   __le32  tcrst;
+   __le32  tcrsm;
+   __u8resv6[40];
+
+   /* Reserved area */
+   __u8resv7[2816];
+
+   /* Vendor specific */
+   __u8vs[1024];
+};
+
 /*
  * Check we didn't inadvertently grow the command struct
  */
@@ -198,6 +250,8 @@ static inline void _nvme_nvm_check_size(void)
BUILD_BUG_ON(sizeof(struct nvme_nvm_id12_addrf) != 16);
BUILD_BUG_ON(sizeof(struct nvme_nvm_id12) != NVME_IDENTIFY_DATA_SIZE);
BUILD_BUG_ON(sizeof(struct nvme_nvm_bb_tbl) != 64);
+   BUILD_BUG_ON(sizeof(struct nvme_nvm_id20_addrf) != 8);
+   BUILD_BUG_ON(sizeof(struct nvme_nvm_id20) != NVME_IDENTIFY_DATA_SIZE);
 }
 
 static int init_grp(struct nvm_id *nvm_id, struct nvme_nvm_id12 *id12)
@@ -256,6 +310,49 @@ static int init_grp(struct nvm_id *nvm_id, struct 
nvme_nvm_id12 *id12)
return 0;
 }
 
+static int nvme_nvm_setup_12(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
+   struct nvme_nvm_id12 *id)
+{
+   nvm_id->ver_id = id->ver_id;
+   nvm_id->vmnt = id->vmnt;
+   nvm_id->cap = le32_to_cpu(id->cap);
+   nvm_id->dom = le32_to_cpu(id->dom);
+   memcpy(_id->ppaf, >ppaf,
+   sizeof(struct nvm_addr_format));
+
+   return init_grp(nvm_id, id);
+}
+
+static int nvme_nvm_setup_20(struct nvm_dev *nvmdev, struct nvm_id *nvm_id,
+   struct nvme_nvm_id20 *id)
+{
+   nvm_id->ver_id = id->mjr;
+
+   nvm_id->num_ch = le16_to_cpu(id->num_grp);
+   nvm_id->num_lun = le16_to_cpu(id->num_pu);
+   nvm_id->num_chk = le32_to_cpu(id->num_chk);
+   nvm_id->clba = le32_to_cpu(id->clba);
+
+   nvm_id->ws_min = le32_to_cpu(id->ws_min);
+   nvm_id->ws_opt = le32_to_cpu(id->ws_opt);
+   nvm_id->mw_cunits = le32_to_cpu(id->mw_cunits);
+
+   nvm_id->trdt = le32_to_cpu(id->trdt);
+   nvm_id->trdm = le32_to_cpu(id->trdm);
+   nvm_id->tprt = le32_to_cpu(id->twrt);
+   nvm_id->tprm = le32_to_cpu(id->twrm);
+   nvm_id->tbet = le32_to_cpu(id->tcrst);
+   nvm_id->tbem = le32_to_cpu(id->tcrsm);
+
+   /* calculated values */
+   nvm_id->ws_per_chk = nvm_id->clba / nvm_id->ws_min;
+
+   /* 1.2 compatibility */
+   nvm_id->ws_seq