linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V2 00/20] Add CXL LSA 2.1 format support in nvdimm and cxl pmem
       [not found] <CGME20250730121221epcas5p3ffb9e643af6b8ae07cfccf0bdee90e37@epcas5p3.samsung.com>
@ 2025-07-30 12:11 ` Neeraj Kumar
       [not found]   ` <CGME20250730121223epcas5p1386bdf99a0af820dd4411fbdbd413cd5@epcas5p1.samsung.com>
                     ` (20 more replies)
  0 siblings, 21 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:11 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

Introduction:
=============
CXL Persistent Memory (Pmem) devices region, namespace and content must be
persistent across system reboot. In order to achieve this persistency, it
uses Label Storage Area (LSA) to store respective metadata. During system
reboot, stored metadata in LSA is used to bring back the region, namespace
and content of CXL device in its previous state.
CXL specification provides Get_LSA (4102h) and Set_LSA (4103h) mailbox
commands to access the LSA area. nvdimm driver is using same commands to
get/set LSA data.

There are three types of LSA format and these are part of following
specifications: 
 - v1.1: https://pmem.io/documents/NVDIMM_Namespace_Spec.pdf
 - v1.2: https://uefi.org/sites/default/files/resources/UEFI_Spec_2_7.pdf
 - v2.1: https://computeexpresslink.org/wp-content/uploads/2024/02/CXL-2.0-Specification.pdf

Basic differences between these LSA formats:
 - v1.1: Support Namespace persistency. Size of Namespace Label is 128 bytes
 - v1.2: Support Namespace persistency. Size of Namespace Label is 256 bytes
 - v2.1: Support Namespace and Region persistency. Size of Namespace and
   Region Label is 256 bytes.

Linux nvdimm driver supports only v1.1 and v1.2 LSA format. CXL pmem device
require support of LSA v2.1 format for region and namespace persistency.
Initial support of LSA 2.1 was add in [1].

This patchset adds support of LSA 2.1 in nvdimm and cxl pmem driver.

Patch 1:     Introduce NDD_CXL_LABEL flag and Update cxl label index as per v2.1
Patch 2-4:   Update namespace label as per v2.1
Patch 5-12:  Introduce cxl region labels and modify existing change accordingly
Patch 13:    Refactor cxl pmem region auto assembly
Patch 14-18: Save cxl region info in LSA and region recreation during reboot
Patch 19:    Segregate out cxl pmem region code from region.c to pmem_region.c
Patch 20:    Introduce cxl region addition/deletion attributes


Testing:
========
In order to test this patchset, I also added the support of LSA v2.1 format
in ndctl. ndctl changes are available at [2]. After review, I’ll push in
ndctl repo for community review.

1. Used Qemu using following CXL topology
   M2="-object memory-backend-file,id=cxl-mem1,share=on,mem-path=$TMP_DIR/cxltest.raw,size=512M \
       -object memory-backend-file,id=cxl-lsa1,share=on,mem-path=$TMP_DIR/lsa.raw,size=1M \
       -object memory-backend-file,id=cxl-mem2,share=on,mem-path=$TMP_DIR/cxltest2.raw,size=512M \
       -object memory-backend-file,id=cxl-lsa2,share=on,mem-path=$TMP_DIR/lsa2.raw,size=1M \
       -device pxb-cxl,bus_nr=10,bus=pcie.0,id=cxl.1 \
       -device cxl-rp,port=1,bus=cxl.1,id=root_port11,chassis=0,slot=1 \
       -device cxl-type3,bus=root_port11,memdev=cxl-mem1,lsa=cxl-lsa1,id=cxl-pmem1,sn=1 \
       -device cxl-rp,port=2,bus=cxl.1,id=root_port12,chassis=0,slot=2 \
       -device cxl-type3,bus=root_port12,memdev=cxl-mem2,lsa=cxl-lsa2,id=cxl-pmem2,sn=2 \
       -M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=4G,cxl-fmw.0.interleave-granularity=8k"

2. Create cxl region on both devices
	cxl create-region -d decoder0.0 -m mem0
	cxl create-region -d decoder0.0 -m mem1

	root@QEMUCXL6060pmem:~# cxl list
	[
	  {
	    "memdevs":[
	      {
	        "memdev":"mem0",
	        "pmem_size":536870912,
	        "serial":2,
	        "host":"0000:0c:00.0",
	        "firmware_version":"BWFW VERSION 00"
	      },
	      {
	        "memdev":"mem1",
	        "pmem_size":536870912,
	        "serial":1,
	        "host":"0000:0b:00.0",
	        "firmware_version":"BWFW VERSION 00"
	      }
	    ]
	  },
	  {
	    "regions":[
	      {
	        "region":"region0",
	        "resource":45365592064,
	        "size":536870912,
	        "type":"pmem",
	        "interleave_ways":1,
	        "interleave_granularity":256,
	        "decode_state":"commit",
	        "qos_class_mismatch":true
	      },
	      {
	        "region":"region1",
	        "resource":45902462976,
	        "size":536870912,
	        "type":"pmem",
	        "interleave_ways":1,
	        "interleave_granularity":256,
	        "decode_state":"commit",
	        "qos_class_mismatch":true
	      }
	    ]
	  }
	]

3. Re-Start Qemu and we could see cxl region persistency using "cxl list"

4. Create namespace for both regions
	root@QEMUCXL6060pmem:~# time ndctl create-namespace --mode=fsdax --region=region0 --size=128M
	{
	  "dev":"namespace0.0",
	  "mode":"fsdax",
	  "map":"dev",
	  "size":"124.00 MiB (130.02 MB)",
	  "uuid":"8a125dcb-f992-406d-b3ad-be82fc518f05",
	  "sector_size":512,
	  "align":2097152,
	  "blockdev":"pmem0"
	}
	
	real    0m31.866s
	user    0m0.183s
	sys     0m14.855s

	root@QEMUCXL6060pmem:~# time ndctl create-namespace --mode=fsdax --region=region1 --size=256M
	{
	  "dev":"namespace1.0",
	  "mode":"fsdax",
	  "map":"dev",
	  "size":"250.00 MiB (262.14 MB)",
	  "uuid":"8e16d950-c11d-4253-94a0-5b2928926433",
	  "sector_size":512,
	  "align":2097152,
	  "blockdev":"pmem1"
	}
	
	real    0m44.359s
	user    0m0.196s
	sys     0m26.768s

	root@QEMUCXL6060pmem:~# time ndctl create-namespace --mode=fsdax --region=region0 --size=256M
	{
	  "dev":"namespace0.1",
	  "mode":"fsdax",
	  "map":"dev",
	  "size":"250.00 MiB (262.14 MB)",
	  "uuid":"f3170bfe-548a-4ce4-ae00-145a24e70426",
	  "sector_size":512,
	  "align":2097152,
	  "blockdev":"pmem0.1"
	}
	
	real    0m44.004s
	user    0m0.220s
	sys     0m25.711s

	root@QEMUCXL6060pmem:~# time ndctl create-namespace --mode=fsdax --region=region1 --size=128M
	{
	  "dev":"namespace1.1",
	  "mode":"fsdax",
	  "map":"dev",
	  "size":"124.00 MiB (130.02 MB)",
	  "uuid":"6318d2d9-bc78-4896-84f9-6c18c3a8f58c",
	  "sector_size":512,
	  "align":2097152,
	  "blockdev":"pmem1.1"
	}
	
	real    0m36.612s
	user    0m0.225s
	sys     0m16.457s

	root@QEMUCXL6060pmem:~# ndctl list
	[
	  {
	    "dev":"namespace1.0",
	    "mode":"fsdax",
	    "map":"dev",
	    "size":262144000,
	    "uuid":"e07564eb-6653-4d67-ab07-434c22474001",
	    "sector_size":512,
	    "align":2097152,
	    "blockdev":"pmem1"
	  },
	  {
	    "dev":"namespace1.1",
	    "mode":"fsdax",
	    "map":"dev",
	    "size":130023424,
	    "uuid":"27dfd65a-c428-426a-8316-f340a59e0671",
	    "sector_size":512,
	    "align":2097152,
	    "blockdev":"pmem1.1"
	  },
	  {
	    "dev":"namespace0.1",
	    "mode":"fsdax",
	    "map":"dev",
	    "size":130023424,
	    "uuid":"689b4135-668d-4885-b138-b86f27d7602f",
	    "sector_size":512,
	    "align":2097152,
	    "blockdev":"pmem0.1"
	  },
	  {
	    "dev":"namespace0.0",
	    "mode":"fsdax",
	    "map":"dev",
	    "size":262144000,
	    "uuid":"ed15c67a-842d-4d5d-8996-be3aa24985e4",
	    "sector_size":512,
	    "align":2097152,
	    "blockdev":"pmem0"
	  }
	]

5. Re-Start Qemu and we could see
	- Region persistency using "cxl list"
	- Namespace persistency using "ndctl list" and cat /proc/iomem

	root@QEMUCXL6060pmem:~# cat /proc/iomem
	
	a90000000-b8fffffff : CXL Window 0
	  a90000000-aafffffff : Persistent Memory
	    a90000000-aafffffff : region0
	      a90000000-a97ffffff : namespace0.0
	      a98000000-aa7ffffff : namespace0.1
	  ab0000000-acfffffff : Persistent Memory
	    ab0000000-acfffffff : region1
	      ab0000000-abfffffff : namespace1.0
	      ac0000000-ac7ffffff : namespace1.1
	

	- NOTE: We can see some lag in restart, Its WIP

6. Also verify LSA version using "ndctl read-labels -j nmem0"
	root@QEMUCXL6060pmem:~# ndctl read-labels -j nmem0
	{
	  "dev":"nmem0",
	  "index":[
	    {
	      "signature":"NAMESPACE_INDEX",
	      "major":2,
	      "minor":1,
	      "labelsize":256,
	      "seq":2,
	      "nslot":4090
	    },
	    {
	      "signature":"NAMESPACE_INDEX",
	      "major":2,
	      "minor":1,
	      "labelsize":256,
	      "seq":1,
	      "nslot":4090
	    }
	  ],
	  "label":[
	    {
	      "type":"68bb2c0a-5a77-4937-9f85-3caf41a0f93c",
	      "uuid":"cbb3fe1e-9345-4ae7-95ca-2638db27ee7d",
	      "name":"",
	      "flags":8,
	      "nrange":1,
	      "position":0,
	      "dpa":134217728,
	      "rawsize":268435456,
	      "slot":0,
	      "align":0,
	      "region_uuid":"50d806c8-fd11-49eb-b19e-77fc67f6364b",
	      "abstraction_uuid":"266400ba-fb9f-4677-bcb0-968f11d0d225",
	      "lbasize":512
	    },
	    {
	      "type":"529d7c61-da07-47c4-a93f-ecdf2c06f444",
	      "uuid":"50d806c8-fd11-49eb-b19e-77fc67f6364b",
	      "flags":0,
	      "nlabel":1,
	      "position":0,
	      "dpa":0,
	      "rawsize":536870912,
	      "hpa":45365592064,
	      "slot":1,
	      "interleave granularity":256,
	      "align":0
	    },
	    {
	      "type":"68bb2c0a-5a77-4937-9f85-3caf41a0f93c",
	      "uuid":"d9ef8d35-ef84-4111-b302-bce53c94a2ad",
	      "name":"",
	      "flags":0,
	      "nrange":1,
	      "position":0,
	      "dpa":0,
	      "rawsize":134217728,
	      "slot":2,
	      "align":0,
	      "region_uuid":"50d806c8-fd11-49eb-b19e-77fc67f6364b",
	      "abstraction_uuid":"266400ba-fb9f-4677-bcb0-968f11d0d225",
	      "lbasize":512
	    },
	    {
	      "type":"68bb2c0a-5a77-4937-9f85-3caf41a0f93c",
	      "uuid":"cbb3fe1e-9345-4ae7-95ca-2638db27ee7d",
	      "name":"",
	      "flags":0,
	      "nrange":1,
	      "position":0,
	      "dpa":134217728,
	      "rawsize":268435456,
	      "slot":3,
	      "align":0,
	      "region_uuid":"50d806c8-fd11-49eb-b19e-77fc67f6364b",
	      "abstraction_uuid":"266400ba-fb9f-4677-bcb0-968f11d0d225",
	      "lbasize":512
	    }
	  ]
	}
	read 1 nmem

	- NOTE: We have following UUID types as per CXL Spec
		"type":"529d7c61-da07-47c4-a93f-ecdf2c06f444" is region label
		"type":"68bb2c0a-5a77-4937-9f85-3caf41a0f93c" is namespace label


Limitation (WIP):
================
Current changes only support interleave way == 1


Observation:
============
First time namespace creation using ndctl takes around 10 to 20 second time
while executing "devm_memremap_pages" at [3]

As using this patchset, after auto region creation, namespace creation is
happening in boot sequence (if nvdimm and cxl drivers are static), It is
therefore boot sequence is increased by around 10 to 20 sec.

Changes
=======
Changes in v1 -> v2
- v1 patch-set was broken. Find the v1 links at [4] and [5]
[PATCH 01/20]
- Simplify return in nvdimm_check_cxl_label_format() [Jonathan]
- Add spec reference while updating LSA major/minor [Jonathan, Dave]
[PATCH 02/20]
- Elaborate commit message with more information [Jonathan, Ira]
- Minimize extra re-naming to avoid churn & complexity [Johathan]
[PATCH 05/20]
- Use guard(mutex)(&nd_mapping->lock) [Jonathan]
[PATCH 06/20]
- Use switch in place if condition check [Jonathan]
- Fix wrong style for multiline comments in this file [Jonathan]
- Fix wrong condition check in del_labels()
- Bail out extra condition check using extra variable [Jonathan]
[PATCH 07/20]
- Modify init_labels function to init_labels() [Jonathan]
[PATCH 08/20]
- Simplify return in is_region_label() and flip if condition [Jonathan]
[PATCH 12/20]
- Fix comment syntax [Jonathan]
[PATCH 13/20]
- Elaborate commit message and remove history statement from comment [Jonathan]
- Move cxl_region_discovery() from core/port.c to core/region.c [Dave]
[PATCH 14/20]
- Spell check fix in commit message [Jonathan]
- Use ACQUIRE() instead of down_write_killable() [Jonathan]
- Fix extra return check [Jonathan]
- Rename port to root_port to avoid long indirection [Jonathan]
- Remove cxl_wq_flush() as its not required [Jonathan, Dave]
- Add comment of attaching just one target [Jonathan]
- Rename update_region_size() to resize_or_free_region_hpa() [Dave]
- Rename val to size in resize_or_free_region_hpa() [Dave]
- Share common code using helper function in size_store() [Dave]
- Rename update_region_dpa_size() to resize_or_free_dpa() [Dave]
- Rename u64 in place of unsigned long long [Dave]
- Share common code using helper function in dpa_size_store() [Dave]
- Rename CXL_DECODER_PMEM with CXL_PARTMODE_PMEM [Dave]
- Share common code using helper function in commit_store() [Dave]
- Update verbose information about devm_cxl_pmem_add_region() [Dave]
- Renamed and refactored __create_region() to cxl_create_region() [Dave]
[PATCH 15/20]
- Avoid blank line [Jonathan]
- Rename root-cxl-port to CXL port [Dave]
- Add comment to release device ref taken via device_find_child() [Dave]
- Rename cxl_find_root_decoder() to cxl_find_root_decoder_by_port() [Dave]
[PATCH 18/20]
- Avoid extra nvdimm validity check [Jonathan]
- Flip logic to check for unhandled case first [Jonathan]
- Simplify return in match_ep_decoder() [Dave]
- Use lockdep_assert_held() in create_pmem_region() [Dave]
- To use lock moved create_pmem_region() from cxl/pmem.c to core/region.c
[PATCH 19/20]
- Spell check fix in commit message [Jonathan]
- Fix LIBNVDIMM selection condition check in cxl/Kconfig [Jonathan]
[PATCH 20/20]
- Add Documentation/ABI/testing/sysfs-bus-cxl [Jonathan]
- Use ACQUIRE() instead of down_write_killable() [Jonathan]
- Drop trailing comma on terminating entries [Jonathan]


[1]: https://lore.kernel.org/all/163116432405.2460985.5547867384570123403.stgit@dwillia2-desk3.amr.corp.intel.com/
[2]: https://github.com/neerajoss/ndctl/tree/linux-cxl/CXL_LSA_2.1_Support
[3]: https://elixir.bootlin.com/linux/v6.13.7/source/drivers/nvdimm/pmem.c#L520
[4] v1 Cover Letter: https://lore.kernel.org/linux-cxl/1931444790.41750165203442.JavaMail.epsvc@epcpadp1new/
[5] v1 Rest Thread: https://lore.kernel.org/linux-cxl/158453976.61750165203630.JavaMail.epsvc@epcpadp1new/


Neeraj Kumar (20):
  nvdimm/label: Introduce NDD_CXL_LABEL flag to set cxl label format
  nvdimm/label: Prep patch to accommodate cxl lsa 2.1 support
  nvdimm/namespace_label: Add namespace label changes as per CXL LSA v2.1
  nvdimm/label: CXL labels skip the need for 'interleave-set cookie'
  nvdimm/region_label: Add region label updation routine
  nvdimm/region_label: Add region label deletion routine
  nvdimm/namespace_label: Update namespace init_labels and its region_uuid
  nvdimm/label: Include region label in slot validation
  nvdimm/namespace_label: Skip region label during ns label DPA reservation
  nvdimm/region_label: Preserve cxl region information from region label
  nvdimm/region_label: Export routine to fetch region information
  nvdimm/namespace_label: Skip region label during namespace creation
  cxl/mem: Refactor cxl pmem region auto-assembling
  cxl/region: Add devm_cxl_pmem_add_region() for pmem region creation
  cxl: Add a routine to find cxl root decoder on cxl bus using cxl port
  cxl/mem: Preserve cxl root decoder during mem probe
  cxl/pmem: Preserve region information into nd_set
  cxl/pmem: Add support of cxl lsa 2.1 support in cxl pmem
  cxl/pmem_region: Prep patch to accommodate pmem_region attributes
  cxl/pmem_region: Add sysfs attribute cxl region label updation/deletion

 Documentation/ABI/testing/sysfs-bus-cxl |  22 ++
 drivers/cxl/Kconfig                     |  12 +
 drivers/cxl/core/Makefile               |   1 +
 drivers/cxl/core/core.h                 |   9 +-
 drivers/cxl/core/pmem_region.c          | 294 ++++++++++++++++
 drivers/cxl/core/port.c                 |  58 +++-
 drivers/cxl/core/region.c               | 400 +++++++++++-----------
 drivers/cxl/cxl.h                       |  54 ++-
 drivers/cxl/cxlmem.h                    |   1 +
 drivers/cxl/mem.c                       |  24 +-
 drivers/cxl/pmem.c                      |  15 +-
 drivers/cxl/port.c                      |  39 +--
 drivers/nvdimm/dimm.c                   |   5 +
 drivers/nvdimm/dimm_devs.c              |  25 ++
 drivers/nvdimm/label.c                  | 426 ++++++++++++++++++++----
 drivers/nvdimm/label.h                  |  20 +-
 drivers/nvdimm/namespace_devs.c         | 110 +++++-
 drivers/nvdimm/nd-core.h                |   2 +
 drivers/nvdimm/nd.h                     |  79 ++++-
 drivers/nvdimm/region_devs.c            |   5 +
 include/linux/libnvdimm.h               |  28 ++
 tools/testing/cxl/Kbuild                |   1 +
 22 files changed, 1279 insertions(+), 351 deletions(-)
 create mode 100644 drivers/cxl/core/pmem_region.c


base-commit: f11a5f89910a7ae970fbce4fdc02d86a8ba8570f
-- 
2.34.1

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

* [PATCH V2 01/20] nvdimm/label: Introduce NDD_CXL_LABEL flag to set cxl label format
       [not found]   ` <CGME20250730121223epcas5p1386bdf99a0af820dd4411fbdbd413cd5@epcas5p1.samsung.com>
@ 2025-07-30 12:11     ` Neeraj Kumar
  2025-08-13 13:12       ` Jonathan Cameron
  0 siblings, 1 reply; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:11 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

Prior to LSA 2.1 version, LSA contain only namespace labels. LSA 2.1
introduced in CXL 2.0 Spec, which contain region label along with
namespace label.

NDD_LABELING flag is used for namespace. Introduced NDD_CXL_LABEL
flag for region label. Based on these flags nvdimm driver performs
operation on namespace label or region label.

NDD_CXL_LABEL will be utilized by cxl driver to enable LSA2.1 region
label support

Accordingly updated label index version

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 drivers/nvdimm/dimm.c      |  1 +
 drivers/nvdimm/dimm_devs.c |  7 +++++++
 drivers/nvdimm/label.c     | 22 ++++++++++++++++++----
 drivers/nvdimm/nd.h        |  1 +
 include/linux/libnvdimm.h  |  3 +++
 5 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c
index 91d9163ee303..8753b5cd91cc 100644
--- a/drivers/nvdimm/dimm.c
+++ b/drivers/nvdimm/dimm.c
@@ -62,6 +62,7 @@ static int nvdimm_probe(struct device *dev)
 	if (rc < 0)
 		dev_dbg(dev, "failed to unlock dimm: %d\n", rc);
 
+	ndd->cxl = nvdimm_check_cxl_label_format(ndd->dev);
 
 	/*
 	 * EACCES failures reading the namespace label-area-properties
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index 21498d461fde..6149770c1b27 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -18,6 +18,13 @@
 
 static DEFINE_IDA(dimm_ida);
 
+bool nvdimm_check_cxl_label_format(struct device *dev)
+{
+	struct nvdimm *nvdimm = to_nvdimm(dev);
+
+	return test_bit(NDD_CXL_LABEL, &nvdimm->flags);
+}
+
 /*
  * Retrieve bus and dimm handle and return if this bus supports
  * get_config_data commands
diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
index 04f4a049599a..7a011ee02d79 100644
--- a/drivers/nvdimm/label.c
+++ b/drivers/nvdimm/label.c
@@ -688,11 +688,25 @@ static int nd_label_write_index(struct nvdimm_drvdata *ndd, int index, u32 seq,
 		- (unsigned long) to_namespace_index(ndd, 0);
 	nsindex->labeloff = __cpu_to_le64(offset);
 	nsindex->nslot = __cpu_to_le32(nslot);
-	nsindex->major = __cpu_to_le16(1);
-	if (sizeof_namespace_label(ndd) < 256)
+
+	/* Set LSA Label Index Version */
+	if (ndd->cxl) {
+		/* CXL r3.2 Spec: Table 9-9 Label Index Block Layout */
+		nsindex->major = __cpu_to_le16(2);
 		nsindex->minor = __cpu_to_le16(1);
-	else
-		nsindex->minor = __cpu_to_le16(2);
+	} else {
+		nsindex->major = __cpu_to_le16(1);
+		/*
+		 * NVDIMM Namespace Specification
+		 * Table 2: Namespace Label Index Block Fields
+		 */
+		if (sizeof_namespace_label(ndd) < 256)
+			nsindex->minor = __cpu_to_le16(1);
+		else
+		 /* UEFI Specification 2.7: Label Index Block Definitions */
+			nsindex->minor = __cpu_to_le16(2);
+	}
+
 	nsindex->checksum = __cpu_to_le64(0);
 	if (flags & ND_NSINDEX_INIT) {
 		unsigned long *free = (unsigned long *) nsindex->free;
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index cc5c8f3f81e8..1cc06cc58d14 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -522,6 +522,7 @@ void nvdimm_set_labeling(struct device *dev);
 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);
 #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 e772aae71843..0a55900842c8 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -44,6 +44,9 @@ enum {
 	/* dimm provider wants synchronous registration by __nvdimm_create() */
 	NDD_REGISTER_SYNC = 8,
 
+	/* dimm supports region labels (LSA Format 2.1) */
+	NDD_CXL_LABEL = 9,
+
 	/* need to set a limit somewhere, but yes, this is likely overkill */
 	ND_IOCTL_MAX_BUFLEN = SZ_4M,
 	ND_CMD_MAX_ELEM = 5,
-- 
2.34.1


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

* [PATCH V2 02/20] nvdimm/label: Prep patch to accommodate cxl lsa 2.1 support
       [not found]   ` <CGME20250730121224epcas5p3c3a6563ce186d2fdb9c3ff5f66e37f3e@epcas5p3.samsung.com>
@ 2025-07-30 12:11     ` Neeraj Kumar
  2025-08-13 13:23       ` Jonathan Cameron
                         ` (3 more replies)
  0 siblings, 4 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:11 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

LSA 2.1 format introduces region label, which can also reside
into LSA along with only namespace label as per v1.1 and v1.2

As both namespace and region labels are of same size of 256 bytes.
Thus renamed "struct nd_namespace_label" to "struct nd_lsa_label",
where both namespace label and region label can stay as union.

No functional change introduced.

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 drivers/nvdimm/label.c          | 58 +++++++++++++++++++--------------
 drivers/nvdimm/label.h          | 12 ++++++-
 drivers/nvdimm/namespace_devs.c | 33 +++++++++++++------
 drivers/nvdimm/nd.h             |  2 +-
 4 files changed, 68 insertions(+), 37 deletions(-)

diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
index 7a011ee02d79..75bc11da4c11 100644
--- a/drivers/nvdimm/label.c
+++ b/drivers/nvdimm/label.c
@@ -271,7 +271,7 @@ static void nd_label_copy(struct nvdimm_drvdata *ndd,
 	memcpy(dst, src, sizeof_namespace_index(ndd));
 }
 
-static struct nd_namespace_label *nd_label_base(struct nvdimm_drvdata *ndd)
+static struct nd_lsa_label *nd_label_base(struct nvdimm_drvdata *ndd)
 {
 	void *base = to_namespace_index(ndd, 0);
 
@@ -279,7 +279,7 @@ static struct nd_namespace_label *nd_label_base(struct nvdimm_drvdata *ndd)
 }
 
 static int to_slot(struct nvdimm_drvdata *ndd,
-		struct nd_namespace_label *nd_label)
+		struct nd_lsa_label *nd_label)
 {
 	unsigned long label, base;
 
@@ -289,14 +289,14 @@ static int to_slot(struct nvdimm_drvdata *ndd,
 	return (label - base) / sizeof_namespace_label(ndd);
 }
 
-static struct nd_namespace_label *to_label(struct nvdimm_drvdata *ndd, int slot)
+static struct nd_lsa_label *to_label(struct nvdimm_drvdata *ndd, int slot)
 {
 	unsigned long label, base;
 
 	base = (unsigned long) nd_label_base(ndd);
 	label = base + sizeof_namespace_label(ndd) * slot;
 
-	return (struct nd_namespace_label *) label;
+	return (struct nd_lsa_label *) label;
 }
 
 #define for_each_clear_bit_le(bit, addr, size) \
@@ -382,9 +382,10 @@ static void nsl_calculate_checksum(struct nvdimm_drvdata *ndd,
 }
 
 static bool slot_valid(struct nvdimm_drvdata *ndd,
-		struct nd_namespace_label *nd_label, u32 slot)
+		struct nd_lsa_label *lsa_label, u32 slot)
 {
 	bool valid;
+	struct nd_namespace_label *nd_label = &lsa_label->ns_label;
 
 	/* check that we are written where we expect to be written */
 	if (slot != nsl_get_slot(ndd, nd_label))
@@ -405,6 +406,7 @@ int nd_label_reserve_dpa(struct nvdimm_drvdata *ndd)
 		return 0; /* no label, nothing to reserve */
 
 	for_each_clear_bit_le(slot, free, nslot) {
+		struct nd_lsa_label *lsa_label;
 		struct nd_namespace_label *nd_label;
 		struct nd_region *nd_region = NULL;
 		struct nd_label_id label_id;
@@ -412,9 +414,10 @@ int nd_label_reserve_dpa(struct nvdimm_drvdata *ndd)
 		uuid_t label_uuid;
 		u32 flags;
 
-		nd_label = to_label(ndd, slot);
+		lsa_label = to_label(ndd, slot);
+		nd_label = &lsa_label->ns_label;
 
-		if (!slot_valid(ndd, nd_label, slot))
+		if (!slot_valid(ndd, lsa_label, slot))
 			continue;
 
 		nsl_get_uuid(ndd, nd_label, &label_uuid);
@@ -565,11 +568,13 @@ int nd_label_active_count(struct nvdimm_drvdata *ndd)
 		return 0;
 
 	for_each_clear_bit_le(slot, free, nslot) {
+		struct nd_lsa_label *lsa_label;
 		struct nd_namespace_label *nd_label;
 
-		nd_label = to_label(ndd, slot);
+		lsa_label = to_label(ndd, slot);
+		nd_label = &lsa_label->ns_label;
 
-		if (!slot_valid(ndd, nd_label, slot)) {
+		if (!slot_valid(ndd, lsa_label, slot)) {
 			u32 label_slot = nsl_get_slot(ndd, nd_label);
 			u64 size = nsl_get_rawsize(ndd, nd_label);
 			u64 dpa = nsl_get_dpa(ndd, nd_label);
@@ -584,7 +589,7 @@ int nd_label_active_count(struct nvdimm_drvdata *ndd)
 	return count;
 }
 
-struct nd_namespace_label *nd_label_active(struct nvdimm_drvdata *ndd, int n)
+struct nd_lsa_label *nd_label_active(struct nvdimm_drvdata *ndd, int n)
 {
 	struct nd_namespace_index *nsindex;
 	unsigned long *free;
@@ -594,10 +599,10 @@ struct nd_namespace_label *nd_label_active(struct nvdimm_drvdata *ndd, int n)
 		return NULL;
 
 	for_each_clear_bit_le(slot, free, nslot) {
-		struct nd_namespace_label *nd_label;
+		struct nd_lsa_label *lsa_label;
 
-		nd_label = to_label(ndd, slot);
-		if (!slot_valid(ndd, nd_label, slot))
+		lsa_label = to_label(ndd, slot);
+		if (!slot_valid(ndd, lsa_label, slot))
 			continue;
 
 		if (n-- == 0)
@@ -738,7 +743,7 @@ static int nd_label_write_index(struct nvdimm_drvdata *ndd, int index, u32 seq,
 }
 
 static unsigned long nd_label_offset(struct nvdimm_drvdata *ndd,
-		struct nd_namespace_label *nd_label)
+		struct nd_lsa_label *nd_label)
 {
 	return (unsigned long) nd_label
 		- (unsigned long) to_namespace_index(ndd, 0);
@@ -892,6 +897,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
 	struct nd_namespace_common *ndns = &nspm->nsio.common;
 	struct nd_interleave_set *nd_set = nd_region->nd_set;
 	struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
+	struct nd_lsa_label *lsa_label;
 	struct nd_namespace_label *nd_label;
 	struct nd_namespace_index *nsindex;
 	struct nd_label_ent *label_ent;
@@ -923,8 +929,10 @@ static int __pmem_label_update(struct nd_region *nd_region,
 		return -ENXIO;
 	dev_dbg(ndd->dev, "allocated: %d\n", slot);
 
-	nd_label = to_label(ndd, slot);
-	memset(nd_label, 0, sizeof_namespace_label(ndd));
+	lsa_label = to_label(ndd, slot);
+	memset(lsa_label, 0, sizeof_namespace_label(ndd));
+
+	nd_label = &lsa_label->ns_label;
 	nsl_set_uuid(ndd, nd_label, nspm->uuid);
 	nsl_set_name(ndd, nd_label, nspm->alt_name);
 	nsl_set_flags(ndd, nd_label, flags);
@@ -942,7 +950,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
 	nd_dbg_dpa(nd_region, ndd, res, "\n");
 
 	/* update label */
-	offset = nd_label_offset(ndd, nd_label);
+	offset = nd_label_offset(ndd, lsa_label);
 	rc = nvdimm_set_config_data(ndd, offset, nd_label,
 			sizeof_namespace_label(ndd));
 	if (rc < 0)
@@ -954,7 +962,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
 		if (!label_ent->label)
 			continue;
 		if (test_and_clear_bit(ND_LABEL_REAP, &label_ent->flags) ||
-		    nsl_uuid_equal(ndd, label_ent->label, nspm->uuid))
+		    nsl_uuid_equal(ndd, &label_ent->label->ns_label, nspm->uuid))
 			reap_victim(nd_mapping, label_ent);
 	}
 
@@ -964,14 +972,14 @@ static int __pmem_label_update(struct nd_region *nd_region,
 	if (rc == 0) {
 		list_for_each_entry(label_ent, &nd_mapping->labels, list)
 			if (!label_ent->label) {
-				label_ent->label = nd_label;
-				nd_label = NULL;
+				label_ent->label = lsa_label;
+				lsa_label = NULL;
 				break;
 			}
-		dev_WARN_ONCE(&nspm->nsio.common.dev, nd_label,
+		dev_WARN_ONCE(&nspm->nsio.common.dev, lsa_label,
 				"failed to track label: %d\n",
-				to_slot(ndd, nd_label));
-		if (nd_label)
+				to_slot(ndd, lsa_label));
+		if (lsa_label)
 			rc = -ENXIO;
 	}
 	mutex_unlock(&nd_mapping->lock);
@@ -1042,12 +1050,12 @@ static int del_labels(struct nd_mapping *nd_mapping, uuid_t *uuid)
 
 	mutex_lock(&nd_mapping->lock);
 	list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list) {
-		struct nd_namespace_label *nd_label = label_ent->label;
+		struct nd_lsa_label *nd_label = label_ent->label;
 
 		if (!nd_label)
 			continue;
 		active++;
-		if (!nsl_uuid_equal(ndd, nd_label, uuid))
+		if (!nsl_uuid_equal(ndd, &nd_label->ns_label, uuid))
 			continue;
 		active--;
 		slot = to_slot(ndd, nd_label);
diff --git a/drivers/nvdimm/label.h b/drivers/nvdimm/label.h
index 0650fb4b9821..4883b3a1320f 100644
--- a/drivers/nvdimm/label.h
+++ b/drivers/nvdimm/label.h
@@ -183,6 +183,16 @@ struct nd_namespace_label {
 	};
 };
 
+/*
+ * LSA 2.1 format introduces region label, which can also reside
+ * into LSA along with only namespace label as per v1.1 and v1.2
+ */
+struct nd_lsa_label {
+	union {
+		struct nd_namespace_label ns_label;
+	};
+};
+
 #define NVDIMM_BTT_GUID "8aed63a2-29a2-4c66-8b12-f05d15d3922a"
 #define NVDIMM_BTT2_GUID "18633bfc-1735-4217-8ac9-17239282d3f8"
 #define NVDIMM_PFN_GUID "266400ba-fb9f-4677-bcb0-968f11d0d225"
@@ -215,7 +225,7 @@ struct nvdimm_drvdata;
 int nd_label_data_init(struct nvdimm_drvdata *ndd);
 size_t sizeof_namespace_index(struct nvdimm_drvdata *ndd);
 int nd_label_active_count(struct nvdimm_drvdata *ndd);
-struct nd_namespace_label *nd_label_active(struct nvdimm_drvdata *ndd, int n);
+struct nd_lsa_label *nd_label_active(struct nvdimm_drvdata *ndd, int n);
 u32 nd_label_alloc_slot(struct nvdimm_drvdata *ndd);
 bool nd_label_free_slot(struct nvdimm_drvdata *ndd, u32 slot);
 u32 nd_label_nfree(struct nvdimm_drvdata *ndd);
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index 55cfbf1e0a95..bdf1ed6f23d8 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -1009,10 +1009,11 @@ static int namespace_update_uuid(struct nd_region *nd_region,
 
 		mutex_lock(&nd_mapping->lock);
 		list_for_each_entry(label_ent, &nd_mapping->labels, list) {
-			struct nd_namespace_label *nd_label = label_ent->label;
+			struct nd_namespace_label *nd_label;
 			struct nd_label_id label_id;
 			uuid_t uuid;
 
+			nd_label = &label_ent->label->ns_label;
 			if (!nd_label)
 				continue;
 			nsl_get_uuid(ndd, nd_label, &uuid);
@@ -1573,11 +1574,14 @@ static bool has_uuid_at_pos(struct nd_region *nd_region, const uuid_t *uuid,
 		bool found_uuid = false;
 
 		list_for_each_entry(label_ent, &nd_mapping->labels, list) {
-			struct nd_namespace_label *nd_label = label_ent->label;
+			struct nd_lsa_label *lsa_label = label_ent->label;
+			struct nd_namespace_label *nd_label;
 			u16 position;
 
-			if (!nd_label)
+			if (!lsa_label)
 				continue;
+
+			nd_label = &lsa_label->ns_label;
 			position = nsl_get_position(ndd, nd_label);
 
 			if (!nsl_validate_isetcookie(ndd, nd_label, cookie))
@@ -1615,17 +1619,21 @@ static int select_pmem_id(struct nd_region *nd_region, const uuid_t *pmem_id)
 	for (i = 0; i < nd_region->ndr_mappings; i++) {
 		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
 		struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
+		struct nd_lsa_label *lsa_label = NULL;
 		struct nd_namespace_label *nd_label = NULL;
 		u64 hw_start, hw_end, pmem_start, pmem_end;
 		struct nd_label_ent *label_ent;
 
 		lockdep_assert_held(&nd_mapping->lock);
 		list_for_each_entry(label_ent, &nd_mapping->labels, list) {
-			nd_label = label_ent->label;
-			if (!nd_label)
+			lsa_label = label_ent->label;
+			if (!lsa_label)
 				continue;
+
+			nd_label = &lsa_label->ns_label;
 			if (nsl_uuid_equal(ndd, nd_label, pmem_id))
 				break;
+			lsa_label = NULL;
 			nd_label = NULL;
 		}
 
@@ -1746,19 +1754,21 @@ static struct device *create_namespace_pmem(struct nd_region *nd_region,
 
 	/* Calculate total size and populate namespace properties from label0 */
 	for (i = 0; i < nd_region->ndr_mappings; i++) {
+		struct nd_lsa_label *lsa_label;
 		struct nd_namespace_label *label0;
 		struct nvdimm_drvdata *ndd;
 
 		nd_mapping = &nd_region->mapping[i];
 		label_ent = list_first_entry_or_null(&nd_mapping->labels,
 				typeof(*label_ent), list);
-		label0 = label_ent ? label_ent->label : NULL;
+		lsa_label = label_ent ? label_ent->label : NULL;
 
-		if (!label0) {
+		if (!lsa_label) {
 			WARN_ON(1);
 			continue;
 		}
 
+		label0 = &lsa_label->ns_label;
 		ndd = to_ndd(nd_mapping);
 		size += nsl_get_rawsize(ndd, label0);
 		if (nsl_get_position(ndd, label0) != 0)
@@ -1943,12 +1953,15 @@ static struct device **scan_labels(struct nd_region *nd_region)
 
 	/* "safe" because create_namespace_pmem() might list_move() label_ent */
 	list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list) {
-		struct nd_namespace_label *nd_label = label_ent->label;
+		struct nd_lsa_label *lsa_label = label_ent->label;
+		struct nd_namespace_label *nd_label;
 		struct device **__devs;
 
-		if (!nd_label)
+		if (!lsa_label)
 			continue;
 
+		nd_label = &lsa_label->ns_label;
+
 		/* skip labels that describe extents outside of the region */
 		if (nsl_get_dpa(ndd, nd_label) < nd_mapping->start ||
 		    nsl_get_dpa(ndd, nd_label) > map_end)
@@ -2122,7 +2135,7 @@ static int init_active_labels(struct nd_region *nd_region)
 		if (!count)
 			continue;
 		for (j = 0; j < count; j++) {
-			struct nd_namespace_label *label;
+			struct nd_lsa_label *label;
 
 			label_ent = kzalloc(sizeof(*label_ent), GFP_KERNEL);
 			if (!label_ent)
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 1cc06cc58d14..61348dee687d 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -376,7 +376,7 @@ enum nd_label_flags {
 struct nd_label_ent {
 	struct list_head list;
 	unsigned long flags;
-	struct nd_namespace_label *label;
+	struct nd_lsa_label *label;
 };
 
 enum nd_mapping_lock_class {
-- 
2.34.1


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

* [PATCH V2 03/20] nvdimm/namespace_label: Add namespace label changes as per CXL LSA v2.1
       [not found]   ` <CGME20250730121225epcas5p2742d108bd0c52c8d7d46b655892c5c19@epcas5p2.samsung.com>
@ 2025-07-30 12:11     ` Neeraj Kumar
  2025-07-31 13:12       ` kernel test robot
                         ` (3 more replies)
  0 siblings, 4 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:11 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

CXL 3.2 Spec mentions CXL LSA 2.1 Namespace Labels at section 9.13.2.5
Modified __pmem_label_update function using setter functions to update
namespace label as per CXL LSA 2.1

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 drivers/nvdimm/label.c |  3 +++
 drivers/nvdimm/nd.h    | 27 +++++++++++++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
index 75bc11da4c11..3f8a6bdb77c7 100644
--- a/drivers/nvdimm/label.c
+++ b/drivers/nvdimm/label.c
@@ -933,6 +933,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
 	memset(lsa_label, 0, sizeof_namespace_label(ndd));
 
 	nd_label = &lsa_label->ns_label;
+	nsl_set_type(ndd, nd_label);
 	nsl_set_uuid(ndd, nd_label, nspm->uuid);
 	nsl_set_name(ndd, nd_label, nspm->alt_name);
 	nsl_set_flags(ndd, nd_label, flags);
@@ -944,7 +945,9 @@ static int __pmem_label_update(struct nd_region *nd_region,
 	nsl_set_lbasize(ndd, nd_label, nspm->lbasize);
 	nsl_set_dpa(ndd, nd_label, res->start);
 	nsl_set_slot(ndd, nd_label, slot);
+	nsl_set_alignment(ndd, nd_label, 0);
 	nsl_set_type_guid(ndd, nd_label, &nd_set->type_guid);
+	nsl_set_region_uuid(ndd, nd_label, NULL);
 	nsl_set_claim_class(ndd, nd_label, ndns->claim_class);
 	nsl_calculate_checksum(ndd, nd_label);
 	nd_dbg_dpa(nd_region, ndd, res, "\n");
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 61348dee687d..651847f1bbf9 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -295,6 +295,33 @@ static inline const u8 *nsl_uuid_raw(struct nvdimm_drvdata *ndd,
 	return nd_label->efi.uuid;
 }
 
+static inline void nsl_set_type(struct nvdimm_drvdata *ndd,
+				struct nd_namespace_label *ns_label)
+{
+	uuid_t tmp;
+
+	if (ndd->cxl) {
+		uuid_parse(CXL_NAMESPACE_UUID, &tmp);
+		export_uuid(ns_label->cxl.type, &tmp);
+	}
+}
+
+static inline void nsl_set_alignment(struct nvdimm_drvdata *ndd,
+				     struct nd_namespace_label *ns_label,
+				     u32 align)
+{
+	if (ndd->cxl)
+		ns_label->cxl.align = __cpu_to_le16(align);
+}
+
+static inline void nsl_set_region_uuid(struct nvdimm_drvdata *ndd,
+				       struct nd_namespace_label *ns_label,
+				       const uuid_t *uuid)
+{
+	if (ndd->cxl)
+		export_uuid(ns_label->cxl.region_uuid, uuid);
+}
+
 bool nsl_validate_type_guid(struct nvdimm_drvdata *ndd,
 			    struct nd_namespace_label *nd_label, guid_t *guid);
 enum nvdimm_claim_class nsl_get_claim_class(struct nvdimm_drvdata *ndd,
-- 
2.34.1


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

* [PATCH V2 04/20] nvdimm/label: CXL labels skip the need for 'interleave-set cookie'
       [not found]   ` <CGME20250730121227epcas5p4675fdb3130de49cd99351c5efd09e29e@epcas5p4.samsung.com>
@ 2025-07-30 12:11     ` Neeraj Kumar
  2025-08-13 13:44       ` Jonathan Cameron
                         ` (2 more replies)
  0 siblings, 3 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:11 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

CXL LSA v2.1 utilizes the region labels stored in the LSA for interleave
set configuration instead of interleave-set cookie used in previous LSA
versions. As interleave-set cookie is not required for CXL LSA v2.1 format
so skip its usage for CXL LSA 2.1 format

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 drivers/nvdimm/namespace_devs.c | 3 ++-
 drivers/nvdimm/region_devs.c    | 5 +++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index bdf1ed6f23d8..5b73119dc8fd 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -1692,7 +1692,8 @@ static struct device *create_namespace_pmem(struct nd_region *nd_region,
 	int rc = 0;
 	u16 i;
 
-	if (cookie == 0) {
+	/* CXL labels skip the need for 'interleave-set cookie' */
+	if (!ndd->cxl && cookie == 0) {
 		dev_dbg(&nd_region->dev, "invalid interleave-set-cookie\n");
 		return ERR_PTR(-ENXIO);
 	}
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index de1ee5ebc851..2debe60f8bf0 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -858,6 +858,11 @@ u64 nd_region_interleave_set_cookie(struct nd_region *nd_region,
 	if (!nd_set)
 		return 0;
 
+	/* CXL labels skip the need for 'interleave-set cookie' */
+	if (nsindex && __le16_to_cpu(nsindex->major) == 2
+			&& __le16_to_cpu(nsindex->minor) == 1)
+		return 0;
+
 	if (nsindex && __le16_to_cpu(nsindex->major) == 1
 			&& __le16_to_cpu(nsindex->minor) == 1)
 		return nd_set->cookie1;
-- 
2.34.1


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

* [PATCH V2 05/20] nvdimm/region_label: Add region label updation routine
       [not found]   ` <CGME20250730121228epcas5p411e5cc6d29fb9417178dbd07a1d8f02d@epcas5p4.samsung.com>
@ 2025-07-30 12:11     ` Neeraj Kumar
  2025-07-31 15:07       ` kernel test robot
                         ` (4 more replies)
  0 siblings, 5 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:11 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

Added __pmem_region_label_update region label update routine to update
region label.

Also used guard(mutex)(&nd_mapping->lock) in place of mutex_lock() and
mutex_unlock()

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 drivers/nvdimm/label.c          | 171 +++++++++++++++++++++++++++++---
 drivers/nvdimm/label.h          |   2 +
 drivers/nvdimm/namespace_devs.c |  12 +++
 drivers/nvdimm/nd.h             |  20 ++++
 include/linux/libnvdimm.h       |   8 ++
 5 files changed, 198 insertions(+), 15 deletions(-)

diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
index 3f8a6bdb77c7..94f2d0ba7aca 100644
--- a/drivers/nvdimm/label.c
+++ b/drivers/nvdimm/label.c
@@ -381,6 +381,16 @@ static void nsl_calculate_checksum(struct nvdimm_drvdata *ndd,
 	nsl_set_checksum(ndd, nd_label, sum);
 }
 
+static void rgl_calculate_checksum(struct nvdimm_drvdata *ndd,
+				   struct cxl_region_label *rg_label)
+{
+	u64 sum;
+
+	rgl_set_checksum(rg_label, 0);
+	sum = nd_fletcher64(rg_label, sizeof_namespace_label(ndd), 1);
+	rgl_set_checksum(rg_label, sum);
+}
+
 static bool slot_valid(struct nvdimm_drvdata *ndd,
 		struct nd_lsa_label *lsa_label, u32 slot)
 {
@@ -960,7 +970,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
 		return rc;
 
 	/* Garbage collect the previous label */
-	mutex_lock(&nd_mapping->lock);
+	guard(mutex)(&nd_mapping->lock);
 	list_for_each_entry(label_ent, &nd_mapping->labels, list) {
 		if (!label_ent->label)
 			continue;
@@ -972,20 +982,20 @@ static int __pmem_label_update(struct nd_region *nd_region,
 	/* update index */
 	rc = nd_label_write_index(ndd, ndd->ns_next,
 			nd_inc_seq(__le32_to_cpu(nsindex->seq)), 0);
-	if (rc == 0) {
-		list_for_each_entry(label_ent, &nd_mapping->labels, list)
-			if (!label_ent->label) {
-				label_ent->label = lsa_label;
-				lsa_label = NULL;
-				break;
-			}
-		dev_WARN_ONCE(&nspm->nsio.common.dev, lsa_label,
-				"failed to track label: %d\n",
-				to_slot(ndd, lsa_label));
-		if (lsa_label)
-			rc = -ENXIO;
-	}
-	mutex_unlock(&nd_mapping->lock);
+	if (rc)
+		return rc;
+
+	list_for_each_entry(label_ent, &nd_mapping->labels, list)
+		if (!label_ent->label) {
+			label_ent->label = lsa_label;
+			lsa_label = NULL;
+			break;
+		}
+	dev_WARN_ONCE(&nspm->nsio.common.dev, lsa_label,
+			"failed to track label: %d\n",
+			to_slot(ndd, lsa_label));
+	if (lsa_label)
+		rc = -ENXIO;
 
 	return rc;
 }
@@ -1127,6 +1137,137 @@ int nd_pmem_namespace_label_update(struct nd_region *nd_region,
 	return 0;
 }
 
+static int __pmem_region_label_update(struct nd_region *nd_region,
+		struct nd_mapping *nd_mapping, int pos, unsigned long flags)
+{
+	struct nd_interleave_set *nd_set = nd_region->nd_set;
+	struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
+	struct nd_lsa_label *nd_label;
+	struct cxl_region_label *rg_label;
+	struct nd_namespace_index *nsindex;
+	struct nd_label_ent *label_ent;
+	unsigned long *free;
+	u32 nslot, slot;
+	size_t offset;
+	int rc;
+	uuid_t tmp;
+
+	if (!preamble_next(ndd, &nsindex, &free, &nslot))
+		return -ENXIO;
+
+	/* allocate and write the label to the staging (next) index */
+	slot = nd_label_alloc_slot(ndd);
+	if (slot == UINT_MAX)
+		return -ENXIO;
+	dev_dbg(ndd->dev, "allocated: %d\n", slot);
+
+	nd_label = to_label(ndd, slot);
+
+	memset(nd_label, 0, sizeof_namespace_label(ndd));
+	rg_label = &nd_label->rg_label;
+
+	/* Set Region Label Format identification UUID */
+	uuid_parse(CXL_REGION_UUID, &tmp);
+	export_uuid(nd_label->rg_label.type, &tmp);
+
+	/* Set Current Region Label UUID */
+	export_uuid(nd_label->rg_label.uuid, &nd_set->uuid);
+
+	rg_label->flags = __cpu_to_le32(flags);
+	rg_label->nlabel = __cpu_to_le16(nd_region->ndr_mappings);
+	rg_label->position = __cpu_to_le16(pos);
+	rg_label->dpa = __cpu_to_le64(nd_mapping->start);
+	rg_label->rawsize = __cpu_to_le64(nd_mapping->size);
+	rg_label->hpa = __cpu_to_le64(nd_set->res->start);
+	rg_label->slot = __cpu_to_le32(slot);
+	rg_label->ig = __cpu_to_le32(nd_set->interleave_granularity);
+	rg_label->align = __cpu_to_le16(0);
+
+	/* Update fletcher64 Checksum */
+	rgl_calculate_checksum(ndd, rg_label);
+
+	/* update label */
+	offset = nd_label_offset(ndd, nd_label);
+	rc = nvdimm_set_config_data(ndd, offset, nd_label,
+			sizeof_namespace_label(ndd));
+	if (rc < 0) {
+		nd_label_free_slot(ndd, slot);
+		return rc;
+	}
+
+	/* Garbage collect the previous label */
+	guard(mutex)(&nd_mapping->lock);
+	list_for_each_entry(label_ent, &nd_mapping->labels, list) {
+		if (!label_ent->label)
+			continue;
+		if (rgl_uuid_equal(&label_ent->label->rg_label, &nd_set->uuid))
+			reap_victim(nd_mapping, label_ent);
+	}
+
+	/* update index */
+	rc = nd_label_write_index(ndd, ndd->ns_next,
+			nd_inc_seq(__le32_to_cpu(nsindex->seq)), 0);
+	if (rc)
+		return rc;
+
+	list_for_each_entry(label_ent, &nd_mapping->labels, list)
+		if (!label_ent->label) {
+			label_ent->label = nd_label;
+			nd_label = NULL;
+			break;
+		}
+	dev_WARN_ONCE(&nd_region->dev, nd_label,
+			"failed to track label: %d\n",
+			to_slot(ndd, nd_label));
+	if (nd_label)
+		rc = -ENXIO;
+
+	return rc;
+}
+
+int nd_pmem_region_label_update(struct nd_region *nd_region)
+{
+	int i, rc;
+
+	for (i = 0; i < nd_region->ndr_mappings; i++) {
+		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
+		struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
+
+		/* No need to update region label for non cxl format */
+		if (!ndd->cxl)
+			continue;
+
+		/* Init labels to include region label */
+		rc = init_labels(nd_mapping, 1);
+
+		if (rc < 0)
+			return rc;
+
+		rc = __pmem_region_label_update(nd_region, nd_mapping, i,
+					NSLABEL_FLAG_UPDATING);
+
+		if (rc)
+			return rc;
+	}
+
+	/* Clear the UPDATING flag per UEFI 2.7 expectations */
+	for (i = 0; i < nd_region->ndr_mappings; i++) {
+		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
+		struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
+
+		/* No need to update region label for non cxl format */
+		if (!ndd->cxl)
+			continue;
+
+		rc = __pmem_region_label_update(nd_region, nd_mapping, i, 0);
+
+		if (rc)
+			return rc;
+	}
+
+	return 0;
+}
+
 int __init nd_label_init(void)
 {
 	WARN_ON(guid_parse(NVDIMM_BTT_GUID, &nvdimm_btt_guid));
diff --git a/drivers/nvdimm/label.h b/drivers/nvdimm/label.h
index 4883b3a1320f..0f428695017d 100644
--- a/drivers/nvdimm/label.h
+++ b/drivers/nvdimm/label.h
@@ -190,6 +190,7 @@ struct nd_namespace_label {
 struct nd_lsa_label {
 	union {
 		struct nd_namespace_label ns_label;
+		struct cxl_region_label rg_label;
 	};
 };
 
@@ -233,4 +234,5 @@ struct nd_region;
 struct nd_namespace_pmem;
 int nd_pmem_namespace_label_update(struct nd_region *nd_region,
 		struct nd_namespace_pmem *nspm, resource_size_t size);
+int nd_pmem_region_label_update(struct nd_region *nd_region);
 #endif /* __LABEL_H__ */
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index 5b73119dc8fd..02ae8162566c 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -232,6 +232,18 @@ static ssize_t __alt_name_store(struct device *dev, const char *buf,
 	return rc;
 }
 
+int nd_region_label_update(struct nd_region *nd_region)
+{
+	int rc;
+
+	nvdimm_bus_lock(&nd_region->dev);
+	rc = nd_pmem_region_label_update(nd_region);
+	nvdimm_bus_unlock(&nd_region->dev);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(nd_region_label_update);
+
 static int nd_namespace_label_update(struct nd_region *nd_region,
 		struct device *dev)
 {
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 651847f1bbf9..15d94e3937f0 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -322,6 +322,26 @@ static inline void nsl_set_region_uuid(struct nvdimm_drvdata *ndd,
 		export_uuid(ns_label->cxl.region_uuid, uuid);
 }
 
+static inline bool rgl_uuid_equal(struct cxl_region_label *rg_label,
+				  const uuid_t *uuid)
+{
+	uuid_t tmp;
+
+	import_uuid(&tmp, rg_label->uuid);
+	return uuid_equal(&tmp, uuid);
+}
+
+static inline u64 rgl_get_checksum(struct cxl_region_label *rg_label)
+{
+	return __le64_to_cpu(rg_label->checksum);
+}
+
+static inline void rgl_set_checksum(struct cxl_region_label *rg_label,
+				    u64 checksum)
+{
+	rg_label->checksum = __cpu_to_le64(checksum);
+}
+
 bool nsl_validate_type_guid(struct nvdimm_drvdata *ndd,
 			    struct nd_namespace_label *nd_label, guid_t *guid);
 enum nvdimm_claim_class nsl_get_claim_class(struct nvdimm_drvdata *ndd,
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index 0a55900842c8..b06bd45373f4 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -115,6 +115,13 @@ struct nd_interleave_set {
 	u64 altcookie;
 
 	guid_t type_guid;
+
+	/* v2.1 region label info */
+	uuid_t uuid;
+	int interleave_ways;
+	int interleave_granularity;
+	struct resource *res;
+	int nr_targets;
 };
 
 struct nd_mapping_desc {
@@ -302,6 +309,7 @@ int nvdimm_has_flush(struct nd_region *nd_region);
 int nvdimm_has_cache(struct nd_region *nd_region);
 int nvdimm_in_overwrite(struct nvdimm *nvdimm);
 bool is_nvdimm_sync(struct nd_region *nd_region);
+int nd_region_label_update(struct nd_region *nd_region);
 
 static inline int nvdimm_ctl(struct nvdimm *nvdimm, unsigned int cmd, void *buf,
 		unsigned int buf_len, int *cmd_rc)
-- 
2.34.1


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

* [PATCH V2 06/20] nvdimm/region_label: Add region label deletion routine
       [not found]   ` <CGME20250730121230epcas5p11650f090de55d0a2db541ee32e9a6fee@epcas5p1.samsung.com>
@ 2025-07-30 12:11     ` Neeraj Kumar
  2025-08-13 14:53       ` Jonathan Cameron
  2025-08-15 22:22       ` Dave Jiang
  0 siblings, 2 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:11 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

Added cxl v2.1 format region label deletion routine. This function is
used to delete region label from LSA

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 drivers/nvdimm/label.c          | 77 ++++++++++++++++++++++++++++++---
 drivers/nvdimm/label.h          |  6 +++
 drivers/nvdimm/namespace_devs.c | 12 +++++
 drivers/nvdimm/nd.h             |  9 ++++
 include/linux/libnvdimm.h       |  1 +
 5 files changed, 100 insertions(+), 5 deletions(-)

diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
index 94f2d0ba7aca..be18278d6cea 100644
--- a/drivers/nvdimm/label.c
+++ b/drivers/nvdimm/label.c
@@ -1044,7 +1044,8 @@ static int init_labels(struct nd_mapping *nd_mapping, int num_labels)
 	return max(num_labels, old_num_labels);
 }
 
-static int del_labels(struct nd_mapping *nd_mapping, uuid_t *uuid)
+static int del_labels(struct nd_mapping *nd_mapping, uuid_t *uuid,
+		enum label_type ltype)
 {
 	struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
 	struct nd_label_ent *label_ent, *e;
@@ -1068,8 +1069,23 @@ static int del_labels(struct nd_mapping *nd_mapping, uuid_t *uuid)
 		if (!nd_label)
 			continue;
 		active++;
-		if (!nsl_uuid_equal(ndd, &nd_label->ns_label, uuid))
-			continue;
+
+		switch (ltype) {
+		case NS_LABEL_TYPE:
+			if (!nsl_uuid_equal(ndd, &nd_label->ns_label, uuid))
+				continue;
+
+			break;
+		case RG_LABEL_TYPE:
+			if (!rgl_uuid_equal(&nd_label->rg_label, uuid))
+				continue;
+
+			break;
+		default:
+			dev_err(ndd->dev, "Invalid label type\n");
+			return 0;
+		}
+
 		active--;
 		slot = to_slot(ndd, nd_label);
 		nd_label_free_slot(ndd, slot);
@@ -1079,7 +1095,7 @@ static int del_labels(struct nd_mapping *nd_mapping, uuid_t *uuid)
 	}
 	list_splice_tail_init(&list, &nd_mapping->labels);
 
-	if (active == 0) {
+	if ((ltype == NS_LABEL_TYPE) && (active == 0)) {
 		nd_mapping_free_labels(nd_mapping);
 		dev_dbg(ndd->dev, "no more active labels\n");
 	}
@@ -1101,7 +1117,8 @@ int nd_pmem_namespace_label_update(struct nd_region *nd_region,
 		int count = 0;
 
 		if (size == 0) {
-			rc = del_labels(nd_mapping, nspm->uuid);
+			rc = del_labels(nd_mapping, nspm->uuid,
+					NS_LABEL_TYPE);
 			if (rc)
 				return rc;
 			continue;
@@ -1268,6 +1285,56 @@ int nd_pmem_region_label_update(struct nd_region *nd_region)
 	return 0;
 }
 
+int nd_pmem_region_label_delete(struct nd_region *nd_region)
+{
+	int i, rc;
+	struct nd_interleave_set *nd_set = nd_region->nd_set;
+	struct nd_label_ent *label_ent;
+	int ns_region_cnt = 0;
+
+	for (i = 0; i < nd_region->ndr_mappings; i++) {
+		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
+		struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
+
+		/* Find non cxl format supported ndr_mappings */
+		if (!ndd->cxl) {
+			dev_info(&nd_region->dev, "Region label unsupported\n");
+			return -EINVAL;
+		}
+
+		/* Find if any NS label using this region */
+		mutex_lock(&nd_mapping->lock);
+		list_for_each_entry(label_ent, &nd_mapping->labels, list) {
+			if (!label_ent->label)
+				continue;
+
+			/*
+			 * Check if any available NS labels has same
+			 * region_uuid in LSA
+			 */
+			if (nsl_region_uuid_equal(&label_ent->label->ns_label,
+						  &nd_set->uuid))
+				ns_region_cnt++;
+		}
+		mutex_unlock(&nd_mapping->lock);
+	}
+
+	if (ns_region_cnt) {
+		dev_dbg(&nd_region->dev, "Region/Namespace label in use\n");
+		return -EBUSY;
+	}
+
+	for (i = 0; i < nd_region->ndr_mappings; i++) {
+		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
+
+		rc = del_labels(nd_mapping, &nd_set->uuid, RG_LABEL_TYPE);
+		if (rc)
+			return rc;
+	}
+
+	return 0;
+}
+
 int __init nd_label_init(void)
 {
 	WARN_ON(guid_parse(NVDIMM_BTT_GUID, &nvdimm_btt_guid));
diff --git a/drivers/nvdimm/label.h b/drivers/nvdimm/label.h
index 0f428695017d..cc14068511cf 100644
--- a/drivers/nvdimm/label.h
+++ b/drivers/nvdimm/label.h
@@ -30,6 +30,11 @@ enum {
 	ND_NSINDEX_INIT = 0x1,
 };
 
+enum label_type {
+	RG_LABEL_TYPE,
+	NS_LABEL_TYPE,
+};
+
 /**
  * struct nd_namespace_index - label set superblock
  * @sig: NAMESPACE_INDEX\0
@@ -235,4 +240,5 @@ struct nd_namespace_pmem;
 int nd_pmem_namespace_label_update(struct nd_region *nd_region,
 		struct nd_namespace_pmem *nspm, resource_size_t size);
 int nd_pmem_region_label_update(struct nd_region *nd_region);
+int nd_pmem_region_label_delete(struct nd_region *nd_region);
 #endif /* __LABEL_H__ */
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index 02ae8162566c..e5c2f78ca7dd 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -244,6 +244,18 @@ int nd_region_label_update(struct nd_region *nd_region)
 }
 EXPORT_SYMBOL_GPL(nd_region_label_update);
 
+int nd_region_label_delete(struct nd_region *nd_region)
+{
+	int rc;
+
+	nvdimm_bus_lock(&nd_region->dev);
+	rc = nd_pmem_region_label_delete(nd_region);
+	nvdimm_bus_unlock(&nd_region->dev);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(nd_region_label_delete);
+
 static int nd_namespace_label_update(struct nd_region *nd_region,
 		struct device *dev)
 {
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 15d94e3937f0..6585747154c2 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -322,6 +322,15 @@ static inline void nsl_set_region_uuid(struct nvdimm_drvdata *ndd,
 		export_uuid(ns_label->cxl.region_uuid, uuid);
 }
 
+static inline bool nsl_region_uuid_equal(struct nd_namespace_label *ns_label,
+				  const uuid_t *uuid)
+{
+	uuid_t tmp;
+
+	import_uuid(&tmp, ns_label->cxl.region_uuid);
+	return uuid_equal(&tmp, uuid);
+}
+
 static inline bool rgl_uuid_equal(struct cxl_region_label *rg_label,
 				  const uuid_t *uuid)
 {
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index b06bd45373f4..b2e16914ab52 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -310,6 +310,7 @@ int nvdimm_has_cache(struct nd_region *nd_region);
 int nvdimm_in_overwrite(struct nvdimm *nvdimm);
 bool is_nvdimm_sync(struct nd_region *nd_region);
 int nd_region_label_update(struct nd_region *nd_region);
+int nd_region_label_delete(struct nd_region *nd_region);
 
 static inline int nvdimm_ctl(struct nvdimm *nvdimm, unsigned int cmd, void *buf,
 		unsigned int buf_len, int *cmd_rc)
-- 
2.34.1


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

* [PATCH V2 07/20] nvdimm/namespace_label: Update namespace init_labels and its region_uuid
       [not found]   ` <CGME20250730121231epcas5p2c12cb2b4914279d1f1c93e56a32c3908@epcas5p2.samsung.com>
@ 2025-07-30 12:11     ` Neeraj Kumar
  2025-08-13 14:58       ` Jonathan Cameron
  2025-08-19 18:56       ` Ira Weiny
  0 siblings, 2 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:11 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

nd_mapping->labels maintains the list of labels present into LSA.
init_labels() prepares this list while adding new label into LSA
and updates nd_mapping->labels accordingly. During cxl region
creation nd_mapping->labels list and LSA was updated with one
region label. Therefore during new namespace label creation
pre-include the previously created region label, so increase
num_labels count by 1.

Also updated nsl_set_region_uuid with region uuid with which
namespace is associated with.

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 drivers/nvdimm/label.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
index be18278d6cea..fd02b557612e 100644
--- a/drivers/nvdimm/label.c
+++ b/drivers/nvdimm/label.c
@@ -957,7 +957,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
 	nsl_set_slot(ndd, nd_label, slot);
 	nsl_set_alignment(ndd, nd_label, 0);
 	nsl_set_type_guid(ndd, nd_label, &nd_set->type_guid);
-	nsl_set_region_uuid(ndd, nd_label, NULL);
+	nsl_set_region_uuid(ndd, nd_label, &nd_set->uuid);
 	nsl_set_claim_class(ndd, nd_label, ndns->claim_class);
 	nsl_calculate_checksum(ndd, nd_label);
 	nd_dbg_dpa(nd_region, ndd, res, "\n");
@@ -1129,7 +1129,8 @@ int nd_pmem_namespace_label_update(struct nd_region *nd_region,
 				count++;
 		WARN_ON_ONCE(!count);
 
-		rc = init_labels(nd_mapping, count);
+		/* Adding 1 to pre include the already added region label */
+		rc = init_labels(nd_mapping, count + 1);
 		if (rc < 0)
 			return rc;
 
-- 
2.34.1


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

* [PATCH V2 08/20] nvdimm/label: Include region label in slot validation
       [not found]   ` <CGME20250730121232epcas5p4cd632fe09d1bc51499d9e3ac3c2633b3@epcas5p4.samsung.com>
@ 2025-07-30 12:11     ` Neeraj Kumar
  2025-08-13 15:07       ` Jonathan Cameron
  0 siblings, 1 reply; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:11 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

slot validation routine validates label slot by calculating label
checksum. It was only validating namespace label. This changeset also
validates region label if present.

Also validate and calculate lsa v2.1 namespace label checksum

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 drivers/nvdimm/label.c | 55 ++++++++++++++++++++++++++++++++++--------
 drivers/nvdimm/nd.h    | 19 +++++++++++++++
 2 files changed, 64 insertions(+), 10 deletions(-)

diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
index fd02b557612e..c4748e30f2b6 100644
--- a/drivers/nvdimm/label.c
+++ b/drivers/nvdimm/label.c
@@ -359,7 +359,7 @@ static bool nsl_validate_checksum(struct nvdimm_drvdata *ndd,
 {
 	u64 sum, sum_save;
 
-	if (!ndd->cxl && !efi_namespace_label_has(ndd, checksum))
+	if (!efi_namespace_label_has(ndd, checksum))
 		return true;
 
 	sum_save = nsl_get_checksum(ndd, nd_label);
@@ -374,13 +374,25 @@ static void nsl_calculate_checksum(struct nvdimm_drvdata *ndd,
 {
 	u64 sum;
 
-	if (!ndd->cxl && !efi_namespace_label_has(ndd, checksum))
+	if (!efi_namespace_label_has(ndd, checksum))
 		return;
 	nsl_set_checksum(ndd, nd_label, 0);
 	sum = nd_fletcher64(nd_label, sizeof_namespace_label(ndd), 1);
 	nsl_set_checksum(ndd, nd_label, sum);
 }
 
+static bool rgl_validate_checksum(struct nvdimm_drvdata *ndd,
+				  struct cxl_region_label *rg_label)
+{
+	u64 sum, sum_save;
+
+	sum_save = rgl_get_checksum(rg_label);
+	rgl_set_checksum(rg_label, 0);
+	sum = nd_fletcher64(rg_label, sizeof_namespace_label(ndd), 1);
+	rgl_set_checksum(rg_label, sum_save);
+	return sum == sum_save;
+}
+
 static void rgl_calculate_checksum(struct nvdimm_drvdata *ndd,
 				   struct cxl_region_label *rg_label)
 {
@@ -395,14 +407,27 @@ static bool slot_valid(struct nvdimm_drvdata *ndd,
 		struct nd_lsa_label *lsa_label, u32 slot)
 {
 	bool valid;
+	char *label_name;
 	struct nd_namespace_label *nd_label = &lsa_label->ns_label;
+	struct cxl_region_label *rg_label = &lsa_label->rg_label;
 
 	/* check that we are written where we expect to be written */
-	if (slot != nsl_get_slot(ndd, nd_label))
-		return false;
-	valid = nsl_validate_checksum(ndd, nd_label);
+	if (is_region_label(ndd, lsa_label)) {
+		label_name = "rg";
+		if (slot != rgl_get_slot(rg_label))
+			return false;
+		valid = rgl_validate_checksum(ndd, rg_label);
+	} else {
+		label_name = "ns";
+		if (slot != nsl_get_slot(ndd, nd_label))
+			return false;
+		valid = nsl_validate_checksum(ndd, nd_label);
+	}
+
 	if (!valid)
-		dev_dbg(ndd->dev, "fail checksum. slot: %d\n", slot);
+		dev_dbg(ndd->dev, "%s label checksum fail. slot: %d\n",
+			label_name, slot);
+
 	return valid;
 }
 
@@ -580,18 +605,28 @@ int nd_label_active_count(struct nvdimm_drvdata *ndd)
 	for_each_clear_bit_le(slot, free, nslot) {
 		struct nd_lsa_label *lsa_label;
 		struct nd_namespace_label *nd_label;
+		struct cxl_region_label *rg_label;
+		u32 lslot;
+		u64 size, dpa;
 
 		lsa_label = to_label(ndd, slot);
 		nd_label = &lsa_label->ns_label;
+		rg_label = &lsa_label->rg_label;
 
 		if (!slot_valid(ndd, lsa_label, slot)) {
-			u32 label_slot = nsl_get_slot(ndd, nd_label);
-			u64 size = nsl_get_rawsize(ndd, nd_label);
-			u64 dpa = nsl_get_dpa(ndd, nd_label);
+			if (is_region_label(ndd, lsa_label)) {
+				lslot = __le32_to_cpu(rg_label->slot);
+				size = __le64_to_cpu(rg_label->rawsize);
+				dpa = __cpu_to_le64(rg_label->dpa);
+			} else {
+				lslot = nsl_get_slot(ndd, nd_label);
+				size = nsl_get_rawsize(ndd, nd_label);
+				dpa = nsl_get_dpa(ndd, nd_label);
+			}
 
 			dev_dbg(ndd->dev,
 				"slot%d invalid slot: %d dpa: %llx size: %llx\n",
-					slot, label_slot, dpa, size);
+					slot, lslot, dpa, size);
 			continue;
 		}
 		count++;
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 6585747154c2..4145c7df2a8f 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -331,6 +331,20 @@ static inline bool nsl_region_uuid_equal(struct nd_namespace_label *ns_label,
 	return uuid_equal(&tmp, uuid);
 }
 
+static inline bool is_region_label(struct nvdimm_drvdata *ndd,
+				   struct nd_lsa_label *nd_label)
+{
+	uuid_t ns_type, region_type;
+
+	if (!ndd->cxl)
+		return false;
+
+	uuid_parse(CXL_REGION_UUID, &region_type);
+	import_uuid(&ns_type, nd_label->ns_label.cxl.type);
+	return uuid_equal(&region_type, &ns_type);
+
+}
+
 static inline bool rgl_uuid_equal(struct cxl_region_label *rg_label,
 				  const uuid_t *uuid)
 {
@@ -340,6 +354,11 @@ static inline bool rgl_uuid_equal(struct cxl_region_label *rg_label,
 	return uuid_equal(&tmp, uuid);
 }
 
+static inline u32 rgl_get_slot(struct cxl_region_label *rg_label)
+{
+	return __le32_to_cpu(rg_label->slot);
+}
+
 static inline u64 rgl_get_checksum(struct cxl_region_label *rg_label)
 {
 	return __le64_to_cpu(rg_label->checksum);
-- 
2.34.1


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

* [PATCH V2 09/20] nvdimm/namespace_label: Skip region label during ns label DPA reservation
       [not found]   ` <CGME20250730121234epcas5p2605fbec7bc95f6096550792844b8f8ee@epcas5p2.samsung.com>
@ 2025-07-30 12:11     ` Neeraj Kumar
  2025-08-13 15:09       ` Jonathan Cameron
  0 siblings, 1 reply; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:11 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

If Namespace label is present in LSA during nvdimm_probe then DPA
reservation is required. But this reservation is not required by region
label. Therefore if LSA scanning finds any region label, skip it.

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 drivers/nvdimm/label.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
index c4748e30f2b6..064a945dcdd1 100644
--- a/drivers/nvdimm/label.c
+++ b/drivers/nvdimm/label.c
@@ -452,6 +452,10 @@ int nd_label_reserve_dpa(struct nvdimm_drvdata *ndd)
 		lsa_label = to_label(ndd, slot);
 		nd_label = &lsa_label->ns_label;
 
+		/* skip region label, dpa reservation for ns label only */
+		if (is_region_label(ndd, lsa_label))
+			continue;
+
 		if (!slot_valid(ndd, lsa_label, slot))
 			continue;
 
-- 
2.34.1


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

* [PATCH V2 10/20] nvdimm/region_label: Preserve cxl region information from region label
       [not found]   ` <CGME20250730121235epcas5p4494147524e77e99bc16d9b510e8971a4@epcas5p4.samsung.com>
@ 2025-07-30 12:11     ` Neeraj Kumar
  2025-08-13 15:11       ` Jonathan Cameron
  0 siblings, 1 reply; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:11 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

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 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 064a945dcdd1..bcac05371f87 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 *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 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 4145c7df2a8f..f78c8fc1de8a 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -598,6 +598,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


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

* [PATCH V2 11/20] nvdimm/region_label: Export routine to fetch region information
       [not found]   ` <CGME20250730121236epcas5p4b8939ed1bfff468c965a9dbd6bc261b6@epcas5p4.samsung.com>
@ 2025-07-30 12:12     ` Neeraj Kumar
  2025-08-13 15:13       ` Jonathan Cameron
  0 siblings, 1 reply; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:12 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

cxl region information preserved from LSA need to be exported so as to
use by cxl driver for cxl region re-creation

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 drivers/nvdimm/dimm_devs.c | 18 ++++++++++++++++++
 include/linux/libnvdimm.h  |  2 ++
 2 files changed, 20 insertions(+)

diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index 6149770c1b27..dece150580c4 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -280,6 +280,24 @@ void *nvdimm_provider_data(struct nvdimm *nvdimm)
 }
 EXPORT_SYMBOL_GPL(nvdimm_provider_data);
 
+bool nvdimm_has_cxl_region(struct nvdimm *nvdimm)
+{
+	if (nvdimm)
+		return nvdimm->is_region_label;
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(nvdimm_has_cxl_region);
+
+void *nvdimm_get_cxl_region_param(struct nvdimm *nvdimm)
+{
+	if (nvdimm)
+		return &nvdimm->cxl_region_params;
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(nvdimm_get_cxl_region_param);
+
 static ssize_t commands_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index cdabb43a8a7f..9a5d17c4b89b 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -325,6 +325,8 @@ int nvdimm_in_overwrite(struct nvdimm *nvdimm);
 bool is_nvdimm_sync(struct nd_region *nd_region);
 int nd_region_label_update(struct nd_region *nd_region);
 int nd_region_label_delete(struct nd_region *nd_region);
+bool nvdimm_has_cxl_region(struct nvdimm *nvdimm);
+void *nvdimm_get_cxl_region_param(struct nvdimm *nvdimm);
 
 static inline int nvdimm_ctl(struct nvdimm *nvdimm, unsigned int cmd, void *buf,
 		unsigned int buf_len, int *cmd_rc)
-- 
2.34.1


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

* [PATCH V2 12/20] nvdimm/namespace_label: Skip region label during namespace creation
       [not found]   ` <CGME20250730121238epcas5p212dcce5cc5713173913ee154d5098a2c@epcas5p2.samsung.com>
@ 2025-07-30 12:12     ` Neeraj Kumar
  2025-08-13 15:55       ` Jonathan Cameron
  0 siblings, 1 reply; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:12 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

During namespace creation skip presence of region label if present.
Also preserve region label into labels list if present.

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 drivers/nvdimm/namespace_devs.c | 50 +++++++++++++++++++++++++++++----
 1 file changed, 45 insertions(+), 5 deletions(-)

diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index e5c2f78ca7dd..8edd26407939 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -1985,6 +1985,10 @@ static struct device **scan_labels(struct nd_region *nd_region)
 		if (!lsa_label)
 			continue;
 
+		/* skip region labels if present */
+		if (is_region_label(ndd, lsa_label))
+			continue;
+
 		nd_label = &lsa_label->ns_label;
 
 		/* skip labels that describe extents outside of the region */
@@ -2025,9 +2029,30 @@ static struct device **scan_labels(struct nd_region *nd_region)
 
 	if (count == 0) {
 		struct nd_namespace_pmem *nspm;
+		for (i = 0; i < nd_region->ndr_mappings; i++) {
+			struct nd_label_ent *le, *e;
+			LIST_HEAD(list);
 
-		/* Publish a zero-sized namespace for userspace to configure. */
-		nd_mapping_free_labels(nd_mapping);
+			nd_mapping = &nd_region->mapping[i];
+			if (list_empty(&nd_mapping->labels))
+				continue;
+
+			list_for_each_entry_safe(le, e, &nd_mapping->labels,
+						 list) {
+				struct nd_lsa_label *nd_label = le->label;
+
+				/* preserve region labels if present */
+				if (is_region_label(ndd, nd_label))
+					list_move_tail(&le->list, &list);
+			}
+
+			/*
+			 * Publish a zero-sized namespace for userspace
+			 * to configure.
+			 */
+			nd_mapping_free_labels(nd_mapping);
+			list_splice_init(&list, &nd_mapping->labels);
+		}
 		nspm = kzalloc(sizeof(*nspm), GFP_KERNEL);
 		if (!nspm)
 			goto err;
@@ -2039,7 +2064,7 @@ static struct device **scan_labels(struct nd_region *nd_region)
 	} else if (is_memory(&nd_region->dev)) {
 		/* clean unselected labels */
 		for (i = 0; i < nd_region->ndr_mappings; i++) {
-			struct list_head *l, *e;
+			struct nd_label_ent *le, *e;
 			LIST_HEAD(list);
 			int j;
 
@@ -2050,10 +2075,25 @@ static struct device **scan_labels(struct nd_region *nd_region)
 			}
 
 			j = count;
-			list_for_each_safe(l, e, &nd_mapping->labels) {
+			list_for_each_entry_safe(le, e, &nd_mapping->labels,
+						 list) {
+				struct nd_lsa_label *nd_label = le->label;
+
+				/* preserve region labels */
+				if (is_region_label(ndd, nd_label)) {
+					list_move_tail(&le->list, &list);
+					continue;
+				}
+
+				/*
+				 * Once preserving selected ns label done
+				 * break out of loop
+				 */
 				if (!j--)
 					break;
-				list_move_tail(l, &list);
+
+				/* preserve selected ns label */
+				list_move_tail(&le->list, &list);
 			}
 			nd_mapping_free_labels(nd_mapping);
 			list_splice_init(&list, &nd_mapping->labels);
-- 
2.34.1


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

* [PATCH V2 13/20] cxl/mem: Refactor cxl pmem region auto-assembling
       [not found]   ` <CGME20250730121239epcas5p37956b2999f61e17e8dbfbde7972cef35@epcas5p3.samsung.com>
@ 2025-07-30 12:12     ` Neeraj Kumar
  2025-08-20 16:41       ` Dave Jiang
  0 siblings, 1 reply; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:12 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

In 84ec985944ef3, devm_cxl_add_nvdimm() sequence was changed and called
before devm_cxl_add_endpoint(). It's because cxl pmem region auto-assembly
used to get called at last in cxl_endpoint_port_probe(), which requires
cxl_nvd presence.

For cxl region persistency, region creation happens during nvdimm_probe
which need the completion of endpoint probe.

In order to accommodate both cxl pmem region auto-assembly and cxl region
persistency, refactored following

1. Re-Sequence devm_cxl_add_nvdimm() after devm_cxl_add_endpoint(). This
   will be called only after successful completion of endpoint probe.

2. Moved cxl pmem region auto-assembly from cxl_endpoint_port_probe() to
   cxl_mem_probe() after devm_cxl_add_nvdimm(). It gurantees both the
   completion of endpoint probe and cxl_nvd presence before its call.

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 drivers/cxl/core/region.c | 33 +++++++++++++++++++++++++++++++++
 drivers/cxl/cxl.h         |  4 ++++
 drivers/cxl/mem.c         | 24 +++++++++++++++---------
 drivers/cxl/port.c        | 39 +--------------------------------------
 4 files changed, 53 insertions(+), 47 deletions(-)

diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index e9bf42d91689..eef501f3384c 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -3497,6 +3497,39 @@ int cxl_add_to_region(struct cxl_endpoint_decoder *cxled)
 }
 EXPORT_SYMBOL_NS_GPL(cxl_add_to_region, "CXL");
 
+static int discover_region(struct device *dev, void *unused)
+{
+	struct cxl_endpoint_decoder *cxled;
+	int rc;
+
+	if (!is_endpoint_decoder(dev))
+		return 0;
+
+	cxled = to_cxl_endpoint_decoder(dev);
+	if ((cxled->cxld.flags & CXL_DECODER_F_ENABLE) == 0)
+		return 0;
+
+	if (cxled->state != CXL_DECODER_STATE_AUTO)
+		return 0;
+
+	/*
+	 * Region enumeration is opportunistic, if this add-event fails,
+	 * continue to the next endpoint decoder.
+	 */
+	rc = cxl_add_to_region(cxled);
+	if (rc)
+		dev_dbg(dev, "failed to add to region: %#llx-%#llx\n",
+			cxled->cxld.hpa_range.start, cxled->cxld.hpa_range.end);
+
+	return 0;
+}
+
+void cxl_region_discovery(struct cxl_port *port)
+{
+	device_for_each_child(&port->dev, NULL, discover_region);
+}
+EXPORT_SYMBOL_NS_GPL(cxl_region_discovery, "CXL");
+
 u64 cxl_port_get_spa_cache_alias(struct cxl_port *endpoint, u64 spa)
 {
 	struct cxl_region_ref *iter;
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index b7111e3568d0..6edcec95e9ba 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -864,6 +864,7 @@ struct cxl_pmem_region *to_cxl_pmem_region(struct device *dev);
 int cxl_add_to_region(struct cxl_endpoint_decoder *cxled);
 struct cxl_dax_region *to_cxl_dax_region(struct device *dev);
 u64 cxl_port_get_spa_cache_alias(struct cxl_port *endpoint, u64 spa);
+void cxl_region_discovery(struct cxl_port *port);
 #else
 static inline bool is_cxl_pmem_region(struct device *dev)
 {
@@ -886,6 +887,9 @@ static inline u64 cxl_port_get_spa_cache_alias(struct cxl_port *endpoint,
 {
 	return 0;
 }
+static inline void cxl_region_discovery(struct cxl_port *port)
+{
+}
 #endif
 
 void cxl_endpoint_parse_cdat(struct cxl_port *port);
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index 6e6777b7bafb..54501616ff09 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -152,15 +152,6 @@ static int cxl_mem_probe(struct device *dev)
 		return -ENXIO;
 	}
 
-	if (cxl_pmem_size(cxlds) && IS_ENABLED(CONFIG_CXL_PMEM)) {
-		rc = devm_cxl_add_nvdimm(parent_port, cxlmd);
-		if (rc) {
-			if (rc == -ENODEV)
-				dev_info(dev, "PMEM disabled by platform\n");
-			return rc;
-		}
-	}
-
 	if (dport->rch)
 		endpoint_parent = parent_port->uport_dev;
 	else
@@ -184,6 +175,21 @@ static int cxl_mem_probe(struct device *dev)
 	if (rc)
 		dev_dbg(dev, "CXL memdev EDAC registration failed rc=%d\n", rc);
 
+	if (cxl_pmem_size(cxlds) && IS_ENABLED(CONFIG_CXL_PMEM)) {
+		rc = devm_cxl_add_nvdimm(parent_port, cxlmd);
+		if (rc) {
+			if (rc == -ENODEV)
+				dev_info(dev, "PMEM disabled by platform\n");
+			return rc;
+		}
+	}
+
+	/*
+	 * Now that all endpoint decoders are successfully enumerated, try to
+	 * assemble region autodiscovery from committed decoders.
+	 */
+	cxl_region_discovery(cxlmd->endpoint);
+
 	/*
 	 * The kernel may be operating out of CXL memory on this device,
 	 * there is no spec defined way to determine whether this device
diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c
index fe4b593331da..090ae3577f32 100644
--- a/drivers/cxl/port.c
+++ b/drivers/cxl/port.c
@@ -30,33 +30,6 @@ static void schedule_detach(void *cxlmd)
 	schedule_cxl_memdev_detach(cxlmd);
 }
 
-static int discover_region(struct device *dev, void *unused)
-{
-	struct cxl_endpoint_decoder *cxled;
-	int rc;
-
-	if (!is_endpoint_decoder(dev))
-		return 0;
-
-	cxled = to_cxl_endpoint_decoder(dev);
-	if ((cxled->cxld.flags & CXL_DECODER_F_ENABLE) == 0)
-		return 0;
-
-	if (cxled->state != CXL_DECODER_STATE_AUTO)
-		return 0;
-
-	/*
-	 * Region enumeration is opportunistic, if this add-event fails,
-	 * continue to the next endpoint decoder.
-	 */
-	rc = cxl_add_to_region(cxled);
-	if (rc)
-		dev_dbg(dev, "failed to add to region: %#llx-%#llx\n",
-			cxled->cxld.hpa_range.start, cxled->cxld.hpa_range.end);
-
-	return 0;
-}
-
 static int cxl_switch_port_probe(struct cxl_port *port)
 {
 	struct cxl_hdm *cxlhdm;
@@ -121,17 +94,7 @@ static int cxl_endpoint_port_probe(struct cxl_port *port)
 	if (rc)
 		return rc;
 
-	rc = devm_cxl_enumerate_decoders(cxlhdm, &info);
-	if (rc)
-		return rc;
-
-	/*
-	 * Now that all endpoint decoders are successfully enumerated, try to
-	 * assemble regions from committed decoders
-	 */
-	device_for_each_child(&port->dev, NULL, discover_region);
-
-	return 0;
+	return devm_cxl_enumerate_decoders(cxlhdm, &info);
 }
 
 static int cxl_port_probe(struct device *dev)
-- 
2.34.1


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

* [PATCH V2 14/20] cxl/region: Add devm_cxl_pmem_add_region() for pmem region creation
       [not found]   ` <CGME20250730121241epcas5p3e5708a89d764d1de9322fd759f921de0@epcas5p3.samsung.com>
@ 2025-07-30 12:12     ` Neeraj Kumar
  2025-08-20  0:30       ` Dave Jiang
  0 siblings, 1 reply; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:12 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

devm_cxl_pmem_add_region() is used to create cxl region based on region
information scanned from LSA.

devm_cxl_add_region() is used to just allocate cxlr and its fields are
filled later by userspace tool using device attributes (*_store()).

Inspiration for devm_cxl_pmem_add_region() is taken from these device
attributes (_store*) calls. It allocates cxlr and fills information
parsed from LSA and calls device_add(&cxlr->dev) to initiate further
region creation porbes

Renamed __create_region() to cxl_create_region() and make it an exported
routine. This will be used in later patch to create cxl region after
fetching region information from LSA.

Also created some helper routines and refactored dpa_size_store(),
commit_store() to avoid duplicate code usage in devm_cxl_pmem_add_region()

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 drivers/cxl/core/core.h   |   1 +
 drivers/cxl/core/port.c   |  29 ++++++----
 drivers/cxl/core/region.c | 118 +++++++++++++++++++++++++++++++++-----
 drivers/cxl/cxl.h         |  12 ++++
 4 files changed, 134 insertions(+), 26 deletions(-)

diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
index 2669f251d677..80c83e0117c6 100644
--- a/drivers/cxl/core/core.h
+++ b/drivers/cxl/core/core.h
@@ -94,6 +94,7 @@ int cxl_dpa_free(struct cxl_endpoint_decoder *cxled);
 resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled);
 resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled);
 bool cxl_resource_contains_addr(const struct resource *res, const resource_size_t addr);
+ssize_t resize_or_free_dpa(struct cxl_endpoint_decoder *cxled, u64 size);
 
 enum cxl_rcrb {
 	CXL_RCRB_DOWNSTREAM,
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index 29197376b18e..ba743e31f721 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -243,16 +243,9 @@ static ssize_t dpa_size_show(struct device *dev, struct device_attribute *attr,
 	return sysfs_emit(buf, "%pa\n", &size);
 }
 
-static ssize_t dpa_size_store(struct device *dev, struct device_attribute *attr,
-			      const char *buf, size_t len)
+ssize_t resize_or_free_dpa(struct cxl_endpoint_decoder *cxled, u64 size)
 {
-	struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(dev);
-	unsigned long long size;
-	ssize_t rc;
-
-	rc = kstrtoull(buf, 0, &size);
-	if (rc)
-		return rc;
+	int rc;
 
 	if (!IS_ALIGNED(size, SZ_256M))
 		return -EINVAL;
@@ -262,9 +255,23 @@ static ssize_t dpa_size_store(struct device *dev, struct device_attribute *attr,
 		return rc;
 
 	if (size == 0)
-		return len;
+		return 0;
+
+	return cxl_dpa_alloc(cxled, size);
+}
+
+static ssize_t dpa_size_store(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t len)
+{
+	struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(dev);
+	unsigned long long size;
+	ssize_t rc;
+
+	rc = kstrtoull(buf, 0, &size);
+	if (rc)
+		return rc;
 
-	rc = cxl_dpa_alloc(cxled, size);
+	rc = resize_or_free_dpa(cxled, size);
 	if (rc)
 		return rc;
 
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index eef501f3384c..8578e046aa78 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -703,6 +703,23 @@ static int free_hpa(struct cxl_region *cxlr)
 	return 0;
 }
 
+static ssize_t resize_or_free_region_hpa(struct cxl_region *cxlr, u64 size)
+{
+	int rc;
+
+	ACQUIRE(rwsem_write_kill, rwsem)(&cxl_rwsem.region);
+	rc = ACQUIRE_ERR(rwsem_write_kill, &rwsem);
+	if (rc)
+		return rc;
+
+	if (size)
+		rc = alloc_hpa(cxlr, size);
+	else
+		rc = free_hpa(cxlr);
+
+	return rc;
+}
+
 static ssize_t size_store(struct device *dev, struct device_attribute *attr,
 			  const char *buf, size_t len)
 {
@@ -714,15 +731,7 @@ static ssize_t size_store(struct device *dev, struct device_attribute *attr,
 	if (rc)
 		return rc;
 
-	ACQUIRE(rwsem_write_kill, rwsem)(&cxl_rwsem.region);
-	if ((rc = ACQUIRE_ERR(rwsem_write_kill, &rwsem)))
-		return rc;
-
-	if (val)
-		rc = alloc_hpa(cxlr, val);
-	else
-		rc = free_hpa(cxlr);
-
+	rc = resize_or_free_region_hpa(cxlr, val);
 	if (rc)
 		return rc;
 
@@ -2569,6 +2578,76 @@ static struct cxl_region *devm_cxl_add_region(struct cxl_root_decoder *cxlrd,
 	return ERR_PTR(rc);
 }
 
+static struct cxl_region *
+devm_cxl_pmem_add_region(struct cxl_root_decoder *cxlrd,
+			 int id,
+			 enum cxl_partition_mode mode,
+			 enum cxl_decoder_type type,
+			 struct cxl_pmem_region_params *params,
+			 struct cxl_decoder *cxld)
+{
+	struct cxl_port *root_port;
+	struct cxl_region *cxlr;
+	struct cxl_endpoint_decoder *cxled;
+	struct cxl_region_params *p;
+	struct device *dev;
+	int rc;
+
+	cxlr = cxl_region_alloc(cxlrd, id);
+	if (IS_ERR(cxlr))
+		return cxlr;
+	cxlr->mode = mode;
+	cxlr->type = type;
+
+	dev = &cxlr->dev;
+	rc = dev_set_name(dev, "region%d", id);
+	if (rc)
+		goto err;
+
+	p = &cxlr->params;
+	p->uuid = params->uuid;
+	p->interleave_ways = params->nlabel;
+	p->interleave_granularity = params->ig;
+
+	if (resize_or_free_region_hpa(cxlr, params->rawsize))
+		goto err;
+
+	cxled = to_cxl_endpoint_decoder(&cxld->dev);
+	if (resize_or_free_dpa(cxled, 0))
+		goto err;
+
+	if (cxl_dpa_set_part(cxled, CXL_PARTMODE_PMEM))
+		goto err;
+
+	if (resize_or_free_dpa(cxled, params->rawsize))
+		goto err;
+
+	/* Attaching only one target due to interleave_way == 1 */
+	if (attach_target(cxlr, cxled, params->position, TASK_INTERRUPTIBLE))
+		goto err;
+
+	if (__commit(cxlr))
+		goto err;
+
+	rc = device_add(dev);
+	if (rc)
+		goto err;
+
+	root_port = to_cxl_port(cxlrd->cxlsd.cxld.dev.parent);
+	rc = devm_add_action_or_reset(root_port->uport_dev,
+			unregister_region, cxlr);
+	if (rc)
+		return ERR_PTR(rc);
+
+	dev_dbg(root_port->uport_dev, "%s: created %s\n",
+		dev_name(&cxlrd->cxlsd.cxld.dev), dev_name(dev));
+	return cxlr;
+
+err:
+	put_device(dev);
+	return ERR_PTR(rc);
+}
+
 static ssize_t __create_region_show(struct cxl_root_decoder *cxlrd, char *buf)
 {
 	return sysfs_emit(buf, "region%u\n", atomic_read(&cxlrd->region_id));
@@ -2586,8 +2665,10 @@ static ssize_t create_ram_region_show(struct device *dev,
 	return __create_region_show(to_cxl_root_decoder(dev), buf);
 }
 
-static struct cxl_region *__create_region(struct cxl_root_decoder *cxlrd,
-					  enum cxl_partition_mode mode, int id)
+struct cxl_region *cxl_create_region(struct cxl_root_decoder *cxlrd,
+				     enum cxl_partition_mode mode, int id,
+				     struct cxl_pmem_region_params *params,
+				     struct cxl_decoder *cxld)
 {
 	int rc;
 
@@ -2609,8 +2690,14 @@ static struct cxl_region *__create_region(struct cxl_root_decoder *cxlrd,
 		return ERR_PTR(-EBUSY);
 	}
 
-	return devm_cxl_add_region(cxlrd, id, mode, CXL_DECODER_HOSTONLYMEM);
+	if (params)
+		return devm_cxl_pmem_add_region(cxlrd, id, mode,
+				CXL_DECODER_HOSTONLYMEM, params, cxld);
+	else
+		return devm_cxl_add_region(cxlrd, id, mode,
+				CXL_DECODER_HOSTONLYMEM);
 }
+EXPORT_SYMBOL_NS_GPL(cxl_create_region, "CXL");
 
 static ssize_t create_region_store(struct device *dev, const char *buf,
 				   size_t len, enum cxl_partition_mode mode)
@@ -2623,7 +2710,7 @@ static ssize_t create_region_store(struct device *dev, const char *buf,
 	if (rc != 1)
 		return -EINVAL;
 
-	cxlr = __create_region(cxlrd, mode, id);
+	cxlr = cxl_create_region(cxlrd, mode, id, NULL, NULL);
 	if (IS_ERR(cxlr))
 		return PTR_ERR(cxlr);
 
@@ -3414,8 +3501,9 @@ static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd,
 	struct cxl_region *cxlr;
 
 	do {
-		cxlr = __create_region(cxlrd, cxlds->part[part].mode,
-				       atomic_read(&cxlrd->region_id));
+		cxlr = cxl_create_region(cxlrd, cxlds->part[part].mode,
+					 atomic_read(&cxlrd->region_id),
+					 NULL, NULL);
 	} while (IS_ERR(cxlr) && PTR_ERR(cxlr) == -EBUSY);
 
 	if (IS_ERR(cxlr)) {
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index 6edcec95e9ba..129db2e49aa7 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -865,6 +865,10 @@ int cxl_add_to_region(struct cxl_endpoint_decoder *cxled);
 struct cxl_dax_region *to_cxl_dax_region(struct device *dev);
 u64 cxl_port_get_spa_cache_alias(struct cxl_port *endpoint, u64 spa);
 void cxl_region_discovery(struct cxl_port *port);
+struct cxl_region *cxl_create_region(struct cxl_root_decoder *cxlrd,
+				     enum cxl_partition_mode mode, int id,
+				     struct cxl_pmem_region_params *params,
+				     struct cxl_decoder *cxld);
 #else
 static inline bool is_cxl_pmem_region(struct device *dev)
 {
@@ -890,6 +894,14 @@ static inline u64 cxl_port_get_spa_cache_alias(struct cxl_port *endpoint,
 static inline void cxl_region_discovery(struct cxl_port *port)
 {
 }
+static inline struct cxl_region *
+cxl_create_region(struct cxl_root_decoder *cxlrd,
+		  enum cxl_partition_mode mode, int id,
+		  struct cxl_pmem_region_params *params,
+		  struct cxl_decoder *cxld)
+{
+	return NULL;
+}
 #endif
 
 void cxl_endpoint_parse_cdat(struct cxl_port *port);
-- 
2.34.1


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

* [PATCH V2 15/20] cxl: Add a routine to find cxl root decoder on cxl bus using cxl port
       [not found]   ` <CGME20250730121242epcas5p4bdfc11e82e28d525364262fb2b6d8feb@epcas5p4.samsung.com>
@ 2025-07-30 12:12     ` Neeraj Kumar
  0 siblings, 0 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:12 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

Add cxl_find_root_decoder_by_port() to find root decoder on cxl bus.
It is used to find root decoder using cxl port.

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 drivers/cxl/core/port.c | 27 +++++++++++++++++++++++++++
 drivers/cxl/cxl.h       |  1 +
 2 files changed, 28 insertions(+)

diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index ba743e31f721..c1bb0e0286ed 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -524,6 +524,33 @@ struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev)
 }
 EXPORT_SYMBOL_NS_GPL(to_cxl_switch_decoder, "CXL");
 
+static int match_root_decoder(struct device *dev, const void *data)
+{
+	return is_root_decoder(dev);
+}
+
+/**
+ * cxl_find_root_decoder_by_port() - find a cxl root decoder on cxl bus
+ * @port: any descendant port in CXL port topology
+ */
+struct cxl_root_decoder *cxl_find_root_decoder_by_port(struct cxl_port *port)
+{
+	struct cxl_root *cxl_root __free(put_cxl_root) = find_cxl_root(port);
+	struct device *dev;
+
+	if (!cxl_root)
+		return NULL;
+
+	dev = device_find_child(&cxl_root->port.dev, NULL, match_root_decoder);
+	if (!dev)
+		return NULL;
+
+	/* Release device ref taken via device_find_child() */
+	put_device(dev);
+	return to_cxl_root_decoder(dev);
+}
+EXPORT_SYMBOL_NS_GPL(cxl_find_root_decoder_by_port, "CXL");
+
 static void cxl_ep_release(struct cxl_ep *ep)
 {
 	put_device(ep->ep);
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index 129db2e49aa7..e249372b642d 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -857,6 +857,7 @@ struct cxl_nvdimm *to_cxl_nvdimm(struct device *dev);
 bool is_cxl_nvdimm(struct device *dev);
 int devm_cxl_add_nvdimm(struct cxl_port *parent_port, struct cxl_memdev *cxlmd);
 struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_port *port);
+struct cxl_root_decoder *cxl_find_root_decoder_by_port(struct cxl_port *port);
 
 #ifdef CONFIG_CXL_REGION
 bool is_cxl_pmem_region(struct device *dev);
-- 
2.34.1


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

* [PATCH V2 16/20] cxl/mem: Preserve cxl root decoder during mem probe
       [not found]   ` <CGME20250730121243epcas5p4c40126a3cf5c8019b36eb8287c3ec2c8@epcas5p4.samsung.com>
@ 2025-07-30 12:12     ` Neeraj Kumar
  0 siblings, 0 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:12 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

Saved root decoder info is required for cxl region persistency

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 drivers/cxl/cxlmem.h | 1 +
 drivers/cxl/mem.c    | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index 751478dfc410..72dfcf4671f2 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -59,6 +59,7 @@ struct cxl_memdev {
 	struct cxl_nvdimm_bridge *cxl_nvb;
 	struct cxl_nvdimm *cxl_nvd;
 	struct cxl_port *endpoint;
+	struct cxl_root_decoder *cxlrd;
 	int id;
 	int depth;
 	u8 scrub_cycle;
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index 54501616ff09..1a0da7253a24 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -152,6 +152,8 @@ static int cxl_mem_probe(struct device *dev)
 		return -ENXIO;
 	}
 
+	cxlmd->cxlrd = cxl_find_root_decoder_by_port(parent_port);
+
 	if (dport->rch)
 		endpoint_parent = parent_port->uport_dev;
 	else
-- 
2.34.1


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

* [PATCH V2 17/20] cxl/pmem: Preserve region information into nd_set
       [not found]   ` <CGME20250730121245epcas5p247b6675350f4f7e70e9b3c8465340e84@epcas5p2.samsung.com>
@ 2025-07-30 12:12     ` Neeraj Kumar
  0 siblings, 0 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:12 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

Save region information stored in cxlr to nd_set during
cxl_pmem_region_probe in nd_set. This saved region information is being
stored into LSA, which will be used for cxl region persistence

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 drivers/cxl/pmem.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c
index e197883690ef..38a5bcdc68ce 100644
--- a/drivers/cxl/pmem.c
+++ b/drivers/cxl/pmem.c
@@ -377,6 +377,7 @@ static int cxl_pmem_region_probe(struct device *dev)
 	struct nd_mapping_desc mappings[CXL_DECODER_MAX_INTERLEAVE];
 	struct cxl_pmem_region *cxlr_pmem = to_cxl_pmem_region(dev);
 	struct cxl_region *cxlr = cxlr_pmem->cxlr;
+	struct cxl_region_params *p = &cxlr->params;
 	struct cxl_nvdimm_bridge *cxl_nvb = cxlr->cxl_nvb;
 	struct cxl_pmem_region_info *info = NULL;
 	struct nd_interleave_set *nd_set;
@@ -465,12 +466,12 @@ static int cxl_pmem_region_probe(struct device *dev)
 	ndr_desc.num_mappings = cxlr_pmem->nr_mappings;
 	ndr_desc.mapping = mappings;
 
-	/*
-	 * TODO enable CXL labels which skip the need for 'interleave-set cookie'
-	 */
-	nd_set->cookie1 =
-		nd_fletcher64(info, sizeof(*info) * cxlr_pmem->nr_mappings, 0);
-	nd_set->cookie2 = nd_set->cookie1;
+	nd_set->uuid = p->uuid;
+	nd_set->interleave_ways = p->interleave_ways;
+	nd_set->interleave_granularity = p->interleave_granularity;
+	nd_set->res = p->res;
+	nd_set->nr_targets =  p->nr_targets;
+
 	ndr_desc.nd_set = nd_set;
 
 	cxlr_pmem->nd_region =
-- 
2.34.1


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

* [PATCH V2 18/20] cxl/pmem: Add support of cxl lsa 2.1 support in cxl pmem
       [not found]   ` <CGME20250730121246epcas5p48a2fd8e653f05a0282cbffc1f702f26f@epcas5p4.samsung.com>
@ 2025-07-30 12:12     ` Neeraj Kumar
  2025-07-31  1:36       ` kernel test robot
  0 siblings, 1 reply; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:12 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

Add support of cxl lsa 2.1 using NDD_CXL_LABEL flag. It also creates cxl
region based on region information parsed from LSA.

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 drivers/cxl/core/region.c | 58 +++++++++++++++++++++++++++++++++++++++
 drivers/cxl/cxl.h         |  4 +++
 drivers/cxl/pmem.c        |  2 ++
 3 files changed, 64 insertions(+)

diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index 8578e046aa78..19ccdd136da0 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -2665,6 +2665,64 @@ static ssize_t create_ram_region_show(struct device *dev,
 	return __create_region_show(to_cxl_root_decoder(dev), buf);
 }
 
+static int match_free_ep_decoder(struct device *dev, const void *data)
+{
+	struct cxl_decoder *cxld = to_cxl_decoder(dev);
+
+	return !cxld->region;
+}
+
+static struct cxl_decoder *cxl_find_free_ep_decoder(struct cxl_port *port)
+{
+	struct device *dev;
+
+	dev = device_find_child(&port->dev, NULL, match_free_ep_decoder);
+	if (!dev)
+		return NULL;
+
+	/* Release device ref taken via device_find_child() */
+	put_device(dev);
+	return to_cxl_decoder(dev);
+}
+
+void create_pmem_region(struct nvdimm *nvdimm)
+{
+	struct cxl_nvdimm *cxl_nvd;
+	struct cxl_memdev *cxlmd;
+	struct cxl_nvdimm_bridge *cxl_nvb;
+	struct cxl_pmem_region_params *params;
+	struct cxl_root_decoder *cxlrd;
+	struct cxl_decoder *cxld;
+	struct cxl_region *cxlr;
+
+	if (!nvdimm_has_cxl_region(nvdimm))
+		return;
+
+	lockdep_assert_held(&cxl_rwsem.region);
+	cxl_nvd = nvdimm_provider_data(nvdimm);
+	params = nvdimm_get_cxl_region_param(nvdimm);
+	cxlmd = cxl_nvd->cxlmd;
+	cxl_nvb = cxlmd->cxl_nvb;
+	cxlrd = cxlmd->cxlrd;
+
+	/*
+	 * FIXME: Limitation: Region creation support only for
+	 * interleave way == 1
+	 */
+	if (!(params->nlabel == 1))
+		dev_info(&cxlmd->dev,
+			 "Region Creation is not supported with iw > 1\n");
+	else {
+		cxld = cxl_find_free_ep_decoder(cxlmd->endpoint);
+		cxlr = cxl_create_region(cxlrd, CXL_PARTMODE_PMEM,
+					 atomic_read(&cxlrd->region_id),
+					 params, cxld);
+		if (IS_ERR(cxlr))
+			dev_info(&cxlmd->dev, "Region Creation failed\n");
+	}
+}
+EXPORT_SYMBOL_NS_GPL(create_pmem_region, "CXL");
+
 struct cxl_region *cxl_create_region(struct cxl_root_decoder *cxlrd,
 				     enum cxl_partition_mode mode, int id,
 				     struct cxl_pmem_region_params *params,
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index e249372b642d..51c56069f451 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -870,6 +870,7 @@ struct cxl_region *cxl_create_region(struct cxl_root_decoder *cxlrd,
 				     enum cxl_partition_mode mode, int id,
 				     struct cxl_pmem_region_params *params,
 				     struct cxl_decoder *cxld);
+void create_pmem_region(struct nvdimm *nvdimm);
 #else
 static inline bool is_cxl_pmem_region(struct device *dev)
 {
@@ -903,6 +904,9 @@ cxl_create_region(struct cxl_root_decoder *cxlrd,
 {
 	return NULL;
 }
+static inline void create_pmem_region(struct nvdimm *nvdimm)
+{
+}
 #endif
 
 void cxl_endpoint_parse_cdat(struct cxl_port *port);
diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c
index 38a5bcdc68ce..4a7428a5a82c 100644
--- a/drivers/cxl/pmem.c
+++ b/drivers/cxl/pmem.c
@@ -135,6 +135,7 @@ static int cxl_nvdimm_probe(struct device *dev)
 		return rc;
 
 	set_bit(NDD_LABELING, &flags);
+	set_bit(NDD_CXL_LABEL, &flags);
 	set_bit(NDD_REGISTER_SYNC, &flags);
 	set_bit(ND_CMD_GET_CONFIG_SIZE, &cmd_mask);
 	set_bit(ND_CMD_GET_CONFIG_DATA, &cmd_mask);
@@ -155,6 +156,7 @@ static int cxl_nvdimm_probe(struct device *dev)
 		return -ENOMEM;
 
 	dev_set_drvdata(dev, nvdimm);
+	create_pmem_region(nvdimm);
 	return devm_add_action_or_reset(dev, unregister_nvdimm, nvdimm);
 }
 
-- 
2.34.1


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

* [PATCH V2 19/20] cxl/pmem_region: Prep patch to accommodate pmem_region attributes
       [not found]   ` <CGME20250730121247epcas5p425b79da65bcb003917cbf02fc047a7db@epcas5p4.samsung.com>
@ 2025-07-30 12:12     ` Neeraj Kumar
  2025-07-31  1:57       ` kernel test robot
  2025-07-31  2:17       ` kernel test robot
  0 siblings, 2 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:12 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

Created a separate file core/pmem_region.c along with CONFIG_PMEM_REGION
Moved pmem_region related code from core/region.c to core/pmem_region.c
For region label update, need to create device attribute, which calls
nvdimm exported function thus making pmem_region dependent on libnvdimm.
Because of this dependency of pmem region on libnvdimm, segregated pmem
region related code from core/region.c

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 drivers/cxl/Kconfig            |  12 ++
 drivers/cxl/core/Makefile      |   1 +
 drivers/cxl/core/core.h        |   8 +-
 drivers/cxl/core/pmem_region.c | 202 +++++++++++++++++++++++++++++++++
 drivers/cxl/core/port.c        |   2 +-
 drivers/cxl/core/region.c      | 191 +------------------------------
 drivers/cxl/cxl.h              |  34 ++++--
 tools/testing/cxl/Kbuild       |   1 +
 8 files changed, 251 insertions(+), 200 deletions(-)
 create mode 100644 drivers/cxl/core/pmem_region.c

diff --git a/drivers/cxl/Kconfig b/drivers/cxl/Kconfig
index 48b7314afdb8..33d9fceb5975 100644
--- a/drivers/cxl/Kconfig
+++ b/drivers/cxl/Kconfig
@@ -211,6 +211,18 @@ config CXL_REGION
 
 	  If unsure say 'y'
 
+config CXL_PMEM_REGION
+	bool "CXL: Pmem Region Support"
+	default CXL_BUS
+	depends on CXL_REGION
+	select LIBNVDIMM
+	help
+	  Enable the CXL core to enumerate and provision CXL pmem regions.
+	  A CXL pmem region need to update region label into LSA. For LSA
+	  updation/deletion libnvdimm is required.
+
+	  If unsure say 'y'
+
 config CXL_REGION_INVALIDATION_TEST
 	bool "CXL: Region Cache Management Bypass (TEST)"
 	depends on CXL_REGION
diff --git a/drivers/cxl/core/Makefile b/drivers/cxl/core/Makefile
index 5ad8fef210b5..399157beb917 100644
--- a/drivers/cxl/core/Makefile
+++ b/drivers/cxl/core/Makefile
@@ -17,6 +17,7 @@ cxl_core-y += cdat.o
 cxl_core-y += ras.o
 cxl_core-$(CONFIG_TRACING) += trace.o
 cxl_core-$(CONFIG_CXL_REGION) += region.o
+cxl_core-$(CONFIG_CXL_PMEM_REGION) += pmem_region.o
 cxl_core-$(CONFIG_CXL_MCE) += mce.o
 cxl_core-$(CONFIG_CXL_FEATURES) += features.o
 cxl_core-$(CONFIG_CXL_EDAC_MEM_FEATURES) += edac.o
diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
index 80c83e0117c6..e3869c3d53bf 100644
--- a/drivers/cxl/core/core.h
+++ b/drivers/cxl/core/core.h
@@ -34,7 +34,6 @@ int cxl_decoder_detach(struct cxl_region *cxlr,
 #define CXL_REGION_ATTR(x) (&dev_attr_##x.attr)
 #define CXL_REGION_TYPE(x) (&cxl_region_type)
 #define SET_CXL_REGION_ATTR(x) (&dev_attr_##x.attr),
-#define CXL_PMEM_REGION_TYPE(x) (&cxl_pmem_region_type)
 #define CXL_DAX_REGION_TYPE(x) (&cxl_dax_region_type)
 int cxl_region_init(void);
 void cxl_region_exit(void);
@@ -74,10 +73,15 @@ static inline void cxl_region_exit(void)
 #define CXL_REGION_ATTR(x) NULL
 #define CXL_REGION_TYPE(x) NULL
 #define SET_CXL_REGION_ATTR(x)
-#define CXL_PMEM_REGION_TYPE(x) NULL
 #define CXL_DAX_REGION_TYPE(x) NULL
 #endif
 
+#ifdef CONFIG_CXL_PMEM_REGION
+#define CXL_PMEM_REGION_TYPE (&cxl_pmem_region_type)
+#else
+#define CXL_PMEM_REGION_TYPE NULL
+#endif
+
 struct cxl_send_command;
 struct cxl_mem_query_commands;
 int cxl_query_cmd(struct cxl_mailbox *cxl_mbox,
diff --git a/drivers/cxl/core/pmem_region.c b/drivers/cxl/core/pmem_region.c
new file mode 100644
index 000000000000..cd1177d345e6
--- /dev/null
+++ b/drivers/cxl/core/pmem_region.c
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2020 Intel Corporation. */
+#include <linux/device.h>
+#include <linux/memregion.h>
+#include <cxlmem.h>
+#include <cxl.h>
+#include "core.h"
+
+/**
+ * DOC: cxl pmem region
+ *
+ * The core CXL PMEM region infrastructure supports persistent memory
+ * region creation using LIBNVDIMM subsystem. It has dependency on
+ * LIBNVDIMM, pmem region need updation of cxl region information into
+ * LSA. LIBNVDIMM dependency is only for pmem region, it is therefore
+ * need this separate file.
+ */
+
+bool is_cxl_pmem_region(struct device *dev)
+{
+	return dev->type == &cxl_pmem_region_type;
+}
+EXPORT_SYMBOL_NS_GPL(is_cxl_pmem_region, "CXL");
+
+struct cxl_pmem_region *to_cxl_pmem_region(struct device *dev)
+{
+	if (dev_WARN_ONCE(dev, !is_cxl_pmem_region(dev),
+			  "not a cxl_pmem_region device\n"))
+		return NULL;
+	return container_of(dev, struct cxl_pmem_region, dev);
+}
+EXPORT_SYMBOL_NS_GPL(to_cxl_pmem_region, "CXL");
+
+static void cxl_pmem_region_release(struct device *dev)
+{
+	struct cxl_pmem_region *cxlr_pmem = to_cxl_pmem_region(dev);
+	int i;
+
+	for (i = 0; i < cxlr_pmem->nr_mappings; i++) {
+		struct cxl_memdev *cxlmd = cxlr_pmem->mapping[i].cxlmd;
+
+		put_device(&cxlmd->dev);
+	}
+
+	kfree(cxlr_pmem);
+}
+
+static const struct attribute_group *cxl_pmem_region_attribute_groups[] = {
+	&cxl_base_attribute_group,
+	NULL,
+};
+
+const struct device_type cxl_pmem_region_type = {
+	.name = "cxl_pmem_region",
+	.release = cxl_pmem_region_release,
+	.groups = cxl_pmem_region_attribute_groups,
+};
+
+static struct lock_class_key cxl_pmem_region_key;
+
+static int cxl_pmem_region_alloc(struct cxl_region *cxlr)
+{
+	struct cxl_region_params *p = &cxlr->params;
+	struct cxl_nvdimm_bridge *cxl_nvb;
+	struct device *dev;
+	int i;
+
+	guard(rwsem_read)(&cxl_rwsem.region);
+	if (p->state != CXL_CONFIG_COMMIT)
+		return -ENXIO;
+
+	struct cxl_pmem_region *cxlr_pmem __free(kfree) =
+		kzalloc(struct_size(cxlr_pmem, mapping, p->nr_targets), GFP_KERNEL);
+	if (!cxlr_pmem)
+		return -ENOMEM;
+
+	cxlr_pmem->hpa_range.start = p->res->start;
+	cxlr_pmem->hpa_range.end = p->res->end;
+
+	/* Snapshot the region configuration underneath the cxl_region_rwsem */
+	cxlr_pmem->nr_mappings = p->nr_targets;
+	for (i = 0; i < p->nr_targets; i++) {
+		struct cxl_endpoint_decoder *cxled = p->targets[i];
+		struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
+		struct cxl_pmem_region_mapping *m = &cxlr_pmem->mapping[i];
+
+		/*
+		 * Regions never span CXL root devices, so by definition the
+		 * bridge for one device is the same for all.
+		 */
+		if (i == 0) {
+			cxl_nvb = cxl_find_nvdimm_bridge(cxlmd->endpoint);
+			if (!cxl_nvb)
+				return -ENODEV;
+			cxlr->cxl_nvb = cxl_nvb;
+		}
+		m->cxlmd = cxlmd;
+		get_device(&cxlmd->dev);
+		m->start = cxled->dpa_res->start;
+		m->size = resource_size(cxled->dpa_res);
+		m->position = i;
+	}
+
+	dev = &cxlr_pmem->dev;
+	device_initialize(dev);
+	lockdep_set_class(&dev->mutex, &cxl_pmem_region_key);
+	device_set_pm_not_required(dev);
+	dev->parent = &cxlr->dev;
+	dev->bus = &cxl_bus_type;
+	dev->type = &cxl_pmem_region_type;
+	cxlr_pmem->cxlr = cxlr;
+	cxlr->cxlr_pmem = no_free_ptr(cxlr_pmem);
+
+	return 0;
+}
+
+static void cxlr_pmem_unregister(void *_cxlr_pmem)
+{
+	struct cxl_pmem_region *cxlr_pmem = _cxlr_pmem;
+	struct cxl_region *cxlr = cxlr_pmem->cxlr;
+	struct cxl_nvdimm_bridge *cxl_nvb = cxlr->cxl_nvb;
+
+	/*
+	 * Either the bridge is in ->remove() context under the device_lock(),
+	 * or cxlr_release_nvdimm() is cancelling the bridge's release action
+	 * for @cxlr_pmem and doing it itself (while manually holding the bridge
+	 * lock).
+	 */
+	device_lock_assert(&cxl_nvb->dev);
+	cxlr->cxlr_pmem = NULL;
+	cxlr_pmem->cxlr = NULL;
+	device_unregister(&cxlr_pmem->dev);
+}
+
+static void cxlr_release_nvdimm(void *_cxlr)
+{
+	struct cxl_region *cxlr = _cxlr;
+	struct cxl_nvdimm_bridge *cxl_nvb = cxlr->cxl_nvb;
+
+	scoped_guard(device, &cxl_nvb->dev) {
+		if (cxlr->cxlr_pmem)
+			devm_release_action(&cxl_nvb->dev, cxlr_pmem_unregister,
+					    cxlr->cxlr_pmem);
+	}
+	cxlr->cxl_nvb = NULL;
+	put_device(&cxl_nvb->dev);
+}
+
+/**
+ * devm_cxl_add_pmem_region() - add a cxl_region-to-nd_region bridge
+ * @cxlr: parent CXL region for this pmem region bridge device
+ *
+ * Return: 0 on success negative error code on failure.
+ */
+int devm_cxl_add_pmem_region(struct cxl_region *cxlr)
+{
+	struct cxl_pmem_region *cxlr_pmem;
+	struct cxl_nvdimm_bridge *cxl_nvb;
+	struct device *dev;
+	int rc;
+
+	rc = cxl_pmem_region_alloc(cxlr);
+	if (rc)
+		return rc;
+	cxlr_pmem = cxlr->cxlr_pmem;
+	cxl_nvb = cxlr->cxl_nvb;
+
+	dev = &cxlr_pmem->dev;
+	rc = dev_set_name(dev, "pmem_region%d", cxlr->id);
+	if (rc)
+		goto err;
+
+	rc = device_add(dev);
+	if (rc)
+		goto err;
+
+	dev_dbg(&cxlr->dev, "%s: register %s\n", dev_name(dev->parent),
+		dev_name(dev));
+
+	scoped_guard(device, &cxl_nvb->dev) {
+		if (cxl_nvb->dev.driver)
+			rc = devm_add_action_or_reset(&cxl_nvb->dev,
+						      cxlr_pmem_unregister,
+						      cxlr_pmem);
+		else
+			rc = -ENXIO;
+	}
+
+	if (rc)
+		goto err_bridge;
+
+	/* @cxlr carries a reference on @cxl_nvb until cxlr_release_nvdimm */
+	return devm_add_action_or_reset(&cxlr->dev, cxlr_release_nvdimm, cxlr);
+
+err:
+	put_device(dev);
+err_bridge:
+	put_device(&cxl_nvb->dev);
+	cxlr->cxl_nvb = NULL;
+	return rc;
+}
+EXPORT_SYMBOL_NS_GPL(devm_cxl_add_pmem_region, "CXL");
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index c1bb0e0286ed..11ddf7ed8357 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -53,7 +53,7 @@ static int cxl_device_id(const struct device *dev)
 		return CXL_DEVICE_NVDIMM_BRIDGE;
 	if (dev->type == &cxl_nvdimm_type)
 		return CXL_DEVICE_NVDIMM;
-	if (dev->type == CXL_PMEM_REGION_TYPE())
+	if (dev->type == CXL_PMEM_REGION_TYPE)
 		return CXL_DEVICE_PMEM_REGION;
 	if (dev->type == CXL_DAX_REGION_TYPE())
 		return CXL_DEVICE_DAX_REGION;
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index 19ccdd136da0..f064e031c28a 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -30,8 +30,6 @@
  * 3. Decoder targets
  */
 
-static struct cxl_region *to_cxl_region(struct device *dev);
-
 #define __ACCESS_ATTR_RO(_level, _name) {				\
 	.attr	= { .name = __stringify(_name), .mode = 0444 },		\
 	.show	= _name##_access##_level##_show,			\
@@ -2385,7 +2383,7 @@ bool is_cxl_region(struct device *dev)
 }
 EXPORT_SYMBOL_NS_GPL(is_cxl_region, "CXL");
 
-static struct cxl_region *to_cxl_region(struct device *dev)
+struct cxl_region *to_cxl_region(struct device *dev)
 {
 	if (dev_WARN_ONCE(dev, dev->type != &cxl_region_type,
 			  "not a cxl_region device\n"))
@@ -2393,6 +2391,7 @@ static struct cxl_region *to_cxl_region(struct device *dev)
 
 	return container_of(dev, struct cxl_region, dev);
 }
+EXPORT_SYMBOL_NS_GPL(to_cxl_region, "CXL");
 
 static void unregister_region(void *_cxlr)
 {
@@ -2839,46 +2838,6 @@ static ssize_t delete_region_store(struct device *dev,
 }
 DEVICE_ATTR_WO(delete_region);
 
-static void cxl_pmem_region_release(struct device *dev)
-{
-	struct cxl_pmem_region *cxlr_pmem = to_cxl_pmem_region(dev);
-	int i;
-
-	for (i = 0; i < cxlr_pmem->nr_mappings; i++) {
-		struct cxl_memdev *cxlmd = cxlr_pmem->mapping[i].cxlmd;
-
-		put_device(&cxlmd->dev);
-	}
-
-	kfree(cxlr_pmem);
-}
-
-static const struct attribute_group *cxl_pmem_region_attribute_groups[] = {
-	&cxl_base_attribute_group,
-	NULL,
-};
-
-const struct device_type cxl_pmem_region_type = {
-	.name = "cxl_pmem_region",
-	.release = cxl_pmem_region_release,
-	.groups = cxl_pmem_region_attribute_groups,
-};
-
-bool is_cxl_pmem_region(struct device *dev)
-{
-	return dev->type == &cxl_pmem_region_type;
-}
-EXPORT_SYMBOL_NS_GPL(is_cxl_pmem_region, "CXL");
-
-struct cxl_pmem_region *to_cxl_pmem_region(struct device *dev)
-{
-	if (dev_WARN_ONCE(dev, !is_cxl_pmem_region(dev),
-			  "not a cxl_pmem_region device\n"))
-		return NULL;
-	return container_of(dev, struct cxl_pmem_region, dev);
-}
-EXPORT_SYMBOL_NS_GPL(to_cxl_pmem_region, "CXL");
-
 struct cxl_poison_context {
 	struct cxl_port *port;
 	int part;
@@ -3133,64 +3092,6 @@ u64 cxl_dpa_to_hpa(struct cxl_region *cxlr, const struct cxl_memdev *cxlmd,
 	return hpa;
 }
 
-static struct lock_class_key cxl_pmem_region_key;
-
-static int cxl_pmem_region_alloc(struct cxl_region *cxlr)
-{
-	struct cxl_region_params *p = &cxlr->params;
-	struct cxl_nvdimm_bridge *cxl_nvb;
-	struct device *dev;
-	int i;
-
-	guard(rwsem_read)(&cxl_rwsem.region);
-	if (p->state != CXL_CONFIG_COMMIT)
-		return -ENXIO;
-
-	struct cxl_pmem_region *cxlr_pmem __free(kfree) =
-		kzalloc(struct_size(cxlr_pmem, mapping, p->nr_targets), GFP_KERNEL);
-	if (!cxlr_pmem)
-		return -ENOMEM;
-
-	cxlr_pmem->hpa_range.start = p->res->start;
-	cxlr_pmem->hpa_range.end = p->res->end;
-
-	/* Snapshot the region configuration underneath the cxl_rwsem.region */
-	cxlr_pmem->nr_mappings = p->nr_targets;
-	for (i = 0; i < p->nr_targets; i++) {
-		struct cxl_endpoint_decoder *cxled = p->targets[i];
-		struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
-		struct cxl_pmem_region_mapping *m = &cxlr_pmem->mapping[i];
-
-		/*
-		 * Regions never span CXL root devices, so by definition the
-		 * bridge for one device is the same for all.
-		 */
-		if (i == 0) {
-			cxl_nvb = cxl_find_nvdimm_bridge(cxlmd->endpoint);
-			if (!cxl_nvb)
-				return -ENODEV;
-			cxlr->cxl_nvb = cxl_nvb;
-		}
-		m->cxlmd = cxlmd;
-		get_device(&cxlmd->dev);
-		m->start = cxled->dpa_res->start;
-		m->size = resource_size(cxled->dpa_res);
-		m->position = i;
-	}
-
-	dev = &cxlr_pmem->dev;
-	device_initialize(dev);
-	lockdep_set_class(&dev->mutex, &cxl_pmem_region_key);
-	device_set_pm_not_required(dev);
-	dev->parent = &cxlr->dev;
-	dev->bus = &cxl_bus_type;
-	dev->type = &cxl_pmem_region_type;
-	cxlr_pmem->cxlr = cxlr;
-	cxlr->cxlr_pmem = no_free_ptr(cxlr_pmem);
-
-	return 0;
-}
-
 static void cxl_dax_region_release(struct device *dev)
 {
 	struct cxl_dax_region *cxlr_dax = to_cxl_dax_region(dev);
@@ -3254,92 +3155,6 @@ static struct cxl_dax_region *cxl_dax_region_alloc(struct cxl_region *cxlr)
 	return cxlr_dax;
 }
 
-static void cxlr_pmem_unregister(void *_cxlr_pmem)
-{
-	struct cxl_pmem_region *cxlr_pmem = _cxlr_pmem;
-	struct cxl_region *cxlr = cxlr_pmem->cxlr;
-	struct cxl_nvdimm_bridge *cxl_nvb = cxlr->cxl_nvb;
-
-	/*
-	 * Either the bridge is in ->remove() context under the device_lock(),
-	 * or cxlr_release_nvdimm() is cancelling the bridge's release action
-	 * for @cxlr_pmem and doing it itself (while manually holding the bridge
-	 * lock).
-	 */
-	device_lock_assert(&cxl_nvb->dev);
-	cxlr->cxlr_pmem = NULL;
-	cxlr_pmem->cxlr = NULL;
-	device_unregister(&cxlr_pmem->dev);
-}
-
-static void cxlr_release_nvdimm(void *_cxlr)
-{
-	struct cxl_region *cxlr = _cxlr;
-	struct cxl_nvdimm_bridge *cxl_nvb = cxlr->cxl_nvb;
-
-	scoped_guard(device, &cxl_nvb->dev) {
-		if (cxlr->cxlr_pmem)
-			devm_release_action(&cxl_nvb->dev, cxlr_pmem_unregister,
-					    cxlr->cxlr_pmem);
-	}
-	cxlr->cxl_nvb = NULL;
-	put_device(&cxl_nvb->dev);
-}
-
-/**
- * devm_cxl_add_pmem_region() - add a cxl_region-to-nd_region bridge
- * @cxlr: parent CXL region for this pmem region bridge device
- *
- * Return: 0 on success negative error code on failure.
- */
-static int devm_cxl_add_pmem_region(struct cxl_region *cxlr)
-{
-	struct cxl_pmem_region *cxlr_pmem;
-	struct cxl_nvdimm_bridge *cxl_nvb;
-	struct device *dev;
-	int rc;
-
-	rc = cxl_pmem_region_alloc(cxlr);
-	if (rc)
-		return rc;
-	cxlr_pmem = cxlr->cxlr_pmem;
-	cxl_nvb = cxlr->cxl_nvb;
-
-	dev = &cxlr_pmem->dev;
-	rc = dev_set_name(dev, "pmem_region%d", cxlr->id);
-	if (rc)
-		goto err;
-
-	rc = device_add(dev);
-	if (rc)
-		goto err;
-
-	dev_dbg(&cxlr->dev, "%s: register %s\n", dev_name(dev->parent),
-		dev_name(dev));
-
-	scoped_guard(device, &cxl_nvb->dev) {
-		if (cxl_nvb->dev.driver)
-			rc = devm_add_action_or_reset(&cxl_nvb->dev,
-						      cxlr_pmem_unregister,
-						      cxlr_pmem);
-		else
-			rc = -ENXIO;
-	}
-
-	if (rc)
-		goto err_bridge;
-
-	/* @cxlr carries a reference on @cxl_nvb until cxlr_release_nvdimm */
-	return devm_add_action_or_reset(&cxlr->dev, cxlr_release_nvdimm, cxlr);
-
-err:
-	put_device(dev);
-err_bridge:
-	put_device(&cxl_nvb->dev);
-	cxlr->cxl_nvb = NULL;
-	return rc;
-}
-
 static void cxlr_dax_unregister(void *_cxlr_dax)
 {
 	struct cxl_dax_region *cxlr_dax = _cxlr_dax;
@@ -3780,6 +3595,8 @@ static int cxl_region_probe(struct device *dev)
 			dev_dbg(&cxlr->dev, "CXL EDAC registration for region_id=%d failed\n",
 				cxlr->id);
 
+		if (!IS_ENABLED(CONFIG_CXL_PMEM_REGION))
+			return -EINVAL;
 		return devm_cxl_add_pmem_region(cxlr);
 	case CXL_PARTMODE_RAM:
 		rc = devm_cxl_region_edac_register(cxlr);
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index 51c56069f451..b7592cc76192 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -816,6 +816,7 @@ int cxl_dvsec_rr_decode(struct cxl_dev_state *cxlds,
 			struct cxl_endpoint_dvsec_info *info);
 
 bool is_cxl_region(struct device *dev);
+struct cxl_region *to_cxl_region(struct device *dev);
 
 extern const struct bus_type cxl_bus_type;
 
@@ -860,8 +861,6 @@ struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_port *port);
 struct cxl_root_decoder *cxl_find_root_decoder_by_port(struct cxl_port *port);
 
 #ifdef CONFIG_CXL_REGION
-bool is_cxl_pmem_region(struct device *dev);
-struct cxl_pmem_region *to_cxl_pmem_region(struct device *dev);
 int cxl_add_to_region(struct cxl_endpoint_decoder *cxled);
 struct cxl_dax_region *to_cxl_dax_region(struct device *dev);
 u64 cxl_port_get_spa_cache_alias(struct cxl_port *endpoint, u64 spa);
@@ -872,14 +871,6 @@ struct cxl_region *cxl_create_region(struct cxl_root_decoder *cxlrd,
 				     struct cxl_decoder *cxld);
 void create_pmem_region(struct nvdimm *nvdimm);
 #else
-static inline bool is_cxl_pmem_region(struct device *dev)
-{
-	return false;
-}
-static inline struct cxl_pmem_region *to_cxl_pmem_region(struct device *dev)
-{
-	return NULL;
-}
 static inline int cxl_add_to_region(struct cxl_endpoint_decoder *cxled)
 {
 	return 0;
@@ -909,6 +900,29 @@ static inline void create_pmem_region(struct nvdimm *nvdimm)
 }
 #endif
 
+#ifdef CONFIG_CXL_PMEM_REGION
+bool is_cxl_pmem_region(struct device *dev);
+struct cxl_pmem_region *to_cxl_pmem_region(struct device *dev);
+int devm_cxl_add_pmem_region(struct cxl_region *cxlr);
+void create_pmem_region(struct nvdimm *nvdimm);
+#else
+static inline bool is_cxl_pmem_region(struct device *dev)
+{
+	return false;
+}
+static inline struct cxl_pmem_region *to_cxl_pmem_region(struct device *dev)
+{
+	return NULL;
+}
+static inline int devm_cxl_add_pmem_region(struct cxl_region *cxlr)
+{
+	return 0;
+}
+static inline void create_pmem_region(struct nvdimm *nvdimm)
+{
+}
+#endif
+
 void cxl_endpoint_parse_cdat(struct cxl_port *port);
 void cxl_switch_parse_cdat(struct cxl_port *port);
 
diff --git a/tools/testing/cxl/Kbuild b/tools/testing/cxl/Kbuild
index d07f14cb7aa4..cf58ada337b7 100644
--- a/tools/testing/cxl/Kbuild
+++ b/tools/testing/cxl/Kbuild
@@ -64,6 +64,7 @@ cxl_core-y += $(CXL_CORE_SRC)/cdat.o
 cxl_core-y += $(CXL_CORE_SRC)/ras.o
 cxl_core-$(CONFIG_TRACING) += $(CXL_CORE_SRC)/trace.o
 cxl_core-$(CONFIG_CXL_REGION) += $(CXL_CORE_SRC)/region.o
+cxl_core-$(CONFIG_CXL_PMEM_REGION) += $(CXL_CORE_SRC)/pmem_region.o
 cxl_core-$(CONFIG_CXL_MCE) += $(CXL_CORE_SRC)/mce.o
 cxl_core-$(CONFIG_CXL_FEATURES) += $(CXL_CORE_SRC)/features.o
 cxl_core-$(CONFIG_CXL_EDAC_MEM_FEATURES) += $(CXL_CORE_SRC)/edac.o
-- 
2.34.1


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

* [PATCH V2 20/20] cxl/pmem_region: Add sysfs attribute cxl region label updation/deletion
       [not found]   ` <CGME20250730121249epcas5p249c2e3fec3464cfea3a1c84bc285cd49@epcas5p2.samsung.com>
@ 2025-07-30 12:12     ` Neeraj Kumar
  2025-07-31 10:36       ` kernel test robot
  0 siblings, 1 reply; 67+ messages in thread
From: Neeraj Kumar @ 2025-07-30 12:12 UTC (permalink / raw)
  To: linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

Using these attributes region label is added/deleted into LSA. These
attributes are called from userspace (ndctl) after region creation.

Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
---
 Documentation/ABI/testing/sysfs-bus-cxl | 22 ++++++
 drivers/cxl/core/pmem_region.c          | 94 ++++++++++++++++++++++++-
 drivers/cxl/cxl.h                       |  1 +
 3 files changed, 116 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/sysfs-bus-cxl b/Documentation/ABI/testing/sysfs-bus-cxl
index 6b4e8c7a963d..5b47a02a99ef 100644
--- a/Documentation/ABI/testing/sysfs-bus-cxl
+++ b/Documentation/ABI/testing/sysfs-bus-cxl
@@ -615,3 +615,25 @@ Description:
 		The count is persistent across power loss and wraps back to 0
 		upon overflow. If this file is not present, the device does not
 		have the necessary support for dirty tracking.
+
+
+What:		/sys/bus/cxl/devices/regionZ/pmem_regionZ/region_label_update
+Date:		July, 2025
+KernelVersion:	v6.16
+Contact:	linux-cxl@vger.kernel.org
+Description:
+		(RW) Write a boolean 'true' string value to this attribute to
+		update cxl region information into LSA as region label. It
+		uses nvdimm nd_region_label_update() to update cxl region
+		information saved during cxl region creation into LSA. This
+		attribute must be called at last during cxl region creation.
+
+
+What:		/sys/bus/cxl/devices/regionZ/pmem_regionZ/region_label_delete
+Date:		July, 2025
+KernelVersion:	v6.16
+Contact:	linux-cxl@vger.kernel.org
+Description:
+		(WO) When a boolean 'true' is written to this attribute then
+		pmem_region driver deletes cxl region label from LSA using
+		nvdimm nd_region_label_delete()
diff --git a/drivers/cxl/core/pmem_region.c b/drivers/cxl/core/pmem_region.c
index cd1177d345e6..cc9ef2f9a2b3 100644
--- a/drivers/cxl/core/pmem_region.c
+++ b/drivers/cxl/core/pmem_region.c
@@ -45,9 +45,101 @@ static void cxl_pmem_region_release(struct device *dev)
 	kfree(cxlr_pmem);
 }
 
+static ssize_t region_label_update_store(struct device *dev,
+					 struct device_attribute *attr,
+					 const char *buf, size_t len)
+{
+	struct cxl_pmem_region *cxlr_pmem = to_cxl_pmem_region(dev);
+	struct cxl_region *cxlr = cxlr_pmem->cxlr;
+	struct cxl_region_params *p = &cxlr->params;
+	ssize_t rc;
+	bool update;
+
+	rc = kstrtobool(buf, &update);
+	if (rc)
+		return rc;
+
+	ACQUIRE(rwsem_write_kill, rwsem)(&cxl_rwsem.region);
+	rc = ACQUIRE_ERR(rwsem_write_kill, &rwsem);
+	if (rc)
+		return rc;
+
+	/* Region not yet committed */
+	if (update && p->state != CXL_CONFIG_COMMIT) {
+		dev_dbg(dev, "region not committed, can't update into LSA\n");
+		return -ENXIO;
+	}
+
+	if (cxlr && cxlr->cxlr_pmem && cxlr->cxlr_pmem->nd_region) {
+		rc = nd_region_label_update(cxlr->cxlr_pmem->nd_region);
+		if (!rc)
+			p->region_label_state = 1;
+	}
+
+	if (rc)
+		return rc;
+
+	return len;
+}
+
+static ssize_t region_label_update_show(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct cxl_pmem_region *cxlr_pmem = to_cxl_pmem_region(dev);
+	struct cxl_region *cxlr = cxlr_pmem->cxlr;
+	struct cxl_region_params *p = &cxlr->params;
+	ssize_t rc;
+
+	ACQUIRE(rwsem_read_intr, rwsem)(&cxl_rwsem.region);
+	rc = ACQUIRE_ERR(rwsem_read_intr, &rwsem);
+	if (rc)
+		return rc;
+
+	return sysfs_emit(buf, "%d\n", p->region_label_state);
+}
+static DEVICE_ATTR_RW(region_label_update);
+
+static ssize_t region_label_delete_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t len)
+{
+	struct cxl_pmem_region *cxlr_pmem = to_cxl_pmem_region(dev);
+	struct cxl_region *cxlr = cxlr_pmem->cxlr;
+	struct cxl_region_params *p = &cxlr->params;
+	ssize_t rc;
+
+	ACQUIRE(rwsem_write_kill, rwsem)(&cxl_rwsem.region);
+	rc = ACQUIRE_ERR(rwsem_write_kill, &rwsem);
+	if (rc)
+		return rc;
+
+	if (cxlr && cxlr->cxlr_pmem && cxlr->cxlr_pmem->nd_region) {
+		rc = nd_region_label_delete(cxlr->cxlr_pmem->nd_region);
+		if (rc)
+			return rc;
+	}
+
+	p->region_label_state = 0;
+
+	return len;
+}
+DEVICE_ATTR_WO(region_label_delete);
+
+static struct attribute *cxl_pmem_region_attrs[] = {
+	&dev_attr_region_label_update.attr,
+	&dev_attr_region_label_delete.attr,
+	NULL
+};
+
+struct attribute_group cxl_pmem_region_group = {
+	.attrs = cxl_pmem_region_attrs,
+};
+
 static const struct attribute_group *cxl_pmem_region_attribute_groups[] = {
 	&cxl_base_attribute_group,
-	NULL,
+	&cxl_pmem_region_group,
+	NULL
 };
 
 const struct device_type cxl_pmem_region_type = {
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index b7592cc76192..f3faa419ddc5 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -475,6 +475,7 @@ enum cxl_config_state {
  */
 struct cxl_region_params {
 	enum cxl_config_state state;
+	int region_label_state;
 	uuid_t uuid;
 	int interleave_ways;
 	int interleave_granularity;
-- 
2.34.1


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

* Re: [PATCH V2 18/20] cxl/pmem: Add support of cxl lsa 2.1 support in cxl pmem
  2025-07-30 12:12     ` [PATCH V2 18/20] cxl/pmem: Add support of cxl lsa 2.1 support in cxl pmem Neeraj Kumar
@ 2025-07-31  1:36       ` kernel test robot
  0 siblings, 0 replies; 67+ messages in thread
From: kernel test robot @ 2025-07-31  1:36 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: oe-kbuild-all, a.manzanares, vishak.g, neeraj.kernel,
	Neeraj Kumar

Hi Neeraj,

kernel test robot noticed the following build warnings:

[auto build test WARNING on f11a5f89910a7ae970fbce4fdc02d86a8ba8570f]

url:    https://github.com/intel-lab-lkp/linux/commits/Neeraj-Kumar/nvdimm-label-Introduce-NDD_CXL_LABEL-flag-to-set-cxl-label-format/20250730-202209
base:   f11a5f89910a7ae970fbce4fdc02d86a8ba8570f
patch link:    https://lore.kernel.org/r/20250730121209.303202-19-s.neeraj%40samsung.com
patch subject: [PATCH V2 18/20] cxl/pmem: Add support of cxl lsa 2.1 support in cxl pmem
config: i386-randconfig-011-20250731 (https://download.01.org/0day-ci/archive/20250731/202507310929.lJ3DlrYh-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14+deb12u1) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250731/202507310929.lJ3DlrYh-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202507310929.lJ3DlrYh-lkp@intel.com/

All warnings (new ones prefixed by >>):

   drivers/cxl/core/region.c: In function 'create_pmem_region':
>> drivers/cxl/core/region.c:2692:35: warning: variable 'cxl_nvb' set but not used [-Wunused-but-set-variable]
    2692 |         struct cxl_nvdimm_bridge *cxl_nvb;
         |                                   ^~~~~~~


vim +/cxl_nvb +2692 drivers/cxl/core/region.c

  2687	
  2688	void create_pmem_region(struct nvdimm *nvdimm)
  2689	{
  2690		struct cxl_nvdimm *cxl_nvd;
  2691		struct cxl_memdev *cxlmd;
> 2692		struct cxl_nvdimm_bridge *cxl_nvb;
  2693		struct cxl_pmem_region_params *params;
  2694		struct cxl_root_decoder *cxlrd;
  2695		struct cxl_decoder *cxld;
  2696		struct cxl_region *cxlr;
  2697	
  2698		if (!nvdimm_has_cxl_region(nvdimm))
  2699			return;
  2700	
  2701		lockdep_assert_held(&cxl_rwsem.region);
  2702		cxl_nvd = nvdimm_provider_data(nvdimm);
  2703		params = nvdimm_get_cxl_region_param(nvdimm);
  2704		cxlmd = cxl_nvd->cxlmd;
  2705		cxl_nvb = cxlmd->cxl_nvb;
  2706		cxlrd = cxlmd->cxlrd;
  2707	
  2708		/*
  2709		 * FIXME: Limitation: Region creation support only for
  2710		 * interleave way == 1
  2711		 */
  2712		if (!(params->nlabel == 1))
  2713			dev_info(&cxlmd->dev,
  2714				 "Region Creation is not supported with iw > 1\n");
  2715		else {
  2716			cxld = cxl_find_free_ep_decoder(cxlmd->endpoint);
  2717			cxlr = cxl_create_region(cxlrd, CXL_PARTMODE_PMEM,
  2718						 atomic_read(&cxlrd->region_id),
  2719						 params, cxld);
  2720			if (IS_ERR(cxlr))
  2721				dev_info(&cxlmd->dev, "Region Creation failed\n");
  2722		}
  2723	}
  2724	EXPORT_SYMBOL_NS_GPL(create_pmem_region, "CXL");
  2725	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH V2 19/20] cxl/pmem_region: Prep patch to accommodate pmem_region attributes
  2025-07-30 12:12     ` [PATCH V2 19/20] cxl/pmem_region: Prep patch to accommodate pmem_region attributes Neeraj Kumar
@ 2025-07-31  1:57       ` kernel test robot
  2025-07-31  2:17       ` kernel test robot
  1 sibling, 0 replies; 67+ messages in thread
From: kernel test robot @ 2025-07-31  1:57 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: oe-kbuild-all, a.manzanares, vishak.g, neeraj.kernel,
	Neeraj Kumar

Hi Neeraj,

kernel test robot noticed the following build errors:

[auto build test ERROR on f11a5f89910a7ae970fbce4fdc02d86a8ba8570f]

url:    https://github.com/intel-lab-lkp/linux/commits/Neeraj-Kumar/nvdimm-label-Introduce-NDD_CXL_LABEL-flag-to-set-cxl-label-format/20250730-202209
base:   f11a5f89910a7ae970fbce4fdc02d86a8ba8570f
patch link:    https://lore.kernel.org/r/20250730121209.303202-20-s.neeraj%40samsung.com
patch subject: [PATCH V2 19/20] cxl/pmem_region: Prep patch to accommodate pmem_region attributes
config: i386-buildonly-randconfig-001-20250731 (https://download.01.org/0day-ci/archive/20250731/202507310942.77glfQS3-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14+deb12u1) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250731/202507310942.77glfQS3-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202507310942.77glfQS3-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from drivers/cxl/cxlmem.h:12,
                    from drivers/cxl/pci.c:15:
>> drivers/cxl/cxl.h:921:20: error: redefinition of 'create_pmem_region'
     921 | static inline void create_pmem_region(struct nvdimm *nvdimm)
         |                    ^~~~~~~~~~~~~~~~~~
   drivers/cxl/cxl.h:898:20: note: previous definition of 'create_pmem_region' with type 'void(struct nvdimm *)'
     898 | static inline void create_pmem_region(struct nvdimm *nvdimm)
         |                    ^~~~~~~~~~~~~~~~~~


vim +/create_pmem_region +921 drivers/cxl/cxl.h

   902	
   903	#ifdef CONFIG_CXL_PMEM_REGION
   904	bool is_cxl_pmem_region(struct device *dev);
   905	struct cxl_pmem_region *to_cxl_pmem_region(struct device *dev);
   906	int devm_cxl_add_pmem_region(struct cxl_region *cxlr);
   907	void create_pmem_region(struct nvdimm *nvdimm);
   908	#else
   909	static inline bool is_cxl_pmem_region(struct device *dev)
   910	{
   911		return false;
   912	}
   913	static inline struct cxl_pmem_region *to_cxl_pmem_region(struct device *dev)
   914	{
   915		return NULL;
   916	}
   917	static inline int devm_cxl_add_pmem_region(struct cxl_region *cxlr)
   918	{
   919		return 0;
   920	}
 > 921	static inline void create_pmem_region(struct nvdimm *nvdimm)
   922	{
   923	}
   924	#endif
   925	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH V2 19/20] cxl/pmem_region: Prep patch to accommodate pmem_region attributes
  2025-07-30 12:12     ` [PATCH V2 19/20] cxl/pmem_region: Prep patch to accommodate pmem_region attributes Neeraj Kumar
  2025-07-31  1:57       ` kernel test robot
@ 2025-07-31  2:17       ` kernel test robot
  1 sibling, 0 replies; 67+ messages in thread
From: kernel test robot @ 2025-07-31  2:17 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: Paul Gazzillo, Necip Fazil Yildiran, oe-kbuild-all, a.manzanares,
	vishak.g, neeraj.kernel, Neeraj Kumar

Hi Neeraj,

kernel test robot noticed the following build warnings:

[auto build test WARNING on f11a5f89910a7ae970fbce4fdc02d86a8ba8570f]

url:    https://github.com/intel-lab-lkp/linux/commits/Neeraj-Kumar/nvdimm-label-Introduce-NDD_CXL_LABEL-flag-to-set-cxl-label-format/20250730-202209
base:   f11a5f89910a7ae970fbce4fdc02d86a8ba8570f
patch link:    https://lore.kernel.org/r/20250730121209.303202-20-s.neeraj%40samsung.com
patch subject: [PATCH V2 19/20] cxl/pmem_region: Prep patch to accommodate pmem_region attributes
config: x86_64-kismet-CONFIG_LIBNVDIMM-CONFIG_CXL_PMEM_REGION-0-0 (https://download.01.org/0day-ci/archive/20250731/202507311017.7ApKmtQc-lkp@intel.com/config)
reproduce: (https://download.01.org/0day-ci/archive/20250731/202507311017.7ApKmtQc-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202507311017.7ApKmtQc-lkp@intel.com/

kismet warnings: (new ones prefixed by >>)
>> kismet: WARNING: unmet direct dependencies detected for LIBNVDIMM when selected by CXL_PMEM_REGION
   WARNING: unmet direct dependencies detected for LIBNVDIMM
     Depends on [n]: PHYS_ADDR_T_64BIT [=y] && HAS_IOMEM [=y] && BLK_DEV [=n]
     Selected by [y]:
     - CXL_PMEM_REGION [=y] && CXL_BUS [=y] && CXL_REGION [=y]

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH V2 20/20] cxl/pmem_region: Add sysfs attribute cxl region label updation/deletion
  2025-07-30 12:12     ` [PATCH V2 20/20] cxl/pmem_region: Add sysfs attribute cxl region label updation/deletion Neeraj Kumar
@ 2025-07-31 10:36       ` kernel test robot
  0 siblings, 0 replies; 67+ messages in thread
From: kernel test robot @ 2025-07-31 10:36 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: oe-kbuild-all, a.manzanares, vishak.g, neeraj.kernel,
	Neeraj Kumar

Hi Neeraj,

kernel test robot noticed the following build warnings:

[auto build test WARNING on f11a5f89910a7ae970fbce4fdc02d86a8ba8570f]

url:    https://github.com/intel-lab-lkp/linux/commits/Neeraj-Kumar/nvdimm-label-Introduce-NDD_CXL_LABEL-flag-to-set-cxl-label-format/20250730-202209
base:   f11a5f89910a7ae970fbce4fdc02d86a8ba8570f
patch link:    https://lore.kernel.org/r/20250730121209.303202-21-s.neeraj%40samsung.com
patch subject: [PATCH V2 20/20] cxl/pmem_region: Add sysfs attribute cxl region label updation/deletion
config: i386-randconfig-062-20250731 (https://download.01.org/0day-ci/archive/20250731/202507311814.ngKmd10b-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14+deb12u1) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250731/202507311814.ngKmd10b-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202507311814.ngKmd10b-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/cxl/core/pmem_region.c:127:1: sparse: sparse: symbol 'dev_attr_region_label_delete' was not declared. Should it be static?
>> drivers/cxl/core/pmem_region.c:135:24: sparse: sparse: symbol 'cxl_pmem_region_group' was not declared. Should it be static?

vim +/dev_attr_region_label_delete +127 drivers/cxl/core/pmem_region.c

   102	
   103	static ssize_t region_label_delete_store(struct device *dev,
   104					   struct device_attribute *attr,
   105					   const char *buf, size_t len)
   106	{
   107		struct cxl_pmem_region *cxlr_pmem = to_cxl_pmem_region(dev);
   108		struct cxl_region *cxlr = cxlr_pmem->cxlr;
   109		struct cxl_region_params *p = &cxlr->params;
   110		ssize_t rc;
   111	
   112		ACQUIRE(rwsem_write_kill, rwsem)(&cxl_rwsem.region);
   113		rc = ACQUIRE_ERR(rwsem_write_kill, &rwsem);
   114		if (rc)
   115			return rc;
   116	
   117		if (cxlr && cxlr->cxlr_pmem && cxlr->cxlr_pmem->nd_region) {
   118			rc = nd_region_label_delete(cxlr->cxlr_pmem->nd_region);
   119			if (rc)
   120				return rc;
   121		}
   122	
   123		p->region_label_state = 0;
   124	
   125		return len;
   126	}
 > 127	DEVICE_ATTR_WO(region_label_delete);
   128	
   129	static struct attribute *cxl_pmem_region_attrs[] = {
   130		&dev_attr_region_label_update.attr,
   131		&dev_attr_region_label_delete.attr,
   132		NULL
   133	};
   134	
 > 135	struct attribute_group cxl_pmem_region_group = {
   136		.attrs = cxl_pmem_region_attrs,
   137	};
   138	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH V2 03/20] nvdimm/namespace_label: Add namespace label changes as per CXL LSA v2.1
  2025-07-30 12:11     ` [PATCH V2 03/20] nvdimm/namespace_label: Add namespace label changes as per CXL LSA v2.1 Neeraj Kumar
@ 2025-07-31 13:12       ` kernel test robot
  2025-08-13 13:27       ` Jonathan Cameron
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 67+ messages in thread
From: kernel test robot @ 2025-07-31 13:12 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: oe-kbuild-all, a.manzanares, vishak.g, neeraj.kernel,
	Neeraj Kumar

Hi Neeraj,

kernel test robot noticed the following build warnings:

[auto build test WARNING on f11a5f89910a7ae970fbce4fdc02d86a8ba8570f]

url:    https://github.com/intel-lab-lkp/linux/commits/Neeraj-Kumar/nvdimm-label-Introduce-NDD_CXL_LABEL-flag-to-set-cxl-label-format/20250730-202209
base:   f11a5f89910a7ae970fbce4fdc02d86a8ba8570f
patch link:    https://lore.kernel.org/r/20250730121209.303202-4-s.neeraj%40samsung.com
patch subject: [PATCH V2 03/20] nvdimm/namespace_label: Add namespace label changes as per CXL LSA v2.1
config: x86_64-randconfig-121-20250731 (https://download.01.org/0day-ci/archive/20250731/202507312016.4ga8UpF5-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14+deb12u1) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250731/202507312016.4ga8UpF5-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202507312016.4ga8UpF5-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
   drivers/nvdimm/label.c: note: in included file (through drivers/nvdimm/nd-core.h):
>> drivers/nvdimm/nd.h:314:37: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le32 [usertype] align @@     got restricted __le16 [usertype] @@
   drivers/nvdimm/nd.h:314:37: sparse:     expected restricted __le32 [usertype] align
   drivers/nvdimm/nd.h:314:37: sparse:     got restricted __le16 [usertype]

vim +314 drivers/nvdimm/nd.h

   308	
   309	static inline void nsl_set_alignment(struct nvdimm_drvdata *ndd,
   310					     struct nd_namespace_label *ns_label,
   311					     u32 align)
   312	{
   313		if (ndd->cxl)
 > 314			ns_label->cxl.align = __cpu_to_le16(align);
   315	}
   316	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH V2 05/20] nvdimm/region_label: Add region label updation routine
  2025-07-30 12:11     ` [PATCH V2 05/20] nvdimm/region_label: Add region label updation routine Neeraj Kumar
@ 2025-07-31 15:07       ` kernel test robot
  2025-08-13 14:48       ` Jonathan Cameron
                         ` (3 subsequent siblings)
  4 siblings, 0 replies; 67+ messages in thread
From: kernel test robot @ 2025-07-31 15:07 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: oe-kbuild-all, a.manzanares, vishak.g, neeraj.kernel,
	Neeraj Kumar

Hi Neeraj,

kernel test robot noticed the following build warnings:

[auto build test WARNING on f11a5f89910a7ae970fbce4fdc02d86a8ba8570f]

url:    https://github.com/intel-lab-lkp/linux/commits/Neeraj-Kumar/nvdimm-label-Introduce-NDD_CXL_LABEL-flag-to-set-cxl-label-format/20250730-202209
base:   f11a5f89910a7ae970fbce4fdc02d86a8ba8570f
patch link:    https://lore.kernel.org/r/20250730121209.303202-6-s.neeraj%40samsung.com
patch subject: [PATCH V2 05/20] nvdimm/region_label: Add region label updation routine
config: x86_64-randconfig-121-20250731 (https://download.01.org/0day-ci/archive/20250731/202507312211.ovRqDhYY-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14+deb12u1) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250731/202507312211.ovRqDhYY-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202507312211.ovRqDhYY-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/nvdimm/label.c:1184:25: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le32 [usertype] align @@     got restricted __le16 [usertype] @@
   drivers/nvdimm/label.c:1184:25: sparse:     expected restricted __le32 [usertype] align
   drivers/nvdimm/label.c:1184:25: sparse:     got restricted __le16 [usertype]
   drivers/nvdimm/label.c: note: in included file (through drivers/nvdimm/nd-core.h):
   drivers/nvdimm/nd.h:314:37: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le32 [usertype] align @@     got restricted __le16 [usertype] @@
   drivers/nvdimm/nd.h:314:37: sparse:     expected restricted __le32 [usertype] align
   drivers/nvdimm/nd.h:314:37: sparse:     got restricted __le16 [usertype]

vim +1184 drivers/nvdimm/label.c

  1139	
  1140	static int __pmem_region_label_update(struct nd_region *nd_region,
  1141			struct nd_mapping *nd_mapping, int pos, unsigned long flags)
  1142	{
  1143		struct nd_interleave_set *nd_set = nd_region->nd_set;
  1144		struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
  1145		struct nd_lsa_label *nd_label;
  1146		struct cxl_region_label *rg_label;
  1147		struct nd_namespace_index *nsindex;
  1148		struct nd_label_ent *label_ent;
  1149		unsigned long *free;
  1150		u32 nslot, slot;
  1151		size_t offset;
  1152		int rc;
  1153		uuid_t tmp;
  1154	
  1155		if (!preamble_next(ndd, &nsindex, &free, &nslot))
  1156			return -ENXIO;
  1157	
  1158		/* allocate and write the label to the staging (next) index */
  1159		slot = nd_label_alloc_slot(ndd);
  1160		if (slot == UINT_MAX)
  1161			return -ENXIO;
  1162		dev_dbg(ndd->dev, "allocated: %d\n", slot);
  1163	
  1164		nd_label = to_label(ndd, slot);
  1165	
  1166		memset(nd_label, 0, sizeof_namespace_label(ndd));
  1167		rg_label = &nd_label->rg_label;
  1168	
  1169		/* Set Region Label Format identification UUID */
  1170		uuid_parse(CXL_REGION_UUID, &tmp);
  1171		export_uuid(nd_label->rg_label.type, &tmp);
  1172	
  1173		/* Set Current Region Label UUID */
  1174		export_uuid(nd_label->rg_label.uuid, &nd_set->uuid);
  1175	
  1176		rg_label->flags = __cpu_to_le32(flags);
  1177		rg_label->nlabel = __cpu_to_le16(nd_region->ndr_mappings);
  1178		rg_label->position = __cpu_to_le16(pos);
  1179		rg_label->dpa = __cpu_to_le64(nd_mapping->start);
  1180		rg_label->rawsize = __cpu_to_le64(nd_mapping->size);
  1181		rg_label->hpa = __cpu_to_le64(nd_set->res->start);
  1182		rg_label->slot = __cpu_to_le32(slot);
  1183		rg_label->ig = __cpu_to_le32(nd_set->interleave_granularity);
> 1184		rg_label->align = __cpu_to_le16(0);
  1185	
  1186		/* Update fletcher64 Checksum */
  1187		rgl_calculate_checksum(ndd, rg_label);
  1188	
  1189		/* update label */
  1190		offset = nd_label_offset(ndd, nd_label);
  1191		rc = nvdimm_set_config_data(ndd, offset, nd_label,
  1192				sizeof_namespace_label(ndd));
  1193		if (rc < 0) {
  1194			nd_label_free_slot(ndd, slot);
  1195			return rc;
  1196		}
  1197	
  1198		/* Garbage collect the previous label */
  1199		guard(mutex)(&nd_mapping->lock);
  1200		list_for_each_entry(label_ent, &nd_mapping->labels, list) {
  1201			if (!label_ent->label)
  1202				continue;
  1203			if (rgl_uuid_equal(&label_ent->label->rg_label, &nd_set->uuid))
  1204				reap_victim(nd_mapping, label_ent);
  1205		}
  1206	
  1207		/* update index */
  1208		rc = nd_label_write_index(ndd, ndd->ns_next,
  1209				nd_inc_seq(__le32_to_cpu(nsindex->seq)), 0);
  1210		if (rc)
  1211			return rc;
  1212	
  1213		list_for_each_entry(label_ent, &nd_mapping->labels, list)
  1214			if (!label_ent->label) {
  1215				label_ent->label = nd_label;
  1216				nd_label = NULL;
  1217				break;
  1218			}
  1219		dev_WARN_ONCE(&nd_region->dev, nd_label,
  1220				"failed to track label: %d\n",
  1221				to_slot(ndd, nd_label));
  1222		if (nd_label)
  1223			rc = -ENXIO;
  1224	
  1225		return rc;
  1226	}
  1227	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH V2 00/20] Add CXL LSA 2.1 format support in nvdimm and cxl pmem
  2025-07-30 12:11 ` [PATCH V2 00/20] Add CXL LSA 2.1 format support in nvdimm and cxl pmem Neeraj Kumar
                     ` (19 preceding siblings ...)
       [not found]   ` <CGME20250730121249epcas5p249c2e3fec3464cfea3a1c84bc285cd49@epcas5p2.samsung.com>
@ 2025-08-07  9:02   ` Neeraj Kumar
  2025-08-12 21:46     ` Dave Jiang
  20 siblings, 1 reply; 67+ messages in thread
From: Neeraj Kumar @ 2025-08-07  9:02 UTC (permalink / raw)
  To: Dan Williams, Davidlohr Bueso, Jonathan Cameron, Dave Jiang,
	Ira Weiny, Alison Schofield, Vishal Verma, linux-cxl, nvdimm,
	linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, cpgs

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

On 30/07/25 05:41PM, Neeraj Kumar wrote:
>Introduction:
>=============
>CXL Persistent Memory (Pmem) devices region, namespace and content must be
>persistent across system reboot. In order to achieve this persistency, it
>uses Label Storage Area (LSA) to store respective metadata. During system
>reboot, stored metadata in LSA is used to bring back the region, namespace
>and content of CXL device in its previous state.
>CXL specification provides Get_LSA (4102h) and Set_LSA (4103h) mailbox
>commands to access the LSA area. nvdimm driver is using same commands to
>get/set LSA data.
>

Hi Jonathan, Dave and Ira

I have addressed the review comments of V1 patch-set and sent out this
V2 Patch-set.
0-Day Kernel Test bot has reported couple of minor issues which I will
address in next series.

Can you please have a look at this V2 series and let me know your
feedback.


Regards,
Neeraj

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH V2 00/20] Add CXL LSA 2.1 format support in nvdimm and cxl pmem
  2025-08-07  9:02   ` [PATCH V2 00/20] Add CXL LSA 2.1 format support in nvdimm and cxl pmem Neeraj Kumar
@ 2025-08-12 21:46     ` Dave Jiang
  0 siblings, 0 replies; 67+ messages in thread
From: Dave Jiang @ 2025-08-12 21:46 UTC (permalink / raw)
  To: Neeraj Kumar, Dan Williams, Davidlohr Bueso, Jonathan Cameron,
	Ira Weiny, Alison Schofield, Vishal Verma, linux-cxl, nvdimm,
	linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, cpgs



On 8/7/25 2:02 AM, Neeraj Kumar wrote:
> On 30/07/25 05:41PM, Neeraj Kumar wrote:
>> Introduction:
>> =============
>> CXL Persistent Memory (Pmem) devices region, namespace and content must be
>> persistent across system reboot. In order to achieve this persistency, it
>> uses Label Storage Area (LSA) to store respective metadata. During system
>> reboot, stored metadata in LSA is used to bring back the region, namespace
>> and content of CXL device in its previous state.
>> CXL specification provides Get_LSA (4102h) and Set_LSA (4103h) mailbox
>> commands to access the LSA area. nvdimm driver is using same commands to
>> get/set LSA data.
>>
> 
> Hi Jonathan, Dave and Ira
> 
> I have addressed the review comments of V1 patch-set and sent out this
> V2 Patch-set.
> 0-Day Kernel Test bot has reported couple of minor issues which I will
> address in next series.
> 
> Can you please have a look at this V2 series and let me know your
> feedback.

Hi Neeraj,
It's on my review queue. Will try to get to it soon.

Also, it seems that lore is still not happy your mailer. 
https://lore.kernel.org/linux-cxl/1983025922.01754829002385.JavaMail.epsvc@epcpadp1new/T/#t

See all the [not found] threading. Just FYI.

DJ


> 
> 
> Regards,
> Neeraj
> 


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

* Re: [PATCH V2 01/20] nvdimm/label: Introduce NDD_CXL_LABEL flag to set cxl label format
  2025-07-30 12:11     ` [PATCH V2 01/20] nvdimm/label: Introduce NDD_CXL_LABEL flag to set cxl label format Neeraj Kumar
@ 2025-08-13 13:12       ` Jonathan Cameron
  2025-08-15 18:06         ` Dave Jiang
  2025-09-04 13:20         ` Neeraj Kumar
  0 siblings, 2 replies; 67+ messages in thread
From: Jonathan Cameron @ 2025-08-13 13:12 UTC (permalink / raw)
  To: Neeraj Kumar
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel

On Wed, 30 Jul 2025 17:41:50 +0530
Neeraj Kumar <s.neeraj@samsung.com> wrote:

> Prior to LSA 2.1 version, LSA contain only namespace labels. LSA 2.1
> introduced in CXL 2.0 Spec, which contain region label along with
> namespace label.
> 
> NDD_LABELING flag is used for namespace. Introduced NDD_CXL_LABEL
> flag for region label. Based on these flags nvdimm driver performs
> operation on namespace label or region label.
> 
> NDD_CXL_LABEL will be utilized by cxl driver to enable LSA2.1 region
> label support
> 
> Accordingly updated label index version
> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
Hi Neeraj,

A few comments inline.

> diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
> index 04f4a049599a..7a011ee02d79 100644
> --- a/drivers/nvdimm/label.c
> +++ b/drivers/nvdimm/label.c
> @@ -688,11 +688,25 @@ static int nd_label_write_index(struct nvdimm_drvdata *ndd, int index, u32 seq,
>  		- (unsigned long) to_namespace_index(ndd, 0);
>  	nsindex->labeloff = __cpu_to_le64(offset);
>  	nsindex->nslot = __cpu_to_le32(nslot);
> -	nsindex->major = __cpu_to_le16(1);
> -	if (sizeof_namespace_label(ndd) < 256)
> +
> +	/* Set LSA Label Index Version */
> +	if (ndd->cxl) {
> +		/* CXL r3.2 Spec: Table 9-9 Label Index Block Layout */
> +		nsindex->major = __cpu_to_le16(2);
>  		nsindex->minor = __cpu_to_le16(1);
> -	else
> -		nsindex->minor = __cpu_to_le16(2);
> +	} else {
> +		nsindex->major = __cpu_to_le16(1);
> +		/*
> +		 * NVDIMM Namespace Specification
> +		 * Table 2: Namespace Label Index Block Fields
> +		 */
> +		if (sizeof_namespace_label(ndd) < 256)
> +			nsindex->minor = __cpu_to_le16(1);
> +		else
> +		 /* UEFI Specification 2.7: Label Index Block Definitions */

Odd comment alignment. Either put it on the else so
		else /* UEFI 2.7: Label Index Block Defintions */

or indent it an extra tab

		else
			/* UEFI 2.7: Label Index Block Definitions */
			
> +			nsindex->minor = __cpu_to_le16(2);
> +	}
> +
>  	nsindex->checksum = __cpu_to_le64(0);
>  	if (flags & ND_NSINDEX_INIT) {
>  		unsigned long *free = (unsigned long *) nsindex->free;

> diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
> index e772aae71843..0a55900842c8 100644
> --- a/include/linux/libnvdimm.h
> +++ b/include/linux/libnvdimm.h
> @@ -44,6 +44,9 @@ enum {
>  	/* dimm provider wants synchronous registration by __nvdimm_create() */
>  	NDD_REGISTER_SYNC = 8,
>  
> +	/* dimm supports region labels (LSA Format 2.1) */
> +	NDD_CXL_LABEL = 9,

This enum is 'curious'.  It combined flags from a bunch of different
flags fields and some stuff that are nothing to do with flags.

Anyhow, putting that aside I'd either rename it to something like
NDD_REGION_LABELING (similar to NDD_LABELING that is there for namespace labels
or just have it a meaning it is LSA Format 2.1 and drop the fact htat
also means region labels are supported.

Combination of a comment that talks about one thing and a definition name
that doesn't associate with it seems confusing to me.

Jonathan


> +
>  	/* need to set a limit somewhere, but yes, this is likely overkill */
>  	ND_IOCTL_MAX_BUFLEN = SZ_4M,
>  	ND_CMD_MAX_ELEM = 5,


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

* Re: [PATCH V2 02/20] nvdimm/label: Prep patch to accommodate cxl lsa 2.1 support
  2025-07-30 12:11     ` [PATCH V2 02/20] nvdimm/label: Prep patch to accommodate cxl lsa 2.1 support Neeraj Kumar
@ 2025-08-13 13:23       ` Jonathan Cameron
  2025-09-04 13:27         ` Neeraj Kumar
  2025-08-15 22:02       ` Dave Jiang
                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 67+ messages in thread
From: Jonathan Cameron @ 2025-08-13 13:23 UTC (permalink / raw)
  To: Neeraj Kumar
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel

On Wed, 30 Jul 2025 17:41:51 +0530
Neeraj Kumar <s.neeraj@samsung.com> wrote:

> LSA 2.1 format introduces region label, which can also reside
> into LSA along with only namespace label as per v1.1 and v1.2
> 
> As both namespace and region labels are of same size of 256 bytes.
> Thus renamed "struct nd_namespace_label" to "struct nd_lsa_label",
> where both namespace label and region label can stay as union.

Maybe add something on why it makes sense to use a union rather than
new handling.

> 
> No functional change introduced.
> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
> ---
A few minor comments inline.


> diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
> index 55cfbf1e0a95..bdf1ed6f23d8 100644
> --- a/drivers/nvdimm/namespace_devs.c
> +++ b/drivers/nvdimm/namespace_devs.c
> @@ -1615,17 +1619,21 @@ static int select_pmem_id(struct nd_region *nd_region, const uuid_t *pmem_id)
>  	for (i = 0; i < nd_region->ndr_mappings; i++) {
>  		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
>  		struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
> +		struct nd_lsa_label *lsa_label = NULL;
Why not pull this into the scope below.

>  		struct nd_namespace_label *nd_label = NULL;
>  		u64 hw_start, hw_end, pmem_start, pmem_end;
>  		struct nd_label_ent *label_ent;
>  
>  		lockdep_assert_held(&nd_mapping->lock);
>  		list_for_each_entry(label_ent, &nd_mapping->labels, list) {
e.g.
			struct nd_lsa_label *lsa_label = label_ent->label;

then no need to set it to NULL later.

> -			nd_label = label_ent->label;
> -			if (!nd_label)
> +			lsa_label = label_ent->label;
> +			if (!lsa_label)
>  				continue;
> +
> +			nd_label = &lsa_label->ns_label;
>  			if (nsl_uuid_equal(ndd, nd_label, pmem_id))
>  				break;
> +			lsa_label = NULL;
>  			nd_label = NULL;
>  		}
>  
> @@ -1746,19 +1754,21 @@ static struct device *create_namespace_pmem(struct nd_region *nd_region,
>  
>  	/* Calculate total size and populate namespace properties from label0 */
>  	for (i = 0; i < nd_region->ndr_mappings; i++) {
> +		struct nd_lsa_label *lsa_label;
>  		struct nd_namespace_label *label0;
>  		struct nvdimm_drvdata *ndd;
>  
>  		nd_mapping = &nd_region->mapping[i];
>  		label_ent = list_first_entry_or_null(&nd_mapping->labels,
>  				typeof(*label_ent), list);
> -		label0 = label_ent ? label_ent->label : NULL;
> +		lsa_label = label_ent ? label_ent->label : NULL;
>  
> -		if (!label0) {
> +		if (!lsa_label) {
>  			WARN_ON(1);
>  			continue;
>  		}
>  
> +		label0 = &lsa_label->ns_label;
>  		ndd = to_ndd(nd_mapping);
>  		size += nsl_get_rawsize(ndd, label0);
>  		if (nsl_get_position(ndd, label0) != 0)
>


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

* Re: [PATCH V2 03/20] nvdimm/namespace_label: Add namespace label changes as per CXL LSA v2.1
  2025-07-30 12:11     ` [PATCH V2 03/20] nvdimm/namespace_label: Add namespace label changes as per CXL LSA v2.1 Neeraj Kumar
  2025-07-31 13:12       ` kernel test robot
@ 2025-08-13 13:27       ` Jonathan Cameron
  2025-09-04 13:40         ` Neeraj Kumar
  2025-08-19 15:57       ` Ira Weiny
  2025-08-19 19:36       ` Ira Weiny
  3 siblings, 1 reply; 67+ messages in thread
From: Jonathan Cameron @ 2025-08-13 13:27 UTC (permalink / raw)
  To: Neeraj Kumar
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel

On Wed, 30 Jul 2025 17:41:52 +0530
Neeraj Kumar <s.neeraj@samsung.com> wrote:

> CXL 3.2 Spec mentions CXL LSA 2.1 Namespace Labels at section 9.13.2.5
> Modified __pmem_label_update function using setter functions to update
> namespace label as per CXL LSA 2.1
> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>

> diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
> index 61348dee687d..651847f1bbf9 100644
> --- a/drivers/nvdimm/nd.h
> +++ b/drivers/nvdimm/nd.h
> @@ -295,6 +295,33 @@ static inline const u8 *nsl_uuid_raw(struct nvdimm_drvdata *ndd,

> +static inline void nsl_set_alignment(struct nvdimm_drvdata *ndd,
> +				     struct nd_namespace_label *ns_label,
> +				     u32 align)
> +{
> +	if (ndd->cxl)
> +		ns_label->cxl.align = __cpu_to_le16(align);

The bot caught this one, it should be __cpu_to_le32(align);

> +}


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

* Re: [PATCH V2 04/20] nvdimm/label: CXL labels skip the need for 'interleave-set cookie'
  2025-07-30 12:11     ` [PATCH V2 04/20] nvdimm/label: CXL labels skip the need for 'interleave-set cookie' Neeraj Kumar
@ 2025-08-13 13:44       ` Jonathan Cameron
  2025-09-04 13:54         ` Neeraj Kumar
  2025-08-15 21:02       ` Dave Jiang
  2025-08-19 16:04       ` Ira Weiny
  2 siblings, 1 reply; 67+ messages in thread
From: Jonathan Cameron @ 2025-08-13 13:44 UTC (permalink / raw)
  To: Neeraj Kumar
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel

On Wed, 30 Jul 2025 17:41:53 +0530
Neeraj Kumar <s.neeraj@samsung.com> wrote:

> CXL LSA v2.1 utilizes the region labels stored in the LSA for interleave
> set configuration instead of interleave-set cookie used in previous LSA
> versions. As interleave-set cookie is not required for CXL LSA v2.1 format
> so skip its usage for CXL LSA 2.1 format
> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>

Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>

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

* Re: [PATCH V2 05/20] nvdimm/region_label: Add region label updation routine
  2025-07-30 12:11     ` [PATCH V2 05/20] nvdimm/region_label: Add region label updation routine Neeraj Kumar
  2025-07-31 15:07       ` kernel test robot
@ 2025-08-13 14:48       ` Jonathan Cameron
  2025-09-04 14:06         ` Neeraj Kumar
  2025-08-15 21:55       ` Dave Jiang
                         ` (2 subsequent siblings)
  4 siblings, 1 reply; 67+ messages in thread
From: Jonathan Cameron @ 2025-08-13 14:48 UTC (permalink / raw)
  To: Neeraj Kumar
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel

On Wed, 30 Jul 2025 17:41:54 +0530
Neeraj Kumar <s.neeraj@samsung.com> wrote:

> Added __pmem_region_label_update region label update routine to update
> region label.
> 
> Also used guard(mutex)(&nd_mapping->lock) in place of mutex_lock() and
> mutex_unlock()
> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>

A few comments inline,

Thanks,

Jonathan


>  static bool slot_valid(struct nvdimm_drvdata *ndd,
>  		struct nd_lsa_label *lsa_label, u32 slot)
>  {
> @@ -960,7 +970,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  		return rc;
>  
>  	/* Garbage collect the previous label */
> -	mutex_lock(&nd_mapping->lock);
> +	guard(mutex)(&nd_mapping->lock);
>  	list_for_each_entry(label_ent, &nd_mapping->labels, list) {
>  		if (!label_ent->label)
>  			continue;
> @@ -972,20 +982,20 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  	/* update index */
>  	rc = nd_label_write_index(ndd, ndd->ns_next,
>  			nd_inc_seq(__le32_to_cpu(nsindex->seq)), 0);
> -	if (rc == 0) {
> -		list_for_each_entry(label_ent, &nd_mapping->labels, list)
> -			if (!label_ent->label) {
> -				label_ent->label = lsa_label;
> -				lsa_label = NULL;
> -				break;
> -			}
> -		dev_WARN_ONCE(&nspm->nsio.common.dev, lsa_label,
> -				"failed to track label: %d\n",
> -				to_slot(ndd, lsa_label));
> -		if (lsa_label)
> -			rc = -ENXIO;
> -	}
> -	mutex_unlock(&nd_mapping->lock);
> +	if (rc)
> +		return rc;
> +
> +	list_for_each_entry(label_ent, &nd_mapping->labels, list)
> +		if (!label_ent->label) {
> +			label_ent->label = lsa_label;
> +			lsa_label = NULL;
> +			break;
> +		}
> +	dev_WARN_ONCE(&nspm->nsio.common.dev, lsa_label,
> +			"failed to track label: %d\n",
> +			to_slot(ndd, lsa_label));
> +	if (lsa_label)
> +		rc = -ENXIO;
	if (lsa_label)
		return -ENXIO;

	return 0;

is a little clearer.

>  
>  	return rc;
>  }
> @@ -1127,6 +1137,137 @@ int nd_pmem_namespace_label_update(struct nd_region *nd_region,
>  	return 0;
>  }
>  
> +static int __pmem_region_label_update(struct nd_region *nd_region,
> +		struct nd_mapping *nd_mapping, int pos, unsigned long flags)
> +{
> +	struct nd_interleave_set *nd_set = nd_region->nd_set;
> +	struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
> +	struct nd_lsa_label *nd_label;
> +	struct cxl_region_label *rg_label;
> +	struct nd_namespace_index *nsindex;
> +	struct nd_label_ent *label_ent;
> +	unsigned long *free;
> +	u32 nslot, slot;
> +	size_t offset;
> +	int rc;
> +	uuid_t tmp;
> +
> +	if (!preamble_next(ndd, &nsindex, &free, &nslot))
> +		return -ENXIO;
> +
> +	/* allocate and write the label to the staging (next) index */
> +	slot = nd_label_alloc_slot(ndd);
> +	if (slot == UINT_MAX)
> +		return -ENXIO;
> +	dev_dbg(ndd->dev, "allocated: %d\n", slot);
> +
> +	nd_label = to_label(ndd, slot);
> +
> +	memset(nd_label, 0, sizeof_namespace_label(ndd));
> +	rg_label = &nd_label->rg_label;
> +
> +	/* Set Region Label Format identification UUID */
> +	uuid_parse(CXL_REGION_UUID, &tmp);
> +	export_uuid(nd_label->rg_label.type, &tmp);

	export_uuid(rg_label->type, &tmp);

> +
> +	/* Set Current Region Label UUID */
> +	export_uuid(nd_label->rg_label.uuid, &nd_set->uuid);

	export_uuid(rg_label->uuid, &nd_set->uuid);


> +
> +	rg_label->flags = __cpu_to_le32(flags);
> +	rg_label->nlabel = __cpu_to_le16(nd_region->ndr_mappings);
> +	rg_label->position = __cpu_to_le16(pos);
> +	rg_label->dpa = __cpu_to_le64(nd_mapping->start);
> +	rg_label->rawsize = __cpu_to_le64(nd_mapping->size);
> +	rg_label->hpa = __cpu_to_le64(nd_set->res->start);
> +	rg_label->slot = __cpu_to_le32(slot);
> +	rg_label->ig = __cpu_to_le32(nd_set->interleave_granularity);
> +	rg_label->align = __cpu_to_le16(0);

As the bot complained... It's le32

> +
> +	/* Update fletcher64 Checksum */
> +	rgl_calculate_checksum(ndd, rg_label);
> +
> +	/* update label */
> +	offset = nd_label_offset(ndd, nd_label);
> +	rc = nvdimm_set_config_data(ndd, offset, nd_label,
> +			sizeof_namespace_label(ndd));
> +	if (rc < 0) {
> +		nd_label_free_slot(ndd, slot);
> +		return rc;
> +	}
> +
> +	/* Garbage collect the previous label */
> +	guard(mutex)(&nd_mapping->lock);
> +	list_for_each_entry(label_ent, &nd_mapping->labels, list) {
> +		if (!label_ent->label)
> +			continue;
> +		if (rgl_uuid_equal(&label_ent->label->rg_label, &nd_set->uuid))
> +			reap_victim(nd_mapping, label_ent);
> +	}
> +
> +	/* update index */
> +	rc = nd_label_write_index(ndd, ndd->ns_next,
> +			nd_inc_seq(__le32_to_cpu(nsindex->seq)), 0);
> +	if (rc)
> +		return rc;
> +
> +	list_for_each_entry(label_ent, &nd_mapping->labels, list)
> +		if (!label_ent->label) {
> +			label_ent->label = nd_label;
> +			nd_label = NULL;
> +			break;
> +		}
> +	dev_WARN_ONCE(&nd_region->dev, nd_label,
> +			"failed to track label: %d\n",
> +			to_slot(ndd, nd_label));
> +	if (nd_label)
> +		rc = -ENXIO;

		return -ENXIO;

> +

	return 0;

is clearer.

> +	return rc;
> +}
> +
> +int nd_pmem_region_label_update(struct nd_region *nd_region)
> +{
> +	int i, rc;
> +
> +	for (i = 0; i < nd_region->ndr_mappings; i++) {
> +		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
> +		struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
> +
> +		/* No need to update region label for non cxl format */
> +		if (!ndd->cxl)
> +			continue;
> +
> +		/* Init labels to include region label */
> +		rc = init_labels(nd_mapping, 1);
> +

No blank line here - keep the error check closely associated with the
thing that it is checking.

> +		if (rc < 0)
> +			return rc;
> +
> +		rc = __pmem_region_label_update(nd_region, nd_mapping, i,
> +					NSLABEL_FLAG_UPDATING);
> +

Same here.

> +		if (rc)
> +			return rc;
> +	}
> +
> +	/* Clear the UPDATING flag per UEFI 2.7 expectations */
> +	for (i = 0; i < nd_region->ndr_mappings; i++) {
> +		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
> +		struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
> +
> +		/* No need to update region label for non cxl format */
> +		if (!ndd->cxl)
> +			continue;
> +
> +		rc = __pmem_region_label_update(nd_region, nd_mapping, i, 0);
> +

and here.

> +		if (rc)
> +			return rc;
> +	}
> +
> +	return 0;
> +}
> +
>  int __init nd_label_init(void)
>  {
>  	WARN_ON(guid_parse(NVDIMM_BTT_GUID, &nvdimm_btt_guid));
> diff --git a/drivers/nvdimm/label.h b/drivers/nvdimm/label.h
> index 4883b3a1320f..0f428695017d 100644
> --- a/drivers/nvdimm/label.h
> +++ b/drivers/nvdimm/label.h
> @@ -190,6 +190,7 @@ struct nd_namespace_label {
>  struct nd_lsa_label {

Would be better to have this explicitly as a union
unless later patches add more elements.  That way it'll 
be obvious at all sites where it is used that it can be one
of several things.

>  	union {
>  		struct nd_namespace_label ns_label;
> +		struct cxl_region_label rg_label;
>  	};
>  };
>  
> @@ -233,4 +234,5 @@ struct nd_region;
>  struct nd_namespace_pmem;
>  int nd_pmem_namespace_label_update(struct nd_region *nd_region,
>  		struct nd_namespace_pmem *nspm, resource_size_t size);
> +int nd_pmem_region_label_update(struct nd_region *nd_region);
>  #endif /* __LABEL_H__ */



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

* Re: [PATCH V2 06/20] nvdimm/region_label: Add region label deletion routine
  2025-07-30 12:11     ` [PATCH V2 06/20] nvdimm/region_label: Add region label deletion routine Neeraj Kumar
@ 2025-08-13 14:53       ` Jonathan Cameron
  2025-09-04 14:20         ` Neeraj Kumar
  2025-08-15 22:22       ` Dave Jiang
  1 sibling, 1 reply; 67+ messages in thread
From: Jonathan Cameron @ 2025-08-13 14:53 UTC (permalink / raw)
  To: Neeraj Kumar
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel

On Wed, 30 Jul 2025 17:41:55 +0530
Neeraj Kumar <s.neeraj@samsung.com> wrote:

> Added cxl v2.1 format region label deletion routine. This function is
> used to delete region label from LSA
> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
> ---
>  drivers/nvdimm/label.c          | 77 ++++++++++++++++++++++++++++++---
>  drivers/nvdimm/label.h          |  6 +++
>  drivers/nvdimm/namespace_devs.c | 12 +++++
>  drivers/nvdimm/nd.h             |  9 ++++
>  include/linux/libnvdimm.h       |  1 +
>  5 files changed, 100 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
> index 94f2d0ba7aca..be18278d6cea 100644
> --- a/drivers/nvdimm/label.c
> +++ b/drivers/nvdimm/label.c
> @@ -1044,7 +1044,8 @@ static int init_labels(struct nd_mapping *nd_mapping, int num_labels)
>  	return max(num_labels, old_num_labels);
>  }
>  
> -static int del_labels(struct nd_mapping *nd_mapping, uuid_t *uuid)
> +static int del_labels(struct nd_mapping *nd_mapping, uuid_t *uuid,
> +		enum label_type ltype)
>  {
>  	struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
>  	struct nd_label_ent *label_ent, *e;
> @@ -1068,8 +1069,23 @@ static int del_labels(struct nd_mapping *nd_mapping, uuid_t *uuid)
>  		if (!nd_label)
>  			continue;
>  		active++;
> -		if (!nsl_uuid_equal(ndd, &nd_label->ns_label, uuid))
> -			continue;
> +
> +		switch (ltype) {
> +		case NS_LABEL_TYPE:
> +			if (!nsl_uuid_equal(ndd, &nd_label->ns_label, uuid))
> +				continue;
> +
> +			break;
> +		case RG_LABEL_TYPE:
> +			if (!rgl_uuid_equal(&nd_label->rg_label, uuid))
> +				continue;
> +
> +			break;
> +		default:
> +			dev_err(ndd->dev, "Invalid label type\n");
> +			return 0;

Given you pass in an enum and both elements are covered by other cases
shouldn't need a default here.

> +		}
> +
>  		active--;
>  		slot = to_slot(ndd, nd_label);
>  		nd_label_free_slot(ndd, slot);



> @@ -1268,6 +1285,56 @@ int nd_pmem_region_label_update(struct nd_region *nd_region)
>  	return 0;
>  }
>  
> +int nd_pmem_region_label_delete(struct nd_region *nd_region)
> +{
> +	int i, rc;
> +	struct nd_interleave_set *nd_set = nd_region->nd_set;
> +	struct nd_label_ent *label_ent;
> +	int ns_region_cnt = 0;
> +
> +	for (i = 0; i < nd_region->ndr_mappings; i++) {
> +		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
> +		struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
> +
> +		/* Find non cxl format supported ndr_mappings */
> +		if (!ndd->cxl) {
> +			dev_info(&nd_region->dev, "Region label unsupported\n");

I'd go with "Unsupported region label".  The other way around kind of implies
a deficiency in the code, whereas point here is that new stuff may be added to
the spec that we don't yet understand.

> +			return -EINVAL;
> +		}
> +
> +		/* Find if any NS label using this region */
> +		mutex_lock(&nd_mapping->lock);

I'd go for guard here probably as the scope will mean it gets unlocked
at end of this loop step.


		guard(mutex)(&nd_mapping->lock);
> +		list_for_each_entry(label_ent, &nd_mapping->labels, list) {
> +			if (!label_ent->label)
> +				continue;
> +
> +			/*
> +			 * Check if any available NS labels has same
> +			 * region_uuid in LSA
> +			 */
> +			if (nsl_region_uuid_equal(&label_ent->label->ns_label,
> +						  &nd_set->uuid))
> +				ns_region_cnt++;
> +		}
> +		mutex_unlock(&nd_mapping->lock);
> +	}
> +
> +	if (ns_region_cnt) {
> +		dev_dbg(&nd_region->dev, "Region/Namespace label in use\n");
> +		return -EBUSY;
> +	}
> +
> +	for (i = 0; i < nd_region->ndr_mappings; i++) {
> +		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
> +
> +		rc = del_labels(nd_mapping, &nd_set->uuid, RG_LABEL_TYPE);
> +		if (rc)
> +			return rc;
> +	}
> +
> +	return 0;
> +}
> +
>  int __init nd_label_init(void)
>  {
>  	WARN_ON(guid_parse(NVDIMM_BTT_GUID, &nvdimm_btt_guid));
>
> @@ -235,4 +240,5 @@ struct nd_namespace_pmem;
>  int nd_pmem_namespace_label_update(struct nd_region *nd_region,
>  		struct nd_namespace_pmem *nspm, resource_size_t size);
>  int nd_pmem_region_label_update(struct nd_region *nd_region);
> +int nd_pmem_region_label_delete(struct nd_region *nd_region);
>  #endif /* __LABEL_H__ */



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

* Re: [PATCH V2 07/20] nvdimm/namespace_label: Update namespace init_labels and its region_uuid
  2025-07-30 12:11     ` [PATCH V2 07/20] nvdimm/namespace_label: Update namespace init_labels and its region_uuid Neeraj Kumar
@ 2025-08-13 14:58       ` Jonathan Cameron
  2025-09-04 14:24         ` Neeraj Kumar
  2025-08-19 18:56       ` Ira Weiny
  1 sibling, 1 reply; 67+ messages in thread
From: Jonathan Cameron @ 2025-08-13 14:58 UTC (permalink / raw)
  To: Neeraj Kumar
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel

On Wed, 30 Jul 2025 17:41:56 +0530
Neeraj Kumar <s.neeraj@samsung.com> wrote:

> nd_mapping->labels maintains the list of labels present into LSA.
> init_labels() prepares this list while adding new label into LSA
> and updates nd_mapping->labels accordingly. During cxl region
> creation nd_mapping->labels list and LSA was updated with one
> region label. Therefore during new namespace label creation
> pre-include the previously created region label, so increase
> num_labels count by 1.
> 
> Also updated nsl_set_region_uuid with region uuid with which
> namespace is associated with.

Any reason these are in the same patch?  I'd like to have
seen a bit more on why this 'Also' change is here and a separate
patch might make that easier to see.

> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
> ---
>  drivers/nvdimm/label.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
> index be18278d6cea..fd02b557612e 100644
> --- a/drivers/nvdimm/label.c
> +++ b/drivers/nvdimm/label.c
> @@ -957,7 +957,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  	nsl_set_slot(ndd, nd_label, slot);
>  	nsl_set_alignment(ndd, nd_label, 0);
>  	nsl_set_type_guid(ndd, nd_label, &nd_set->type_guid);
> -	nsl_set_region_uuid(ndd, nd_label, NULL);
> +	nsl_set_region_uuid(ndd, nd_label, &nd_set->uuid);
>  	nsl_set_claim_class(ndd, nd_label, ndns->claim_class);
>  	nsl_calculate_checksum(ndd, nd_label);
>  	nd_dbg_dpa(nd_region, ndd, res, "\n");
> @@ -1129,7 +1129,8 @@ int nd_pmem_namespace_label_update(struct nd_region *nd_region,
>  				count++;
>  		WARN_ON_ONCE(!count);
>  
> -		rc = init_labels(nd_mapping, count);
> +		/* Adding 1 to pre include the already added region label */
> +		rc = init_labels(nd_mapping, count + 1);
>  		if (rc < 0)
>  			return rc;
>  


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

* Re: [PATCH V2 08/20] nvdimm/label: Include region label in slot validation
  2025-07-30 12:11     ` [PATCH V2 08/20] nvdimm/label: Include region label in slot validation Neeraj Kumar
@ 2025-08-13 15:07       ` Jonathan Cameron
  2025-09-04 14:30         ` Neeraj Kumar
  0 siblings, 1 reply; 67+ messages in thread
From: Jonathan Cameron @ 2025-08-13 15:07 UTC (permalink / raw)
  To: Neeraj Kumar
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel

On Wed, 30 Jul 2025 17:41:57 +0530
Neeraj Kumar <s.neeraj@samsung.com> wrote:

> slot validation routine validates label slot by calculating label

Slot validation ... or
The slot validation routing ...


> checksum. It was only validating namespace label. This changeset also
> validates region label if present.
> 
> Also validate and calculate lsa v2.1 namespace label checksum

LSA v2.1 ...


> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
Otherwise LGTM

Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>




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

* Re: [PATCH V2 09/20] nvdimm/namespace_label: Skip region label during ns label DPA reservation
  2025-07-30 12:11     ` [PATCH V2 09/20] nvdimm/namespace_label: Skip region label during ns label DPA reservation Neeraj Kumar
@ 2025-08-13 15:09       ` Jonathan Cameron
  2025-09-04 14:31         ` Neeraj Kumar
  0 siblings, 1 reply; 67+ messages in thread
From: Jonathan Cameron @ 2025-08-13 15:09 UTC (permalink / raw)
  To: Neeraj Kumar
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel

On Wed, 30 Jul 2025 17:41:58 +0530
Neeraj Kumar <s.neeraj@samsung.com> wrote:

> If Namespace label is present in LSA during nvdimm_probe then DPA
> reservation is required. But this reservation is not required by region
> label. Therefore if LSA scanning finds any region label, skip it.
> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
> ---
>  drivers/nvdimm/label.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
> index c4748e30f2b6..064a945dcdd1 100644
> --- a/drivers/nvdimm/label.c
> +++ b/drivers/nvdimm/label.c
> @@ -452,6 +452,10 @@ int nd_label_reserve_dpa(struct nvdimm_drvdata *ndd)
>  		lsa_label = to_label(ndd, slot);
>  		nd_label = &lsa_label->ns_label;
>  
> +		/* skip region label, dpa reservation for ns label only */
Confusing comment and not clear if skip applies just to region label or
to dpa reservation as well.

		/* Skip region label.  DPA reservation is for NS label only. */

or something along those lines (assuming I have understood this right!)
> +		if (is_region_label(ndd, lsa_label))
> +			continue;
> +
>  		if (!slot_valid(ndd, lsa_label, slot))
>  			continue;
>  


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

* Re: [PATCH V2 10/20] nvdimm/region_label: Preserve cxl region information from region label
  2025-07-30 12:11     ` [PATCH V2 10/20] nvdimm/region_label: Preserve cxl region information from region label Neeraj Kumar
@ 2025-08-13 15:11       ` Jonathan Cameron
  2025-09-04 14:33         ` Neeraj Kumar
  0 siblings, 1 reply; 67+ messages in thread
From: Jonathan Cameron @ 2025-08-13 15:11 UTC (permalink / raw)
  To: Neeraj Kumar
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel

On Wed, 30 Jul 2025 17:41:59 +0530
Neeraj Kumar <s.neeraj@samsung.com> wrote:

> 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>

See below.

> diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
> index 064a945dcdd1..bcac05371f87 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 *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 */

In practice, is this a significant issue or not?  I.e. should we not
merge this series until this has been revisited?

> +		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;
> +}


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

* Re: [PATCH V2 11/20] nvdimm/region_label: Export routine to fetch region information
  2025-07-30 12:12     ` [PATCH V2 11/20] nvdimm/region_label: Export routine to fetch region information Neeraj Kumar
@ 2025-08-13 15:13       ` Jonathan Cameron
  0 siblings, 0 replies; 67+ messages in thread
From: Jonathan Cameron @ 2025-08-13 15:13 UTC (permalink / raw)
  To: Neeraj Kumar
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel

On Wed, 30 Jul 2025 17:42:00 +0530
Neeraj Kumar <s.neeraj@samsung.com> wrote:

> cxl region information preserved from LSA need to be exported so as to
> use by cxl driver for cxl region re-creation

CXL region information preserved from the LAS needs to be exported for
use by the CXL driver for CXL region re-creation.

> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>


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

* Re: [PATCH V2 12/20] nvdimm/namespace_label: Skip region label during namespace creation
  2025-07-30 12:12     ` [PATCH V2 12/20] nvdimm/namespace_label: Skip region label during namespace creation Neeraj Kumar
@ 2025-08-13 15:55       ` Jonathan Cameron
  2025-09-04 14:34         ` Neeraj Kumar
  0 siblings, 1 reply; 67+ messages in thread
From: Jonathan Cameron @ 2025-08-13 15:55 UTC (permalink / raw)
  To: Neeraj Kumar
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel

On Wed, 30 Jul 2025 17:42:01 +0530
Neeraj Kumar <s.neeraj@samsung.com> wrote:

> During namespace creation skip presence of region label if present.

Confusing description.  What does skipping presence mean?
Reword.

During namespace creation, skip any region labels found.


> Also preserve region label into labels list if present.
> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
> ---
>  drivers/nvdimm/namespace_devs.c | 50 +++++++++++++++++++++++++++++----
>  1 file changed, 45 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
> index e5c2f78ca7dd..8edd26407939 100644
> --- a/drivers/nvdimm/namespace_devs.c
> +++ b/drivers/nvdimm/namespace_devs.c
> @@ -1985,6 +1985,10 @@ static struct device **scan_labels(struct nd_region *nd_region)
>  		if (!lsa_label)
>  			continue;
>  
> +		/* skip region labels if present */

This is kind of obvious comment. I'd drop it.

> +		if (is_region_label(ndd, lsa_label))
> +			continue;
> +
>  		nd_label = &lsa_label->ns_label;
>  


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

* Re: [PATCH V2 01/20] nvdimm/label: Introduce NDD_CXL_LABEL flag to set cxl label format
  2025-08-13 13:12       ` Jonathan Cameron
@ 2025-08-15 18:06         ` Dave Jiang
  2025-09-04 13:20         ` Neeraj Kumar
  1 sibling, 0 replies; 67+ messages in thread
From: Dave Jiang @ 2025-08-15 18:06 UTC (permalink / raw)
  To: Jonathan Cameron, Neeraj Kumar
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel



On 8/13/25 6:12 AM, Jonathan Cameron wrote:
> On Wed, 30 Jul 2025 17:41:50 +0530
> Neeraj Kumar <s.neeraj@samsung.com> wrote:
> 
>> Prior to LSA 2.1 version, LSA contain only namespace labels. LSA 2.1
>> introduced in CXL 2.0 Spec, which contain region label along with
>> namespace label.
>>
>> NDD_LABELING flag is used for namespace. Introduced NDD_CXL_LABEL
>> flag for region label. Based on these flags nvdimm driver performs
>> operation on namespace label or region label.
>>
>> NDD_CXL_LABEL will be utilized by cxl driver to enable LSA2.1 region
>> label support
>>
>> Accordingly updated label index version
>>
>> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
> Hi Neeraj,
> 
> A few comments inline.
> 
>> diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
>> index 04f4a049599a..7a011ee02d79 100644
>> --- a/drivers/nvdimm/label.c
>> +++ b/drivers/nvdimm/label.c
>> @@ -688,11 +688,25 @@ static int nd_label_write_index(struct nvdimm_drvdata *ndd, int index, u32 seq,
>>  		- (unsigned long) to_namespace_index(ndd, 0);
>>  	nsindex->labeloff = __cpu_to_le64(offset);
>>  	nsindex->nslot = __cpu_to_le32(nslot);
>> -	nsindex->major = __cpu_to_le16(1);
>> -	if (sizeof_namespace_label(ndd) < 256)
>> +
>> +	/* Set LSA Label Index Version */
>> +	if (ndd->cxl) {
>> +		/* CXL r3.2 Spec: Table 9-9 Label Index Block Layout */
>> +		nsindex->major = __cpu_to_le16(2);
>>  		nsindex->minor = __cpu_to_le16(1);
>> -	else
>> -		nsindex->minor = __cpu_to_le16(2);
>> +	} else {
>> +		nsindex->major = __cpu_to_le16(1);
>> +		/*
>> +		 * NVDIMM Namespace Specification
>> +		 * Table 2: Namespace Label Index Block Fields
>> +		 */
>> +		if (sizeof_namespace_label(ndd) < 256)
>> +			nsindex->minor = __cpu_to_le16(1);
>> +		else
>> +		 /* UEFI Specification 2.7: Label Index Block Definitions */
> 
> Odd comment alignment. Either put it on the else so
> 		else /* UEFI 2.7: Label Index Block Defintions */
> 
> or indent it an extra tab
> 
> 		else
> 			/* UEFI 2.7: Label Index Block Definitions */
> 			
>> +			nsindex->minor = __cpu_to_le16(2);
>> +	}
>> +
>>  	nsindex->checksum = __cpu_to_le64(0);
>>  	if (flags & ND_NSINDEX_INIT) {
>>  		unsigned long *free = (unsigned long *) nsindex->free;
> 
>> diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
>> index e772aae71843..0a55900842c8 100644
>> --- a/include/linux/libnvdimm.h
>> +++ b/include/linux/libnvdimm.h
>> @@ -44,6 +44,9 @@ enum {
>>  	/* dimm provider wants synchronous registration by __nvdimm_create() */
>>  	NDD_REGISTER_SYNC = 8,
>>  
>> +	/* dimm supports region labels (LSA Format 2.1) */
>> +	NDD_CXL_LABEL = 9,
> 
> This enum is 'curious'.  It combined flags from a bunch of different
> flags fields and some stuff that are nothing to do with flags.
> 
> Anyhow, putting that aside I'd either rename it to something like
> NDD_REGION_LABELING (similar to NDD_LABELING that is there for namespace labels
> or just have it a meaning it is LSA Format 2.1 and drop the fact htat
> also means region labels are supported.

I agree. I had a conversation with Dan about it where I mentioned calling it CXL to describe LSA 2.1 just doesn't seem quite right. He also offered up something like NDD_REGION_LABELING instead of NDD_CXL_LABEL. So +1 to this comment.

DJ 

> 
> Combination of a comment that talks about one thing and a definition name
> that doesn't associate with it seems confusing to me.
> 
> Jonathan
> 
> 
>> +
>>  	/* need to set a limit somewhere, but yes, this is likely overkill */
>>  	ND_IOCTL_MAX_BUFLEN = SZ_4M,
>>  	ND_CMD_MAX_ELEM = 5,
> 
> 


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

* Re: [PATCH V2 04/20] nvdimm/label: CXL labels skip the need for 'interleave-set cookie'
  2025-07-30 12:11     ` [PATCH V2 04/20] nvdimm/label: CXL labels skip the need for 'interleave-set cookie' Neeraj Kumar
  2025-08-13 13:44       ` Jonathan Cameron
@ 2025-08-15 21:02       ` Dave Jiang
  2025-08-19 16:04       ` Ira Weiny
  2 siblings, 0 replies; 67+ messages in thread
From: Dave Jiang @ 2025-08-15 21:02 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel



On 7/30/25 5:11 AM, Neeraj Kumar wrote:
> CXL LSA v2.1 utilizes the region labels stored in the LSA for interleave
> set configuration instead of interleave-set cookie used in previous LSA
> versions. As interleave-set cookie is not required for CXL LSA v2.1 format
> so skip its usage for CXL LSA 2.1 format
> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
> ---
>  drivers/nvdimm/namespace_devs.c | 3 ++-
>  drivers/nvdimm/region_devs.c    | 5 +++++
>  2 files changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
> index bdf1ed6f23d8..5b73119dc8fd 100644
> --- a/drivers/nvdimm/namespace_devs.c
> +++ b/drivers/nvdimm/namespace_devs.c
> @@ -1692,7 +1692,8 @@ static struct device *create_namespace_pmem(struct nd_region *nd_region,
>  	int rc = 0;
>  	u16 i;
>  
> -	if (cookie == 0) {
> +	/* CXL labels skip the need for 'interleave-set cookie' */

This comment doesn't make sense to me. If it's a CXL label, we continue to execute. There's no skipping. Or are you trying to say if it's CXL label, then checking of cookie value is unnecessary? But the cookie value still is being used later on. Maybe a bit more comments on what's going on here would be helpful.

DJ

> +	if (!ndd->cxl && cookie == 0) {
>  		dev_dbg(&nd_region->dev, "invalid interleave-set-cookie\n");
>  		return ERR_PTR(-ENXIO);
>  	}
> diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
> index de1ee5ebc851..2debe60f8bf0 100644
> --- a/drivers/nvdimm/region_devs.c
> +++ b/drivers/nvdimm/region_devs.c
> @@ -858,6 +858,11 @@ u64 nd_region_interleave_set_cookie(struct nd_region *nd_region,
>  	if (!nd_set)
>  		return 0;
>  
> +	/* CXL labels skip the need for 'interleave-set cookie' */
> +	if (nsindex && __le16_to_cpu(nsindex->major) == 2
> +			&& __le16_to_cpu(nsindex->minor) == 1)
> +		return 0;
> +
>  	if (nsindex && __le16_to_cpu(nsindex->major) == 1
>  			&& __le16_to_cpu(nsindex->minor) == 1)
>  		return nd_set->cookie1;


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

* Re: [PATCH V2 05/20] nvdimm/region_label: Add region label updation routine
  2025-07-30 12:11     ` [PATCH V2 05/20] nvdimm/region_label: Add region label updation routine Neeraj Kumar
  2025-07-31 15:07       ` kernel test robot
  2025-08-13 14:48       ` Jonathan Cameron
@ 2025-08-15 21:55       ` Dave Jiang
  2025-08-15 23:12       ` Dave Jiang
  2025-08-19 18:16       ` Ira Weiny
  4 siblings, 0 replies; 67+ messages in thread
From: Dave Jiang @ 2025-08-15 21:55 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel



On 7/30/25 5:11 AM, Neeraj Kumar wrote:
> Added __pmem_region_label_update region label update routine to update
> region label.
> 
> Also used guard(mutex)(&nd_mapping->lock) in place of mutex_lock() and
> mutex_unlock()
> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>

Subject, s/updation/update/ ?

> ---
>  drivers/nvdimm/label.c          | 171 +++++++++++++++++++++++++++++---
>  drivers/nvdimm/label.h          |   2 +
>  drivers/nvdimm/namespace_devs.c |  12 +++
>  drivers/nvdimm/nd.h             |  20 ++++
>  include/linux/libnvdimm.h       |   8 ++
>  5 files changed, 198 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
> index 3f8a6bdb77c7..94f2d0ba7aca 100644
> --- a/drivers/nvdimm/label.c
> +++ b/drivers/nvdimm/label.c
> @@ -381,6 +381,16 @@ static void nsl_calculate_checksum(struct nvdimm_drvdata *ndd,
>  	nsl_set_checksum(ndd, nd_label, sum);
>  }
>  
> +static void rgl_calculate_checksum(struct nvdimm_drvdata *ndd,

region_label_checksum()? rgl/rg is just a bit jarring to read even though I get nvdimm already has nd and nsl etc.

> +				   struct cxl_region_label *rg_label)

Prefer just spell out region_label

> +{
> +	u64 sum;
> +
> +	rgl_set_checksum(rg_label, 0);
> +	sum = nd_fletcher64(rg_label, sizeof_namespace_label(ndd), 1);
> +	rgl_set_checksum(rg_label, sum);
> +}
> +
>  static bool slot_valid(struct nvdimm_drvdata *ndd,
>  		struct nd_lsa_label *lsa_label, u32 slot)
>  {
> @@ -960,7 +970,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  		return rc;
>  
>  	/* Garbage collect the previous label */
> -	mutex_lock(&nd_mapping->lock);
> +	guard(mutex)(&nd_mapping->lock);
>  	list_for_each_entry(label_ent, &nd_mapping->labels, list) {
>  		if (!label_ent->label)
>  			continue;
> @@ -972,20 +982,20 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  	/* update index */
>  	rc = nd_label_write_index(ndd, ndd->ns_next,
>  			nd_inc_seq(__le32_to_cpu(nsindex->seq)), 0);
> -	if (rc == 0) {
> -		list_for_each_entry(label_ent, &nd_mapping->labels, list)
> -			if (!label_ent->label) {
> -				label_ent->label = lsa_label;
> -				lsa_label = NULL;
> -				break;
> -			}
> -		dev_WARN_ONCE(&nspm->nsio.common.dev, lsa_label,
> -				"failed to track label: %d\n",
> -				to_slot(ndd, lsa_label));
> -		if (lsa_label)
> -			rc = -ENXIO;
> -	}
> -	mutex_unlock(&nd_mapping->lock);
> +	if (rc)
> +		return rc;
> +
> +	list_for_each_entry(label_ent, &nd_mapping->labels, list)
> +		if (!label_ent->label) {
> +			label_ent->label = lsa_label;
> +			lsa_label = NULL;
> +			break;
> +		}

Would've preferred the original code to look like:

list_for_each_entry(label_ent, &nd_mapping->labels, list) {
	if (label_ent->label)
		continue;

	label_ent->label = lsa_label;
	lsa_label = NULL;
	break;
}

But ah well....

> +	dev_WARN_ONCE(&nspm->nsio.common.dev, lsa_label,> +			"failed to track label: %d\n",
> +			to_slot(ndd, lsa_label));
> +	if (lsa_label)
> +		rc = -ENXIO;

Just return here as Jonathan already mentioned. guard() helps with cleaning that up.

>  
>  	return rc;
>  }
> @@ -1127,6 +1137,137 @@ int nd_pmem_namespace_label_update(struct nd_region *nd_region,
>  	return 0;
>  }
>  
> +static int __pmem_region_label_update(struct nd_region *nd_region,
> +		struct nd_mapping *nd_mapping, int pos, unsigned long flags)
> +{
> +	struct nd_interleave_set *nd_set = nd_region->nd_set;
> +	struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
> +	struct nd_lsa_label *nd_label;
> +	struct cxl_region_label *rg_label;
> +	struct nd_namespace_index *nsindex;> +	struct nd_label_ent *label_ent;
> +	unsigned long *free;
> +	u32 nslot, slot;
> +	size_t offset;
> +	int rc;
> +	uuid_t tmp;

uuid instead of tmp would make the variable clearer to read

Also please arrange variable ordering in reverse xmas tree. 

> +
> +	if (!preamble_next(ndd, &nsindex, &free, &nslot))
> +		return -ENXIO;
> +
> +	/* allocate and write the label to the staging (next) index */
> +	slot = nd_label_alloc_slot(ndd);
> +	if (slot == UINT_MAX)
> +		return -ENXIO;
> +	dev_dbg(ndd->dev, "allocated: %d\n", slot);
> +
> +	nd_label = to_label(ndd, slot);
> +
> +	memset(nd_label, 0, sizeof_namespace_label(ndd));
> +	rg_label = &nd_label->rg_label;
> +
> +	/* Set Region Label Format identification UUID */
> +	uuid_parse(CXL_REGION_UUID, &tmp);
> +	export_uuid(nd_label->rg_label.type, &tmp);
> +
> +	/* Set Current Region Label UUID */
> +	export_uuid(nd_label->rg_label.uuid, &nd_set->uuid);
> +
> +	rg_label->flags = __cpu_to_le32(flags);
> +	rg_label->nlabel = __cpu_to_le16(nd_region->ndr_mappings);
> +	rg_label->position = __cpu_to_le16(pos);
> +	rg_label->dpa = __cpu_to_le64(nd_mapping->start);
> +	rg_label->rawsize = __cpu_to_le64(nd_mapping->size);
> +	rg_label->hpa = __cpu_to_le64(nd_set->res->start);
> +	rg_label->slot = __cpu_to_le32(slot);
> +	rg_label->ig = __cpu_to_le32(nd_set->interleave_granularity);
> +	rg_label->align = __cpu_to_le16(0);
> +
> +	/* Update fletcher64 Checksum */
> +	rgl_calculate_checksum(ndd, rg_label);
> +
> +	/* update label */
> +	offset = nd_label_offset(ndd, nd_label);
> +	rc = nvdimm_set_config_data(ndd, offset, nd_label,
> +			sizeof_namespace_label(ndd));
> +	if (rc < 0) {
> +		nd_label_free_slot(ndd, slot);
> +		return rc;
> +	}
> +
> +	/* Garbage collect the previous label */
> +	guard(mutex)(&nd_mapping->lock);
> +	list_for_each_entry(label_ent, &nd_mapping->labels, list) {
> +		if (!label_ent->label)
> +			continue;
> +		if (rgl_uuid_equal(&label_ent->label->rg_label, &nd_set->uuid))
> +			reap_victim(nd_mapping, label_ent);
> +	}
> +
> +	/* update index */
> +	rc = nd_label_write_index(ndd, ndd->ns_next,
> +			nd_inc_seq(__le32_to_cpu(nsindex->seq)), 0);
> +	if (rc)
> +		return rc;
> +
> +	list_for_each_entry(label_ent, &nd_mapping->labels, list)
> +		if (!label_ent->label) {
> +			label_ent->label = nd_label;
> +			nd_label = NULL;
> +			break;
> +		}
> +	dev_WARN_ONCE(&nd_region->dev, nd_label,
> +			"failed to track label: %d\n",
> +			to_slot(ndd, nd_label));
> +	if (nd_label)
> +		rc = -ENXIO;
just return here

> +
> +	return rc;
> +}
> +
> +int nd_pmem_region_label_update(struct nd_region *nd_region)
> +{
> +	int i, rc;
> +
> +	for (i = 0; i < nd_region->ndr_mappings; i++) {
> +		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
> +		struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
> +
> +		/* No need to update region label for non cxl format */
> +		if (!ndd->cxl)
> +			continue;

Would there be a mix of different nd mappings? I wonder if you can just 'return 0' if you find ndd->cxl on the first one and just skip everything.

> +
> +		/* Init labels to include region label */
> +		rc = init_labels(nd_mapping, 1);
> +
> +		if (rc < 0)
> +			return rc;
> +
> +		rc = __pmem_region_label_update(nd_region, nd_mapping, i,
> +					NSLABEL_FLAG_UPDATING);
> +
> +		if (rc)
> +			return rc;
> +	}
> +
> +	/* Clear the UPDATING flag per UEFI 2.7 expectations */
> +	for (i = 0; i < nd_region->ndr_mappings; i++) {
> +		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
> +		struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
> +
> +		/* No need to update region label for non cxl format */
> +		if (!ndd->cxl)
> +			continue;
> +> +		rc = __pmem_region_label_update(nd_region, nd_mapping, i, 0);
> +
> +		if (rc)
> +			return rc;
> +	}
> +
> +	return 0;
> +}
> +
>  int __init nd_label_init(void)
>  {
>  	WARN_ON(guid_parse(NVDIMM_BTT_GUID, &nvdimm_btt_guid));
> diff --git a/drivers/nvdimm/label.h b/drivers/nvdimm/label.h
> index 4883b3a1320f..0f428695017d 100644
> --- a/drivers/nvdimm/label.h
> +++ b/drivers/nvdimm/label.h
> @@ -190,6 +190,7 @@ struct nd_namespace_label {
>  struct nd_lsa_label {
>  	union {
>  		struct nd_namespace_label ns_label;
> +		struct cxl_region_label rg_label;
>  	};
>  };
>  
> @@ -233,4 +234,5 @@ struct nd_region;
>  struct nd_namespace_pmem;
>  int nd_pmem_namespace_label_update(struct nd_region *nd_region,
>  		struct nd_namespace_pmem *nspm, resource_size_t size);
> +int nd_pmem_region_label_update(struct nd_region *nd_region);
>  #endif /* __LABEL_H__ */
> diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
> index 5b73119dc8fd..02ae8162566c 100644
> --- a/drivers/nvdimm/namespace_devs.c
> +++ b/drivers/nvdimm/namespace_devs.c
> @@ -232,6 +232,18 @@ static ssize_t __alt_name_store(struct device *dev, const char *buf,
>  	return rc;
>  }
>  
> +int nd_region_label_update(struct nd_region *nd_region)
> +{
> +	int rc;
> +
> +	nvdimm_bus_lock(&nd_region->dev);
> +	rc = nd_pmem_region_label_update(nd_region);
> +	nvdimm_bus_unlock(&nd_region->dev);
> +
> +	return rc;
> +}
> +EXPORT_SYMBOL_GPL(nd_region_label_update);
> +
>  static int nd_namespace_label_update(struct nd_region *nd_region,
>  		struct device *dev)
>  {
> diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
> index 651847f1bbf9..15d94e3937f0 100644
> --- a/drivers/nvdimm/nd.h
> +++ b/drivers/nvdimm/nd.h
> @@ -322,6 +322,26 @@ static inline void nsl_set_region_uuid(struct nvdimm_drvdata *ndd,
>  		export_uuid(ns_label->cxl.region_uuid, uuid);
>  }
>  
> +static inline bool rgl_uuid_equal(struct cxl_region_label *rg_label,
> +				  const uuid_t *uuid)

region_label_uuid_equal() and region_label

> +{
> +	uuid_t tmp;

tmp_uuid

> +
> +	import_uuid(&tmp, rg_label->uuid);
> +	return uuid_equal(&tmp, uuid);
> +}
> +
> +static inline u64 rgl_get_checksum(struct cxl_region_label *rg_label)

region_label_get_checksum()

> +{
> +	return __le64_to_cpu(rg_label->checksum);
> +}
> +
> +static inline void rgl_set_checksum(struct cxl_region_label *rg_label,
region_label_set_checksum()

> +				    u64 checksum)
> +{
> +	rg_label->checksum = __cpu_to_le64(checksum);
> +}
> +
>  bool nsl_validate_type_guid(struct nvdimm_drvdata *ndd,
>  			    struct nd_namespace_label *nd_label, guid_t *guid);
>  enum nvdimm_claim_class nsl_get_claim_class(struct nvdimm_drvdata *ndd,
> diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
> index 0a55900842c8..b06bd45373f4 100644
> --- a/include/linux/libnvdimm.h
> +++ b/include/linux/libnvdimm.h
> @@ -115,6 +115,13 @@ struct nd_interleave_set {
>  	u64 altcookie;
>  
>  	guid_t type_guid;
> +
> +	/* v2.1 region label info */
> +	uuid_t uuid;
> +	int interleave_ways;
> +	int interleave_granularity;
> +	struct resource *res;
> +	int nr_targets;
>  };
>  
>  struct nd_mapping_desc {
> @@ -302,6 +309,7 @@ int nvdimm_has_flush(struct nd_region *nd_region);
>  int nvdimm_has_cache(struct nd_region *nd_region);
>  int nvdimm_in_overwrite(struct nvdimm *nvdimm);
>  bool is_nvdimm_sync(struct nd_region *nd_region);
> +int nd_region_label_update(struct nd_region *nd_region);
>  
>  static inline int nvdimm_ctl(struct nvdimm *nvdimm, unsigned int cmd, void *buf,
>  		unsigned int buf_len, int *cmd_rc)


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

* Re: [PATCH V2 02/20] nvdimm/label: Prep patch to accommodate cxl lsa 2.1 support
  2025-07-30 12:11     ` [PATCH V2 02/20] nvdimm/label: Prep patch to accommodate cxl lsa 2.1 support Neeraj Kumar
  2025-08-13 13:23       ` Jonathan Cameron
@ 2025-08-15 22:02       ` Dave Jiang
  2025-08-18 21:48       ` Dave Jiang
  2025-08-19 15:38       ` Ira Weiny
  3 siblings, 0 replies; 67+ messages in thread
From: Dave Jiang @ 2025-08-15 22:02 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel



On 7/30/25 5:11 AM, Neeraj Kumar wrote:
> LSA 2.1 format introduces region label, which can also reside
> into LSA along with only namespace label as per v1.1 and v1.2
> 
> As both namespace and region labels are of same size of 256 bytes.
> Thus renamed "struct nd_namespace_label" to "struct nd_lsa_label",
> where both namespace label and region label can stay as union.
> 
> No functional change introduced.
> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
> ---
>  drivers/nvdimm/label.c          | 58 +++++++++++++++++++--------------
>  drivers/nvdimm/label.h          | 12 ++++++-
>  drivers/nvdimm/namespace_devs.c | 33 +++++++++++++------
>  drivers/nvdimm/nd.h             |  2 +-
>  4 files changed, 68 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
> index 7a011ee02d79..75bc11da4c11 100644
> --- a/drivers/nvdimm/label.c
> +++ b/drivers/nvdimm/label.c
> @@ -271,7 +271,7 @@ static void nd_label_copy(struct nvdimm_drvdata *ndd,
>  	memcpy(dst, src, sizeof_namespace_index(ndd));
>  }
>  
> -static struct nd_namespace_label *nd_label_base(struct nvdimm_drvdata *ndd)
> +static struct nd_lsa_label *nd_label_base(struct nvdimm_drvdata *ndd)
>  {
>  	void *base = to_namespace_index(ndd, 0);
>  
> @@ -279,7 +279,7 @@ static struct nd_namespace_label *nd_label_base(struct nvdimm_drvdata *ndd)
>  }
>  
>  static int to_slot(struct nvdimm_drvdata *ndd,
> -		struct nd_namespace_label *nd_label)
> +		struct nd_lsa_label *nd_label)
>  {
>  	unsigned long label, base;
>  
> @@ -289,14 +289,14 @@ static int to_slot(struct nvdimm_drvdata *ndd,
>  	return (label - base) / sizeof_namespace_label(ndd);
>  }
>  
> -static struct nd_namespace_label *to_label(struct nvdimm_drvdata *ndd, int slot)
> +static struct nd_lsa_label *to_label(struct nvdimm_drvdata *ndd, int slot)
>  {
>  	unsigned long label, base;
>  
>  	base = (unsigned long) nd_label_base(ndd);
>  	label = base + sizeof_namespace_label(ndd) * slot;
>  
> -	return (struct nd_namespace_label *) label;
> +	return (struct nd_lsa_label *) label;
>  }
>  
>  #define for_each_clear_bit_le(bit, addr, size) \
> @@ -382,9 +382,10 @@ static void nsl_calculate_checksum(struct nvdimm_drvdata *ndd,
>  }
>  
>  static bool slot_valid(struct nvdimm_drvdata *ndd,
> -		struct nd_namespace_label *nd_label, u32 slot)
> +		struct nd_lsa_label *lsa_label, u32 slot)
>  {
>  	bool valid;
> +	struct nd_namespace_label *nd_label = &lsa_label->ns_label;
>  
>  	/* check that we are written where we expect to be written */
>  	if (slot != nsl_get_slot(ndd, nd_label))
> @@ -405,6 +406,7 @@ int nd_label_reserve_dpa(struct nvdimm_drvdata *ndd)
>  		return 0; /* no label, nothing to reserve */
>  
>  	for_each_clear_bit_le(slot, free, nslot) {
> +		struct nd_lsa_label *lsa_label;
>  		struct nd_namespace_label *nd_label;
>  		struct nd_region *nd_region = NULL;
>  		struct nd_label_id label_id;
> @@ -412,9 +414,10 @@ int nd_label_reserve_dpa(struct nvdimm_drvdata *ndd)
>  		uuid_t label_uuid;
>  		u32 flags;
>  
> -		nd_label = to_label(ndd, slot);
> +		lsa_label = to_label(ndd, slot);
> +		nd_label = &lsa_label->ns_label;
>  
> -		if (!slot_valid(ndd, nd_label, slot))
> +		if (!slot_valid(ndd, lsa_label, slot))
>  			continue;
>  
>  		nsl_get_uuid(ndd, nd_label, &label_uuid);
> @@ -565,11 +568,13 @@ int nd_label_active_count(struct nvdimm_drvdata *ndd)
>  		return 0;
>  
>  	for_each_clear_bit_le(slot, free, nslot) {
> +		struct nd_lsa_label *lsa_label;
>  		struct nd_namespace_label *nd_label;
>  
> -		nd_label = to_label(ndd, slot);
> +		lsa_label = to_label(ndd, slot);
> +		nd_label = &lsa_label->ns_label;
>  
> -		if (!slot_valid(ndd, nd_label, slot)) {
> +		if (!slot_valid(ndd, lsa_label, slot)) {
>  			u32 label_slot = nsl_get_slot(ndd, nd_label);
>  			u64 size = nsl_get_rawsize(ndd, nd_label);
>  			u64 dpa = nsl_get_dpa(ndd, nd_label);
> @@ -584,7 +589,7 @@ int nd_label_active_count(struct nvdimm_drvdata *ndd)
>  	return count;
>  }
>  
> -struct nd_namespace_label *nd_label_active(struct nvdimm_drvdata *ndd, int n)
> +struct nd_lsa_label *nd_label_active(struct nvdimm_drvdata *ndd, int n)
>  {
>  	struct nd_namespace_index *nsindex;
>  	unsigned long *free;
> @@ -594,10 +599,10 @@ struct nd_namespace_label *nd_label_active(struct nvdimm_drvdata *ndd, int n)
>  		return NULL;
>  
>  	for_each_clear_bit_le(slot, free, nslot) {
> -		struct nd_namespace_label *nd_label;
> +		struct nd_lsa_label *lsa_label;
>  
> -		nd_label = to_label(ndd, slot);
> -		if (!slot_valid(ndd, nd_label, slot))
> +		lsa_label = to_label(ndd, slot);
> +		if (!slot_valid(ndd, lsa_label, slot))
>  			continue;
>  
>  		if (n-- == 0)
> @@ -738,7 +743,7 @@ static int nd_label_write_index(struct nvdimm_drvdata *ndd, int index, u32 seq,
>  }
>  
>  static unsigned long nd_label_offset(struct nvdimm_drvdata *ndd,
> -		struct nd_namespace_label *nd_label)
> +		struct nd_lsa_label *nd_label)
>  {
>  	return (unsigned long) nd_label
>  		- (unsigned long) to_namespace_index(ndd, 0);
> @@ -892,6 +897,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  	struct nd_namespace_common *ndns = &nspm->nsio.common;
>  	struct nd_interleave_set *nd_set = nd_region->nd_set;
>  	struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
> +	struct nd_lsa_label *lsa_label;
>  	struct nd_namespace_label *nd_label;
>  	struct nd_namespace_index *nsindex;
>  	struct nd_label_ent *label_ent;
> @@ -923,8 +929,10 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  		return -ENXIO;
>  	dev_dbg(ndd->dev, "allocated: %d\n", slot);
>  
> -	nd_label = to_label(ndd, slot);
> -	memset(nd_label, 0, sizeof_namespace_label(ndd));
> +	lsa_label = to_label(ndd, slot);
> +	memset(lsa_label, 0, sizeof_namespace_label(ndd));
> +
> +	nd_label = &lsa_label->ns_label;
>  	nsl_set_uuid(ndd, nd_label, nspm->uuid);
>  	nsl_set_name(ndd, nd_label, nspm->alt_name);
>  	nsl_set_flags(ndd, nd_label, flags);
> @@ -942,7 +950,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  	nd_dbg_dpa(nd_region, ndd, res, "\n");
>  
>  	/* update label */
> -	offset = nd_label_offset(ndd, nd_label);
> +	offset = nd_label_offset(ndd, lsa_label);
>  	rc = nvdimm_set_config_data(ndd, offset, nd_label,
>  			sizeof_namespace_label(ndd));
>  	if (rc < 0)
> @@ -954,7 +962,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  		if (!label_ent->label)
>  			continue;
>  		if (test_and_clear_bit(ND_LABEL_REAP, &label_ent->flags) ||
> -		    nsl_uuid_equal(ndd, label_ent->label, nspm->uuid))
> +		    nsl_uuid_equal(ndd, &label_ent->label->ns_label, nspm->uuid))
>  			reap_victim(nd_mapping, label_ent);
>  	}
>  
> @@ -964,14 +972,14 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  	if (rc == 0) {
>  		list_for_each_entry(label_ent, &nd_mapping->labels, list)
>  			if (!label_ent->label) {
> -				label_ent->label = nd_label;
> -				nd_label = NULL;
> +				label_ent->label = lsa_label;
> +				lsa_label = NULL;
>  				break;
>  			}
> -		dev_WARN_ONCE(&nspm->nsio.common.dev, nd_label,
> +		dev_WARN_ONCE(&nspm->nsio.common.dev, lsa_label,
>  				"failed to track label: %d\n",
> -				to_slot(ndd, nd_label));
> -		if (nd_label)
> +				to_slot(ndd, lsa_label));
> +		if (lsa_label)
>  			rc = -ENXIO;
>  	}
>  	mutex_unlock(&nd_mapping->lock);
> @@ -1042,12 +1050,12 @@ static int del_labels(struct nd_mapping *nd_mapping, uuid_t *uuid)
>  
>  	mutex_lock(&nd_mapping->lock);
>  	list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list) {
> -		struct nd_namespace_label *nd_label = label_ent->label;
> +		struct nd_lsa_label *nd_label = label_ent->label;
>  
>  		if (!nd_label)
>  			continue;
>  		active++;
> -		if (!nsl_uuid_equal(ndd, nd_label, uuid))
> +		if (!nsl_uuid_equal(ndd, &nd_label->ns_label, uuid))
>  			continue;
>  		active--;
>  		slot = to_slot(ndd, nd_label);
> diff --git a/drivers/nvdimm/label.h b/drivers/nvdimm/label.h
> index 0650fb4b9821..4883b3a1320f 100644
> --- a/drivers/nvdimm/label.h
> +++ b/drivers/nvdimm/label.h
> @@ -183,6 +183,16 @@ struct nd_namespace_label {
>  	};
>  };
>  
> +/*
> + * LSA 2.1 format introduces region label, which can also reside
> + * into LSA along with only namespace label as per v1.1 and v1.2
> + */
> +struct nd_lsa_label {
> +	union {
> +		struct nd_namespace_label ns_label;
> +	};
> +};

I think originally 'struct nd_namespace_label' wrapped a union to avoid changing code that already has 'struct nd_namespace_label' in the function. But since you are creating a whole new thing, maybe just create a union directly since you end up touching all the function parameters in this patch anyways.

union nd_lsa_label {
	struct nd_namespace_label ns_label;
	struct cxl_region_label region_label;
};

DJ

> +
>  #define NVDIMM_BTT_GUID "8aed63a2-29a2-4c66-8b12-f05d15d3922a"
>  #define NVDIMM_BTT2_GUID "18633bfc-1735-4217-8ac9-17239282d3f8"
>  #define NVDIMM_PFN_GUID "266400ba-fb9f-4677-bcb0-968f11d0d225"
> @@ -215,7 +225,7 @@ struct nvdimm_drvdata;
>  int nd_label_data_init(struct nvdimm_drvdata *ndd);
>  size_t sizeof_namespace_index(struct nvdimm_drvdata *ndd);
>  int nd_label_active_count(struct nvdimm_drvdata *ndd);
> -struct nd_namespace_label *nd_label_active(struct nvdimm_drvdata *ndd, int n);
> +struct nd_lsa_label *nd_label_active(struct nvdimm_drvdata *ndd, int n);
>  u32 nd_label_alloc_slot(struct nvdimm_drvdata *ndd);
>  bool nd_label_free_slot(struct nvdimm_drvdata *ndd, u32 slot);
>  u32 nd_label_nfree(struct nvdimm_drvdata *ndd);
> diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
> index 55cfbf1e0a95..bdf1ed6f23d8 100644
> --- a/drivers/nvdimm/namespace_devs.c
> +++ b/drivers/nvdimm/namespace_devs.c
> @@ -1009,10 +1009,11 @@ static int namespace_update_uuid(struct nd_region *nd_region,
>  
>  		mutex_lock(&nd_mapping->lock);
>  		list_for_each_entry(label_ent, &nd_mapping->labels, list) {
> -			struct nd_namespace_label *nd_label = label_ent->label;
> +			struct nd_namespace_label *nd_label;
>  			struct nd_label_id label_id;
>  			uuid_t uuid;
>  
> +			nd_label = &label_ent->label->ns_label;
>  			if (!nd_label)
>  				continue;
>  			nsl_get_uuid(ndd, nd_label, &uuid);
> @@ -1573,11 +1574,14 @@ static bool has_uuid_at_pos(struct nd_region *nd_region, const uuid_t *uuid,
>  		bool found_uuid = false;
>  
>  		list_for_each_entry(label_ent, &nd_mapping->labels, list) {
> -			struct nd_namespace_label *nd_label = label_ent->label;
> +			struct nd_lsa_label *lsa_label = label_ent->label;
> +			struct nd_namespace_label *nd_label;
>  			u16 position;
>  
> -			if (!nd_label)
> +			if (!lsa_label)
>  				continue;
> +
> +			nd_label = &lsa_label->ns_label;
>  			position = nsl_get_position(ndd, nd_label);
>  
>  			if (!nsl_validate_isetcookie(ndd, nd_label, cookie))
> @@ -1615,17 +1619,21 @@ static int select_pmem_id(struct nd_region *nd_region, const uuid_t *pmem_id)
>  	for (i = 0; i < nd_region->ndr_mappings; i++) {
>  		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
>  		struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
> +		struct nd_lsa_label *lsa_label = NULL;
>  		struct nd_namespace_label *nd_label = NULL;
>  		u64 hw_start, hw_end, pmem_start, pmem_end;
>  		struct nd_label_ent *label_ent;
>  
>  		lockdep_assert_held(&nd_mapping->lock);
>  		list_for_each_entry(label_ent, &nd_mapping->labels, list) {
> -			nd_label = label_ent->label;
> -			if (!nd_label)
> +			lsa_label = label_ent->label;
> +			if (!lsa_label)
>  				continue;
> +
> +			nd_label = &lsa_label->ns_label;
>  			if (nsl_uuid_equal(ndd, nd_label, pmem_id))
>  				break;
> +			lsa_label = NULL;
>  			nd_label = NULL;
>  		}
>  
> @@ -1746,19 +1754,21 @@ static struct device *create_namespace_pmem(struct nd_region *nd_region,
>  
>  	/* Calculate total size and populate namespace properties from label0 */
>  	for (i = 0; i < nd_region->ndr_mappings; i++) {
> +		struct nd_lsa_label *lsa_label;
>  		struct nd_namespace_label *label0;
>  		struct nvdimm_drvdata *ndd;
>  
>  		nd_mapping = &nd_region->mapping[i];
>  		label_ent = list_first_entry_or_null(&nd_mapping->labels,
>  				typeof(*label_ent), list);
> -		label0 = label_ent ? label_ent->label : NULL;
> +		lsa_label = label_ent ? label_ent->label : NULL;
>  
> -		if (!label0) {
> +		if (!lsa_label) {
>  			WARN_ON(1);
>  			continue;
>  		}
>  
> +		label0 = &lsa_label->ns_label;
>  		ndd = to_ndd(nd_mapping);
>  		size += nsl_get_rawsize(ndd, label0);
>  		if (nsl_get_position(ndd, label0) != 0)
> @@ -1943,12 +1953,15 @@ static struct device **scan_labels(struct nd_region *nd_region)
>  
>  	/* "safe" because create_namespace_pmem() might list_move() label_ent */
>  	list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list) {
> -		struct nd_namespace_label *nd_label = label_ent->label;
> +		struct nd_lsa_label *lsa_label = label_ent->label;
> +		struct nd_namespace_label *nd_label;
>  		struct device **__devs;
>  
> -		if (!nd_label)
> +		if (!lsa_label)
>  			continue;
>  
> +		nd_label = &lsa_label->ns_label;
> +
>  		/* skip labels that describe extents outside of the region */
>  		if (nsl_get_dpa(ndd, nd_label) < nd_mapping->start ||
>  		    nsl_get_dpa(ndd, nd_label) > map_end)
> @@ -2122,7 +2135,7 @@ static int init_active_labels(struct nd_region *nd_region)
>  		if (!count)
>  			continue;
>  		for (j = 0; j < count; j++) {
> -			struct nd_namespace_label *label;
> +			struct nd_lsa_label *label;
>  
>  			label_ent = kzalloc(sizeof(*label_ent), GFP_KERNEL);
>  			if (!label_ent)
> diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
> index 1cc06cc58d14..61348dee687d 100644
> --- a/drivers/nvdimm/nd.h
> +++ b/drivers/nvdimm/nd.h
> @@ -376,7 +376,7 @@ enum nd_label_flags {
>  struct nd_label_ent {
>  	struct list_head list;
>  	unsigned long flags;
> -	struct nd_namespace_label *label;
> +	struct nd_lsa_label *label;
>  };
>  
>  enum nd_mapping_lock_class {


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

* Re: [PATCH V2 06/20] nvdimm/region_label: Add region label deletion routine
  2025-07-30 12:11     ` [PATCH V2 06/20] nvdimm/region_label: Add region label deletion routine Neeraj Kumar
  2025-08-13 14:53       ` Jonathan Cameron
@ 2025-08-15 22:22       ` Dave Jiang
  1 sibling, 0 replies; 67+ messages in thread
From: Dave Jiang @ 2025-08-15 22:22 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel



On 7/30/25 5:11 AM, Neeraj Kumar wrote:
> Added cxl v2.1 format region label deletion routine. This function is
> used to delete region label from LSA
> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
> ---
>  drivers/nvdimm/label.c          | 77 ++++++++++++++++++++++++++++++---
>  drivers/nvdimm/label.h          |  6 +++
>  drivers/nvdimm/namespace_devs.c | 12 +++++
>  drivers/nvdimm/nd.h             |  9 ++++
>  include/linux/libnvdimm.h       |  1 +
>  5 files changed, 100 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
> index 94f2d0ba7aca..be18278d6cea 100644
> --- a/drivers/nvdimm/label.c
> +++ b/drivers/nvdimm/label.c
> @@ -1044,7 +1044,8 @@ static int init_labels(struct nd_mapping *nd_mapping, int num_labels)
>  	return max(num_labels, old_num_labels);
>  }
>  
> -static int del_labels(struct nd_mapping *nd_mapping, uuid_t *uuid)
> +static int del_labels(struct nd_mapping *nd_mapping, uuid_t *uuid,
> +		enum label_type ltype)
>  {
>  	struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
>  	struct nd_label_ent *label_ent, *e;
> @@ -1068,8 +1069,23 @@ static int del_labels(struct nd_mapping *nd_mapping, uuid_t *uuid)
>  		if (!nd_label)
>  			continue;
>  		active++;
> -		if (!nsl_uuid_equal(ndd, &nd_label->ns_label, uuid))
> -			continue;
> +
> +		switch (ltype) {
> +		case NS_LABEL_TYPE:
> +			if (!nsl_uuid_equal(ndd, &nd_label->ns_label, uuid))
> +				continue;
> +
> +			break;
> +		case RG_LABEL_TYPE:
> +			if (!rgl_uuid_equal(&nd_label->rg_label, uuid))
> +				continue;
> +
> +			break;
> +		default:
> +			dev_err(ndd->dev, "Invalid label type\n");
> +			return 0;
> +		}
> +
>  		active--;
>  		slot = to_slot(ndd, nd_label);
>  		nd_label_free_slot(ndd, slot);
> @@ -1079,7 +1095,7 @@ static int del_labels(struct nd_mapping *nd_mapping, uuid_t *uuid)
>  	}
>  	list_splice_tail_init(&list, &nd_mapping->labels);
>  
> -	if (active == 0) {
> +	if ((ltype == NS_LABEL_TYPE) && (active == 0)) {
>  		nd_mapping_free_labels(nd_mapping);
>  		dev_dbg(ndd->dev, "no more active labels\n");
>  	}
> @@ -1101,7 +1117,8 @@ int nd_pmem_namespace_label_update(struct nd_region *nd_region,
>  		int count = 0;
>  
>  		if (size == 0) {
> -			rc = del_labels(nd_mapping, nspm->uuid);
> +			rc = del_labels(nd_mapping, nspm->uuid,
> +					NS_LABEL_TYPE);
>  			if (rc)
>  				return rc;
>  			continue;
> @@ -1268,6 +1285,56 @@ int nd_pmem_region_label_update(struct nd_region *nd_region)
>  	return 0;
>  }
>  
> +int nd_pmem_region_label_delete(struct nd_region *nd_region)
> +{
> +	int i, rc;
> +	struct nd_interleave_set *nd_set = nd_region->nd_set;
> +	struct nd_label_ent *label_ent;
> +	int ns_region_cnt = 0;

reverse xmas tree pls

> +
> +	for (i = 0; i < nd_region->ndr_mappings; i++) {
> +		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
> +		struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
> +
> +		/* Find non cxl format supported ndr_mappings */
> +		if (!ndd->cxl) {
> +			dev_info(&nd_region->dev, "Region label unsupported\n");
> +			return -EINVAL;
> +		}
> +
> +		/* Find if any NS label using this region */
> +		mutex_lock(&nd_mapping->lock);
> +		list_for_each_entry(label_ent, &nd_mapping->labels, list) {
> +			if (!label_ent->label)
> +				continue;
> +
> +			/*
> +			 * Check if any available NS labels has same
> +			 * region_uuid in LSA
> +			 */
> +			if (nsl_region_uuid_equal(&label_ent->label->ns_label,
> +						  &nd_set->uuid))
> +				ns_region_cnt++;
> +		}
> +		mutex_unlock(&nd_mapping->lock);
> +	}
> +
> +	if (ns_region_cnt) {
> +		dev_dbg(&nd_region->dev, "Region/Namespace label in use\n");
> +		return -EBUSY;
> +	}
> +
> +	for (i = 0; i < nd_region->ndr_mappings; i++) {
> +		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
> +
> +		rc = del_labels(nd_mapping, &nd_set->uuid, RG_LABEL_TYPE);
> +		if (rc)
> +			return rc;
> +	}
> +
> +	return 0;
> +}
> +
>  int __init nd_label_init(void)
>  {
>  	WARN_ON(guid_parse(NVDIMM_BTT_GUID, &nvdimm_btt_guid));
> diff --git a/drivers/nvdimm/label.h b/drivers/nvdimm/label.h
> index 0f428695017d..cc14068511cf 100644
> --- a/drivers/nvdimm/label.h
> +++ b/drivers/nvdimm/label.h
> @@ -30,6 +30,11 @@ enum {
>  	ND_NSINDEX_INIT = 0x1,
>  };
>  
> +enum label_type {
> +	RG_LABEL_TYPE,

REGION_LABEL_TYPE preferred

> +	NS_LABEL_TYPE,
> +};
> +
>  /**
>   * struct nd_namespace_index - label set superblock
>   * @sig: NAMESPACE_INDEX\0
> @@ -235,4 +240,5 @@ struct nd_namespace_pmem;
>  int nd_pmem_namespace_label_update(struct nd_region *nd_region,
>  		struct nd_namespace_pmem *nspm, resource_size_t size);
>  int nd_pmem_region_label_update(struct nd_region *nd_region);
> +int nd_pmem_region_label_delete(struct nd_region *nd_region);
>  #endif /* __LABEL_H__ */
> diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
> index 02ae8162566c..e5c2f78ca7dd 100644
> --- a/drivers/nvdimm/namespace_devs.c
> +++ b/drivers/nvdimm/namespace_devs.c
> @@ -244,6 +244,18 @@ int nd_region_label_update(struct nd_region *nd_region)
>  }
>  EXPORT_SYMBOL_GPL(nd_region_label_update);
>  
> +int nd_region_label_delete(struct nd_region *nd_region)
> +{
> +	int rc;
> +
> +	nvdimm_bus_lock(&nd_region->dev);
> +	rc = nd_pmem_region_label_delete(nd_region);
> +	nvdimm_bus_unlock(&nd_region->dev);
> +
> +	return rc;
> +}
> +EXPORT_SYMBOL_GPL(nd_region_label_delete);
> +
>  static int nd_namespace_label_update(struct nd_region *nd_region,
>  		struct device *dev)
>  {
> diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
> index 15d94e3937f0..6585747154c2 100644
> --- a/drivers/nvdimm/nd.h
> +++ b/drivers/nvdimm/nd.h
> @@ -322,6 +322,15 @@ static inline void nsl_set_region_uuid(struct nvdimm_drvdata *ndd,
>  		export_uuid(ns_label->cxl.region_uuid, uuid);
>  }
>  
> +static inline bool nsl_region_uuid_equal(struct nd_namespace_label *ns_label,
> +				  const uuid_t *uuid)
> +{
> +	uuid_t tmp;

s/tmp/uuid/

> +
> +	import_uuid(&tmp, ns_label->cxl.region_uuid);
> +	return uuid_equal(&tmp, uuid);
> +}
> +
>  static inline bool rgl_uuid_equal(struct cxl_region_label *rg_label,
>  				  const uuid_t *uuid)
>  {
> diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
> index b06bd45373f4..b2e16914ab52 100644
> --- a/include/linux/libnvdimm.h
> +++ b/include/linux/libnvdimm.h
> @@ -310,6 +310,7 @@ int nvdimm_has_cache(struct nd_region *nd_region);
>  int nvdimm_in_overwrite(struct nvdimm *nvdimm);
>  bool is_nvdimm_sync(struct nd_region *nd_region);
>  int nd_region_label_update(struct nd_region *nd_region);
> +int nd_region_label_delete(struct nd_region *nd_region);
>  
>  static inline int nvdimm_ctl(struct nvdimm *nvdimm, unsigned int cmd, void *buf,
>  		unsigned int buf_len, int *cmd_rc)


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

* Re: [PATCH V2 05/20] nvdimm/region_label: Add region label updation routine
  2025-07-30 12:11     ` [PATCH V2 05/20] nvdimm/region_label: Add region label updation routine Neeraj Kumar
                         ` (2 preceding siblings ...)
  2025-08-15 21:55       ` Dave Jiang
@ 2025-08-15 23:12       ` Dave Jiang
  2025-08-19 18:16       ` Ira Weiny
  4 siblings, 0 replies; 67+ messages in thread
From: Dave Jiang @ 2025-08-15 23:12 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel



On 7/30/25 5:11 AM, Neeraj Kumar wrote:
<snip>

> diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
> index 651847f1bbf9..15d94e3937f0 100644
> --- a/drivers/nvdimm/nd.h
> +++ b/drivers/nvdimm/nd.h
> @@ -322,6 +322,26 @@ static inline void nsl_set_region_uuid(struct nvdimm_drvdata *ndd,
>  		export_uuid(ns_label->cxl.region_uuid, uuid);
>  }
>  
> +static inline bool rgl_uuid_equal(struct cxl_region_label *rg_label,
> +				  const uuid_t *uuid)
> +{
> +	uuid_t tmp;
> +
> +	import_uuid(&tmp, rg_label->uuid);
> +	return uuid_equal(&tmp, uuid);

Why the extra copy via import_uuid() rather than directly compare rg_labe->uuid vs the uuid param?

DJ

> +}
> +
> +static inline u64 rgl_get_checksum(struct cxl_region_label *rg_label)
> +{
> +	return __le64_to_cpu(rg_label->checksum);
> +}
> +
> +static inline void rgl_set_checksum(struct cxl_region_label *rg_label,
> +				    u64 checksum)
> +{
> +	rg_label->checksum = __cpu_to_le64(checksum);
> +}
> +
>  bool nsl_validate_type_guid(struct nvdimm_drvdata *ndd,
>  			    struct nd_namespace_label *nd_label, guid_t *guid);
>  enum nvdimm_claim_class nsl_get_claim_class(struct nvdimm_drvdata *ndd,
> diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
> index 0a55900842c8..b06bd45373f4 100644
> --- a/include/linux/libnvdimm.h
> +++ b/include/linux/libnvdimm.h
> @@ -115,6 +115,13 @@ struct nd_interleave_set {
>  	u64 altcookie;
>  
>  	guid_t type_guid;
> +
> +	/* v2.1 region label info */
> +	uuid_t uuid;
> +	int interleave_ways;
> +	int interleave_granularity;
> +	struct resource *res;
> +	int nr_targets;
>  };
>  
>  struct nd_mapping_desc {
> @@ -302,6 +309,7 @@ int nvdimm_has_flush(struct nd_region *nd_region);
>  int nvdimm_has_cache(struct nd_region *nd_region);
>  int nvdimm_in_overwrite(struct nvdimm *nvdimm);
>  bool is_nvdimm_sync(struct nd_region *nd_region);
> +int nd_region_label_update(struct nd_region *nd_region);
>  
>  static inline int nvdimm_ctl(struct nvdimm *nvdimm, unsigned int cmd, void *buf,
>  		unsigned int buf_len, int *cmd_rc)


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

* Re: [PATCH V2 02/20] nvdimm/label: Prep patch to accommodate cxl lsa 2.1 support
  2025-07-30 12:11     ` [PATCH V2 02/20] nvdimm/label: Prep patch to accommodate cxl lsa 2.1 support Neeraj Kumar
  2025-08-13 13:23       ` Jonathan Cameron
  2025-08-15 22:02       ` Dave Jiang
@ 2025-08-18 21:48       ` Dave Jiang
  2025-08-19 15:38       ` Ira Weiny
  3 siblings, 0 replies; 67+ messages in thread
From: Dave Jiang @ 2025-08-18 21:48 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel



On 7/30/25 5:11 AM, Neeraj Kumar wrote:
> LSA 2.1 format introduces region label, which can also reside
> into LSA along with only namespace label as per v1.1 and v1.2
> 
> As both namespace and region labels are of same size of 256 bytes.
> Thus renamed "struct nd_namespace_label" to "struct nd_lsa_label",
> where both namespace label and region label can stay as union.
> 
> No functional change introduced.
> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
> ---
>  drivers/nvdimm/label.c          | 58 +++++++++++++++++++--------------
>  drivers/nvdimm/label.h          | 12 ++++++-
>  drivers/nvdimm/namespace_devs.c | 33 +++++++++++++------
>  drivers/nvdimm/nd.h             |  2 +-
>  4 files changed, 68 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
> index 7a011ee02d79..75bc11da4c11 100644
> --- a/drivers/nvdimm/label.c
> +++ b/drivers/nvdimm/label.c
> @@ -271,7 +271,7 @@ static void nd_label_copy(struct nvdimm_drvdata *ndd,
>  	memcpy(dst, src, sizeof_namespace_index(ndd));
>  }
>  
> -static struct nd_namespace_label *nd_label_base(struct nvdimm_drvdata *ndd)
> +static struct nd_lsa_label *nd_label_base(struct nvdimm_drvdata *ndd)

This function caught my eye. I think that given the way it's being used, maybe it should be returning 'unsigned long' instead of a struct given every instance it's being used, it gets converted back to 'unsigned long'.

$ git grep -n nd_label_base
label.c:274:static struct nd_lsa_label *nd_label_base(struct nvdimm_drvdata *ndd)
label.c:287:    base = (unsigned long) nd_label_base(ndd);
label.c:296:    base = (unsigned long) nd_label_base(ndd);
label.c:782:    offset = (unsigned long) nd_label_base(ndd)

>  {
>  	void *base = to_namespace_index(ndd, 0);
>  
> @@ -279,7 +279,7 @@ static struct nd_namespace_label *nd_label_base(struct nvdimm_drvdata *ndd)
>  }
>  
>  static int to_slot(struct nvdimm_drvdata *ndd,
> -		struct nd_namespace_label *nd_label)
> +		struct nd_lsa_label *nd_label)
>  {
>  	unsigned long label, base;
>  
> @@ -289,14 +289,14 @@ static int to_slot(struct nvdimm_drvdata *ndd,
>  	return (label - base) / sizeof_namespace_label(ndd);
>  }
>  
> -static struct nd_namespace_label *to_label(struct nvdimm_drvdata *ndd, int slot)
> +static struct nd_lsa_label *to_label(struct nvdimm_drvdata *ndd, int slot)
>  {
>  	unsigned long label, base;
>  
>  	base = (unsigned long) nd_label_base(ndd);
>  	label = base + sizeof_namespace_label(ndd) * slot;
>  
> -	return (struct nd_namespace_label *) label;
> +	return (struct nd_lsa_label *) label;
>  }
>  
>  #define for_each_clear_bit_le(bit, addr, size) \
> @@ -382,9 +382,10 @@ static void nsl_calculate_checksum(struct nvdimm_drvdata *ndd,
>  }
>  
>  static bool slot_valid(struct nvdimm_drvdata *ndd,
> -		struct nd_namespace_label *nd_label, u32 slot)
> +		struct nd_lsa_label *lsa_label, u32 slot)
>  {
>  	bool valid;
> +	struct nd_namespace_label *nd_label = &lsa_label->ns_label;
>  
>  	/* check that we are written where we expect to be written */
>  	if (slot != nsl_get_slot(ndd, nd_label))
> @@ -405,6 +406,7 @@ int nd_label_reserve_dpa(struct nvdimm_drvdata *ndd)
>  		return 0; /* no label, nothing to reserve */
>  
>  	for_each_clear_bit_le(slot, free, nslot) {
> +		struct nd_lsa_label *lsa_label;
>  		struct nd_namespace_label *nd_label;
>  		struct nd_region *nd_region = NULL;
>  		struct nd_label_id label_id;
> @@ -412,9 +414,10 @@ int nd_label_reserve_dpa(struct nvdimm_drvdata *ndd)
>  		uuid_t label_uuid;
>  		u32 flags;
>  
> -		nd_label = to_label(ndd, slot);
> +		lsa_label = to_label(ndd, slot);
> +		nd_label = &lsa_label->ns_label;
>  
> -		if (!slot_valid(ndd, nd_label, slot))
> +		if (!slot_valid(ndd, lsa_label, slot))
>  			continue;
>  
>  		nsl_get_uuid(ndd, nd_label, &label_uuid);
> @@ -565,11 +568,13 @@ int nd_label_active_count(struct nvdimm_drvdata *ndd)
>  		return 0;
>  
>  	for_each_clear_bit_le(slot, free, nslot) {
> +		struct nd_lsa_label *lsa_label;
>  		struct nd_namespace_label *nd_label;
>  
> -		nd_label = to_label(ndd, slot);
> +		lsa_label = to_label(ndd, slot);
> +		nd_label = &lsa_label->ns_label;
>  
> -		if (!slot_valid(ndd, nd_label, slot)) {
> +		if (!slot_valid(ndd, lsa_label, slot)) {
>  			u32 label_slot = nsl_get_slot(ndd, nd_label);
>  			u64 size = nsl_get_rawsize(ndd, nd_label);
>  			u64 dpa = nsl_get_dpa(ndd, nd_label);
> @@ -584,7 +589,7 @@ int nd_label_active_count(struct nvdimm_drvdata *ndd)
>  	return count;
>  }
>  
> -struct nd_namespace_label *nd_label_active(struct nvdimm_drvdata *ndd, int n)
> +struct nd_lsa_label *nd_label_active(struct nvdimm_drvdata *ndd, int n)
>  {
>  	struct nd_namespace_index *nsindex;
>  	unsigned long *free;
> @@ -594,10 +599,10 @@ struct nd_namespace_label *nd_label_active(struct nvdimm_drvdata *ndd, int n)
>  		return NULL;
>  
>  	for_each_clear_bit_le(slot, free, nslot) {
> -		struct nd_namespace_label *nd_label;
> +		struct nd_lsa_label *lsa_label;
>  
> -		nd_label = to_label(ndd, slot);
> -		if (!slot_valid(ndd, nd_label, slot))
> +		lsa_label = to_label(ndd, slot);
> +		if (!slot_valid(ndd, lsa_label, slot))
>  			continue;
>  
>  		if (n-- == 0)
> @@ -738,7 +743,7 @@ static int nd_label_write_index(struct nvdimm_drvdata *ndd, int index, u32 seq,
>  }
>  
>  static unsigned long nd_label_offset(struct nvdimm_drvdata *ndd,
> -		struct nd_namespace_label *nd_label)
> +		struct nd_lsa_label *nd_label)
>  {
>  	return (unsigned long) nd_label
>  		- (unsigned long) to_namespace_index(ndd, 0);
> @@ -892,6 +897,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  	struct nd_namespace_common *ndns = &nspm->nsio.common;
>  	struct nd_interleave_set *nd_set = nd_region->nd_set;
>  	struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
> +	struct nd_lsa_label *lsa_label;
>  	struct nd_namespace_label *nd_label;
>  	struct nd_namespace_index *nsindex;
>  	struct nd_label_ent *label_ent;
> @@ -923,8 +929,10 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  		return -ENXIO;
>  	dev_dbg(ndd->dev, "allocated: %d\n", slot);
>  
> -	nd_label = to_label(ndd, slot);
> -	memset(nd_label, 0, sizeof_namespace_label(ndd));
> +	lsa_label = to_label(ndd, slot);
> +	memset(lsa_label, 0, sizeof_namespace_label(ndd));
> +
> +	nd_label = &lsa_label->ns_label;
>  	nsl_set_uuid(ndd, nd_label, nspm->uuid);
>  	nsl_set_name(ndd, nd_label, nspm->alt_name);
>  	nsl_set_flags(ndd, nd_label, flags);
> @@ -942,7 +950,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  	nd_dbg_dpa(nd_region, ndd, res, "\n");
>  
>  	/* update label */
> -	offset = nd_label_offset(ndd, nd_label);
> +	offset = nd_label_offset(ndd, lsa_label);
>  	rc = nvdimm_set_config_data(ndd, offset, nd_label,
>  			sizeof_namespace_label(ndd));
>  	if (rc < 0)
> @@ -954,7 +962,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  		if (!label_ent->label)
>  			continue;
>  		if (test_and_clear_bit(ND_LABEL_REAP, &label_ent->flags) ||
> -		    nsl_uuid_equal(ndd, label_ent->label, nspm->uuid))
> +		    nsl_uuid_equal(ndd, &label_ent->label->ns_label, nspm->uuid))
>  			reap_victim(nd_mapping, label_ent);
>  	}
>  
> @@ -964,14 +972,14 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  	if (rc == 0) {
>  		list_for_each_entry(label_ent, &nd_mapping->labels, list)
>  			if (!label_ent->label) {
> -				label_ent->label = nd_label;
> -				nd_label = NULL;
> +				label_ent->label = lsa_label;
> +				lsa_label = NULL;
>  				break;
>  			}
> -		dev_WARN_ONCE(&nspm->nsio.common.dev, nd_label,
> +		dev_WARN_ONCE(&nspm->nsio.common.dev, lsa_label,
>  				"failed to track label: %d\n",
> -				to_slot(ndd, nd_label));
> -		if (nd_label)
> +				to_slot(ndd, lsa_label));
> +		if (lsa_label)
>  			rc = -ENXIO;
>  	}
>  	mutex_unlock(&nd_mapping->lock);
> @@ -1042,12 +1050,12 @@ static int del_labels(struct nd_mapping *nd_mapping, uuid_t *uuid)
>  
>  	mutex_lock(&nd_mapping->lock);
>  	list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list) {
> -		struct nd_namespace_label *nd_label = label_ent->label;
> +		struct nd_lsa_label *nd_label = label_ent->label;
>  
>  		if (!nd_label)
>  			continue;
>  		active++;
> -		if (!nsl_uuid_equal(ndd, nd_label, uuid))
> +		if (!nsl_uuid_equal(ndd, &nd_label->ns_label, uuid))
>  			continue;
>  		active--;
>  		slot = to_slot(ndd, nd_label);
> diff --git a/drivers/nvdimm/label.h b/drivers/nvdimm/label.h
> index 0650fb4b9821..4883b3a1320f 100644
> --- a/drivers/nvdimm/label.h
> +++ b/drivers/nvdimm/label.h
> @@ -183,6 +183,16 @@ struct nd_namespace_label {
>  	};
>  };
>  
> +/*
> + * LSA 2.1 format introduces region label, which can also reside
> + * into LSA along with only namespace label as per v1.1 and v1.2
> + */
> +struct nd_lsa_label {
> +	union {
> +		struct nd_namespace_label ns_label;
> +	};
> +};
> +
>  #define NVDIMM_BTT_GUID "8aed63a2-29a2-4c66-8b12-f05d15d3922a"
>  #define NVDIMM_BTT2_GUID "18633bfc-1735-4217-8ac9-17239282d3f8"
>  #define NVDIMM_PFN_GUID "266400ba-fb9f-4677-bcb0-968f11d0d225"
> @@ -215,7 +225,7 @@ struct nvdimm_drvdata;
>  int nd_label_data_init(struct nvdimm_drvdata *ndd);
>  size_t sizeof_namespace_index(struct nvdimm_drvdata *ndd);
>  int nd_label_active_count(struct nvdimm_drvdata *ndd);
> -struct nd_namespace_label *nd_label_active(struct nvdimm_drvdata *ndd, int n);
> +struct nd_lsa_label *nd_label_active(struct nvdimm_drvdata *ndd, int n);
>  u32 nd_label_alloc_slot(struct nvdimm_drvdata *ndd);
>  bool nd_label_free_slot(struct nvdimm_drvdata *ndd, u32 slot);
>  u32 nd_label_nfree(struct nvdimm_drvdata *ndd);
> diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
> index 55cfbf1e0a95..bdf1ed6f23d8 100644
> --- a/drivers/nvdimm/namespace_devs.c
> +++ b/drivers/nvdimm/namespace_devs.c
> @@ -1009,10 +1009,11 @@ static int namespace_update_uuid(struct nd_region *nd_region,
>  
>  		mutex_lock(&nd_mapping->lock);
>  		list_for_each_entry(label_ent, &nd_mapping->labels, list) {
> -			struct nd_namespace_label *nd_label = label_ent->label;
> +			struct nd_namespace_label *nd_label;
>  			struct nd_label_id label_id;
>  			uuid_t uuid;
>  
> +			nd_label = &label_ent->label->ns_label;
>  			if (!nd_label)
>  				continue;
>  			nsl_get_uuid(ndd, nd_label, &uuid);
> @@ -1573,11 +1574,14 @@ static bool has_uuid_at_pos(struct nd_region *nd_region, const uuid_t *uuid,
>  		bool found_uuid = false;
>  
>  		list_for_each_entry(label_ent, &nd_mapping->labels, list) {
> -			struct nd_namespace_label *nd_label = label_ent->label;
> +			struct nd_lsa_label *lsa_label = label_ent->label;
> +			struct nd_namespace_label *nd_label;
>  			u16 position;
>  
> -			if (!nd_label)
> +			if (!lsa_label)
>  				continue;
> +
> +			nd_label = &lsa_label->ns_label;
>  			position = nsl_get_position(ndd, nd_label);
>  
>  			if (!nsl_validate_isetcookie(ndd, nd_label, cookie))
> @@ -1615,17 +1619,21 @@ static int select_pmem_id(struct nd_region *nd_region, const uuid_t *pmem_id)
>  	for (i = 0; i < nd_region->ndr_mappings; i++) {
>  		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
>  		struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
> +		struct nd_lsa_label *lsa_label = NULL;
>  		struct nd_namespace_label *nd_label = NULL;
>  		u64 hw_start, hw_end, pmem_start, pmem_end;
>  		struct nd_label_ent *label_ent;
>  
>  		lockdep_assert_held(&nd_mapping->lock);
>  		list_for_each_entry(label_ent, &nd_mapping->labels, list) {
> -			nd_label = label_ent->label;
> -			if (!nd_label)
> +			lsa_label = label_ent->label;
> +			if (!lsa_label)
>  				continue;
> +
> +			nd_label = &lsa_label->ns_label;
>  			if (nsl_uuid_equal(ndd, nd_label, pmem_id))
>  				break;
> +			lsa_label = NULL;
>  			nd_label = NULL;
>  		}
>  
> @@ -1746,19 +1754,21 @@ static struct device *create_namespace_pmem(struct nd_region *nd_region,
>  
>  	/* Calculate total size and populate namespace properties from label0 */
>  	for (i = 0; i < nd_region->ndr_mappings; i++) {
> +		struct nd_lsa_label *lsa_label;
>  		struct nd_namespace_label *label0;
>  		struct nvdimm_drvdata *ndd;
>  
>  		nd_mapping = &nd_region->mapping[i];
>  		label_ent = list_first_entry_or_null(&nd_mapping->labels,
>  				typeof(*label_ent), list);
> -		label0 = label_ent ? label_ent->label : NULL;
> +		lsa_label = label_ent ? label_ent->label : NULL;
>  
> -		if (!label0) {
> +		if (!lsa_label) {
>  			WARN_ON(1);
>  			continue;
>  		}
>  
> +		label0 = &lsa_label->ns_label;
>  		ndd = to_ndd(nd_mapping);
>  		size += nsl_get_rawsize(ndd, label0);
>  		if (nsl_get_position(ndd, label0) != 0)
> @@ -1943,12 +1953,15 @@ static struct device **scan_labels(struct nd_region *nd_region)
>  
>  	/* "safe" because create_namespace_pmem() might list_move() label_ent */
>  	list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list) {
> -		struct nd_namespace_label *nd_label = label_ent->label;
> +		struct nd_lsa_label *lsa_label = label_ent->label;
> +		struct nd_namespace_label *nd_label;
>  		struct device **__devs;
>  
> -		if (!nd_label)
> +		if (!lsa_label)
>  			continue;
>  
> +		nd_label = &lsa_label->ns_label;
> +
>  		/* skip labels that describe extents outside of the region */
>  		if (nsl_get_dpa(ndd, nd_label) < nd_mapping->start ||
>  		    nsl_get_dpa(ndd, nd_label) > map_end)
> @@ -2122,7 +2135,7 @@ static int init_active_labels(struct nd_region *nd_region)
>  		if (!count)
>  			continue;
>  		for (j = 0; j < count; j++) {
> -			struct nd_namespace_label *label;
> +			struct nd_lsa_label *label;
>  
>  			label_ent = kzalloc(sizeof(*label_ent), GFP_KERNEL);
>  			if (!label_ent)
> diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
> index 1cc06cc58d14..61348dee687d 100644
> --- a/drivers/nvdimm/nd.h
> +++ b/drivers/nvdimm/nd.h
> @@ -376,7 +376,7 @@ enum nd_label_flags {
>  struct nd_label_ent {
>  	struct list_head list;
>  	unsigned long flags;
> -	struct nd_namespace_label *label;
> +	struct nd_lsa_label *label;

Looking at the series a bit more, I don't think creating 'struct nd_lsa_label' and making all the changes in this patch is necessary. I think an unamed union here of 'struct nd_namespace_label' and 'struct cxl_region_label' should be fine. Most of the CXL region handling should be quite different than namespace handling that the code paths will diverge. Adding a few helper functions should address some of the common code paths or creating separate cxl region based helpers to deal with the rest. i.e. slot_valid() can take a slot number rather than a label type. Being intentional in handling sepcific labeling may be better than trying to force a union between region and namespace labeling.    

>  };
>  
>  enum nd_mapping_lock_class {


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

* Re: [PATCH V2 02/20] nvdimm/label: Prep patch to accommodate cxl lsa 2.1 support
  2025-07-30 12:11     ` [PATCH V2 02/20] nvdimm/label: Prep patch to accommodate cxl lsa 2.1 support Neeraj Kumar
                         ` (2 preceding siblings ...)
  2025-08-18 21:48       ` Dave Jiang
@ 2025-08-19 15:38       ` Ira Weiny
  3 siblings, 0 replies; 67+ messages in thread
From: Ira Weiny @ 2025-08-19 15:38 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

Neeraj Kumar wrote:
> LSA 2.1 format introduces region label, which can also reside
> into LSA along with only namespace label as per v1.1 and v1.2
> 
> As both namespace and region labels are of same size of 256 bytes.

Soft-NAK

Having 2 data structures of the same size is not a reason to combine their
types.

Please explain how nd_namespace_label is related to the new region label
and why combining them is a net benefit.  This change may need to be made
later in the series if that makes it more understandable.

> Thus renamed "struct nd_namespace_label" to "struct nd_lsa_label",
> where both namespace label and region label can stay as union.

For now I'm naking this patch unless there is some justification for
changing all the names vs just introducing "nd_region_label" or whatever
it might need to be named.

Ira

> 
> No functional change introduced.
> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>

[snip]

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

* Re: [PATCH V2 03/20] nvdimm/namespace_label: Add namespace label changes as per CXL LSA v2.1
  2025-07-30 12:11     ` [PATCH V2 03/20] nvdimm/namespace_label: Add namespace label changes as per CXL LSA v2.1 Neeraj Kumar
  2025-07-31 13:12       ` kernel test robot
  2025-08-13 13:27       ` Jonathan Cameron
@ 2025-08-19 15:57       ` Ira Weiny
  2025-08-19 19:36       ` Ira Weiny
  3 siblings, 0 replies; 67+ messages in thread
From: Ira Weiny @ 2025-08-19 15:57 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

Neeraj Kumar wrote:
> CXL 3.2 Spec mentions CXL LSA 2.1 Namespace Labels at section 9.13.2.5
> Modified __pmem_label_update function using setter functions to update
> namespace label as per CXL LSA 2.1

But why?  And didn't we just remove nd_namespace_label in patch 2?

Why are we now defining accessor functions for it?

> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
> ---
>  drivers/nvdimm/label.c |  3 +++
>  drivers/nvdimm/nd.h    | 27 +++++++++++++++++++++++++++
>  2 files changed, 30 insertions(+)
> 
> diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
> index 75bc11da4c11..3f8a6bdb77c7 100644
> --- a/drivers/nvdimm/label.c
> +++ b/drivers/nvdimm/label.c
> @@ -933,6 +933,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  	memset(lsa_label, 0, sizeof_namespace_label(ndd));
>  
>  	nd_label = &lsa_label->ns_label;
> +	nsl_set_type(ndd, nd_label);
>  	nsl_set_uuid(ndd, nd_label, nspm->uuid);
>  	nsl_set_name(ndd, nd_label, nspm->alt_name);
>  	nsl_set_flags(ndd, nd_label, flags);
> @@ -944,7 +945,9 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  	nsl_set_lbasize(ndd, nd_label, nspm->lbasize);
>  	nsl_set_dpa(ndd, nd_label, res->start);
>  	nsl_set_slot(ndd, nd_label, slot);
> +	nsl_set_alignment(ndd, nd_label, 0);
>  	nsl_set_type_guid(ndd, nd_label, &nd_set->type_guid);
> +	nsl_set_region_uuid(ndd, nd_label, NULL);
>  	nsl_set_claim_class(ndd, nd_label, ndns->claim_class);
>  	nsl_calculate_checksum(ndd, nd_label);
>  	nd_dbg_dpa(nd_region, ndd, res, "\n");
> diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
> index 61348dee687d..651847f1bbf9 100644
> --- a/drivers/nvdimm/nd.h
> +++ b/drivers/nvdimm/nd.h
> @@ -295,6 +295,33 @@ static inline const u8 *nsl_uuid_raw(struct nvdimm_drvdata *ndd,
>  	return nd_label->efi.uuid;
>  }
>  
> +static inline void nsl_set_type(struct nvdimm_drvdata *ndd,
> +				struct nd_namespace_label *ns_label)

Set type to what?

Why is driver data passed here?

This reads as an accessor function for some sort of label class but seems
to do some back checking into ndd to set the uuid of the label?

At a minimum this should be *_set_uuid(..., uuid_t uuid)  But I'm not
following this chunk of changes so don't just change it without more
explaination.

> +{
> +	uuid_t tmp;
> +
> +	if (ndd->cxl) {
> +		uuid_parse(CXL_NAMESPACE_UUID, &tmp);
> +		export_uuid(ns_label->cxl.type, &tmp);
> +	}
> +}
> +
> +static inline void nsl_set_alignment(struct nvdimm_drvdata *ndd,
> +				     struct nd_namespace_label *ns_label,
> +				     u32 align)

Why is this needed?

> +{
> +	if (ndd->cxl)
> +		ns_label->cxl.align = __cpu_to_le16(align);
> +}
> +
> +static inline void nsl_set_region_uuid(struct nvdimm_drvdata *ndd,
> +				       struct nd_namespace_label *ns_label,
> +				       const uuid_t *uuid)

Again why?

> +{
> +	if (ndd->cxl)
> +		export_uuid(ns_label->cxl.region_uuid, uuid);

export does a memcpy() and you are passing it NULL.  Is that safe?

Ira

[snip]

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

* Re: [PATCH V2 04/20] nvdimm/label: CXL labels skip the need for 'interleave-set cookie'
  2025-07-30 12:11     ` [PATCH V2 04/20] nvdimm/label: CXL labels skip the need for 'interleave-set cookie' Neeraj Kumar
  2025-08-13 13:44       ` Jonathan Cameron
  2025-08-15 21:02       ` Dave Jiang
@ 2025-08-19 16:04       ` Ira Weiny
  2 siblings, 0 replies; 67+ messages in thread
From: Ira Weiny @ 2025-08-19 16:04 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

Neeraj Kumar wrote:
> CXL LSA v2.1 utilizes the region labels stored in the LSA for interleave
> set configuration instead of interleave-set cookie used in previous LSA
> versions. As interleave-set cookie is not required for CXL LSA v2.1 format
> so skip its usage for CXL LSA 2.1 format
> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>

Seems ok:

Acked-by: Ira Weiny <ira.weiny@intel.com>

[snip]

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

* Re: [PATCH V2 05/20] nvdimm/region_label: Add region label updation routine
  2025-07-30 12:11     ` [PATCH V2 05/20] nvdimm/region_label: Add region label updation routine Neeraj Kumar
                         ` (3 preceding siblings ...)
  2025-08-15 23:12       ` Dave Jiang
@ 2025-08-19 18:16       ` Ira Weiny
  4 siblings, 0 replies; 67+ messages in thread
From: Ira Weiny @ 2025-08-19 18:16 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

RE Subject: [PATCH V2 05/20] nvdimm/region_label: Add region label updation routine
                                                                   ^^^^^^^
								   update

Neeraj Kumar wrote:
> Added __pmem_region_label_update region label update routine to update
  ^^^
  Add

> region label.

How about:

Add __pmem_region_label_update to update region labels.  ???

But is that really what this patch is doing?  And why do we need such a
function?

Why is __pmem_label_update changing?

> 
> Also used guard(mutex)(&nd_mapping->lock) in place of mutex_lock() and
> mutex_unlock()

Why?

I'm not full out naking the patch but I think its purpose needs to be
clear.

More below...

[snip]

>  static bool slot_valid(struct nvdimm_drvdata *ndd,
>  		struct nd_lsa_label *lsa_label, u32 slot)
>  {
> @@ -960,7 +970,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  		return rc;
>  
>  	/* Garbage collect the previous label */
> -	mutex_lock(&nd_mapping->lock);
> +	guard(mutex)(&nd_mapping->lock);

This, and the following hunks, looks like a completely separate change and
should be in it's own pre-patch with a justification of the change.

>  	list_for_each_entry(label_ent, &nd_mapping->labels, list) {
>  		if (!label_ent->label)
>  			continue;
> @@ -972,20 +982,20 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  	/* update index */
>  	rc = nd_label_write_index(ndd, ndd->ns_next,
>  			nd_inc_seq(__le32_to_cpu(nsindex->seq)), 0);
> -	if (rc == 0) {
> -		list_for_each_entry(label_ent, &nd_mapping->labels, list)
> -			if (!label_ent->label) {
> -				label_ent->label = lsa_label;
> -				lsa_label = NULL;
> -				break;
> -			}
> -		dev_WARN_ONCE(&nspm->nsio.common.dev, lsa_label,
> -				"failed to track label: %d\n",
> -				to_slot(ndd, lsa_label));
> -		if (lsa_label)
> -			rc = -ENXIO;
> -	}
> -	mutex_unlock(&nd_mapping->lock);
> +	if (rc)
> +		return rc;
> +
> +	list_for_each_entry(label_ent, &nd_mapping->labels, list)
> +		if (!label_ent->label) {
> +			label_ent->label = lsa_label;
> +			lsa_label = NULL;
> +			break;
> +		}
> +	dev_WARN_ONCE(&nspm->nsio.common.dev, lsa_label,
> +			"failed to track label: %d\n",
> +			to_slot(ndd, lsa_label));
> +	if (lsa_label)
> +		rc = -ENXIO;
>  
>  	return rc;
>  }
> @@ -1127,6 +1137,137 @@ int nd_pmem_namespace_label_update(struct nd_region *nd_region,
>  	return 0;
>  }
>  

[snip]

> diff --git a/drivers/nvdimm/label.h b/drivers/nvdimm/label.h
> index 4883b3a1320f..0f428695017d 100644
> --- a/drivers/nvdimm/label.h
> +++ b/drivers/nvdimm/label.h
> @@ -190,6 +190,7 @@ struct nd_namespace_label {
>  struct nd_lsa_label {
>  	union {
>  		struct nd_namespace_label ns_label;
> +		struct cxl_region_label rg_label;

Why can't struct cxl_region_label be it's own structure?  Or just be part
of the nd_namespace_label union?

>  	};
>  };
>  
> @@ -233,4 +234,5 @@ struct nd_region;
>  struct nd_namespace_pmem;
>  int nd_pmem_namespace_label_update(struct nd_region *nd_region,
>  		struct nd_namespace_pmem *nspm, resource_size_t size);
> +int nd_pmem_region_label_update(struct nd_region *nd_region);
>  #endif /* __LABEL_H__ */
> diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
> index 5b73119dc8fd..02ae8162566c 100644
> --- a/drivers/nvdimm/namespace_devs.c
> +++ b/drivers/nvdimm/namespace_devs.c
> @@ -232,6 +232,18 @@ static ssize_t __alt_name_store(struct device *dev, const char *buf,
>  	return rc;
>  }
>  
> +int nd_region_label_update(struct nd_region *nd_region)

Is this called in a later patch?

Ira

[snip]

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

* Re: [PATCH V2 07/20] nvdimm/namespace_label: Update namespace init_labels and its region_uuid
  2025-07-30 12:11     ` [PATCH V2 07/20] nvdimm/namespace_label: Update namespace init_labels and its region_uuid Neeraj Kumar
  2025-08-13 14:58       ` Jonathan Cameron
@ 2025-08-19 18:56       ` Ira Weiny
  1 sibling, 0 replies; 67+ messages in thread
From: Ira Weiny @ 2025-08-19 18:56 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

Neeraj Kumar wrote:
> nd_mapping->labels maintains the list of labels present into LSA.
> init_labels() prepares this list while adding new label into LSA
> and updates nd_mapping->labels accordingly. During cxl region
> creation nd_mapping->labels list and LSA was updated with one
> region label. Therefore during new namespace label creation
> pre-include the previously created region label, so increase
> num_labels count by 1.

Why does the count of the labels in the list not work?

static int init_labels(struct nd_mapping *nd_mapping, int num_labels)
{
        int i, old_num_labels = 0;
...
        mutex_lock(&nd_mapping->lock);
        list_for_each_entry(label_ent, &nd_mapping->labels, list)
                old_num_labels++;
        mutex_unlock(&nd_mapping->lock);
...

> 
> Also updated nsl_set_region_uuid with region uuid with which
> namespace is associated with.

Whenever using a word like 'Also' in the commit message ask if this should be a
separate patch.  I'm thinking this hunk should be somewhere else in the series.

Ira

> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
> ---
>  drivers/nvdimm/label.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
> index be18278d6cea..fd02b557612e 100644
> --- a/drivers/nvdimm/label.c
> +++ b/drivers/nvdimm/label.c
> @@ -957,7 +957,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
>  	nsl_set_slot(ndd, nd_label, slot);
>  	nsl_set_alignment(ndd, nd_label, 0);
>  	nsl_set_type_guid(ndd, nd_label, &nd_set->type_guid);
> -	nsl_set_region_uuid(ndd, nd_label, NULL);
> +	nsl_set_region_uuid(ndd, nd_label, &nd_set->uuid);
>  	nsl_set_claim_class(ndd, nd_label, ndns->claim_class);
>  	nsl_calculate_checksum(ndd, nd_label);
>  	nd_dbg_dpa(nd_region, ndd, res, "\n");
> @@ -1129,7 +1129,8 @@ int nd_pmem_namespace_label_update(struct nd_region *nd_region,
>  				count++;
>  		WARN_ON_ONCE(!count);
>  
> -		rc = init_labels(nd_mapping, count);
> +		/* Adding 1 to pre include the already added region label */
> +		rc = init_labels(nd_mapping, count + 1);
>  		if (rc < 0)
>  			return rc;
>  
> -- 
> 2.34.1
> 
> 



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

* Re: [PATCH V2 03/20] nvdimm/namespace_label: Add namespace label changes as per CXL LSA v2.1
  2025-07-30 12:11     ` [PATCH V2 03/20] nvdimm/namespace_label: Add namespace label changes as per CXL LSA v2.1 Neeraj Kumar
                         ` (2 preceding siblings ...)
  2025-08-19 15:57       ` Ira Weiny
@ 2025-08-19 19:36       ` Ira Weiny
  3 siblings, 0 replies; 67+ messages in thread
From: Ira Weiny @ 2025-08-19 19:36 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel, Neeraj Kumar

Neeraj Kumar wrote:
> CXL 3.2 Spec mentions CXL LSA 2.1 Namespace Labels at section 9.13.2.5
> Modified __pmem_label_update function using setter functions to update
> namespace label as per CXL LSA 2.1
> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>

[snip]

>  
> +static inline void nsl_set_type(struct nvdimm_drvdata *ndd,
> +				struct nd_namespace_label *ns_label)
> +{
> +	uuid_t tmp;
> +
> +	if (ndd->cxl) {
> +		uuid_parse(CXL_NAMESPACE_UUID, &tmp);
> +		export_uuid(ns_label->cxl.type, &tmp);

One more thing why can't uuid_parse put the UUID directly into type?

I think this is done at least 1 other place.

Ira


[snip]

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

* Re: [PATCH V2 14/20] cxl/region: Add devm_cxl_pmem_add_region() for pmem region creation
  2025-07-30 12:12     ` [PATCH V2 14/20] cxl/region: Add devm_cxl_pmem_add_region() for pmem region creation Neeraj Kumar
@ 2025-08-20  0:30       ` Dave Jiang
  0 siblings, 0 replies; 67+ messages in thread
From: Dave Jiang @ 2025-08-20  0:30 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel



On 7/30/25 5:12 AM, Neeraj Kumar wrote:
> devm_cxl_pmem_add_region() is used to create cxl region based on region
> information scanned from LSA.
> 
> devm_cxl_add_region() is used to just allocate cxlr and its fields are
> filled later by userspace tool using device attributes (*_store()).
> 
> Inspiration for devm_cxl_pmem_add_region() is taken from these device
> attributes (_store*) calls. It allocates cxlr and fills information
> parsed from LSA and calls device_add(&cxlr->dev) to initiate further
> region creation porbes
> 
> Renamed __create_region() to cxl_create_region() and make it an exported
> routine. This will be used in later patch to create cxl region after
> fetching region information from LSA.
> 
> Also created some helper routines and refactored dpa_size_store(),
> commit_store() to avoid duplicate code usage in devm_cxl_pmem_add_region()

"Some helper routines are created to...."

I would drop the "Also"


> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
> ---
>  drivers/cxl/core/core.h   |   1 +
>  drivers/cxl/core/port.c   |  29 ++++++----
>  drivers/cxl/core/region.c | 118 +++++++++++++++++++++++++++++++++-----
>  drivers/cxl/cxl.h         |  12 ++++
>  4 files changed, 134 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
> index 2669f251d677..80c83e0117c6 100644
> --- a/drivers/cxl/core/core.h
> +++ b/drivers/cxl/core/core.h
> @@ -94,6 +94,7 @@ int cxl_dpa_free(struct cxl_endpoint_decoder *cxled);
>  resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled);
>  resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled);
>  bool cxl_resource_contains_addr(const struct resource *res, const resource_size_t addr);
> +ssize_t resize_or_free_dpa(struct cxl_endpoint_decoder *cxled, u64 size);
>  
>  enum cxl_rcrb {
>  	CXL_RCRB_DOWNSTREAM,
> diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
> index 29197376b18e..ba743e31f721 100644
> --- a/drivers/cxl/core/port.c
> +++ b/drivers/cxl/core/port.c
> @@ -243,16 +243,9 @@ static ssize_t dpa_size_show(struct device *dev, struct device_attribute *attr,
>  	return sysfs_emit(buf, "%pa\n", &size);
>  }
>  
> -static ssize_t dpa_size_store(struct device *dev, struct device_attribute *attr,
> -			      const char *buf, size_t len)
> +ssize_t resize_or_free_dpa(struct cxl_endpoint_decoder *cxled, u64 size)

Maybe it should be called cxl_realloc_dpa()? More comments later on...
 
>  {
> -	struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(dev);
> -	unsigned long long size;
> -	ssize_t rc;
> -
> -	rc = kstrtoull(buf, 0, &size);
> -	if (rc)
> -		return rc;
> +	int rc;
>  
>  	if (!IS_ALIGNED(size, SZ_256M))
>  		return -EINVAL;
> @@ -262,9 +255,23 @@ static ssize_t dpa_size_store(struct device *dev, struct device_attribute *attr,
>  		return rc;
>  
>  	if (size == 0)
> -		return len;
> +		return 0;
> +
> +	return cxl_dpa_alloc(cxled, size);
> +}
> +
> +static ssize_t dpa_size_store(struct device *dev, struct device_attribute *attr,
> +			      const char *buf, size_t len)
> +{
> +	struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(dev);
> +	unsigned long long size;
> +	ssize_t rc;
> +
> +	rc = kstrtoull(buf, 0, &size);
> +	if (rc)
> +		return rc;
>  
> -	rc = cxl_dpa_alloc(cxled, size);
> +	rc = resize_or_free_dpa(cxled, size);
>  	if (rc)
>  		return rc;
>  
> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
> index eef501f3384c..8578e046aa78 100644
> --- a/drivers/cxl/core/region.c
> +++ b/drivers/cxl/core/region.c
> @@ -703,6 +703,23 @@ static int free_hpa(struct cxl_region *cxlr)
>  	return 0;
>  }
>  
> +static ssize_t resize_or_free_region_hpa(struct cxl_region *cxlr, u64 size)
> +{
> +	int rc;
> +
> +	ACQUIRE(rwsem_write_kill, rwsem)(&cxl_rwsem.region);
> +	rc = ACQUIRE_ERR(rwsem_write_kill, &rwsem);
> +	if (rc)
> +		return rc;
> +
> +	if (size)
> +		rc = alloc_hpa(cxlr, size);
> +	else
> +		rc = free_hpa(cxlr);
> +
> +	return rc;
> +}

I think it's better to have 2 helper functions rather a single ambiguous one here. alloc_region_hpa() and free_region_hpa(). More on why later.

> +
>  static ssize_t size_store(struct device *dev, struct device_attribute *attr,
>  			  const char *buf, size_t len)
>  {
> @@ -714,15 +731,7 @@ static ssize_t size_store(struct device *dev, struct device_attribute *attr,
>  	if (rc)
>  		return rc;
>  
> -	ACQUIRE(rwsem_write_kill, rwsem)(&cxl_rwsem.region);
> -	if ((rc = ACQUIRE_ERR(rwsem_write_kill, &rwsem)))
> -		return rc;
> -
> -	if (val)
> -		rc = alloc_hpa(cxlr, val);
> -	else
> -		rc = free_hpa(cxlr);
> -
> +	rc = resize_or_free_region_hpa(cxlr, val);
>  	if (rc)
>  		return rc;
>  
> @@ -2569,6 +2578,76 @@ static struct cxl_region *devm_cxl_add_region(struct cxl_root_decoder *cxlrd,
>  	return ERR_PTR(rc);
>  }
>  
> +static struct cxl_region *
> +devm_cxl_pmem_add_region(struct cxl_root_decoder *cxlrd,
> +			 int id,
> +			 enum cxl_partition_mode mode,
> +			 enum cxl_decoder_type type,
> +			 struct cxl_pmem_region_params *params,
> +			 struct cxl_decoder *cxld)
> +{
> +	struct cxl_port *root_port;
> +	struct cxl_region *cxlr;
> +	struct cxl_endpoint_decoder *cxled;
> +	struct cxl_region_params *p;
> +	struct device *dev;
> +	int rc;
> +
> +	cxlr = cxl_region_alloc(cxlrd, id);
I think you can use __free() here to drop all the gotos.

struct cxl_region *cxlr __free(put_cxl_region) = cxl_region_alloc(cxlrd, id);

Just make sure to 'return no_free_ptr(cxlr)' at the successful end.


> +	if (IS_ERR(cxlr))
> +		return cxlr;
> +	cxlr->mode = mode;
> +	cxlr->type = type;
> +
> +	dev = &cxlr->dev;
> +	rc = dev_set_name(dev, "region%d", id);
> +	if (rc)
> +		goto err;
> +
> +	p = &cxlr->params;
> +	p->uuid = params->uuid;
> +	p->interleave_ways = params->nlabel;
> +	p->interleave_granularity = params->ig;
> +
> +	if (resize_or_free_region_hpa(cxlr, params->rawsize))
> +		goto err;

Given this is _add_region(), it really should only be calling alloc_region_hpa() and not have to deal with free. Maybe a check before this and make sure params->rawsize is not 0 is needed.

> +
> +	cxled = to_cxl_endpoint_decoder(&cxld->dev);
> +	if (resize_or_free_dpa(cxled, 0))
Given that resize_or_free_dpa() always frees, is this call necessary here? 

> +		goto err;
> +
> +	if (cxl_dpa_set_part(cxled, CXL_PARTMODE_PMEM))
> +		goto err;
> +
> +	if (resize_or_free_dpa(cxled, params->rawsize))

Seems like it can be called once here instead and it'll just free and then re-allocate whatever size in params->rawsize.

> +		goto err;
> +
> +	/* Attaching only one target due to interleave_way == 1 */
Is it missing a check of interleave_ways here? Also maybe additional comments on why support iw==1 only?

> +	if (attach_target(cxlr, cxled, params->position, TASK_INTERRUPTIBLE))
> +		goto err;
> +
> +	if (__commit(cxlr))
> +		goto err;
> +
> +	rc = device_add(dev);
> +	if (rc)
> +		goto err;
> +
> +	root_port = to_cxl_port(cxlrd->cxlsd.cxld.dev.parent);
> +	rc = devm_add_action_or_reset(root_port->uport_dev,
> +			unregister_region, cxlr);
> +	if (rc)
> +		return ERR_PTR(rc);
> +
> +	dev_dbg(root_port->uport_dev, "%s: created %s\n",
> +		dev_name(&cxlrd->cxlsd.cxld.dev), dev_name(dev));
> +	return cxlr;
> +
> +err:
> +	put_device(dev);
> +	return ERR_PTR(rc);
> +}
> +
>  static ssize_t __create_region_show(struct cxl_root_decoder *cxlrd, char *buf)
>  {
>  	return sysfs_emit(buf, "region%u\n", atomic_read(&cxlrd->region_id));
> @@ -2586,8 +2665,10 @@ static ssize_t create_ram_region_show(struct device *dev,
>  	return __create_region_show(to_cxl_root_decoder(dev), buf);
>  }
>  
> -static struct cxl_region *__create_region(struct cxl_root_decoder *cxlrd,
> -					  enum cxl_partition_mode mode, int id)
> +struct cxl_region *cxl_create_region(struct cxl_root_decoder *cxlrd,
> +				     enum cxl_partition_mode mode, int id,
> +				     struct cxl_pmem_region_params *params,

Maybe name it pmem_params to avoid confusion with cxl region params.

> +				     struct cxl_decoder *cxld)
>  {
>  	int rc;
>  
> @@ -2609,8 +2690,14 @@ static struct cxl_region *__create_region(struct cxl_root_decoder *cxlrd,
>  		return ERR_PTR(-EBUSY);
>  	}
>  
> -	return devm_cxl_add_region(cxlrd, id, mode, CXL_DECODER_HOSTONLYMEM);
> +	if (params)
> +		return devm_cxl_pmem_add_region(cxlrd, id, mode,
> +				CXL_DECODER_HOSTONLYMEM, params, cxld);
> +	else

'else' not needed here. Just directly return.

> +		return devm_cxl_add_region(cxlrd, id, mode,
> +				CXL_DECODER_HOSTONLYMEM);
>  }
> +EXPORT_SYMBOL_NS_GPL(cxl_create_region, "CXL");
>  
>  static ssize_t create_region_store(struct device *dev, const char *buf,
>  				   size_t len, enum cxl_partition_mode mode)
> @@ -2623,7 +2710,7 @@ static ssize_t create_region_store(struct device *dev, const char *buf,
>  	if (rc != 1)
>  		return -EINVAL;
>  
> -	cxlr = __create_region(cxlrd, mode, id);
> +	cxlr = cxl_create_region(cxlrd, mode, id, NULL, NULL);
>  	if (IS_ERR(cxlr))
>  		return PTR_ERR(cxlr);
>  
> @@ -3414,8 +3501,9 @@ static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd,
>  	struct cxl_region *cxlr;
>  
>  	do {
> -		cxlr = __create_region(cxlrd, cxlds->part[part].mode,
> -				       atomic_read(&cxlrd->region_id));
> +		cxlr = cxl_create_region(cxlrd, cxlds->part[part].mode,
> +					 atomic_read(&cxlrd->region_id),
> +					 NULL, NULL);
>  	} while (IS_ERR(cxlr) && PTR_ERR(cxlr) == -EBUSY);
>  
>  	if (IS_ERR(cxlr)) {
> diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
> index 6edcec95e9ba..129db2e49aa7 100644
> --- a/drivers/cxl/cxl.h
> +++ b/drivers/cxl/cxl.h
> @@ -865,6 +865,10 @@ int cxl_add_to_region(struct cxl_endpoint_decoder *cxled);
>  struct cxl_dax_region *to_cxl_dax_region(struct device *dev);
>  u64 cxl_port_get_spa_cache_alias(struct cxl_port *endpoint, u64 spa);
>  void cxl_region_discovery(struct cxl_port *port);
> +struct cxl_region *cxl_create_region(struct cxl_root_decoder *cxlrd,
> +				     enum cxl_partition_mode mode, int id,
> +				     struct cxl_pmem_region_params *params,
> +				     struct cxl_decoder *cxld);
>  #else
>  static inline bool is_cxl_pmem_region(struct device *dev)
>  {
> @@ -890,6 +894,14 @@ static inline u64 cxl_port_get_spa_cache_alias(struct cxl_port *endpoint,
>  static inline void cxl_region_discovery(struct cxl_port *port)
>  {
>  }
> +static inline struct cxl_region *
> +cxl_create_region(struct cxl_root_decoder *cxlrd,
> +		  enum cxl_partition_mode mode, int id,
> +		  struct cxl_pmem_region_params *params,
> +		  struct cxl_decoder *cxld)
> +{
> +	return NULL;

return ERR_PTR(-EOPNOTSUPP);

> +}
>  #endif
>  
>  void cxl_endpoint_parse_cdat(struct cxl_port *port);


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

* Re: [PATCH V2 13/20] cxl/mem: Refactor cxl pmem region auto-assembling
  2025-07-30 12:12     ` [PATCH V2 13/20] cxl/mem: Refactor cxl pmem region auto-assembling Neeraj Kumar
@ 2025-08-20 16:41       ` Dave Jiang
  0 siblings, 0 replies; 67+ messages in thread
From: Dave Jiang @ 2025-08-20 16:41 UTC (permalink / raw)
  To: Neeraj Kumar, linux-cxl, nvdimm, linux-kernel, gost.dev
  Cc: a.manzanares, vishak.g, neeraj.kernel



On 7/30/25 5:12 AM, Neeraj Kumar wrote:
> In 84ec985944ef3, devm_cxl_add_nvdimm() sequence was changed and called
> before devm_cxl_add_endpoint(). It's because cxl pmem region auto-assembly
> used to get called at last in cxl_endpoint_port_probe(), which requires
> cxl_nvd presence.
> 
> For cxl region persistency, region creation happens during nvdimm_probe
> which need the completion of endpoint probe.
> 
> In order to accommodate both cxl pmem region auto-assembly and cxl region
> persistency, refactored following
> 
> 1. Re-Sequence devm_cxl_add_nvdimm() after devm_cxl_add_endpoint(). This
>    will be called only after successful completion of endpoint probe.
> 
> 2. Moved cxl pmem region auto-assembly from cxl_endpoint_port_probe() to
>    cxl_mem_probe() after devm_cxl_add_nvdimm(). It gurantees both the
>    completion of endpoint probe and cxl_nvd presence before its call.

So there are a few issues with doing this. If cxl_endpoint_port_probe() fails, you won't know that while running in cxl_mem_probe(). So you may need to do something similar to here [1] in order to make the probe synchronous with the add endpoint and make sure that the port driver attached successfully. Specifically see changes to devm_cxl_add_memdev().

Also, in endpoint port probe you are holding the device lock and therefore is protected from port removals (endpoint and parents) while you are trying to scan for regions. That is not the case on the memdev probe side if you aren't holding that port lock.

[1]: https://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl.git/commit/?h=for-6.18/cxl-probe-order&id=88aec5ea7a24da00dc92c7778df4851fe4fd3ec6

DJ

> 
> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
> ---
>  drivers/cxl/core/region.c | 33 +++++++++++++++++++++++++++++++++
>  drivers/cxl/cxl.h         |  4 ++++
>  drivers/cxl/mem.c         | 24 +++++++++++++++---------
>  drivers/cxl/port.c        | 39 +--------------------------------------
>  4 files changed, 53 insertions(+), 47 deletions(-)
> 
> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
> index e9bf42d91689..eef501f3384c 100644
> --- a/drivers/cxl/core/region.c
> +++ b/drivers/cxl/core/region.c
> @@ -3497,6 +3497,39 @@ int cxl_add_to_region(struct cxl_endpoint_decoder *cxled)
>  }
>  EXPORT_SYMBOL_NS_GPL(cxl_add_to_region, "CXL");
>  
> +static int discover_region(struct device *dev, void *unused)
> +{
> +	struct cxl_endpoint_decoder *cxled;
> +	int rc;
> +
> +	if (!is_endpoint_decoder(dev))
> +		return 0;
> +
> +	cxled = to_cxl_endpoint_decoder(dev);
> +	if ((cxled->cxld.flags & CXL_DECODER_F_ENABLE) == 0)
> +		return 0;
> +
> +	if (cxled->state != CXL_DECODER_STATE_AUTO)
> +		return 0;
> +
> +	/*
> +	 * Region enumeration is opportunistic, if this add-event fails,
> +	 * continue to the next endpoint decoder.
> +	 */
> +	rc = cxl_add_to_region(cxled);
> +	if (rc)
> +		dev_dbg(dev, "failed to add to region: %#llx-%#llx\n",
> +			cxled->cxld.hpa_range.start, cxled->cxld.hpa_range.end);
> +
> +	return 0;
> +}
> +
> +void cxl_region_discovery(struct cxl_port *port)
> +{
> +	device_for_each_child(&port->dev, NULL, discover_region);
> +}
> +EXPORT_SYMBOL_NS_GPL(cxl_region_discovery, "CXL");
> +
>  u64 cxl_port_get_spa_cache_alias(struct cxl_port *endpoint, u64 spa)
>  {
>  	struct cxl_region_ref *iter;
> diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
> index b7111e3568d0..6edcec95e9ba 100644
> --- a/drivers/cxl/cxl.h
> +++ b/drivers/cxl/cxl.h
> @@ -864,6 +864,7 @@ struct cxl_pmem_region *to_cxl_pmem_region(struct device *dev);
>  int cxl_add_to_region(struct cxl_endpoint_decoder *cxled);
>  struct cxl_dax_region *to_cxl_dax_region(struct device *dev);
>  u64 cxl_port_get_spa_cache_alias(struct cxl_port *endpoint, u64 spa);
> +void cxl_region_discovery(struct cxl_port *port);
>  #else
>  static inline bool is_cxl_pmem_region(struct device *dev)
>  {
> @@ -886,6 +887,9 @@ static inline u64 cxl_port_get_spa_cache_alias(struct cxl_port *endpoint,
>  {
>  	return 0;
>  }
> +static inline void cxl_region_discovery(struct cxl_port *port)
> +{
> +}
>  #endif
>  
>  void cxl_endpoint_parse_cdat(struct cxl_port *port);
> diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
> index 6e6777b7bafb..54501616ff09 100644
> --- a/drivers/cxl/mem.c
> +++ b/drivers/cxl/mem.c
> @@ -152,15 +152,6 @@ static int cxl_mem_probe(struct device *dev)
>  		return -ENXIO;
>  	}
>  
> -	if (cxl_pmem_size(cxlds) && IS_ENABLED(CONFIG_CXL_PMEM)) {
> -		rc = devm_cxl_add_nvdimm(parent_port, cxlmd);
> -		if (rc) {
> -			if (rc == -ENODEV)
> -				dev_info(dev, "PMEM disabled by platform\n");
> -			return rc;
> -		}
> -	}
> -
>  	if (dport->rch)
>  		endpoint_parent = parent_port->uport_dev;
>  	else
> @@ -184,6 +175,21 @@ static int cxl_mem_probe(struct device *dev)
>  	if (rc)
>  		dev_dbg(dev, "CXL memdev EDAC registration failed rc=%d\n", rc);
>  
> +	if (cxl_pmem_size(cxlds) && IS_ENABLED(CONFIG_CXL_PMEM)) {
> +		rc = devm_cxl_add_nvdimm(parent_port, cxlmd);
> +		if (rc) {
> +			if (rc == -ENODEV)
> +				dev_info(dev, "PMEM disabled by platform\n");
> +			return rc;
> +		}
> +	}
> +
> +	/*
> +	 * Now that all endpoint decoders are successfully enumerated, try to
> +	 * assemble region autodiscovery from committed decoders.
> +	 */
> +	cxl_region_discovery(cxlmd->endpoint);
> +
>  	/*
>  	 * The kernel may be operating out of CXL memory on this device,
>  	 * there is no spec defined way to determine whether this device
> diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c
> index fe4b593331da..090ae3577f32 100644
> --- a/drivers/cxl/port.c
> +++ b/drivers/cxl/port.c
> @@ -30,33 +30,6 @@ static void schedule_detach(void *cxlmd)
>  	schedule_cxl_memdev_detach(cxlmd);
>  }
>  
> -static int discover_region(struct device *dev, void *unused)
> -{
> -	struct cxl_endpoint_decoder *cxled;
> -	int rc;
> -
> -	if (!is_endpoint_decoder(dev))
> -		return 0;
> -
> -	cxled = to_cxl_endpoint_decoder(dev);
> -	if ((cxled->cxld.flags & CXL_DECODER_F_ENABLE) == 0)
> -		return 0;
> -
> -	if (cxled->state != CXL_DECODER_STATE_AUTO)
> -		return 0;
> -
> -	/*
> -	 * Region enumeration is opportunistic, if this add-event fails,
> -	 * continue to the next endpoint decoder.
> -	 */
> -	rc = cxl_add_to_region(cxled);
> -	if (rc)
> -		dev_dbg(dev, "failed to add to region: %#llx-%#llx\n",
> -			cxled->cxld.hpa_range.start, cxled->cxld.hpa_range.end);
> -
> -	return 0;
> -}
> -
>  static int cxl_switch_port_probe(struct cxl_port *port)
>  {
>  	struct cxl_hdm *cxlhdm;
> @@ -121,17 +94,7 @@ static int cxl_endpoint_port_probe(struct cxl_port *port)
>  	if (rc)
>  		return rc;
>  
> -	rc = devm_cxl_enumerate_decoders(cxlhdm, &info);
> -	if (rc)
> -		return rc;
> -
> -	/*
> -	 * Now that all endpoint decoders are successfully enumerated, try to
> -	 * assemble regions from committed decoders
> -	 */
> -	device_for_each_child(&port->dev, NULL, discover_region);
> -
> -	return 0;
> +	return devm_cxl_enumerate_decoders(cxlhdm, &info);
>  }
>  
>  static int cxl_port_probe(struct device *dev)


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

* Re: [PATCH V2 01/20] nvdimm/label: Introduce NDD_CXL_LABEL flag to set cxl label format
  2025-08-13 13:12       ` Jonathan Cameron
  2025-08-15 18:06         ` Dave Jiang
@ 2025-09-04 13:20         ` Neeraj Kumar
  1 sibling, 0 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-09-04 13:20 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel, cpgs

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

On 13/08/25 02:12PM, Jonathan Cameron wrote:
>On Wed, 30 Jul 2025 17:41:50 +0530
>Neeraj Kumar <s.neeraj@samsung.com> wrote:
>
>> Prior to LSA 2.1 version, LSA contain only namespace labels. LSA 2.1
>> introduced in CXL 2.0 Spec, which contain region label along with
>> namespace label.
>>
>> NDD_LABELING flag is used for namespace. Introduced NDD_CXL_LABEL
>> flag for region label. Based on these flags nvdimm driver performs
>> operation on namespace label or region label.
>>
>> NDD_CXL_LABEL will be utilized by cxl driver to enable LSA2.1 region
>> label support
>>
>> Accordingly updated label index version
>>
>> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
>Hi Neeraj,
>
>A few comments inline.
>
>> diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
>> index 04f4a049599a..7a011ee02d79 100644
>> --- a/drivers/nvdimm/label.c
>> +++ b/drivers/nvdimm/label.c
>> @@ -688,11 +688,25 @@ static int nd_label_write_index(struct nvdimm_drvdata *ndd, int index, u32 seq,
>>  		- (unsigned long) to_namespace_index(ndd, 0);
>>  	nsindex->labeloff = __cpu_to_le64(offset);
>>  	nsindex->nslot = __cpu_to_le32(nslot);
>> -	nsindex->major = __cpu_to_le16(1);
>> -	if (sizeof_namespace_label(ndd) < 256)
>> +
>> +	/* Set LSA Label Index Version */
>> +	if (ndd->cxl) {
>> +		/* CXL r3.2 Spec: Table 9-9 Label Index Block Layout */
>> +		nsindex->major = __cpu_to_le16(2);
>>  		nsindex->minor = __cpu_to_le16(1);
>> -	else
>> -		nsindex->minor = __cpu_to_le16(2);
>> +	} else {
>> +		nsindex->major = __cpu_to_le16(1);
>> +		/*
>> +		 * NVDIMM Namespace Specification
>> +		 * Table 2: Namespace Label Index Block Fields
>> +		 */
>> +		if (sizeof_namespace_label(ndd) < 256)
>> +			nsindex->minor = __cpu_to_le16(1);
>> +		else
>> +		 /* UEFI Specification 2.7: Label Index Block Definitions */
>
>Odd comment alignment. Either put it on the else so
>		else /* UEFI 2.7: Label Index Block Defintions */
>
>or indent it an extra tab
>
>		else
>			/* UEFI 2.7: Label Index Block Definitions */
>			

Thanks Jonathan, I will fix it in next patch-set

>> +			nsindex->minor = __cpu_to_le16(2);
>> +	}
>> +
>>  	nsindex->checksum = __cpu_to_le64(0);
>>  	if (flags & ND_NSINDEX_INIT) {
>>  		unsigned long *free = (unsigned long *) nsindex->free;
>
>> diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
>> index e772aae71843..0a55900842c8 100644
>> --- a/include/linux/libnvdimm.h
>> +++ b/include/linux/libnvdimm.h
>> @@ -44,6 +44,9 @@ enum {
>>  	/* dimm provider wants synchronous registration by __nvdimm_create() */
>>  	NDD_REGISTER_SYNC = 8,
>>
>> +	/* dimm supports region labels (LSA Format 2.1) */
>> +	NDD_CXL_LABEL = 9,
>
>This enum is 'curious'.  It combined flags from a bunch of different
>flags fields and some stuff that are nothing to do with flags.
>
>Anyhow, putting that aside I'd either rename it to something like
>NDD_REGION_LABELING (similar to NDD_LABELING that is there for namespace labels
>or just have it a meaning it is LSA Format 2.1 and drop the fact htat
>also means region labels are supported.
>
>Combination of a comment that talks about one thing and a definition name
>that doesn't associate with it seems confusing to me.
>
>Jonathan
>

Sure, I will rename it in next patch-set

Regards,
Neeraj

>
>> +
>>  	/* need to set a limit somewhere, but yes, this is likely overkill */
>>  	ND_IOCTL_MAX_BUFLEN = SZ_4M,
>>  	ND_CMD_MAX_ELEM = 5,
>

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH V2 02/20] nvdimm/label: Prep patch to accommodate cxl lsa 2.1 support
  2025-08-13 13:23       ` Jonathan Cameron
@ 2025-09-04 13:27         ` Neeraj Kumar
  0 siblings, 0 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-09-04 13:27 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel, cpgs

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

On 13/08/25 02:23PM, Jonathan Cameron wrote:
>On Wed, 30 Jul 2025 17:41:51 +0530
>Neeraj Kumar <s.neeraj@samsung.com> wrote:
>
>> LSA 2.1 format introduces region label, which can also reside
>> into LSA along with only namespace label as per v1.1 and v1.2
>>
>> As both namespace and region labels are of same size of 256 bytes.
>> Thus renamed "struct nd_namespace_label" to "struct nd_lsa_label",
>> where both namespace label and region label can stay as union.
>
>Maybe add something on why it makes sense to use a union rather than
>new handling.

Currently we have support of LSA v1.1 and v1.2 in Linux, Where LSA can
only accommodate only one type of labels, which is namespace label.

But as per LSA 2.1, LSA can accommodate both namespace and region
labels.

As v1.1 and v1.2 only namespace label therefore we have "struct
nd_namespace_label"

As this patch-set supports LSA 2.1, where an LSA can have any of
namespace or region label.
It is therefore, introduced "struct nd_lsa_label" in-place of "struct
nd_namespace_label"

I understand that this renaming has created some extra noise in existing
code. May be I will revisit this change and try using region label handling
separately instead of using union.

>
>>
>> No functional change introduced.
>>
>> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
>> ---
>A few minor comments inline.
>
>
>> diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
>> index 55cfbf1e0a95..bdf1ed6f23d8 100644
>> --- a/drivers/nvdimm/namespace_devs.c
>> +++ b/drivers/nvdimm/namespace_devs.c
>> @@ -1615,17 +1619,21 @@ static int select_pmem_id(struct nd_region *nd_region, const uuid_t *pmem_id)
>>  	for (i = 0; i < nd_region->ndr_mappings; i++) {
>>  		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
>>  		struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
>> +		struct nd_lsa_label *lsa_label = NULL;
>Why not pull this into the scope below.
>
>>  		struct nd_namespace_label *nd_label = NULL;
>>  		u64 hw_start, hw_end, pmem_start, pmem_end;
>>  		struct nd_label_ent *label_ent;
>>
>>  		lockdep_assert_held(&nd_mapping->lock);
>>  		list_for_each_entry(label_ent, &nd_mapping->labels, list) {
>e.g.
>			struct nd_lsa_label *lsa_label = label_ent->label;
>
>then no need to set it to NULL later.

Thanks Jonathan, I will fix it in next patch-set

Regards,
Neeraj

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH V2 03/20] nvdimm/namespace_label: Add namespace label changes as per CXL LSA v2.1
  2025-08-13 13:27       ` Jonathan Cameron
@ 2025-09-04 13:40         ` Neeraj Kumar
  0 siblings, 0 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-09-04 13:40 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel, cpgs

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

On 13/08/25 02:27PM, Jonathan Cameron wrote:
>On Wed, 30 Jul 2025 17:41:52 +0530
>Neeraj Kumar <s.neeraj@samsung.com> wrote:
>
>> CXL 3.2 Spec mentions CXL LSA 2.1 Namespace Labels at section 9.13.2.5
>> Modified __pmem_label_update function using setter functions to update
>> namespace label as per CXL LSA 2.1
>>
>> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
>
>> diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
>> index 61348dee687d..651847f1bbf9 100644
>> --- a/drivers/nvdimm/nd.h
>> +++ b/drivers/nvdimm/nd.h
>> @@ -295,6 +295,33 @@ static inline const u8 *nsl_uuid_raw(struct nvdimm_drvdata *ndd,
>
>> +static inline void nsl_set_alignment(struct nvdimm_drvdata *ndd,
>> +				     struct nd_namespace_label *ns_label,
>> +				     u32 align)
>> +{
>> +	if (ndd->cxl)
>> +		ns_label->cxl.align = __cpu_to_le16(align);
>
>The bot caught this one, it should be __cpu_to_le32(align);
>

Yes Jonathan, I will fix this in next patch-set

Regards,
Neeraj

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH V2 04/20] nvdimm/label: CXL labels skip the need for 'interleave-set cookie'
  2025-08-13 13:44       ` Jonathan Cameron
@ 2025-09-04 13:54         ` Neeraj Kumar
  0 siblings, 0 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-09-04 13:54 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel, cpgs

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

On 13/08/25 02:44PM, Jonathan Cameron wrote:
>On Wed, 30 Jul 2025 17:41:53 +0530
>Neeraj Kumar <s.neeraj@samsung.com> wrote:
>
>> CXL LSA v2.1 utilizes the region labels stored in the LSA for interleave
>> set configuration instead of interleave-set cookie used in previous LSA
>> versions. As interleave-set cookie is not required for CXL LSA v2.1 format
>> so skip its usage for CXL LSA 2.1 format
>>
>> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
>
>Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>

Thanks Jonathan for review and your RB tag


Regards,
Neeraj

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH V2 05/20] nvdimm/region_label: Add region label updation routine
  2025-08-13 14:48       ` Jonathan Cameron
@ 2025-09-04 14:06         ` Neeraj Kumar
  0 siblings, 0 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-09-04 14:06 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel, cpgs

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

On 13/08/25 03:48PM, Jonathan Cameron wrote:
>On Wed, 30 Jul 2025 17:41:54 +0530
>Neeraj Kumar <s.neeraj@samsung.com> wrote:
>
>> Added __pmem_region_label_update region label update routine to update
>> region label.
>>
>> Also used guard(mutex)(&nd_mapping->lock) in place of mutex_lock() and
>> mutex_unlock()
>>
>> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
>
>A few comments inline,
>
>Thanks,
>
>Jonathan
>
>
>>  static bool slot_valid(struct nvdimm_drvdata *ndd,
>>  		struct nd_lsa_label *lsa_label, u32 slot)
>>  {
>> @@ -960,7 +970,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
>>  		return rc;
>>
>>  	/* Garbage collect the previous label */
>> -	mutex_lock(&nd_mapping->lock);
>> +	guard(mutex)(&nd_mapping->lock);
>>  	list_for_each_entry(label_ent, &nd_mapping->labels, list) {
>>  		if (!label_ent->label)
>>  			continue;
>> @@ -972,20 +982,20 @@ static int __pmem_label_update(struct nd_region *nd_region,
>>  	/* update index */
>>  	rc = nd_label_write_index(ndd, ndd->ns_next,
>>  			nd_inc_seq(__le32_to_cpu(nsindex->seq)), 0);
>> -	if (rc == 0) {
>> -		list_for_each_entry(label_ent, &nd_mapping->labels, list)
>> -			if (!label_ent->label) {
>> -				label_ent->label = lsa_label;
>> -				lsa_label = NULL;
>> -				break;
>> -			}
>> -		dev_WARN_ONCE(&nspm->nsio.common.dev, lsa_label,
>> -				"failed to track label: %d\n",
>> -				to_slot(ndd, lsa_label));
>> -		if (lsa_label)
>> -			rc = -ENXIO;
>> -	}
>> -	mutex_unlock(&nd_mapping->lock);
>> +	if (rc)
>> +		return rc;
>> +
>> +	list_for_each_entry(label_ent, &nd_mapping->labels, list)
>> +		if (!label_ent->label) {
>> +			label_ent->label = lsa_label;
>> +			lsa_label = NULL;
>> +			break;
>> +		}
>> +	dev_WARN_ONCE(&nspm->nsio.common.dev, lsa_label,
>> +			"failed to track label: %d\n",
>> +			to_slot(ndd, lsa_label));
>> +	if (lsa_label)
>> +		rc = -ENXIO;
>	if (lsa_label)
>		return -ENXIO;
>
>	return 0;
>
>is a little clearer.

Sure, I will fix it in next patch-set

>
>>
>>  	return rc;
>>  }
>> @@ -1127,6 +1137,137 @@ int nd_pmem_namespace_label_update(struct nd_region *nd_region,
>>  	return 0;
>>  }
>>
>> +static int __pmem_region_label_update(struct nd_region *nd_region,
>> +		struct nd_mapping *nd_mapping, int pos, unsigned long flags)
>> +{
>> +	struct nd_interleave_set *nd_set = nd_region->nd_set;
>> +	struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
>> +	struct nd_lsa_label *nd_label;
>> +	struct cxl_region_label *rg_label;
>> +	struct nd_namespace_index *nsindex;
>> +	struct nd_label_ent *label_ent;
>> +	unsigned long *free;
>> +	u32 nslot, slot;
>> +	size_t offset;
>> +	int rc;
>> +	uuid_t tmp;
>> +
>> +	if (!preamble_next(ndd, &nsindex, &free, &nslot))
>> +		return -ENXIO;
>> +
>> +	/* allocate and write the label to the staging (next) index */
>> +	slot = nd_label_alloc_slot(ndd);
>> +	if (slot == UINT_MAX)
>> +		return -ENXIO;
>> +	dev_dbg(ndd->dev, "allocated: %d\n", slot);
>> +
>> +	nd_label = to_label(ndd, slot);
>> +
>> +	memset(nd_label, 0, sizeof_namespace_label(ndd));
>> +	rg_label = &nd_label->rg_label;
>> +
>> +	/* Set Region Label Format identification UUID */
>> +	uuid_parse(CXL_REGION_UUID, &tmp);
>> +	export_uuid(nd_label->rg_label.type, &tmp);
>
>	export_uuid(rg_label->type, &tmp);

Thanks Jonathan, I will fix it in next patch-set

>
>> +
>> +	/* Set Current Region Label UUID */
>> +	export_uuid(nd_label->rg_label.uuid, &nd_set->uuid);
>
>	export_uuid(rg_label->uuid, &nd_set->uuid);

Sure, I will fix it in next patch-set

>
>
>> +
>> +	rg_label->flags = __cpu_to_le32(flags);
>> +	rg_label->nlabel = __cpu_to_le16(nd_region->ndr_mappings);
>> +	rg_label->position = __cpu_to_le16(pos);
>> +	rg_label->dpa = __cpu_to_le64(nd_mapping->start);
>> +	rg_label->rawsize = __cpu_to_le64(nd_mapping->size);
>> +	rg_label->hpa = __cpu_to_le64(nd_set->res->start);
>> +	rg_label->slot = __cpu_to_le32(slot);
>> +	rg_label->ig = __cpu_to_le32(nd_set->interleave_granularity);
>> +	rg_label->align = __cpu_to_le16(0);
>
>As the bot complained... It's le32

Yes, I will fix it in next patch-set

>
>> +
>> +	/* Update fletcher64 Checksum */
>> +	rgl_calculate_checksum(ndd, rg_label);
>> +
>> +	/* update label */
>> +	offset = nd_label_offset(ndd, nd_label);
>> +	rc = nvdimm_set_config_data(ndd, offset, nd_label,
>> +			sizeof_namespace_label(ndd));
>> +	if (rc < 0) {
>> +		nd_label_free_slot(ndd, slot);
>> +		return rc;
>> +	}
>> +
>> +	/* Garbage collect the previous label */
>> +	guard(mutex)(&nd_mapping->lock);
>> +	list_for_each_entry(label_ent, &nd_mapping->labels, list) {
>> +		if (!label_ent->label)
>> +			continue;
>> +		if (rgl_uuid_equal(&label_ent->label->rg_label, &nd_set->uuid))
>> +			reap_victim(nd_mapping, label_ent);
>> +	}
>> +
>> +	/* update index */
>> +	rc = nd_label_write_index(ndd, ndd->ns_next,
>> +			nd_inc_seq(__le32_to_cpu(nsindex->seq)), 0);
>> +	if (rc)
>> +		return rc;
>> +
>> +	list_for_each_entry(label_ent, &nd_mapping->labels, list)
>> +		if (!label_ent->label) {
>> +			label_ent->label = nd_label;
>> +			nd_label = NULL;
>> +			break;
>> +		}
>> +	dev_WARN_ONCE(&nd_region->dev, nd_label,
>> +			"failed to track label: %d\n",
>> +			to_slot(ndd, nd_label));
>> +	if (nd_label)
>> +		rc = -ENXIO;
>
>		return -ENXIO;
>
>> +
>
>	return 0;
>
>is clearer.

Sure, I will fix it in next patch-set

>
>> +	return rc;
>> +}
>> +
>> +int nd_pmem_region_label_update(struct nd_region *nd_region)
>> +{
>> +	int i, rc;
>> +
>> +	for (i = 0; i < nd_region->ndr_mappings; i++) {
>> +		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
>> +		struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
>> +
>> +		/* No need to update region label for non cxl format */
>> +		if (!ndd->cxl)
>> +			continue;
>> +
>> +		/* Init labels to include region label */
>> +		rc = init_labels(nd_mapping, 1);
>> +
>
>No blank line here - keep the error check closely associated with the
>thing that it is checking.

Sure, I will fix it in next patch-set

>
>> +		if (rc < 0)
>> +			return rc;
>> +
>> +		rc = __pmem_region_label_update(nd_region, nd_mapping, i,
>> +					NSLABEL_FLAG_UPDATING);
>> +
>
>Same here.

Sure, I will fix it in next patch-set

>
>> +		if (rc)
>> +			return rc;
>> +	}
>> +
>> +	/* Clear the UPDATING flag per UEFI 2.7 expectations */
>> +	for (i = 0; i < nd_region->ndr_mappings; i++) {
>> +		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
>> +		struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
>> +
>> +		/* No need to update region label for non cxl format */
>> +		if (!ndd->cxl)
>> +			continue;
>> +
>> +		rc = __pmem_region_label_update(nd_region, nd_mapping, i, 0);
>> +
>
>and here.

Sure, I will fix it in next patch-set

>
>> +		if (rc)
>> +			return rc;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>>  int __init nd_label_init(void)
>>  {
>>  	WARN_ON(guid_parse(NVDIMM_BTT_GUID, &nvdimm_btt_guid));
>> diff --git a/drivers/nvdimm/label.h b/drivers/nvdimm/label.h
>> index 4883b3a1320f..0f428695017d 100644
>> --- a/drivers/nvdimm/label.h
>> +++ b/drivers/nvdimm/label.h
>> @@ -190,6 +190,7 @@ struct nd_namespace_label {
>>  struct nd_lsa_label {
>
>Would be better to have this explicitly as a union
>unless later patches add more elements.  That way it'll
>be obvious at all sites where it is used that it can be one
>of several things.
>
>>  	union {
>>  		struct nd_namespace_label ns_label;
>> +		struct cxl_region_label rg_label;
>>  	};
>>  };

Thanks Jonathan for your suggestion. I will revisit this change and try
using region label handling separately instead of using union.


Regards,
Neeraj

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH V2 06/20] nvdimm/region_label: Add region label deletion routine
  2025-08-13 14:53       ` Jonathan Cameron
@ 2025-09-04 14:20         ` Neeraj Kumar
  0 siblings, 0 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-09-04 14:20 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel, cpgs

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

On 13/08/25 03:53PM, Jonathan Cameron wrote:
>On Wed, 30 Jul 2025 17:41:55 +0530
>Neeraj Kumar <s.neeraj@samsung.com> wrote:
>
>> Added cxl v2.1 format region label deletion routine. This function is
>> used to delete region label from LSA
>>
>> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
>> ---
>>  drivers/nvdimm/label.c          | 77 ++++++++++++++++++++++++++++++---
>>  drivers/nvdimm/label.h          |  6 +++
>>  drivers/nvdimm/namespace_devs.c | 12 +++++
>>  drivers/nvdimm/nd.h             |  9 ++++
>>  include/linux/libnvdimm.h       |  1 +
>>  5 files changed, 100 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
>> index 94f2d0ba7aca..be18278d6cea 100644
>> --- a/drivers/nvdimm/label.c
>> +++ b/drivers/nvdimm/label.c
>> @@ -1044,7 +1044,8 @@ static int init_labels(struct nd_mapping *nd_mapping, int num_labels)
>>  	return max(num_labels, old_num_labels);
>>  }
>>
>> -static int del_labels(struct nd_mapping *nd_mapping, uuid_t *uuid)
>> +static int del_labels(struct nd_mapping *nd_mapping, uuid_t *uuid,
>> +		enum label_type ltype)
>>  {
>>  	struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
>>  	struct nd_label_ent *label_ent, *e;
>> @@ -1068,8 +1069,23 @@ static int del_labels(struct nd_mapping *nd_mapping, uuid_t *uuid)
>>  		if (!nd_label)
>>  			continue;
>>  		active++;
>> -		if (!nsl_uuid_equal(ndd, &nd_label->ns_label, uuid))
>> -			continue;
>> +
>> +		switch (ltype) {
>> +		case NS_LABEL_TYPE:
>> +			if (!nsl_uuid_equal(ndd, &nd_label->ns_label, uuid))
>> +				continue;
>> +
>> +			break;
>> +		case RG_LABEL_TYPE:
>> +			if (!rgl_uuid_equal(&nd_label->rg_label, uuid))
>> +				continue;
>> +
>> +			break;
>> +		default:
>> +			dev_err(ndd->dev, "Invalid label type\n");
>> +			return 0;
>
>Given you pass in an enum and both elements are covered by other cases
>shouldn't need a default here.

Thanks Jonathan, I will remove the default case in next patch-set

>
>> +		}
>> +
>>  		active--;
>>  		slot = to_slot(ndd, nd_label);
>>  		nd_label_free_slot(ndd, slot);
>
>
>
>> @@ -1268,6 +1285,56 @@ int nd_pmem_region_label_update(struct nd_region *nd_region)
>>  	return 0;
>>  }
>>
>> +int nd_pmem_region_label_delete(struct nd_region *nd_region)
>> +{
>> +	int i, rc;
>> +	struct nd_interleave_set *nd_set = nd_region->nd_set;
>> +	struct nd_label_ent *label_ent;
>> +	int ns_region_cnt = 0;
>> +
>> +	for (i = 0; i < nd_region->ndr_mappings; i++) {
>> +		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
>> +		struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
>> +
>> +		/* Find non cxl format supported ndr_mappings */
>> +		if (!ndd->cxl) {
>> +			dev_info(&nd_region->dev, "Region label unsupported\n");
>
>I'd go with "Unsupported region label".  The other way around kind of implies
>a deficiency in the code, whereas point here is that new stuff may be added to
>the spec that we don't yet understand.

Sure, I will fix it in next patch-set

>
>> +			return -EINVAL;
>> +		}
>> +
>> +		/* Find if any NS label using this region */
>> +		mutex_lock(&nd_mapping->lock);
>
>I'd go for guard here probably as the scope will mean it gets unlocked
>at end of this loop step.
>
>
>		guard(mutex)(&nd_mapping->lock);

Sure Jonathan, I will fix it in next patch-set

Regards,
Neeraj

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH V2 07/20] nvdimm/namespace_label: Update namespace init_labels and its region_uuid
  2025-08-13 14:58       ` Jonathan Cameron
@ 2025-09-04 14:24         ` Neeraj Kumar
  0 siblings, 0 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-09-04 14:24 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel, cpgs

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

On 13/08/25 03:58PM, Jonathan Cameron wrote:
>On Wed, 30 Jul 2025 17:41:56 +0530
>Neeraj Kumar <s.neeraj@samsung.com> wrote:
>
>> nd_mapping->labels maintains the list of labels present into LSA.
>> init_labels() prepares this list while adding new label into LSA
>> and updates nd_mapping->labels accordingly. During cxl region
>> creation nd_mapping->labels list and LSA was updated with one
>> region label. Therefore during new namespace label creation
>> pre-include the previously created region label, so increase
>> num_labels count by 1.
>>
>> Also updated nsl_set_region_uuid with region uuid with which
>> namespace is associated with.
>
>Any reason these are in the same patch?  I'd like to have
>seen a bit more on why this 'Also' change is here and a separate
>patch might make that easier to see.

I will create separate commit to update region_uuid and will remove
'Also' part from commit message. Yes both hunks are not associated,
I just added both to avoid extra commit.


Regards,
Neeraj

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH V2 08/20] nvdimm/label: Include region label in slot validation
  2025-08-13 15:07       ` Jonathan Cameron
@ 2025-09-04 14:30         ` Neeraj Kumar
  0 siblings, 0 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-09-04 14:30 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel, cpgs

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

On 13/08/25 04:07PM, Jonathan Cameron wrote:
>On Wed, 30 Jul 2025 17:41:57 +0530
>Neeraj Kumar <s.neeraj@samsung.com> wrote:
>
>> slot validation routine validates label slot by calculating label
>
>Slot validation ... or
>The slot validation routing ...

Sure, I will fix it in next patch-set

>
>
>> checksum. It was only validating namespace label. This changeset also
>> validates region label if present.
>>
>> Also validate and calculate lsa v2.1 namespace label checksum
>
>LSA v2.1 ...

Sure, I will fix it in next patch-set

>
>
>>
>> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
>Otherwise LGTM
>
>Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>

Thanks Jonathan for your review and RB tag.

Regards,
Neeraj

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH V2 09/20] nvdimm/namespace_label: Skip region label during ns label DPA reservation
  2025-08-13 15:09       ` Jonathan Cameron
@ 2025-09-04 14:31         ` Neeraj Kumar
  0 siblings, 0 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-09-04 14:31 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel, cpgs

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

On 13/08/25 04:09PM, Jonathan Cameron wrote:
>On Wed, 30 Jul 2025 17:41:58 +0530
>Neeraj Kumar <s.neeraj@samsung.com> wrote:
>
>> If Namespace label is present in LSA during nvdimm_probe then DPA
>> reservation is required. But this reservation is not required by region
>> label. Therefore if LSA scanning finds any region label, skip it.
>>
>> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
>> ---
>>  drivers/nvdimm/label.c | 4 ++++
>>  1 file changed, 4 insertions(+)
>>
>> diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
>> index c4748e30f2b6..064a945dcdd1 100644
>> --- a/drivers/nvdimm/label.c
>> +++ b/drivers/nvdimm/label.c
>> @@ -452,6 +452,10 @@ int nd_label_reserve_dpa(struct nvdimm_drvdata *ndd)
>>  		lsa_label = to_label(ndd, slot);
>>  		nd_label = &lsa_label->ns_label;
>>
>> +		/* skip region label, dpa reservation for ns label only */
>Confusing comment and not clear if skip applies just to region label or
>to dpa reservation as well.
>
>		/* Skip region label.  DPA reservation is for NS label only. */
>
>or something along those lines (assuming I have understood this right!)

Sure Jonathan, I will fix it in next patch-set


Regards,
Neeraj

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH V2 10/20] nvdimm/region_label: Preserve cxl region information from region label
  2025-08-13 15:11       ` Jonathan Cameron
@ 2025-09-04 14:33         ` Neeraj Kumar
  0 siblings, 0 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-09-04 14:33 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel, cpgs

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

On 13/08/25 04:11PM, Jonathan Cameron wrote:
>On Wed, 30 Jul 2025 17:41:59 +0530
>Neeraj Kumar <s.neeraj@samsung.com> wrote:
>
>> 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>
>
>See below.
>
>> diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
>> index 064a945dcdd1..bcac05371f87 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 *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 */
>
>In practice, is this a significant issue or not?  I.e. should we not
>merge this series until this has been revisited?

As currently we have support of Interleave way == 1, thats why this
REVISIST. I will remove this, as its not significant issue for merging this series


Regards,
Neeraj

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH V2 12/20] nvdimm/namespace_label: Skip region label during namespace creation
  2025-08-13 15:55       ` Jonathan Cameron
@ 2025-09-04 14:34         ` Neeraj Kumar
  0 siblings, 0 replies; 67+ messages in thread
From: Neeraj Kumar @ 2025-09-04 14:34 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-cxl, nvdimm, linux-kernel, gost.dev, a.manzanares, vishak.g,
	neeraj.kernel, cpgs

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

On 13/08/25 04:55PM, Jonathan Cameron wrote:
>On Wed, 30 Jul 2025 17:42:01 +0530
>Neeraj Kumar <s.neeraj@samsung.com> wrote:
>
>> During namespace creation skip presence of region label if present.
>
>Confusing description.  What does skipping presence mean?
>Reword.
>
>During namespace creation, skip any region labels found.

Thanks Jonathan, I will fix it in next patch-set

>
>
>> Also preserve region label into labels list if present.
>>
>> Signed-off-by: Neeraj Kumar <s.neeraj@samsung.com>
>> ---
>>  drivers/nvdimm/namespace_devs.c | 50 +++++++++++++++++++++++++++++----
>>  1 file changed, 45 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
>> index e5c2f78ca7dd..8edd26407939 100644
>> --- a/drivers/nvdimm/namespace_devs.c
>> +++ b/drivers/nvdimm/namespace_devs.c
>> @@ -1985,6 +1985,10 @@ static struct device **scan_labels(struct nd_region *nd_region)
>>  		if (!lsa_label)
>>  			continue;
>>
>> +		/* skip region labels if present */
>
>This is kind of obvious comment. I'd drop it.

Sure, I will drop it in next patch-set


Regards,
Neeraj

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

end of thread, other threads:[~2025-09-04 14:34 UTC | newest]

Thread overview: 67+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <CGME20250730121221epcas5p3ffb9e643af6b8ae07cfccf0bdee90e37@epcas5p3.samsung.com>
2025-07-30 12:11 ` [PATCH V2 00/20] Add CXL LSA 2.1 format support in nvdimm and cxl pmem Neeraj Kumar
     [not found]   ` <CGME20250730121223epcas5p1386bdf99a0af820dd4411fbdbd413cd5@epcas5p1.samsung.com>
2025-07-30 12:11     ` [PATCH V2 01/20] nvdimm/label: Introduce NDD_CXL_LABEL flag to set cxl label format Neeraj Kumar
2025-08-13 13:12       ` Jonathan Cameron
2025-08-15 18:06         ` Dave Jiang
2025-09-04 13:20         ` Neeraj Kumar
     [not found]   ` <CGME20250730121224epcas5p3c3a6563ce186d2fdb9c3ff5f66e37f3e@epcas5p3.samsung.com>
2025-07-30 12:11     ` [PATCH V2 02/20] nvdimm/label: Prep patch to accommodate cxl lsa 2.1 support Neeraj Kumar
2025-08-13 13:23       ` Jonathan Cameron
2025-09-04 13:27         ` Neeraj Kumar
2025-08-15 22:02       ` Dave Jiang
2025-08-18 21:48       ` Dave Jiang
2025-08-19 15:38       ` Ira Weiny
     [not found]   ` <CGME20250730121225epcas5p2742d108bd0c52c8d7d46b655892c5c19@epcas5p2.samsung.com>
2025-07-30 12:11     ` [PATCH V2 03/20] nvdimm/namespace_label: Add namespace label changes as per CXL LSA v2.1 Neeraj Kumar
2025-07-31 13:12       ` kernel test robot
2025-08-13 13:27       ` Jonathan Cameron
2025-09-04 13:40         ` Neeraj Kumar
2025-08-19 15:57       ` Ira Weiny
2025-08-19 19:36       ` Ira Weiny
     [not found]   ` <CGME20250730121227epcas5p4675fdb3130de49cd99351c5efd09e29e@epcas5p4.samsung.com>
2025-07-30 12:11     ` [PATCH V2 04/20] nvdimm/label: CXL labels skip the need for 'interleave-set cookie' Neeraj Kumar
2025-08-13 13:44       ` Jonathan Cameron
2025-09-04 13:54         ` Neeraj Kumar
2025-08-15 21:02       ` Dave Jiang
2025-08-19 16:04       ` Ira Weiny
     [not found]   ` <CGME20250730121228epcas5p411e5cc6d29fb9417178dbd07a1d8f02d@epcas5p4.samsung.com>
2025-07-30 12:11     ` [PATCH V2 05/20] nvdimm/region_label: Add region label updation routine Neeraj Kumar
2025-07-31 15:07       ` kernel test robot
2025-08-13 14:48       ` Jonathan Cameron
2025-09-04 14:06         ` Neeraj Kumar
2025-08-15 21:55       ` Dave Jiang
2025-08-15 23:12       ` Dave Jiang
2025-08-19 18:16       ` Ira Weiny
     [not found]   ` <CGME20250730121230epcas5p11650f090de55d0a2db541ee32e9a6fee@epcas5p1.samsung.com>
2025-07-30 12:11     ` [PATCH V2 06/20] nvdimm/region_label: Add region label deletion routine Neeraj Kumar
2025-08-13 14:53       ` Jonathan Cameron
2025-09-04 14:20         ` Neeraj Kumar
2025-08-15 22:22       ` Dave Jiang
     [not found]   ` <CGME20250730121231epcas5p2c12cb2b4914279d1f1c93e56a32c3908@epcas5p2.samsung.com>
2025-07-30 12:11     ` [PATCH V2 07/20] nvdimm/namespace_label: Update namespace init_labels and its region_uuid Neeraj Kumar
2025-08-13 14:58       ` Jonathan Cameron
2025-09-04 14:24         ` Neeraj Kumar
2025-08-19 18:56       ` Ira Weiny
     [not found]   ` <CGME20250730121232epcas5p4cd632fe09d1bc51499d9e3ac3c2633b3@epcas5p4.samsung.com>
2025-07-30 12:11     ` [PATCH V2 08/20] nvdimm/label: Include region label in slot validation Neeraj Kumar
2025-08-13 15:07       ` Jonathan Cameron
2025-09-04 14:30         ` Neeraj Kumar
     [not found]   ` <CGME20250730121234epcas5p2605fbec7bc95f6096550792844b8f8ee@epcas5p2.samsung.com>
2025-07-30 12:11     ` [PATCH V2 09/20] nvdimm/namespace_label: Skip region label during ns label DPA reservation Neeraj Kumar
2025-08-13 15:09       ` Jonathan Cameron
2025-09-04 14:31         ` Neeraj Kumar
     [not found]   ` <CGME20250730121235epcas5p4494147524e77e99bc16d9b510e8971a4@epcas5p4.samsung.com>
2025-07-30 12:11     ` [PATCH V2 10/20] nvdimm/region_label: Preserve cxl region information from region label Neeraj Kumar
2025-08-13 15:11       ` Jonathan Cameron
2025-09-04 14:33         ` Neeraj Kumar
     [not found]   ` <CGME20250730121236epcas5p4b8939ed1bfff468c965a9dbd6bc261b6@epcas5p4.samsung.com>
2025-07-30 12:12     ` [PATCH V2 11/20] nvdimm/region_label: Export routine to fetch region information Neeraj Kumar
2025-08-13 15:13       ` Jonathan Cameron
     [not found]   ` <CGME20250730121238epcas5p212dcce5cc5713173913ee154d5098a2c@epcas5p2.samsung.com>
2025-07-30 12:12     ` [PATCH V2 12/20] nvdimm/namespace_label: Skip region label during namespace creation Neeraj Kumar
2025-08-13 15:55       ` Jonathan Cameron
2025-09-04 14:34         ` Neeraj Kumar
     [not found]   ` <CGME20250730121239epcas5p37956b2999f61e17e8dbfbde7972cef35@epcas5p3.samsung.com>
2025-07-30 12:12     ` [PATCH V2 13/20] cxl/mem: Refactor cxl pmem region auto-assembling Neeraj Kumar
2025-08-20 16:41       ` Dave Jiang
     [not found]   ` <CGME20250730121241epcas5p3e5708a89d764d1de9322fd759f921de0@epcas5p3.samsung.com>
2025-07-30 12:12     ` [PATCH V2 14/20] cxl/region: Add devm_cxl_pmem_add_region() for pmem region creation Neeraj Kumar
2025-08-20  0:30       ` Dave Jiang
     [not found]   ` <CGME20250730121242epcas5p4bdfc11e82e28d525364262fb2b6d8feb@epcas5p4.samsung.com>
2025-07-30 12:12     ` [PATCH V2 15/20] cxl: Add a routine to find cxl root decoder on cxl bus using cxl port Neeraj Kumar
     [not found]   ` <CGME20250730121243epcas5p4c40126a3cf5c8019b36eb8287c3ec2c8@epcas5p4.samsung.com>
2025-07-30 12:12     ` [PATCH V2 16/20] cxl/mem: Preserve cxl root decoder during mem probe Neeraj Kumar
     [not found]   ` <CGME20250730121245epcas5p247b6675350f4f7e70e9b3c8465340e84@epcas5p2.samsung.com>
2025-07-30 12:12     ` [PATCH V2 17/20] cxl/pmem: Preserve region information into nd_set Neeraj Kumar
     [not found]   ` <CGME20250730121246epcas5p48a2fd8e653f05a0282cbffc1f702f26f@epcas5p4.samsung.com>
2025-07-30 12:12     ` [PATCH V2 18/20] cxl/pmem: Add support of cxl lsa 2.1 support in cxl pmem Neeraj Kumar
2025-07-31  1:36       ` kernel test robot
     [not found]   ` <CGME20250730121247epcas5p425b79da65bcb003917cbf02fc047a7db@epcas5p4.samsung.com>
2025-07-30 12:12     ` [PATCH V2 19/20] cxl/pmem_region: Prep patch to accommodate pmem_region attributes Neeraj Kumar
2025-07-31  1:57       ` kernel test robot
2025-07-31  2:17       ` kernel test robot
     [not found]   ` <CGME20250730121249epcas5p249c2e3fec3464cfea3a1c84bc285cd49@epcas5p2.samsung.com>
2025-07-30 12:12     ` [PATCH V2 20/20] cxl/pmem_region: Add sysfs attribute cxl region label updation/deletion Neeraj Kumar
2025-07-31 10:36       ` kernel test robot
2025-08-07  9:02   ` [PATCH V2 00/20] Add CXL LSA 2.1 format support in nvdimm and cxl pmem Neeraj Kumar
2025-08-12 21:46     ` Dave Jiang

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