Linux CXL
 help / color / mirror / Atom feed
* [PATCH v3 0/6] cxl: Add CXL type2 accelerator support for cxl_test
@ 2026-06-10 22:23 Dave Jiang
  2026-06-10 22:23 ` [PATCH v3 1/6] cxl/test: Add test for module parameters Dave Jiang
                   ` (5 more replies)
  0 siblings, 6 replies; 12+ messages in thread
From: Dave Jiang @ 2026-06-10 22:23 UTC (permalink / raw)
  To: linux-cxl; +Cc: djbw, dave, jic23, alison.schofield, vishal.l.verma

See individual patches for changes from previous version.

The series is based on v7.1-rc7 with Dan's region devm-cxl_probe_mem()
series [1] plus a 0-day fix [2] and Alejandro's type2 series v27 [3].

Series adds a 'type2_test' module parameter where it setup a mock type2
hierarchy with a mock type2 accelerator device directly under a root
port that has an auto region setup.

It also includes a CXL fix that was encountered when running tests with
the new code.

[
  {
    "memdevs":[
      {
        "memdev":"mem0",
        "ram_size":536870912,
        "ram_qos_class":42,
        "host":"cxl_type2_accel.0",
        "poison_injectable":false
      }
    ]
  },
  {
    "regions":[
      {
        "region":"region0",
        "resource":70300293136384,
        "size":536870912,
        "type":"ram",
        "interleave_ways":1,
        "interleave_granularity":4096,
        "decode_state":"commit"
      }
    ]
  }
]

    "root decoders":[
      {
        "decoder":"decoder0.0",
        "resource":70300293136384,
        "size":1073741824,
        "interleave_ways":1,
        "accelmem_capable":true,
        "qos_class":42,
        "nr_targets":1
      },

[1]: https://lore.kernel.org/linux-cxl/5f399564-7efe-444d-a6cf-2c6176e57ad9@intel.com/T/#t
[2]: https://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl.git/log/?h=for-7.3/cxl-type2-enabling
[3]: https://lore.kernel.org/linux-cxl/20260609215755.8685-1-alejandro.lucero-palau@amd.com/T/#t

Dave Jiang (6):
  cxl/test: Add test for module parameters
  cxl/test: Add type2 support for mock CFMWS0
  cxl/test: Refactor platform device enumerations
  cxl/test: Add hierarchy enumeration support for type2 device
  cxl/test: Fixup hdm init for auto region to support type2
  cxl/test: Add cxl_test accelerator driver

 tools/testing/cxl/test/Kbuild  |   2 +
 tools/testing/cxl/test/accel.c |  66 +++
 tools/testing/cxl/test/cxl.c   | 789 +++++++++++++++++++++++++--------
 3 files changed, 666 insertions(+), 191 deletions(-)
 create mode 100644 tools/testing/cxl/test/accel.c


base-commit: fb6e9f132f0b98c0cf99f8f08ec6ced52139d9b7
-- 
2.54.0


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

* [PATCH v3 1/6] cxl/test: Add test for module parameters
  2026-06-10 22:23 [PATCH v3 0/6] cxl: Add CXL type2 accelerator support for cxl_test Dave Jiang
@ 2026-06-10 22:23 ` Dave Jiang
  2026-06-10 22:32   ` sashiko-bot
  2026-06-10 22:23 ` [PATCH v3 2/6] cxl/test: Add type2 support for mock CFMWS0 Dave Jiang
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Dave Jiang @ 2026-06-10 22:23 UTC (permalink / raw)
  To: linux-cxl; +Cc: djbw, dave, jic23, alison.schofield, vishal.l.verma

Add a test for module paraters during module init to make sure that
only one is activated.

Suggested-by: Alison Schofield <alison.schofield@intel.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 tools/testing/cxl/test/cxl.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
index 296516eecfd6..b00f5161b5f0 100644
--- a/tools/testing/cxl/test/cxl.c
+++ b/tools/testing/cxl/test/cxl.c
@@ -1814,11 +1814,29 @@ static struct attribute *cxl_acpi_attrs[] = {
 };
 ATTRIBUTE_GROUPS(cxl_acpi);
 
+bool __init have_multiple_modparms(void)
+{
+	int count = 0;
+
+	if (interleave_arithmetic)
+		count++;
+	if (extended_linear_cache)
+		count++;
+	if (fail_autoassemble)
+		count++;
+
+	return count > 1;
+}
+
 static __init int cxl_test_init(void)
 {
 	int rc, i;
 	struct range mappable;
 
+	/* Enforce a single module param active at a time */
+	if (have_multiple_modparms())
+		return -EINVAL;
+
 	cxl_acpi_test();
 	cxl_core_test();
 	cxl_mem_test();
-- 
2.54.0


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

* [PATCH v3 2/6] cxl/test: Add type2 support for mock CFMWS0
  2026-06-10 22:23 [PATCH v3 0/6] cxl: Add CXL type2 accelerator support for cxl_test Dave Jiang
  2026-06-10 22:23 ` [PATCH v3 1/6] cxl/test: Add test for module parameters Dave Jiang
@ 2026-06-10 22:23 ` Dave Jiang
  2026-06-10 22:32   ` sashiko-bot
  2026-06-10 22:23 ` [PATCH v3 3/6] cxl/test: Refactor platform device enumerations Dave Jiang
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Dave Jiang @ 2026-06-10 22:23 UTC (permalink / raw)
  To: linux-cxl; +Cc: djbw, dave, jic23, alison.schofield, vishal.l.verma

Add a module parameter 'type2_test' for triggering type2 test support
in cxl_test. Setup the CFMWS0 configuration to be type2 when 'type2_test'
is set.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 tools/testing/cxl/test/cxl.c | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
index b00f5161b5f0..e91c125d557d 100644
--- a/tools/testing/cxl/test/cxl.c
+++ b/tools/testing/cxl/test/cxl.c
@@ -17,6 +17,7 @@
 static int interleave_arithmetic;
 static bool extended_linear_cache;
 static bool fail_autoassemble;
+static bool type2_test;
 
 #define FAKE_QTG_ID	42
 
@@ -384,6 +385,19 @@ static struct {
 	},
 };
 
+static struct acpi_cedt_cfmws type2_cfmws0 = {
+	.header = {
+		.type = ACPI_CEDT_TYPE_CFMWS,
+		.length = sizeof(mock_cedt.cfmws0),
+	},
+	.interleave_ways = 0,
+	.granularity = 4,
+	.restrictions = ACPI_CEDT_CFMWS_RESTRICT_DEVMEM |
+			ACPI_CEDT_CFMWS_RESTRICT_VOLATILE,
+	.qtg_id = FAKE_QTG_ID,
+	.window_size = SZ_256M * 4,
+};
+
 struct acpi_cedt_cfmws *mock_cfmws[] = {
 	[0] = &mock_cedt.cfmws0.cfmws,
 	[1] = &mock_cedt.cfmws1.cfmws,
@@ -472,6 +486,11 @@ static void cfmws_elc_update(struct acpi_cedt_cfmws *window, int index)
 	window->window_size = mock_auto_region_size * 2;
 }
 
+static void update_type2_cfmws(void)
+{
+	memcpy(&mock_cedt.cfmws0.cfmws, &type2_cfmws0, sizeof(type2_cfmws0));
+}
+
 static int populate_cedt(void)
 {
 	struct cxl_mock_res *res;
@@ -493,10 +512,14 @@ static int populate_cedt(void)
 		chbs->length = size;
 	}
 
+	if (type2_test)
+		update_type2_cfmws();
+
 	for (i = cfmws_start; i <= cfmws_end; i++) {
 		struct acpi_cedt_cfmws *window = mock_cfmws[i];
 
-		cfmws_elc_update(window, i);
+		if (i == 0 && !type2_test)
+			cfmws_elc_update(window, i);
 		res = alloc_mock_res(window->window_size, SZ_256M);
 		if (!res)
 			return -ENOMEM;
@@ -1824,6 +1847,8 @@ bool __init have_multiple_modparms(void)
 		count++;
 	if (fail_autoassemble)
 		count++;
+	if (type2_test)
+		count++;
 
 	return count > 1;
 }
@@ -2048,6 +2073,8 @@ module_param(extended_linear_cache, bool, 0444);
 MODULE_PARM_DESC(extended_linear_cache, "Enable extended linear cache support");
 module_param(fail_autoassemble, bool, 0444);
 MODULE_PARM_DESC(fail_autoassemble, "Simulate missing member of an auto-region");
+module_param(type2_test, bool, 0444);
+MODULE_PARM_DESC(type2_test, "Enable type 2 support testing");
 module_init(cxl_test_init);
 module_exit(cxl_test_exit);
 MODULE_LICENSE("GPL v2");
-- 
2.54.0


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

* [PATCH v3 3/6] cxl/test: Refactor platform device enumerations
  2026-06-10 22:23 [PATCH v3 0/6] cxl: Add CXL type2 accelerator support for cxl_test Dave Jiang
  2026-06-10 22:23 ` [PATCH v3 1/6] cxl/test: Add test for module parameters Dave Jiang
  2026-06-10 22:23 ` [PATCH v3 2/6] cxl/test: Add type2 support for mock CFMWS0 Dave Jiang
@ 2026-06-10 22:23 ` Dave Jiang
  2026-06-10 22:32   ` sashiko-bot
  2026-06-10 22:23 ` [PATCH v3 4/6] cxl/test: Add hierarchy enumeration support for type2 device Dave Jiang
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Dave Jiang @ 2026-06-10 22:23 UTC (permalink / raw)
  To: linux-cxl; +Cc: djbw, dave, jic23, alison.schofield, vishal.l.verma

Split all the host bridges, rootports, upstream and downstream ports
enumerations to separate helper functions. This should make adding
type2 hierarchy easier later on.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 tools/testing/cxl/test/cxl.c | 304 ++++++++++++++++++++++++-----------
 1 file changed, 206 insertions(+), 98 deletions(-)

diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
index e91c125d557d..b29be2597064 100644
--- a/tools/testing/cxl/test/cxl.c
+++ b/tools/testing/cxl/test/cxl.c
@@ -1853,10 +1853,196 @@ bool __init have_multiple_modparms(void)
 	return count > 1;
 }
 
+static void host_bridges_remove(void)
+{
+	int i;
+
+	for (i = ARRAY_SIZE(cxl_host_bridge) - 1; i >= 0; i--) {
+		struct platform_device *pdev = cxl_host_bridge[i];
+
+		if (!pdev)
+			break;
+
+		sysfs_remove_link(&pdev->dev.kobj, "physical_node");
+		platform_device_unregister(cxl_host_bridge[i]);
+	}
+}
+
+static int host_bridges_populate(void)
+{
+	int rc = 0;
+
+	for (int i = 0; i < ARRAY_SIZE(cxl_host_bridge); i++) {
+		struct acpi_device *adev = &host_bridge[i];
+		struct platform_device *pdev;
+
+		pdev = platform_device_alloc("cxl_host_bridge", i);
+		if (!pdev)
+			goto err_bridge;
+
+		mock_companion(adev, &pdev->dev);
+		rc = cxl_mock_platform_device_add(pdev, &cxl_host_bridge[i]);
+		if (rc)
+			goto err_bridge;
+
+		mock_pci_bus[i].bridge = &pdev->dev;
+		rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
+				       "physical_node");
+		if (rc)
+			goto err_bridge;
+	}
+
+	return 0;
+
+err_bridge:
+	host_bridges_remove();
+	return rc;
+}
+
+static void cxl_rootports_remove(void)
+{
+	for (int i = ARRAY_SIZE(cxl_root_port) - 1; i >= 0; i--) {
+		struct platform_device *pdev = cxl_root_port[i];
+
+		if (!pdev)
+			break;
+
+		platform_device_unregister(pdev);
+	}
+}
+
+static int cxl_rootports_populate(void)
+{
+	int rc = 0;
+
+	for (int i = 0; i < ARRAY_SIZE(cxl_root_port); i++) {
+		struct platform_device *bridge =
+			cxl_host_bridge[i % ARRAY_SIZE(cxl_host_bridge)];
+		struct platform_device *pdev;
+
+		pdev = platform_device_alloc("cxl_root_port", i);
+		if (!pdev)
+			goto err_port;
+
+		pdev->dev.parent = &bridge->dev;
+
+		rc = cxl_mock_platform_device_add(pdev, &cxl_root_port[i]);
+		if (rc)
+			goto err_port;
+	}
+
+	return 0;
+
+err_port:
+	cxl_rootports_remove();
+	return rc;
+}
+
+static void cxl_usps_remove(void)
+{
+	for (int i = ARRAY_SIZE(cxl_switch_uport) - 1; i >= 0; i--) {
+		struct platform_device *pdev = cxl_switch_uport[i];
+
+		if (!pdev)
+			break;
+
+		platform_device_unregister(cxl_switch_uport[i]);
+	}
+}
+
+static int cxl_usps_populate(void)
+{
+	int rc = 0;
+
+	for (int i = 0; i < ARRAY_SIZE(cxl_switch_uport); i++) {
+		struct platform_device *root_port = cxl_root_port[i];
+		struct platform_device *pdev;
+
+		pdev = platform_device_alloc("cxl_switch_uport", i);
+		if (!pdev)
+			goto err_uport;
+
+		pdev->dev.parent = &root_port->dev;
+
+		rc = cxl_mock_platform_device_add(pdev, &cxl_switch_uport[i]);
+		if (rc)
+			goto err_uport;
+	}
+
+	return 0;
+
+err_uport:
+	cxl_usps_remove();
+	return rc;
+}
+
+static void cxl_dsps_remove(void)
+{
+	for (int i = ARRAY_SIZE(cxl_switch_dport) - 1; i >= 0; i--) {
+		struct platform_device *pdev = cxl_switch_dport[i];
+
+		if (!pdev)
+			break;
+
+		platform_device_unregister(cxl_switch_dport[i]);
+	}
+}
+
+
+static int cxl_dsps_populate(void)
+{
+	int rc = 0;
+
+	for (int i = 0; i < ARRAY_SIZE(cxl_switch_dport); i++) {
+		struct platform_device *uport =
+			cxl_switch_uport[i % ARRAY_SIZE(cxl_switch_uport)];
+		struct platform_device *pdev;
+
+		pdev = platform_device_alloc("cxl_switch_dport", i);
+		if (!pdev)
+			goto err_dport;
+		pdev->dev.parent = &uport->dev;
+
+		rc = cxl_mock_platform_device_add(pdev, &cxl_switch_dport[i]);
+		if (rc)
+			goto err_dport;
+	}
+
+	return 0;
+
+err_dport:
+	cxl_dsps_remove();
+	return rc;
+}
+
+static void cxl_switches_remove(void)
+{
+	cxl_dsps_remove();
+	cxl_usps_remove();
+}
+
+static int cxl_switches_populate(void)
+{
+	int rc;
+
+	BUILD_BUG_ON(ARRAY_SIZE(cxl_switch_uport) != ARRAY_SIZE(cxl_root_port));
+	rc = cxl_usps_populate();
+	if (rc)
+		return rc;
+
+	rc = cxl_dsps_populate();
+	if (rc) {
+		cxl_usps_remove();
+		return rc;
+	}
+
+	return 0;
+}
+
 static __init int cxl_test_init(void)
 {
-	int rc, i;
 	struct range mappable;
+	int rc;
 
 	/* Enforce a single module param active at a time */
 	if (have_multiple_modparms())
@@ -1896,74 +2082,21 @@ static __init int cxl_test_init(void)
 	if (rc)
 		goto err_populate;
 
-	for (i = 0; i < ARRAY_SIZE(cxl_host_bridge); i++) {
-		struct acpi_device *adev = &host_bridge[i];
-		struct platform_device *pdev;
+	rc = host_bridges_populate();
+	if (rc)
+		goto err_populate;
 
-		pdev = platform_device_alloc("cxl_host_bridge", i);
-		if (!pdev)
-			goto err_bridge;
+	rc = cxl_rootports_populate();
+	if (rc)
+		goto err_host_bridges;
 
-		mock_companion(adev, &pdev->dev);
-		rc = cxl_mock_platform_device_add(pdev, &cxl_host_bridge[i]);
-		if (rc)
-			goto err_bridge;
-
-		mock_pci_bus[i].bridge = &pdev->dev;
-		rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
-				       "physical_node");
-		if (rc)
-			goto err_bridge;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(cxl_root_port); i++) {
-		struct platform_device *bridge =
-			cxl_host_bridge[i % ARRAY_SIZE(cxl_host_bridge)];
-		struct platform_device *pdev;
-
-		pdev = platform_device_alloc("cxl_root_port", i);
-		if (!pdev)
-			goto err_port;
-		pdev->dev.parent = &bridge->dev;
-
-		rc = cxl_mock_platform_device_add(pdev, &cxl_root_port[i]);
-		if (rc)
-			goto err_port;
-	}
-
-	BUILD_BUG_ON(ARRAY_SIZE(cxl_switch_uport) != ARRAY_SIZE(cxl_root_port));
-	for (i = 0; i < ARRAY_SIZE(cxl_switch_uport); i++) {
-		struct platform_device *root_port = cxl_root_port[i];
-		struct platform_device *pdev;
-
-		pdev = platform_device_alloc("cxl_switch_uport", i);
-		if (!pdev)
-			goto err_uport;
-		pdev->dev.parent = &root_port->dev;
-
-		rc = cxl_mock_platform_device_add(pdev, &cxl_switch_uport[i]);
-		if (rc)
-			goto err_uport;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(cxl_switch_dport); i++) {
-		struct platform_device *uport =
-			cxl_switch_uport[i % ARRAY_SIZE(cxl_switch_uport)];
-		struct platform_device *pdev;
-
-		pdev = platform_device_alloc("cxl_switch_dport", i);
-		if (!pdev)
-			goto err_dport;
-		pdev->dev.parent = &uport->dev;
-
-		rc = cxl_mock_platform_device_add(pdev, &cxl_switch_dport[i]);
-		if (rc)
-			goto err_dport;
-	}
+	rc = cxl_switches_populate();
+	if (rc)
+		goto err_root_ports;
 
 	rc = cxl_single_topo_init();
 	if (rc)
-		goto err_dport;
+		goto err_switches;
 
 	rc = cxl_rch_topo_init();
 	if (rc)
@@ -1999,24 +2132,12 @@ static __init int cxl_test_init(void)
 	cxl_rch_topo_exit();
 err_single:
 	cxl_single_topo_exit();
-err_dport:
-	for (i = ARRAY_SIZE(cxl_switch_dport) - 1; i >= 0; i--)
-		platform_device_unregister(cxl_switch_dport[i]);
-err_uport:
-	for (i = ARRAY_SIZE(cxl_switch_uport) - 1; i >= 0; i--)
-		platform_device_unregister(cxl_switch_uport[i]);
-err_port:
-	for (i = ARRAY_SIZE(cxl_root_port) - 1; i >= 0; i--)
-		platform_device_unregister(cxl_root_port[i]);
-err_bridge:
-	for (i = ARRAY_SIZE(cxl_host_bridge) - 1; i >= 0; i--) {
-		struct platform_device *pdev = cxl_host_bridge[i];
-
-		if (!pdev)
-			continue;
-		sysfs_remove_link(&pdev->dev.kobj, "physical_node");
-		platform_device_unregister(cxl_host_bridge[i]);
-	}
+err_switches:
+	cxl_switches_remove();
+err_root_ports:
+	cxl_rootports_remove();
+err_host_bridges:
+	host_bridges_remove();
 err_populate:
 	depopulate_all_mock_resources();
 err_gen_pool_add:
@@ -2039,27 +2160,14 @@ static void free_decoder_registry(void)
 
 static __exit void cxl_test_exit(void)
 {
-	int i;
-
 	hmem_test_exit();
 	cxl_mem_exit();
 	platform_device_unregister(cxl_acpi);
 	cxl_rch_topo_exit();
 	cxl_single_topo_exit();
-	for (i = ARRAY_SIZE(cxl_switch_dport) - 1; i >= 0; i--)
-		platform_device_unregister(cxl_switch_dport[i]);
-	for (i = ARRAY_SIZE(cxl_switch_uport) - 1; i >= 0; i--)
-		platform_device_unregister(cxl_switch_uport[i]);
-	for (i = ARRAY_SIZE(cxl_root_port) - 1; i >= 0; i--)
-		platform_device_unregister(cxl_root_port[i]);
-	for (i = ARRAY_SIZE(cxl_host_bridge) - 1; i >= 0; i--) {
-		struct platform_device *pdev = cxl_host_bridge[i];
-
-		if (!pdev)
-			continue;
-		sysfs_remove_link(&pdev->dev.kobj, "physical_node");
-		platform_device_unregister(cxl_host_bridge[i]);
-	}
+	cxl_switches_remove();
+	cxl_rootports_remove();
+	host_bridges_remove();
 	depopulate_all_mock_resources();
 	gen_pool_destroy(cxl_mock_pool);
 	unregister_cxl_mock_ops(&cxl_mock_ops);
-- 
2.54.0


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

* [PATCH v3 4/6] cxl/test: Add hierarchy enumeration support for type2 device
  2026-06-10 22:23 [PATCH v3 0/6] cxl: Add CXL type2 accelerator support for cxl_test Dave Jiang
                   ` (2 preceding siblings ...)
  2026-06-10 22:23 ` [PATCH v3 3/6] cxl/test: Refactor platform device enumerations Dave Jiang
@ 2026-06-10 22:23 ` Dave Jiang
  2026-06-10 22:36   ` sashiko-bot
  2026-06-10 22:23 ` [PATCH v3 5/6] cxl/test: Fixup hdm init for auto region to support type2 Dave Jiang
  2026-06-10 22:23 ` [PATCH v3 6/6] cxl/test: Add cxl_test accelerator driver Dave Jiang
  5 siblings, 1 reply; 12+ messages in thread
From: Dave Jiang @ 2026-06-10 22:23 UTC (permalink / raw)
  To: linux-cxl; +Cc: djbw, dave, jic23, alison.schofield, vishal.l.verma

Add enumeration of type2 device hierarchy in cxl-test. The type2 device
is setup to be directly attached to a root port instead of rp -> switch
-> device that type3 hierarchy is setup..

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 tools/testing/cxl/test/cxl.c | 219 ++++++++++++++++++++++++++++-------
 1 file changed, 178 insertions(+), 41 deletions(-)

diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
index b29be2597064..5186a13b20aa 100644
--- a/tools/testing/cxl/test/cxl.c
+++ b/tools/testing/cxl/test/cxl.c
@@ -28,6 +28,7 @@ static bool type2_test;
 #define NR_CXL_SWITCH_PORTS 2
 #define NR_CXL_PORT_DECODERS 8
 #define NR_BRIDGES (NR_CXL_HOST_BRIDGES + NR_CXL_SINGLE_HOST + NR_CXL_RCH)
+#define NR_CXL_TYPE2_ACCEL 1
 
 #define MOCK_AUTO_REGION_SIZE_DEFAULT SZ_512M
 static int mock_auto_region_size = MOCK_AUTO_REGION_SIZE_DEFAULT;
@@ -1734,19 +1735,90 @@ static void cxl_single_topo_exit(void)
 	}
 }
 
+static void cxl_type3_mem_exit(void)
+{
+	struct platform_device *pdev;
+	int i;
+
+	for (i = ARRAY_SIZE(cxl_rcd) - 1; i >= 0; i--) {
+		pdev = cxl_rcd[i];
+		if (!pdev)
+			break;
+		platform_device_unregister(cxl_rcd[i]);
+	}
+
+	for (i = ARRAY_SIZE(cxl_mem_single) - 1; i >= 0; i--) {
+		pdev = cxl_mem_single[i];
+		if (!pdev)
+			break;
+		platform_device_unregister(cxl_mem_single[i]);
+	}
+
+	for (i = ARRAY_SIZE(cxl_mem) - 1; i >= 0; i--) {
+		pdev = cxl_mem[i];
+		if (!pdev)
+			break;
+		platform_device_unregister(pdev);
+	}
+}
+
+static void cxl_type2_mem_exit(void)
+{
+	for (int i = NR_CXL_TYPE2_ACCEL - 1; i >= 0; i--) {
+		struct platform_device *pdev = cxl_mem[i];
+
+		if (!pdev)
+			break;
+		platform_device_unregister(pdev);
+	}
+}
+
 static void cxl_mem_exit(void)
 {
-	int i;
+	if (type2_test) {
+		cxl_type2_mem_exit();
+		return;
+	}
 
-	for (i = ARRAY_SIZE(cxl_rcd) - 1; i >= 0; i--)
-		platform_device_unregister(cxl_rcd[i]);
-	for (i = ARRAY_SIZE(cxl_mem_single) - 1; i >= 0; i--)
-		platform_device_unregister(cxl_mem_single[i]);
-	for (i = ARRAY_SIZE(cxl_mem) - 1; i >= 0; i--)
+	cxl_type3_mem_exit();
+}
+
+static int cxl_type2_mem_init(void)
+{
+	int i, rc;
+
+	for (i = 0; i < NR_CXL_TYPE2_ACCEL; i++) {
+		struct platform_device *dport = cxl_root_port[i];
+		struct platform_device *pdev;
+
+		pdev = platform_device_alloc("cxl_type2_accel", i);
+		if (!pdev)
+			goto err_mem;
+		pdev->dev.parent = &dport->dev;
+		set_dev_node(&pdev->dev, i % 2);
+
+		rc = platform_device_add(pdev);
+		if (rc) {
+			platform_device_put(pdev);
+			goto err_mem;
+		}
+		cxl_mem[i] = pdev;
+	}
+
+	return 0;
+
+err_mem:
+	for (i = NR_CXL_TYPE2_ACCEL - 1; i >= 0; i--) {
+		struct platform_device *pdev = cxl_mem[i];
+
+		if (!pdev)
+			break;
 		platform_device_unregister(cxl_mem[i]);
+	}
+	return rc;
 }
 
-static int cxl_mem_init(void)
+static int cxl_type3_mem_init(void)
 {
 	int i, rc;
 
@@ -1810,6 +1882,13 @@ static int cxl_mem_init(void)
 	return rc;
 }
 
+static int cxl_mem_init(void)
+{
+	if (type2_test)
+		return cxl_type2_mem_init();
+	return cxl_type3_mem_init();
+}
+
 static ssize_t
 decoder_reset_preserve_registry_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
@@ -2039,6 +2118,92 @@ static int cxl_switches_populate(void)
 	return 0;
 }
 
+static void cxl_type2_topo_exit(void)
+{
+	host_bridges_remove();
+	cxl_rootports_remove();
+}
+
+static int cxl_type2_topo_init(void)
+{
+	int rc;
+
+	rc = host_bridges_populate();
+	if (rc)
+		return rc;
+
+	rc = cxl_rootports_populate();
+	if (rc) {
+		host_bridges_remove();
+		return rc;
+	}
+
+	return 0;
+}
+
+static void cxl_type3_topo_exit(void)
+{
+	host_bridges_remove();
+	cxl_rootports_remove();
+	cxl_switches_remove();
+	cxl_single_topo_exit();
+	cxl_rch_topo_exit();
+}
+
+static int cxl_type3_topo_init(void)
+{
+	int rc;
+
+	rc = host_bridges_populate();
+	if (rc)
+		return rc;
+
+	rc = cxl_rootports_populate();
+	if (rc)
+		goto err_host_bridges;
+
+	rc = cxl_switches_populate();
+	if (rc)
+		goto err_root_ports;
+
+	rc = cxl_single_topo_init();
+	if (rc)
+		goto err_switches;
+
+	rc = cxl_rch_topo_init();
+	if (rc)
+		goto err_single;
+
+	return 0;
+
+err_single:
+	cxl_single_topo_exit();
+err_switches:
+	cxl_switches_remove();
+err_root_ports:
+	cxl_rootports_remove();
+err_host_bridges:
+	host_bridges_remove();
+	return rc;
+}
+
+static void cxl_topo_exit(void)
+{
+	if (type2_test) {
+		cxl_type2_topo_exit();
+		return;
+	}
+
+	cxl_type3_topo_exit();
+}
+
+static int cxl_topo_init(void)
+{
+	if (type2_test)
+		return cxl_type2_topo_init();
+	return cxl_type3_topo_init();
+}
+
 static __init int cxl_test_init(void)
 {
 	struct range mappable;
@@ -2082,29 +2247,13 @@ static __init int cxl_test_init(void)
 	if (rc)
 		goto err_populate;
 
-	rc = host_bridges_populate();
+	rc = cxl_topo_init();
 	if (rc)
 		goto err_populate;
 
-	rc = cxl_rootports_populate();
-	if (rc)
-		goto err_host_bridges;
-
-	rc = cxl_switches_populate();
-	if (rc)
-		goto err_root_ports;
-
-	rc = cxl_single_topo_init();
-	if (rc)
-		goto err_switches;
-
-	rc = cxl_rch_topo_init();
-	if (rc)
-		goto err_single;
-
 	cxl_acpi = platform_device_alloc("cxl_acpi", 0);
 	if (!cxl_acpi)
-		goto err_rch;
+		goto err_topo;
 
 	mock_companion(&acpi0017_mock, &cxl_acpi->dev);
 	acpi0017_mock.dev.bus = &platform_bus_type;
@@ -2112,7 +2261,7 @@ static __init int cxl_test_init(void)
 
 	rc = cxl_mock_platform_device_add(cxl_acpi, NULL);
 	if (rc)
-		goto err_rch;
+		goto err_root;
 
 	rc = cxl_mem_init();
 	if (rc)
@@ -2128,16 +2277,8 @@ static __init int cxl_test_init(void)
 	cxl_mem_exit();
 err_root:
 	platform_device_put(cxl_acpi);
-err_rch:
-	cxl_rch_topo_exit();
-err_single:
-	cxl_single_topo_exit();
-err_switches:
-	cxl_switches_remove();
-err_root_ports:
-	cxl_rootports_remove();
-err_host_bridges:
-	host_bridges_remove();
+err_topo:
+	cxl_topo_exit();
 err_populate:
 	depopulate_all_mock_resources();
 err_gen_pool_add:
@@ -2163,11 +2304,7 @@ static __exit void cxl_test_exit(void)
 	hmem_test_exit();
 	cxl_mem_exit();
 	platform_device_unregister(cxl_acpi);
-	cxl_rch_topo_exit();
-	cxl_single_topo_exit();
-	cxl_switches_remove();
-	cxl_rootports_remove();
-	host_bridges_remove();
+	cxl_topo_exit();
 	depopulate_all_mock_resources();
 	gen_pool_destroy(cxl_mock_pool);
 	unregister_cxl_mock_ops(&cxl_mock_ops);
-- 
2.54.0


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

* [PATCH v3 5/6] cxl/test: Fixup hdm init for auto region to support type2
  2026-06-10 22:23 [PATCH v3 0/6] cxl: Add CXL type2 accelerator support for cxl_test Dave Jiang
                   ` (3 preceding siblings ...)
  2026-06-10 22:23 ` [PATCH v3 4/6] cxl/test: Add hierarchy enumeration support for type2 device Dave Jiang
@ 2026-06-10 22:23 ` Dave Jiang
  2026-06-10 22:23 ` [PATCH v3 6/6] cxl/test: Add cxl_test accelerator driver Dave Jiang
  5 siblings, 0 replies; 12+ messages in thread
From: Dave Jiang @ 2026-06-10 22:23 UTC (permalink / raw)
  To: linux-cxl; +Cc: djbw, dave, jic23, alison.schofield, vishal.l.verma

Add support to setup initialization of decoders in order to support
type2 auto region.

Reviewed-by: Alison Schofield <alison.schofield@intel.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
- rebased against v7.1-rc7
---
 tools/testing/cxl/test/cxl.c | 255 +++++++++++++++++++++++++----------
 1 file changed, 186 insertions(+), 69 deletions(-)

diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
index 5186a13b20aa..7627aeb94790 100644
--- a/tools/testing/cxl/test/cxl.c
+++ b/tools/testing/cxl/test/cxl.c
@@ -1077,74 +1077,26 @@ static int first_decoder(struct device *dev, const void *data)
 	return 0;
 }
 
-/*
- * Initialize a decoder during HDM enumeration.
- *
- * If a saved registry entry exists:
- *   - enabled decoders are restored from the saved programming
- *   - disabled decoders are initialized in a clean disabled state
- *
- * If no registry entry exists the decoder follows the normal mock
- * initialization path, including the special auto-region setup for
- * the first endpoints under host-bridge0.
- *
- * Returns true if decoder state was restored from the registry. In
- * that case the saved decode configuration (including target mapping)
- * has already been applied and the map_targets() is skipped.
- */
-static bool mock_init_hdm_decoder(struct cxl_decoder *cxld)
+enum cxld_init_type {
+	MOCK_DECODER_INIT_DEFAULT,
+	MOCK_DECODER_INIT_SAVED,
+	MOCK_DECODER_INIT_TYPE3_AUTO,
+	MOCK_DECODER_INIT_TYPE2_AUTO,
+};
+
+static enum cxld_init_type get_decoder_init_type(struct cxl_decoder *cxld,
+						 struct platform_device *pdev,
+						 bool hb0,
+						 struct cxl_test_decoder **td)
 {
-	struct acpi_cedt_cfmws *window = mock_cfmws[0];
-	struct platform_device *pdev = NULL;
-	struct cxl_endpoint_decoder *cxled;
-	struct cxl_switch_decoder *cxlsd;
-	struct cxl_port *port, *iter;
-	struct cxl_test_decoder *td;
-	struct cxl_memdev *cxlmd;
-	struct cxl_dport *dport;
-	struct device *dev;
-	bool hb0 = false;
-	u64 base;
-	int i;
+	struct cxl_test_decoder *found_td = cxld_registry_find(cxld);
 
-	if (is_endpoint_decoder(&cxld->dev)) {
-		cxled = to_cxl_endpoint_decoder(&cxld->dev);
-		cxlmd = cxled_to_memdev(cxled);
-		WARN_ON(!dev_is_platform(cxlmd->dev.parent));
-		pdev = to_platform_device(cxlmd->dev.parent);
-
-		/* check is endpoint is attach to host-bridge0 */
-		port = cxled_to_port(cxled);
-		do {
-			if (port->uport_dev == &cxl_host_bridge[0]->dev) {
-				hb0 = true;
-				break;
-			}
-			if (is_cxl_port(port->dev.parent))
-				port = to_cxl_port(port->dev.parent);
-			else
-				port = NULL;
-		} while (port);
-		port = cxled_to_port(cxled);
-	} else {
-		port = to_cxl_port(cxld->dev.parent);
+	if (found_td) {
+		*td = found_td;
+		return MOCK_DECODER_INIT_SAVED;
 	}
 
-	td = cxld_registry_find(cxld);
-	if (td) {
-		bool enabled;
-
-		if (is_switch_decoder(&cxld->dev))
-			enabled = td->cxlsd.cxld.flags & CXL_DECODER_F_ENABLE;
-		else
-			enabled = td->cxled.cxld.flags & CXL_DECODER_F_ENABLE;
-
-		if (enabled)
-			return !cxld_registry_restore(cxld, td);
-
-		init_disabled_mock_decoder(cxld);
-		return false;
-	}
+	*td = NULL;
 
 	/*
 	 * The first decoder on the first 2 devices on the first switch
@@ -1155,15 +1107,111 @@ static bool mock_init_hdm_decoder(struct cxl_decoder *cxld)
 	 * See 'cxl list -BMPu -m cxl_mem.0,cxl_mem.4'
 	 */
 	if (!is_endpoint_decoder(&cxld->dev) || !hb0 || pdev->id % 4 ||
-	    pdev->id > 4 || cxld->id > 0) {
-		default_mock_decoder(cxld);
-		return false;
-	}
+	    pdev->id > 4 || cxld->id > 0)
+		return MOCK_DECODER_INIT_DEFAULT;
+
+	return type2_test ? MOCK_DECODER_INIT_TYPE2_AUTO :
+			    MOCK_DECODER_INIT_TYPE3_AUTO;
+}
+
+static bool mock_decoder_handle_saved(struct cxl_decoder *cxld, struct cxl_test_decoder *td)
+{
+	bool enabled;
+
+	if (is_switch_decoder(&cxld->dev))
+		enabled = td->cxlsd.cxld.flags & CXL_DECODER_F_ENABLE;
+	else
+		enabled = td->cxled.cxld.flags & CXL_DECODER_F_ENABLE;
+
+	if (enabled)
+		return !cxld_registry_restore(cxld, td);
+
+	init_disabled_mock_decoder(cxld);
+	return false;
+}
+
+static void mock_init_hdm_type2_cxled(struct cxl_endpoint_decoder *cxled,
+				      struct cxl_port *port,
+				      struct platform_device *pdev)
+{
+	struct acpi_cedt_cfmws *window = mock_cfmws[0];
+	struct cxl_decoder *cxld = &cxled->cxld;
+	struct cxl_switch_decoder *cxlsd;
+	struct cxl_dport *dport;
+	struct cxl_port *root_port;
+	struct device *dev;
+	u64 base;
+
+	base = window->base_hpa;
+	cxld->hpa_range = (struct range) {
+		.start = base,
+		.end = base + mock_auto_region_size - 1,
+	};
+
+	cxld->interleave_ways = 1;
+	eig_to_granularity(window->granularity, &cxld->interleave_granularity);
+	cxld->target_type = CXL_DECODER_DEVMEM;
+	cxld->flags = CXL_DECODER_F_ENABLE;
+	cxled->state = CXL_DECODER_STATE_AUTO;
+	port->commit_end = cxld->id;
+	devm_cxl_dpa_reserve(cxled, 0,
+			     mock_auto_region_size / cxld->interleave_ways, 0);
+	cxld->commit = mock_decoder_commit;
+	cxld->reset = mock_decoder_reset;
+
+	WARN_ON_ONCE(!cxld_registry_new(cxld));
+	/*
+	 * Now that endpoint decoder is set up, walk up the hierarchy
+	 * and setup the root port decoder targeting @cxlmd.
+	 */
+	dport = port->parent_dport;
+	root_port = dport->port;
+	dev = device_find_child(&root_port->dev, NULL, first_decoder);
+	/*
+	 * Ancestor ports are guaranteed to be enumerated before
+	 * @port, and all ports have at least one decoder.
+	 */
+	if (WARN_ON(!dev))
+		return;
+
+	cxlsd = to_cxl_switch_decoder(dev);
+	cxlsd->target[0] = dport;
+	cxlsd->cxld.target_map[0] = dport->port_id;
+	cxld = &cxlsd->cxld;
+	cxld->target_type = CXL_DECODER_DEVMEM;
+	cxld->flags = CXL_DECODER_F_ENABLE;
+	root_port->commit_end = 0;
+	cxld->interleave_ways = 1;
+	cxld->interleave_granularity = 4096;
+	cxld->hpa_range = (struct range) {
+		.start = base,
+		.end = base + mock_auto_region_size - 1,
+	};
+	cxld->commit = mock_decoder_commit;
+	cxld->reset = mock_decoder_reset;
+
+	cxld_registry_update(cxld);
+	put_device(dev);
+}
+
+static void mock_init_hdm_type3_cxled(struct cxl_endpoint_decoder *cxled,
+				      struct cxl_port *port,
+				      struct platform_device *pdev,
+				      bool hb0)
+{
+	struct acpi_cedt_cfmws *window = mock_cfmws[0];
+	struct cxl_decoder *cxld = &cxled->cxld;
+	struct cxl_switch_decoder *cxlsd;
+	struct cxl_dport *dport;
+	struct cxl_port *iter;
+	struct device *dev;
+	u64 base;
+	int i;
 
 	/* Simulate missing cxl_mem.4 configuration */
 	if (hb0 && pdev->id == 4 && cxld->id == 0 && fail_autoassemble) {
 		default_mock_decoder(cxld);
-		return false;
+		return;
 	}
 
 	base = window->base_hpa;
@@ -1239,7 +1287,76 @@ static bool mock_init_hdm_decoder(struct cxl_decoder *cxld)
 		cxld_registry_update(cxld);
 		put_device(dev);
 	}
+}
 
+/*
+ * Initialize a decoder during HDM enumeration.
+ *
+ * If a saved registry entry exists:
+ *   - enabled decoders are restored from the saved programming
+ *   - disabled decoders are initialized in a clean disabled state
+ *
+ * If no registry entry exists the decoder follows the normal mock
+ * initialization path, including the special auto-region setup for
+ * the first endpoints under host-bridge0.
+ *
+ * Returns true if decoder state was restored from the registry. In
+ * that case the saved decode configuration (including target mapping)
+ * has already been applied and the map_targets() is skipped.
+ */
+static bool mock_init_hdm_decoder(struct cxl_decoder *cxld)
+{
+	struct cxl_endpoint_decoder *cxled = NULL;
+	struct platform_device *pdev = NULL;
+	struct cxl_test_decoder *td;
+	struct cxl_memdev *cxlmd;
+	struct cxl_port *port;
+	bool hb0 = false;
+
+	if (is_endpoint_decoder(&cxld->dev)) {
+		cxled = to_cxl_endpoint_decoder(&cxld->dev);
+		cxlmd = cxled_to_memdev(cxled);
+		WARN_ON(!dev_is_platform(cxlmd->dev.parent));
+		pdev = to_platform_device(cxlmd->dev.parent);
+
+		/* check is endpoint is attach to host-bridge0 */
+		port = cxled_to_port(cxled);
+		do {
+			if (port->uport_dev == &cxl_host_bridge[0]->dev) {
+				hb0 = true;
+				break;
+			}
+			if (is_cxl_port(port->dev.parent))
+				port = to_cxl_port(port->dev.parent);
+			else
+				port = NULL;
+		} while (port);
+		port = cxled_to_port(cxled);
+	} else {
+		port = to_cxl_port(cxld->dev.parent);
+	}
+
+	switch (get_decoder_init_type(cxld, pdev, hb0, &td)) {
+	case MOCK_DECODER_INIT_SAVED:
+		if (WARN_ON(!td))
+			return false;
+		return mock_decoder_handle_saved(cxld, td);
+	case MOCK_DECODER_INIT_DEFAULT:
+		/*
+		 * The default path picks up all the decoders that are not
+		 * endpoint.
+		 */
+		default_mock_decoder(cxld);
+		return false;
+	case MOCK_DECODER_INIT_TYPE3_AUTO:
+		mock_init_hdm_type3_cxled(cxled, port, pdev, hb0);
+		return false;
+	case MOCK_DECODER_INIT_TYPE2_AUTO:
+		mock_init_hdm_type2_cxled(cxled, port, pdev);
+		return false;
+	default:
+		return false;
+	}
 	return false;
 }
 
-- 
2.54.0


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

* [PATCH v3 6/6] cxl/test: Add cxl_test accelerator driver
  2026-06-10 22:23 [PATCH v3 0/6] cxl: Add CXL type2 accelerator support for cxl_test Dave Jiang
                   ` (4 preceding siblings ...)
  2026-06-10 22:23 ` [PATCH v3 5/6] cxl/test: Fixup hdm init for auto region to support type2 Dave Jiang
@ 2026-06-10 22:23 ` Dave Jiang
  2026-06-10 22:37   ` sashiko-bot
  5 siblings, 1 reply; 12+ messages in thread
From: Dave Jiang @ 2026-06-10 22:23 UTC (permalink / raw)
  To: linux-cxl; +Cc: djbw, dave, jic23, alison.schofield, vishal.l.verma

Add a type2 accelerator mock driver for the platform device that
simulates a CXL type2 device. The driver exercises the same
minimal API calls that a real CXL type2 driver would utilize.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
v3:
- Updated to use devm_cxl_probe_mem()
---
 tools/testing/cxl/test/Kbuild  |  2 ++
 tools/testing/cxl/test/accel.c | 66 ++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+)
 create mode 100644 tools/testing/cxl/test/accel.c

diff --git a/tools/testing/cxl/test/Kbuild b/tools/testing/cxl/test/Kbuild
index c168e3c998a7..9a24ddc28488 100644
--- a/tools/testing/cxl/test/Kbuild
+++ b/tools/testing/cxl/test/Kbuild
@@ -5,10 +5,12 @@ obj-m += cxl_test.o
 obj-m += cxl_mock.o
 obj-m += cxl_mock_mem.o
 obj-m += cxl_translate.o
+obj-m += cxl_mock_accel.o
 
 cxl_test-y := cxl.o
 cxl_test-y += hmem_test.o
 cxl_mock-y := mock.o
 cxl_mock_mem-y := mem.o
+cxl_mock_accel-y := accel.o
 
 KBUILD_CFLAGS := $(filter-out -Wmissing-prototypes -Wmissing-declarations, $(KBUILD_CFLAGS))
diff --git a/tools/testing/cxl/test/accel.c b/tools/testing/cxl/test/accel.c
new file mode 100644
index 000000000000..6e1dd6c81510
--- /dev/null
+++ b/tools/testing/cxl/test/accel.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright(c) 2026 Intel Corporation. All rights reserved.
+
+#include <linux/platform_device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/sizes.h>
+#include <cxl/mailbox.h>
+#include <cxlmem.h>
+
+struct mock_cxl_accel {
+	struct cxl_dev_state cxlds;
+	struct cxl_memdev *cxlmd;
+};
+
+static int cxl_mock_accel_probe(struct platform_device *pdev)
+{
+	struct mock_cxl_accel *cxl_accel;
+	struct device *dev = &pdev->dev;
+	struct cxl_dev_state *cxlds;
+	struct cxl_memdev *cxlmd;
+	struct range mock_range;
+	int rc;
+
+	cxl_accel = devm_cxl_dev_state_create(&pdev->dev, CXL_DEVTYPE_DEVMEM,
+					      pdev->dev.id + 1, 0,
+					      struct mock_cxl_accel, cxlds,
+					      false);
+	if (!cxl_accel)
+		return -ENOMEM;
+
+	cxlds = &cxl_accel->cxlds;
+	cxlds->media_ready = true;
+	rc = cxl_set_capacity(cxlds, SZ_512M);
+	if (rc)
+		return rc;
+
+	cxlmd = devm_cxl_probe_mem(cxlds, &mock_range);
+	if (IS_ERR(cxlmd))
+		return PTR_ERR(cxlmd);
+	cxl_accel->cxlmd = cxlmd;
+
+	dev_dbg(dev, "Probed mock accelerator with range %pra\n", &mock_range);
+
+	return 0;
+}
+
+static const struct platform_device_id cxl_mock_accel_ids[] = {
+	{ .name = "cxl_type2_accel", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, cxl_mock_accel_ids);
+
+static struct platform_driver cxl_mock_accel_driver = {
+	.probe = cxl_mock_accel_probe,
+	.id_table = cxl_mock_accel_ids,
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
+	},
+};
+
+module_platform_driver(cxl_mock_accel_driver);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("cxl_test: accelerator device mock module");
+MODULE_IMPORT_NS("CXL");
-- 
2.54.0


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

* Re: [PATCH v3 1/6] cxl/test: Add test for module parameters
  2026-06-10 22:23 ` [PATCH v3 1/6] cxl/test: Add test for module parameters Dave Jiang
@ 2026-06-10 22:32   ` sashiko-bot
  0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-06-10 22:32 UTC (permalink / raw)
  To: Dave Jiang; +Cc: linux-cxl

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] The function `have_multiple_modparms()` fails to check the `hmem_test` module parameter, allowing multiple test parameters to be activated simultaneously.
- [Low] The newly added function `have_multiple_modparms` is missing the `static` modifier, making it globally visible.
--

commit a298e853a144eb87f633b800d6fcf071d2088371
Author: Dave Jiang <dave.jiang@intel.com>

cxl/test: Add test for module parameters

This commit adds a test during module initialization to ensure that only
a single module parameter is activated at a time.

> diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
> index 296516eecfd6a..b00f5161b5f0c 100644
> --- a/tools/testing/cxl/test/cxl.c
> +++ b/tools/testing/cxl/test/cxl.c
> @@ -1814,11 +1814,29 @@ static struct attribute *cxl_acpi_attrs[] = {
>  };
>  ATTRIBUTE_GROUPS(cxl_acpi);
>  
> +bool __init have_multiple_modparms(void)

[Severity: Low]
Should this function be declared static? It appears to only be used locally
within this file, and omitting the static keyword exports it to the global
namespace, which might trigger missing-prototype compiler warnings.

> +{
> +	int count = 0;
> +
> +	if (interleave_arithmetic)
> +		count++;
> +	if (extended_linear_cache)
> +		count++;
> +	if (fail_autoassemble)
> +		count++;

[Severity: Medium]
Does this check miss the hmem_test parameter? The cxl_test module is built
from both cxl.c and hmem_test.c, and hmem_test.c defines its own parameter.
It seems a user could load the module with hmem_test=1 and one of the local
parameters (like extended_linear_cache=1) concurrently, bypassing this check.

> +
> +	return count > 1;
> +}
> +

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260610222328.2272427-1-dave.jiang@intel.com?part=1

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

* Re: [PATCH v3 3/6] cxl/test: Refactor platform device enumerations
  2026-06-10 22:23 ` [PATCH v3 3/6] cxl/test: Refactor platform device enumerations Dave Jiang
@ 2026-06-10 22:32   ` sashiko-bot
  0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-06-10 22:32 UTC (permalink / raw)
  To: Dave Jiang; +Cc: linux-cxl

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Missing error code assignments on `platform_device_alloc` failure cause populate helpers to falsely return success, leading to an invalid pointer dereference crash.
- [Medium] Error handling cleanup loops mistakenly use `break` instead of `continue` in reverse iteration array cleanup functions, causing resource leaks on error paths.
--

commit 166861bc24df0a0108568d617198fe4532f08924
Author: Dave Jiang <dave.jiang@intel.com>
cxl/test: Refactor platform device enumerations

This commit refactors the platform device enumeration in the cxl test
module by splitting host bridges, root ports, and switch port setups
into separate helper functions.

> diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
> index e91c125d557d9..b29be2597064e 100644
> --- a/tools/testing/cxl/test/cxl.c
> +++ b/tools/testing/cxl/test/cxl.c
[ ... ]
> +static void host_bridges_remove(void)
> +{
> +	int i;
> +
> +	for (i = ARRAY_SIZE(cxl_host_bridge) - 1; i >= 0; i--) {
> +		struct platform_device *pdev = cxl_host_bridge[i];
> +
> +		if (!pdev)
> +			break;

[Severity: Medium]
Since this cleanup loop iterates backwards from the end of the array, won't
a break here immediately terminate the loop on the first empty slot?

In the original code, this used a continue to skip empty slots and
successfully reach the populated devices at lower indices. Does this cause
resource leaks when initialization fails partway through?

This same pattern appears to be repeated in cxl_rootports_remove(),
cxl_usps_remove(), and cxl_dsps_remove().

[ ... ]
> +static int host_bridges_populate(void)
> +{
> +	int rc = 0;
> +
> +	for (int i = 0; i < ARRAY_SIZE(cxl_host_bridge); i++) {
>  		struct acpi_device *adev = &host_bridge[i];
>  		struct platform_device *pdev;
>  
[ ... ]
> +		pdev = platform_device_alloc("cxl_host_bridge", i);
> +		if (!pdev)
> +			goto err_bridge;

[Severity: High]
If platform_device_alloc() fails here, does this function return 0
instead of an error code?

Because rc is initialized to 0, returning 0 would cause the main init
function to assume success and proceed.

If initialization proceeds to cxl_rootports_populate(), it will try to set
the parent pointer using a NULL bridge device:

cxl_rootports_populate()
    bridge = cxl_host_bridge[...];
    pdev->dev.parent = &bridge->dev;

Could this cause an invalid pointer dereference when platform_device_add()
is subsequently called? Should this set rc = -ENOMEM before jumping to
the error label?

This missing error code assignment also appears to happen in the new
cxl_rootports_populate(), cxl_usps_populate(), and cxl_dsps_populate()
helper functions.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260610222328.2272427-1-dave.jiang@intel.com?part=3

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

* Re: [PATCH v3 2/6] cxl/test: Add type2 support for mock CFMWS0
  2026-06-10 22:23 ` [PATCH v3 2/6] cxl/test: Add type2 support for mock CFMWS0 Dave Jiang
@ 2026-06-10 22:32   ` sashiko-bot
  0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-06-10 22:32 UTC (permalink / raw)
  To: Dave Jiang; +Cc: linux-cxl

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Potential null pointer dereference if `kzalloc` fails in `alloc_mock_res()`.
--

commit 93dc9b7df44c3fa959f67249d56eb6d830e6a336
Author: Dave Jiang <dave.jiang@intel.com>

cxl/test: Add type2 support for mock CFMWS0

This commit adds a module parameter to trigger type 2 test support in
cxl_test and sets up the CFMWS0 configuration accordingly.

> diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
> index b00f5161b5f0c..e91c125d557d9 100644
> --- a/tools/testing/cxl/test/cxl.c
> +++ b/tools/testing/cxl/test/cxl.c

[ ... ]

> @@ -493,10 +512,14 @@ static int populate_cedt(void)
>  		chbs->length = size;
>  	}
>  
> +	if (type2_test)
> +		update_type2_cfmws();
> +
>  	for (i = cfmws_start; i <= cfmws_end; i++) {
>  		struct acpi_cedt_cfmws *window = mock_cfmws[i];
>  
> -		cfmws_elc_update(window, i);
> +		if (i == 0 && !type2_test)
> +			cfmws_elc_update(window, i);
>  		res = alloc_mock_res(window->window_size, SZ_256M);

[Severity: High]
This isn't a bug introduced by this patch, but while reviewing the use of
alloc_mock_res() here, I noticed a pre-existing issue in that function.

If kzalloc() fails in alloc_mock_res(), does it cause a NULL pointer
dereference?

tools/testing/cxl/test/cxl.c:alloc_mock_res() {
	struct cxl_mock_res *res = kzalloc(sizeof(*res), GFP_KERNEL);
	struct genpool_data_align data = {
		.align = align,
	};
	unsigned long phys;

	INIT_LIST_HEAD(&res->list);
	...
}

Since list is the first member of the struct, &res->list evaluates to NULL
when kzalloc() fails. INIT_LIST_HEAD() will then attempt to write to
list->next and list->prev. 

Should there be a NULL check before initializing the list head?

>  		if (!res)
>  			return -ENOMEM;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260610222328.2272427-1-dave.jiang@intel.com?part=2

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

* Re: [PATCH v3 4/6] cxl/test: Add hierarchy enumeration support for type2 device
  2026-06-10 22:23 ` [PATCH v3 4/6] cxl/test: Add hierarchy enumeration support for type2 device Dave Jiang
@ 2026-06-10 22:36   ` sashiko-bot
  0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-06-10 22:36 UTC (permalink / raw)
  To: Dave Jiang; +Cc: linux-cxl

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Teardown loops iterate backwards but incorrectly use `break` when encountering a NULL pointer, causing persistent resource leaks on error paths.
--

commit 53bf17c5a72c46ea341694a714ad1ee38917639a
Author: Dave Jiang <dave.jiang@intel.com>

cxl/test: Add hierarchy enumeration support for type2 device

Add enumeration of type2 device hierarchy in cxl-test. The type2 device
is setup to be directly attached to a root port instead of rp -> switch
-> device that type3 hierarchy is setup..

> diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
> index b29be2597064e..5186a13b20aa9 100644
> --- a/tools/testing/cxl/test/cxl.c
> +++ b/tools/testing/cxl/test/cxl.c
[ ... ]
> +static int cxl_type2_mem_init(void)
> +{
> +	int i, rc;
[ ... ]
> +err_mem:
> +	for (i = NR_CXL_TYPE2_ACCEL - 1; i >= 0; i--) {
> +		struct platform_device *pdev = cxl_mem[i];
> +
> +		if (!pdev)
> +			break;
> +		platform_device_unregister(cxl_mem[i]);
> +	}
> +	return rc;
>  }

[Severity: Medium]
Will this teardown loop leak successfully allocated devices if an error
occurs before all iterations complete?

Because cxl_mem is populated sequentially starting from index 0, the higher
indices remain NULL if initialization fails partway through. Since this
teardown loop iterates backwards from the max index, it will immediately
hit an uninitialized NULL pointer at the top and break. This skips the
unregistration for any devices that were successfully allocated at lower
indices.

Could this use continue instead of break? Alternatively, since
platform_device_unregister() handles NULL pointers safely, could the check
be omitted entirely?

This same pattern appears in cxl_type2_mem_exit() and cxl_type3_mem_exit()
in this patch, as well as in pre-existing teardown loops like
cxl_usps_remove().

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260610222328.2272427-1-dave.jiang@intel.com?part=4

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

* Re: [PATCH v3 6/6] cxl/test: Add cxl_test accelerator driver
  2026-06-10 22:23 ` [PATCH v3 6/6] cxl/test: Add cxl_test accelerator driver Dave Jiang
@ 2026-06-10 22:37   ` sashiko-bot
  0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-06-10 22:37 UTC (permalink / raw)
  To: Dave Jiang; +Cc: linux-cxl

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] Logic Error: Incorrect device ID field used for device serial number generation
- [Low] Build Failure: Undefined functions `cxl_set_capacity` and `devm_cxl_probe_mem`
--

commit 1221192460bb0724f4ff13dd01d1388c60a7fe54
Author: Dave Jiang <dave.jiang@intel.com>

cxl/test: Add cxl_test accelerator driver

This commit adds a type2 accelerator mock driver for the platform device to
simulate a CXL type2 device. It exercises the minimal API calls that a real
CXL type2 driver would utilize.

> diff --git a/tools/testing/cxl/test/accel.c b/tools/testing/cxl/test/accel.c
> new file mode 100644
> index 0000000000000..6e1dd6c815102
> --- /dev/null
> +++ b/tools/testing/cxl/test/accel.c
> @@ -0,0 +1,66 @@

[ ... ]

> +static int cxl_mock_accel_probe(struct platform_device *pdev)
> +{
> +	struct mock_cxl_accel *cxl_accel;
> +	struct device *dev = &pdev->dev;
> +	struct cxl_dev_state *cxlds;
> +	struct cxl_memdev *cxlmd;
> +	struct range mock_range;
> +	int rc;
> +
> +	cxl_accel = devm_cxl_dev_state_create(&pdev->dev, CXL_DEVTYPE_DEVMEM,
> +					      pdev->dev.id + 1, 0,

[Severity: Medium]
Is pdev->dev.id the correct field to use for the device serial number here?

For dynamically allocated platform devices, pdev->dev.id is usually 0, while
the actual instance identifier is stored in pdev->id. If pdev->dev.id always
evaluates to 0, will all simulated Type 2 accelerator instances end up
sharing the same serial number (1) and conflict during enumeration?

> +					      struct mock_cxl_accel, cxlds,
> +					      false);
> +	if (!cxl_accel)
> +		return -ENOMEM;
> +
> +	cxlds = &cxl_accel->cxlds;
> +	cxlds->media_ready = true;
> +	rc = cxl_set_capacity(cxlds, SZ_512M);

[Severity: Low]
Do cxl_set_capacity() and devm_cxl_probe_mem() below exist in the tree?

It looks like these functions are not defined or declared anywhere, which
might cause the module build to fail with implicit declaration and undefined
symbol errors. Other mock drivers in the tree appear to use
devm_cxl_add_memdev(). Could these function calls be leftovers from an
earlier design?

> +	if (rc)
> +		return rc;
> +
> +	cxlmd = devm_cxl_probe_mem(cxlds, &mock_range);
> +	if (IS_ERR(cxlmd))
> +		return PTR_ERR(cxlmd);
> +	cxl_accel->cxlmd = cxlmd;

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260610222328.2272427-1-dave.jiang@intel.com?part=6

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

end of thread, other threads:[~2026-06-10 22:37 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-10 22:23 [PATCH v3 0/6] cxl: Add CXL type2 accelerator support for cxl_test Dave Jiang
2026-06-10 22:23 ` [PATCH v3 1/6] cxl/test: Add test for module parameters Dave Jiang
2026-06-10 22:32   ` sashiko-bot
2026-06-10 22:23 ` [PATCH v3 2/6] cxl/test: Add type2 support for mock CFMWS0 Dave Jiang
2026-06-10 22:32   ` sashiko-bot
2026-06-10 22:23 ` [PATCH v3 3/6] cxl/test: Refactor platform device enumerations Dave Jiang
2026-06-10 22:32   ` sashiko-bot
2026-06-10 22:23 ` [PATCH v3 4/6] cxl/test: Add hierarchy enumeration support for type2 device Dave Jiang
2026-06-10 22:36   ` sashiko-bot
2026-06-10 22:23 ` [PATCH v3 5/6] cxl/test: Fixup hdm init for auto region to support type2 Dave Jiang
2026-06-10 22:23 ` [PATCH v3 6/6] cxl/test: Add cxl_test accelerator driver Dave Jiang
2026-06-10 22:37   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox