Preserve region information from region label during nvdimm_probe. This
preserved region information is used for creating cxl region to achieve
region persistency across reboot.

Signed-off-by: Neeraj Kumar <s.nee...@samsung.com>
---
 drivers/nvdimm/dimm.c     |  4 ++++
 drivers/nvdimm/label.c    | 41 +++++++++++++++++++++++++++++++++++++++
 drivers/nvdimm/nd-core.h  |  2 ++
 drivers/nvdimm/nd.h       |  1 +
 include/linux/libnvdimm.h | 14 +++++++++++++
 5 files changed, 62 insertions(+)

diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c
index 8753b5cd91cc..da4f37f0ae3b 100644
--- a/drivers/nvdimm/dimm.c
+++ b/drivers/nvdimm/dimm.c
@@ -107,6 +107,10 @@ static int nvdimm_probe(struct device *dev)
        if (rc)
                goto err;
 
+       /* Preserve cxl region info if available */
+       if (ndd->cxl)
+               nvdimm_cxl_region_preserve(ndd);
+
        return 0;
 
  err:
diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
index 3a870798a90c..6a94175e6bb6 100644
--- a/drivers/nvdimm/label.c
+++ b/drivers/nvdimm/label.c
@@ -471,6 +471,47 @@ int nd_label_reserve_dpa(struct nvdimm_drvdata *ndd)
        return 0;
 }
 
+int nvdimm_cxl_region_preserve(struct nvdimm_drvdata *ndd)
+{
+       struct nvdimm *nvdimm = to_nvdimm(ndd->dev);
+       struct cxl_pmem_region_params *params = &nvdimm->cxl_region_params;
+       struct nd_namespace_index *nsindex;
+       unsigned long *free;
+       u32 nslot, slot;
+
+       if (!preamble_current(ndd, &nsindex, &free, &nslot))
+               return 0; /* no label, nothing to preserve */
+
+       for_each_clear_bit_le(slot, free, nslot) {
+               struct nd_lsa_label *nd_label;
+               struct cxl_region_label *rg_label;
+               uuid_t rg_type, region_type;
+
+               nd_label = to_label(ndd, slot);
+               rg_label = &nd_label->rg_label;
+               uuid_parse(CXL_REGION_UUID, &region_type);
+               import_uuid(&rg_type, nd_label->rg_label.type);
+
+               /* REVISIT: Currently preserving only one region */
+               if (uuid_equal(&region_type, &rg_type)) {
+                       nvdimm->is_region_label = true;
+                       import_uuid(&params->uuid, rg_label->uuid);
+                       params->flags = __le32_to_cpu(rg_label->flags);
+                       params->nlabel = __le16_to_cpu(rg_label->nlabel);
+                       params->position = __le16_to_cpu(rg_label->position);
+                       params->dpa = __le64_to_cpu(rg_label->dpa);
+                       params->rawsize = __le64_to_cpu(rg_label->rawsize);
+                       params->hpa = __le64_to_cpu(rg_label->hpa);
+                       params->slot = __le32_to_cpu(rg_label->slot);
+                       params->ig = __le32_to_cpu(rg_label->ig);
+                       params->align = __le32_to_cpu(rg_label->align);
+                       break;
+               }
+       }
+
+       return 0;
+}
+
 int nd_label_data_init(struct nvdimm_drvdata *ndd)
 {
        size_t config_size, read_size, max_xfer, offset;
diff --git a/drivers/nvdimm/nd-core.h b/drivers/nvdimm/nd-core.h
index 86976a9e8a15..71eabf2db389 100644
--- a/drivers/nvdimm/nd-core.h
+++ b/drivers/nvdimm/nd-core.h
@@ -46,6 +46,8 @@ struct nvdimm {
        } sec;
        struct delayed_work dwork;
        const struct nvdimm_fw_ops *fw_ops;
+       bool is_region_label;
+       struct cxl_pmem_region_params cxl_region_params;
 };
 
 static inline unsigned long nvdimm_security_flags(
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index ca8256b31472..33a87924dfee 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -600,6 +600,7 @@ void nvdimm_set_locked(struct device *dev);
 void nvdimm_clear_locked(struct device *dev);
 int nvdimm_security_setup_events(struct device *dev);
 bool nvdimm_check_cxl_label_format(struct device *dev);
+int nvdimm_cxl_region_preserve(struct nvdimm_drvdata *ndd);
 #if IS_ENABLED(CONFIG_NVDIMM_KEYS)
 int nvdimm_security_unlock(struct device *dev);
 #else
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index b2e16914ab52..cdabb43a8a7f 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -106,6 +106,20 @@ struct nd_cmd_desc {
        int out_sizes[ND_CMD_MAX_ELEM];
 };
 
+struct cxl_pmem_region_params {
+       uuid_t uuid;
+       u32 flags;
+       u16 nlabel;
+       u16 position;
+       u64 dpa;
+       u64 rawsize;
+       u64 hpa;
+       u32 slot;
+       u32 ig;
+       u32 align;
+       int nr_targets;
+};
+
 struct nd_interleave_set {
        /* v1.1 definition of the interleave-set-cookie algorithm */
        u64 cookie1;
-- 
2.34.1



Reply via email to