diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-26 06:50:38 -1000 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-26 06:50:38 -1000 |
| commit | d6bbdb67a4b9f2366debd8b5b05b1822490982ef (patch) | |
| tree | 042a9432cce46aacfe9550ccc8cc9ae4cbfac8f0 /tools/testing | |
| parent | 6b4b543fa18757297ac756a6fe6e64f506b7844a (diff) | |
| parent | cf15f9f2361dd4002203716b7b878393c0eee4bf (diff) | |
Merge tag 'cxl-for-7.4' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl
Pull CXL updates from Dave Jiang:
"The headline item is the first part of support for Dynamic Capacity
Devices (DCD). It covers flagging DCD support in the mailbox, reading
the dynamic capacity configuration from the device, gathering DSMAS
data for the DCD partitions, and configuring the dynamic capacity
interrupts. It also adds a documentation update and a cleanup that
enforces partition ordering. DCD is not enabled yet with these code
changes. Patches are applied to reduce the whole set in order to
relief the burden of very large patch set review.
Zero sized HDM decoders are now allowed, along with cxl_test support
for them. There is also a set of decoder hardening patches for switch
decoder enumeration. Latency calculations now account for link width
and use consistent units. The GPF timeout programming has been
reworked. The pull also has a number of misc patches.
A large number of bug fixes against pre-existing issues make up the
rest of the pull. Many of these were flagged by review of patches
posted to the mailing list by sashiko.
Also adding Richard Cheng as a reviewer (R) to the CXL sub-system"
* tag 'cxl-for-7.4' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl: (49 commits)
cxl/events: Test CME counter expiry with equality, not bitwise AND
Documentation/cxl: Document DPA partition layout and ordering rules
cxl/core: Enforce partition order/simplify partition calls
cxl/mem: Configure dynamic capacity interrupts
cxl/pci: Factor out interrupt policy check
cxl/events: Split event msgnum configuration from irq setup
cxl/cdat: Gather DSMAS data for DCD partitions
cxl/mem: Read dynamic capacity configuration from the device
cxl/mbox: Flag support for Dynamic Capacity Devices (DCD)
cxl/acpi: Convert QTG _DSM latencies to picoseconds
cxl: Account for link width in latency calculation
cxl/port: Convert PCIe link latency to nanoseconds
cxl/pci: Update only the Port GPF timeout fields
cxl/pci: Program the Port GPF timeouts before caching the DVSEC
cxl/pci: Use the Device GPF DVSEC for restricted endpoints
cxl/port: Attach endpoints to a dport under the lock that pins it
cxl/core: Hold the dport host lock across dport lookup and use
cxl/port: Clear cached dport pointers when a dport is removed
cxl/region: Warn on user region position mismatch
cxl/acpi: Check ACPI companion before use
...
Diffstat (limited to 'tools/testing')
| -rw-r--r-- | tools/testing/cxl/Kbuild | 16 | ||||
| -rw-r--r-- | tools/testing/cxl/test/cxl.c | 117 | ||||
| -rw-r--r-- | tools/testing/cxl/test/mem.c | 2 |
3 files changed, 109 insertions, 26 deletions
diff --git a/tools/testing/cxl/Kbuild b/tools/testing/cxl/Kbuild index 2be1df80fcc9..e49ce644b4b1 100644 --- a/tools/testing/cxl/Kbuild +++ b/tools/testing/cxl/Kbuild @@ -4,16 +4,20 @@ ldflags-y += --wrap=is_acpi_device_node ldflags-y += --wrap=acpi_evaluate_integer ldflags-y += --wrap=acpi_pci_find_root ldflags-y += --wrap=nvdimm_bus_register -ldflags-y += --wrap=cxl_await_media_ready -ldflags-y += --wrap=devm_cxl_add_rch_dport -ldflags-y += --wrap=cxl_endpoint_parse_cdat -ldflags-y += --wrap=devm_cxl_endpoint_decoders_setup ldflags-y += --wrap=hmat_get_extended_linear_cache_size -ldflags-y += --wrap=devm_cxl_add_dport_by_dev -ldflags-y += --wrap=devm_cxl_switch_port_decoders_setup ldflags-y += --wrap=walk_hmem_resources ldflags-y += --wrap=region_intersects ldflags-y += --wrap=region_intersects_soft_reserve +wrap_cxl_core := --wrap=cxl_await_media_ready +wrap_cxl_core += --wrap=devm_cxl_add_rch_dport +wrap_cxl_core += --wrap=devm_cxl_add_dport_by_dev +wrap_cxl_core += --wrap=devm_cxl_switch_port_decoders_setup +wrap_cxl_core += --wrap=devm_cxl_endpoint_decoders_setup +wrap_cxl_core += --wrap=cxl_endpoint_parse_cdat +LDFLAGS_cxl_acpi.o += $(wrap_cxl_core) +LDFLAGS_cxl_pmem.o += $(wrap_cxl_core) +LDFLAGS_cxl_port.o += $(wrap_cxl_core) +LDFLAGS_cxl_mem.o += $(wrap_cxl_core) DRIVERS := ../../../drivers DAX_HMEM_SRC := $(DRIVERS)/dax/hmem diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c index 62bd92b3be45..3eb1051b1ee8 100644 --- a/tools/testing/cxl/test/cxl.c +++ b/tools/testing/cxl/test/cxl.c @@ -18,6 +18,7 @@ static int interleave_arithmetic; static bool extended_linear_cache; static bool fail_autoassemble; static bool type2_test; +static bool mock_zero_size_decoders; #define FAKE_QTG_ID 42 @@ -872,14 +873,13 @@ static int cxld_registry_restore(struct cxl_decoder *cxld, cxld_copy(cxld, &td->cxled.cxld); cxled->state = td->cxled.state; cxled->skip = td->cxled.skip; - if (range_len(&td->dpa_range)) { - rc = devm_cxl_dpa_reserve(cxled, td->dpa_range.start, - range_len(&td->dpa_range), - td->cxled.skip); - if (rc) { - init_disabled_mock_decoder(cxld); - return rc; - } + /* enabled endpoint decoders hold a reservation, sized or not */ + rc = devm_cxl_dpa_reserve(cxled, td->dpa_range.start, + range_len(&td->dpa_range), + td->cxled.skip); + if (rc) { + init_disabled_mock_decoder(cxld); + return rc; } port->commit_end = cxld->id; } @@ -1072,16 +1072,49 @@ static void default_mock_decoder(struct cxl_decoder *cxld) WARN_ON_ONCE(!cxld_registry_new(cxld)); } -static int first_decoder(struct device *dev, const void *data) +static int match_decoder_by_index(struct device *dev, const void *data) { + int target_id = *(const int *)data; struct cxl_decoder *cxld; if (!is_switch_decoder(dev)) return 0; cxld = to_cxl_decoder(dev); - if (cxld->id == 0) - return 1; - return 0; + return cxld->id == target_id; +} + +/* + * Mock a committed, locked, empty decoder + * (CXL r4.0 8.2.4.20.12). Gated by the mock_zero_size_decoders module + * param so the default cxl_test topology, shared by the region test + * suite, is left undisturbed. + */ +static void size_zero_mock_decoder_ep(struct cxl_decoder *cxld, u64 base) +{ + struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(&cxld->dev); + + cxld->hpa_range = DEFINE_RANGE(base, base - 1); + cxld->interleave_ways = 2; + cxld->interleave_granularity = 4096; + cxld->target_type = CXL_DECODER_HOSTONLYMEM; + cxld->flags = CXL_DECODER_F_ENABLE | CXL_DECODER_F_LOCK; + cxled->state = CXL_DECODER_STATE_AUTO; + /* decoder[0] reserved [0, size/2), empty decoders sit at that watermark */ + devm_cxl_dpa_reserve(cxled, mock_auto_region_size / 2, 0, 0); + cxld->commit = mock_decoder_commit; + cxld->reset = mock_decoder_reset; +} + +static void size_zero_mock_decoder_sw(struct cxl_decoder *cxld, u64 base, + int level) +{ + cxld->flags = CXL_DECODER_F_ENABLE | CXL_DECODER_F_LOCK; + cxld->target_type = CXL_DECODER_HOSTONLYMEM; + cxld->interleave_ways = level == 0 ? 2 : 1; + cxld->interleave_granularity = 4096; + cxld->hpa_range = DEFINE_RANGE(base, base - 1); + cxld->commit = mock_decoder_commit; + cxld->reset = mock_decoder_reset; } enum cxld_init_type { @@ -1114,7 +1147,7 @@ static enum cxld_init_type get_decoder_init_type(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) + pdev->id > 4 || cxld->id > (mock_zero_size_decoders ? 2 : 0)) return MOCK_DECODER_INIT_DEFAULT; return type2_test ? MOCK_DECODER_INIT_TYPE2_AUTO : @@ -1147,6 +1180,7 @@ static void mock_init_hdm_type2_cxled(struct cxl_endpoint_decoder *cxled, struct cxl_port *root_port; struct device *dev; u64 base; + int id = 0; base = window->base_hpa; cxld->hpa_range = (struct range) { @@ -1172,7 +1206,7 @@ static void mock_init_hdm_type2_cxled(struct cxl_endpoint_decoder *cxled, */ dport = port->parent_dport; root_port = dport->port; - dev = device_find_child(&root_port->dev, NULL, first_decoder); + dev = device_find_child(&root_port->dev, &id, match_decoder_by_index); /* * Ancestor ports are guaranteed to be enumerated before * @port, and all ports have at least one decoder. @@ -1232,6 +1266,20 @@ static void mock_init_hdm_type3_cxled(struct cxl_endpoint_decoder *cxled, base = window->base_hpa; if (extended_linear_cache) base += mock_auto_region_size; + + /* + * With mock_zero_size_decoders, decoders 1 and 2 of the special + * endpoints mock committed, locked, empty decoders above the + * decoder[0] auto-region (CXL r4.0 8.2.4.20.12). commit_end then + * points at a zero-size decoder, exercising the zero-size + * reservation and poison-by-endpoint code paths. + */ + if (cxld->id == 1 || cxld->id == 2) { + size_zero_mock_decoder_ep(cxld, base); + port->commit_end = cxld->id; + WARN_ON_ONCE(!cxld_registry_new(cxld)); + return; + } cxld->hpa_range = (struct range) { .start = base, .end = base + mock_auto_region_size - 1, @@ -1255,9 +1303,11 @@ static void mock_init_hdm_type3_cxled(struct cxl_endpoint_decoder *cxled, */ iter = port; for (i = 0; i < 2; i++) { + int id = 0; + dport = iter->parent_dport; iter = dport->port; - dev = device_find_child(&iter->dev, NULL, first_decoder); + dev = device_find_child(&iter->dev, &id, match_decoder_by_index); /* * Ancestor ports are guaranteed to be enumerated before * @port, and all ports have at least one decoder. @@ -1307,6 +1357,26 @@ static void mock_init_hdm_type3_cxled(struct cxl_endpoint_decoder *cxled, cxld_registry_update(cxld); put_device(dev); + + if (!mock_zero_size_decoders) + continue; + + /* + * Mirror the endpoint: commit the next two switch decoders + * as zero-size + locked so the empty-decoder layout extends + * end-to-end through the switch and host bridge. + */ + for (id = 1; id <= 2; id++) { + dev = device_find_child(&iter->dev, &id, + match_decoder_by_index); + if (WARN_ON(!dev)) + continue; + cxld = to_cxl_decoder(dev); + size_zero_mock_decoder_sw(cxld, base, i); + iter->commit_end = id; + cxld_registry_update(cxld); + put_device(dev); + } } } @@ -1945,7 +2015,7 @@ static int cxl_type2_mem_init(void) goto err_mem; } pdev->dev.parent = &dport->dev; - set_dev_node(&pdev->dev, i % 2); + set_dev_node(&pdev->dev, numa_map_to_online_node(i % 2)); rc = cxl_mock_platform_device_add(pdev, &cxl_mem[i]); if (rc) @@ -1974,7 +2044,7 @@ static int cxl_type3_mem_init(void) goto err_mem; } pdev->dev.parent = &dport->dev; - set_dev_node(&pdev->dev, i % 2); + set_dev_node(&pdev->dev, numa_map_to_online_node(i % 2)); rc = cxl_mock_platform_device_add(pdev, &cxl_mem[i]); if (rc) @@ -1991,7 +2061,7 @@ static int cxl_type3_mem_init(void) goto err_single; } pdev->dev.parent = &dport->dev; - set_dev_node(&pdev->dev, i % 2); + set_dev_node(&pdev->dev, numa_map_to_online_node(i % 2)); rc = cxl_mock_platform_device_add(pdev, &cxl_mem_single[i]); if (rc) @@ -2009,7 +2079,7 @@ static int cxl_type3_mem_init(void) goto err_rcd; } pdev->dev.parent = &rch->dev; - set_dev_node(&pdev->dev, i % 2); + set_dev_node(&pdev->dev, numa_map_to_online_node(i % 2)); rc = cxl_mock_platform_device_add(pdev, &cxl_rcd[i]); if (rc) @@ -2076,6 +2146,12 @@ static bool __init have_multiple_modparms(void) count++; if (type2_test) count++; + if (mock_zero_size_decoders) + count++; + + /* Zero-size decoders require decoder[0] to preserve commit order. */ + if (fail_autoassemble && mock_zero_size_decoders) + return true; return count > 1; } @@ -2484,6 +2560,9 @@ 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_param(mock_zero_size_decoders, bool, 0444); +MODULE_PARM_DESC(mock_zero_size_decoders, + "Mock committed, locked, empty decoders under host-bridge0"); module_init(cxl_test_init); module_exit(cxl_test_exit); MODULE_LICENSE("GPL v2"); diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c index 7b756000a1a6..c740372bdaaa 100644 --- a/tools/testing/cxl/test/mem.c +++ b/tools/testing/cxl/test/mem.c @@ -1818,7 +1818,7 @@ static int cxl_mock_mem_probe(struct platform_device *pdev) if (rc) dev_dbg(dev, "No CXL FWCTL setup\n"); - cxl_mem_get_event_records(mds, CXLDEV_EVENT_STATUS_ALL); + cxl_mem_get_event_records(mds, CXLDEV_EVENT_STATUS_STANDARD_LOGS); cxl_mock_test_feat_init(mdata); return 0; |
