[PATCH V3 11/20] nvdimm/region_label: Preserve cxl region information from region label

Neeraj Kumar
2025-09-17T13:30:49Z

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.neeraj@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 bda22cb94e5b..30fc90591093 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 935a0df5b47e..3250e3ecd973 100644
--- a/drivers/nvdimm/label.c
+++ b/drivers/nvdimm/label.c
@@ -473,6 +473,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 *p = &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) {
+ union nd_lsa_label *nd_label;
+ struct cxl_region_label *region_label;
+ uuid_t rg_type, region_type;
+
+ nd_label = (union nd_lsa_label *) to_label(ndd, slot);
+ region_label = &nd_label->region_label;
+ uuid_parse(CXL_REGION_UUID, &region_type);
+ import_uuid(&rg_type, nd_label->region_label.type);
+
+ /* TODO: Currently preserving only one region */
+ if (uuid_equal(&region_type, &rg_type)) {
+ nvdimm->is_region_label = true;
+ import_uuid(&p->uuid, region_label->uuid);
+ p->flags = __le32_to_cpu(region_label->flags);
+ p->nlabel = __le16_to_cpu(region_label->nlabel);
+ p->position = __le16_to_cpu(region_label->position);
+ p->dpa = __le64_to_cpu(region_label->dpa);
+ p->rawsize = __le64_to_cpu(region_label->rawsize);
+ p->hpa = __le64_to_cpu(region_label->hpa);
+ p->slot = __le32_to_cpu(region_label->slot);
+ p->ig = __le32_to_cpu(region_label->ig);
+ p->align = __le32_to_cpu(region_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 bfc6bfeb6e24..a73fac81531e 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 c985f91728dd..2d0f6dd64c52 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -593,6 +593,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_region_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 bbf14a260c93..07ea2e3f821a 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -108,6 +108,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