Commit 3a2b97b3 authored by Dan Williams's avatar Dan Williams Committed by Ira Weiny
Browse files

cxl/test: Improve init-order fidelity relative to real-world systems

The investigation of an initialization failure [1] highlighted that
cxl_test does not reflect the init-order of real world systems. The
expected order is root/bus first then async probing of the memory
devices.

Fix up cxl_test to reflect that order. While it did not reproduce the
initial bug report (since that is dependent on built-in vs modular
builds), it did reveal a separate latent bug in the subsystem's decoder
shutdown flow. Fix for that sent separately.

Link: http://lore.kernel.org/20241004212504.1246-1-gourry@gourry.net

 [1]
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Jonathan Cameron <jonathan.cameron@huawei.com>
Cc: Dave Jiang <dave.jiang@intel.com>
Cc: Alison Schofield <alison.schofield@intel.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
Reviewed-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://patch.msgid.link/172964784521.81806.15791069994065969243.stgit@dwillia2-xfh.jf.intel.com


Signed-off-by: default avatarIra Weiny <ira.weiny@intel.com>
parent 105b6235
Loading
Loading
Loading
Loading
+103 −83
Original line number Diff line number Diff line
@@ -1058,7 +1058,7 @@ static void mock_companion(struct acpi_device *adev, struct device *dev)
#define SZ_64G (SZ_32G * 2)
#endif

static __init int cxl_rch_init(void)
static __init int cxl_rch_topo_init(void)
{
	int rc, i;

@@ -1086,30 +1086,8 @@ static __init int cxl_rch_init(void)
			goto err_bridge;
	}

	for (i = 0; i < ARRAY_SIZE(cxl_rcd); i++) {
		int idx = NR_MEM_MULTI + NR_MEM_SINGLE + i;
		struct platform_device *rch = cxl_rch[i];
		struct platform_device *pdev;

		pdev = platform_device_alloc("cxl_rcd", idx);
		if (!pdev)
			goto err_mem;
		pdev->dev.parent = &rch->dev;
		set_dev_node(&pdev->dev, i % 2);

		rc = platform_device_add(pdev);
		if (rc) {
			platform_device_put(pdev);
			goto err_mem;
		}
		cxl_rcd[i] = pdev;
	}

	return 0;

err_mem:
	for (i = ARRAY_SIZE(cxl_rcd) - 1; i >= 0; i--)
		platform_device_unregister(cxl_rcd[i]);
err_bridge:
	for (i = ARRAY_SIZE(cxl_rch) - 1; i >= 0; i--) {
		struct platform_device *pdev = cxl_rch[i];
@@ -1123,12 +1101,10 @@ static __init int cxl_rch_init(void)
	return rc;
}

static void cxl_rch_exit(void)
static void cxl_rch_topo_exit(void)
{
	int i;

	for (i = ARRAY_SIZE(cxl_rcd) - 1; i >= 0; i--)
		platform_device_unregister(cxl_rcd[i]);
	for (i = ARRAY_SIZE(cxl_rch) - 1; i >= 0; i--) {
		struct platform_device *pdev = cxl_rch[i];

@@ -1139,7 +1115,7 @@ static void cxl_rch_exit(void)
	}
}

static __init int cxl_single_init(void)
static __init int cxl_single_topo_init(void)
{
	int i, rc;

@@ -1224,29 +1200,8 @@ static __init int cxl_single_init(void)
		cxl_swd_single[i] = pdev;
	}

	for (i = 0; i < ARRAY_SIZE(cxl_mem_single); i++) {
		struct platform_device *dport = cxl_swd_single[i];
		struct platform_device *pdev;

		pdev = platform_device_alloc("cxl_mem", NR_MEM_MULTI + 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_single[i] = pdev;
	}

	return 0;

err_mem:
	for (i = ARRAY_SIZE(cxl_mem_single) - 1; i >= 0; i--)
		platform_device_unregister(cxl_mem_single[i]);
err_dport:
	for (i = ARRAY_SIZE(cxl_swd_single) - 1; i >= 0; i--)
		platform_device_unregister(cxl_swd_single[i]);
@@ -1269,12 +1224,10 @@ static __init int cxl_single_init(void)
	return rc;
}

static void cxl_single_exit(void)
static void cxl_single_topo_exit(void)
{
	int i;

	for (i = ARRAY_SIZE(cxl_mem_single) - 1; i >= 0; i--)
		platform_device_unregister(cxl_mem_single[i]);
	for (i = ARRAY_SIZE(cxl_swd_single) - 1; i >= 0; i--)
		platform_device_unregister(cxl_swd_single[i]);
	for (i = ARRAY_SIZE(cxl_swu_single) - 1; i >= 0; i--)
@@ -1291,6 +1244,91 @@ static void cxl_single_exit(void)
	}
}

static void cxl_mem_exit(void)
{
	int i;

	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--)
		platform_device_unregister(cxl_mem[i]);
}

static int cxl_mem_init(void)
{
	int i, rc;

	for (i = 0; i < ARRAY_SIZE(cxl_mem); i++) {
		struct platform_device *dport = cxl_switch_dport[i];
		struct platform_device *pdev;

		pdev = platform_device_alloc("cxl_mem", 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;
	}

	for (i = 0; i < ARRAY_SIZE(cxl_mem_single); i++) {
		struct platform_device *dport = cxl_swd_single[i];
		struct platform_device *pdev;

		pdev = platform_device_alloc("cxl_mem", NR_MEM_MULTI + i);
		if (!pdev)
			goto err_single;
		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_single;
		}
		cxl_mem_single[i] = pdev;
	}

	for (i = 0; i < ARRAY_SIZE(cxl_rcd); i++) {
		int idx = NR_MEM_MULTI + NR_MEM_SINGLE + i;
		struct platform_device *rch = cxl_rch[i];
		struct platform_device *pdev;

		pdev = platform_device_alloc("cxl_rcd", idx);
		if (!pdev)
			goto err_rcd;
		pdev->dev.parent = &rch->dev;
		set_dev_node(&pdev->dev, i % 2);

		rc = platform_device_add(pdev);
		if (rc) {
			platform_device_put(pdev);
			goto err_rcd;
		}
		cxl_rcd[i] = pdev;
	}

	return 0;

err_rcd:
	for (i = ARRAY_SIZE(cxl_rcd) - 1; i >= 0; i--)
		platform_device_unregister(cxl_rcd[i]);
err_single:
	for (i = ARRAY_SIZE(cxl_mem_single) - 1; i >= 0; i--)
		platform_device_unregister(cxl_mem_single[i]);
err_mem:
	for (i = ARRAY_SIZE(cxl_mem) - 1; i >= 0; i--)
		platform_device_unregister(cxl_mem[i]);
	return rc;
}

static __init int cxl_test_init(void)
{
	int rc, i;
@@ -1403,29 +1441,11 @@ static __init int cxl_test_init(void)
		cxl_switch_dport[i] = pdev;
	}

	for (i = 0; i < ARRAY_SIZE(cxl_mem); i++) {
		struct platform_device *dport = cxl_switch_dport[i];
		struct platform_device *pdev;

		pdev = platform_device_alloc("cxl_mem", 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;
	}

	rc = cxl_single_init();
	rc = cxl_single_topo_init();
	if (rc)
		goto err_mem;
		goto err_dport;

	rc = cxl_rch_init();
	rc = cxl_rch_topo_init();
	if (rc)
		goto err_single;

@@ -1438,19 +1458,20 @@ static __init int cxl_test_init(void)

	rc = platform_device_add(cxl_acpi);
	if (rc)
		goto err_add;
		goto err_root;

	rc = cxl_mem_init();
	if (rc)
		goto err_root;

	return 0;

err_add:
err_root:
	platform_device_put(cxl_acpi);
err_rch:
	cxl_rch_exit();
	cxl_rch_topo_exit();
err_single:
	cxl_single_exit();
err_mem:
	for (i = ARRAY_SIZE(cxl_mem) - 1; i >= 0; i--)
		platform_device_unregister(cxl_mem[i]);
	cxl_single_topo_exit();
err_dport:
	for (i = ARRAY_SIZE(cxl_switch_dport) - 1; i >= 0; i--)
		platform_device_unregister(cxl_switch_dport[i]);
@@ -1482,11 +1503,10 @@ static __exit void cxl_test_exit(void)
{
	int i;

	cxl_mem_exit();
	platform_device_unregister(cxl_acpi);
	cxl_rch_exit();
	cxl_single_exit();
	for (i = ARRAY_SIZE(cxl_mem) - 1; i >= 0; i--)
		platform_device_unregister(cxl_mem[i]);
	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--)
+1 −0
Original line number Diff line number Diff line
@@ -1673,6 +1673,7 @@ static struct platform_driver cxl_mock_mem_driver = {
		.name = KBUILD_MODNAME,
		.dev_groups = cxl_mock_mem_groups,
		.groups = cxl_mock_mem_core_groups,
		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
	},
};