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: Dan Williams <dan.j.williams@intel.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://patch.msgid.link/172964784521.81806.15791069994065969243.stgit@dwillia2-xfh.jf.intel.com
Signed-off-by: Ira Weiny <ira.weiny@intel.com>
This commit is contained in:
Dan Williams 2024-10-22 18:44:06 -07:00 committed by Ira Weiny
parent 105b6235ad
commit 3a2b97b321
2 changed files with 104 additions and 83 deletions

View File

@ -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 @@ err_bridge:
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 @@ err_bridge:
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--)

View File

@ -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,
},
};