Skip to content

Commit 7d3eb23

Browse files
committed
tools/testing/cxl: Introduce a mock memory device + driver
Introduce an emulated device-set plus driver to register CXL memory devices, 'struct cxl_memdev' instances, in the mock cxl_test topology. This enables the development of HDM Decoder (Host-managed Device Memory Decoder) programming flow (region provisioning) in an environment that can be updated alongside the kernel as it gains more functionality. Whereas the cxl_pci module looks for CXL memory expanders on the 'pci' bus, the cxl_mock_mem module attaches to CXL expanders on the platform bus emitted by cxl_test. Acked-by: Ben Widawsky <[email protected]> Reported-by: kernel test robot <[email protected]> Reviewed-by: Jonathan Cameron <[email protected]> Link: https://lore.kernel.org/r/163116440099.2460985.10692549614409346604.stgit@dwillia2-desk3.amr.corp.intel.com Signed-off-by: Dan Williams <[email protected]>
1 parent 49be6dd commit 7d3eb23

File tree

8 files changed

+359
-6
lines changed

8 files changed

+359
-6
lines changed

drivers/cxl/core/pmem.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,16 @@ struct cxl_nvdimm_bridge *to_cxl_nvdimm_bridge(struct device *dev)
5151
}
5252
EXPORT_SYMBOL_GPL(to_cxl_nvdimm_bridge);
5353

54-
static int match_nvdimm_bridge(struct device *dev, const void *data)
54+
__mock int match_nvdimm_bridge(struct device *dev, const void *data)
5555
{
5656
return dev->type == &cxl_nvdimm_bridge_type;
5757
}
5858

59-
struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(void)
59+
struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_nvdimm *cxl_nvd)
6060
{
6161
struct device *dev;
6262

63-
dev = bus_find_device(&cxl_bus_type, NULL, NULL, match_nvdimm_bridge);
63+
dev = bus_find_device(&cxl_bus_type, NULL, cxl_nvd, match_nvdimm_bridge);
6464
if (!dev)
6565
return NULL;
6666
return to_cxl_nvdimm_bridge(dev);

drivers/cxl/cxl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ struct cxl_nvdimm_bridge *devm_cxl_add_nvdimm_bridge(struct device *host,
327327
struct cxl_nvdimm *to_cxl_nvdimm(struct device *dev);
328328
bool is_cxl_nvdimm(struct device *dev);
329329
int devm_cxl_add_nvdimm(struct device *host, struct cxl_memdev *cxlmd);
330-
struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(void);
330+
struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_nvdimm *cxl_nvd);
331331

332332
/*
333333
* Unit test builds overrides this to __weak, find the 'strong' version

drivers/cxl/pmem.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ static int cxl_nvdimm_probe(struct device *dev)
3939
struct nvdimm *nvdimm;
4040
int rc;
4141

42-
cxl_nvb = cxl_find_nvdimm_bridge();
42+
cxl_nvb = cxl_find_nvdimm_bridge(cxl_nvd);
4343
if (!cxl_nvb)
4444
return -ENXIO;
4545

tools/testing/cxl/Kbuild

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,6 @@ cxl_core-y += $(CXL_CORE_SRC)/memdev.o
3333
cxl_core-y += $(CXL_CORE_SRC)/mbox.o
3434
cxl_core-y += config_check.o
3535

36+
cxl_core-y += mock_pmem.o
37+
3638
obj-m += test/

tools/testing/cxl/mock_pmem.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/* Copyright(c) 2021 Intel Corporation. All rights reserved. */
3+
#include <cxl.h>
4+
#include "test/mock.h"
5+
#include <core/core.h>
6+
7+
int match_nvdimm_bridge(struct device *dev, const void *data)
8+
{
9+
int index, rc = 0;
10+
struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
11+
const struct cxl_nvdimm *cxl_nvd = data;
12+
13+
if (ops) {
14+
if (dev->type == &cxl_nvdimm_bridge_type &&
15+
(ops->is_mock_dev(dev->parent->parent) ==
16+
ops->is_mock_dev(cxl_nvd->dev.parent->parent)))
17+
rc = 1;
18+
} else
19+
rc = dev->type == &cxl_nvdimm_bridge_type;
20+
21+
put_cxl_mock_ops(index);
22+
23+
return rc;
24+
}

tools/testing/cxl/test/Kbuild

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# SPDX-License-Identifier: GPL-2.0
2+
ccflags-y := -I$(srctree)/drivers/cxl/
3+
24
obj-m += cxl_test.o
35
obj-m += cxl_mock.o
6+
obj-m += cxl_mock_mem.o
47

58
cxl_test-y := cxl.o
69
cxl_mock-y := mock.o
10+
cxl_mock_mem-y := mem.o

tools/testing/cxl/test/cxl.c

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ static struct platform_device *cxl_acpi;
1717
static struct platform_device *cxl_host_bridge[NR_CXL_HOST_BRIDGES];
1818
static struct platform_device
1919
*cxl_root_port[NR_CXL_HOST_BRIDGES * NR_CXL_ROOT_PORTS];
20+
struct platform_device *cxl_mem[NR_CXL_HOST_BRIDGES * NR_CXL_ROOT_PORTS];
2021

2122
static struct acpi_device acpi0017_mock;
2223
static struct acpi_device host_bridge[NR_CXL_HOST_BRIDGES] = {
@@ -36,6 +37,11 @@ static struct acpi_device host_bridge[NR_CXL_HOST_BRIDGES] = {
3637

3738
static bool is_mock_dev(struct device *dev)
3839
{
40+
int i;
41+
42+
for (i = 0; i < ARRAY_SIZE(cxl_mem); i++)
43+
if (dev == &cxl_mem[i]->dev)
44+
return true;
3945
if (dev == &cxl_acpi->dev)
4046
return true;
4147
return false;
@@ -405,6 +411,44 @@ static void mock_companion(struct acpi_device *adev, struct device *dev)
405411
#define SZ_512G (SZ_64G * 8)
406412
#endif
407413

414+
static struct platform_device *alloc_memdev(int id)
415+
{
416+
struct resource res[] = {
417+
[0] = {
418+
.flags = IORESOURCE_MEM,
419+
},
420+
[1] = {
421+
.flags = IORESOURCE_MEM,
422+
.desc = IORES_DESC_PERSISTENT_MEMORY,
423+
},
424+
};
425+
struct platform_device *pdev;
426+
int i, rc;
427+
428+
for (i = 0; i < ARRAY_SIZE(res); i++) {
429+
struct cxl_mock_res *r = alloc_mock_res(SZ_256M);
430+
431+
if (!r)
432+
return NULL;
433+
res[i].start = r->range.start;
434+
res[i].end = r->range.end;
435+
}
436+
437+
pdev = platform_device_alloc("cxl_mem", id);
438+
if (!pdev)
439+
return NULL;
440+
441+
rc = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
442+
if (rc)
443+
goto err;
444+
445+
return pdev;
446+
447+
err:
448+
platform_device_put(pdev);
449+
return NULL;
450+
}
451+
408452
static __init int cxl_test_init(void)
409453
{
410454
int rc, i;
@@ -460,9 +504,27 @@ static __init int cxl_test_init(void)
460504
cxl_root_port[i] = pdev;
461505
}
462506

507+
BUILD_BUG_ON(ARRAY_SIZE(cxl_mem) != ARRAY_SIZE(cxl_root_port));
508+
for (i = 0; i < ARRAY_SIZE(cxl_mem); i++) {
509+
struct platform_device *port = cxl_root_port[i];
510+
struct platform_device *pdev;
511+
512+
pdev = alloc_memdev(i);
513+
if (!pdev)
514+
goto err_mem;
515+
pdev->dev.parent = &port->dev;
516+
517+
rc = platform_device_add(pdev);
518+
if (rc) {
519+
platform_device_put(pdev);
520+
goto err_mem;
521+
}
522+
cxl_mem[i] = pdev;
523+
}
524+
463525
cxl_acpi = platform_device_alloc("cxl_acpi", 0);
464526
if (!cxl_acpi)
465-
goto err_port;
527+
goto err_mem;
466528

467529
mock_companion(&acpi0017_mock, &cxl_acpi->dev);
468530
acpi0017_mock.dev.bus = &platform_bus_type;
@@ -475,6 +537,9 @@ static __init int cxl_test_init(void)
475537

476538
err_add:
477539
platform_device_put(cxl_acpi);
540+
err_mem:
541+
for (i = ARRAY_SIZE(cxl_mem) - 1; i >= 0; i--)
542+
platform_device_unregister(cxl_mem[i]);
478543
err_port:
479544
for (i = ARRAY_SIZE(cxl_root_port) - 1; i >= 0; i--)
480545
platform_device_unregister(cxl_root_port[i]);
@@ -495,6 +560,8 @@ static __exit void cxl_test_exit(void)
495560
int i;
496561

497562
platform_device_unregister(cxl_acpi);
563+
for (i = ARRAY_SIZE(cxl_mem) - 1; i >= 0; i--)
564+
platform_device_unregister(cxl_mem[i]);
498565
for (i = ARRAY_SIZE(cxl_root_port) - 1; i >= 0; i--)
499566
platform_device_unregister(cxl_root_port[i]);
500567
for (i = ARRAY_SIZE(cxl_host_bridge) - 1; i >= 0; i--)

0 commit comments

Comments
 (0)