Add replay_regions() and supporting helpers to the CXL test common library. The helpers capture the current region configuration, trigger a region replay by unbinding and rebinding the cxl_acpi driver, and verify that the regions reconstructed during enumeration match the original configuration.
Replay is enabled by instructing the cxl_test module to preserve its decoder registry across the driver unbind/bind cycle. This allows the decoder programming associated with user-created regions to survive topology teardown so that the regions are reconstructed during driver initialization as auto-discovered regions. Region signatures are derived from region attributes and memdev serial numbers so that the replayed configuration can be compared independent of topology enumeration order and device numbering. These helpers provide a reusable mechanism for CXL tests that need to exercise region replay behavior. A unit test, cxl-region-replay.sh, is posted in a follow-on patch and demonstrates the workflow. Reviewed-by: Dave Jiang <[email protected]> Reviewed-by: "Fabio M. De Francesco" <[email protected]> Tested-by: "Fabio M. De Francesco" <[email protected]> Link: https://lore.kernel.org/r/8646e0b11697e3adb4fc9a83fa486e68a4b9b5c5.1773466514.git.alison.schofi...@intel.com Signed-off-by: Alison Schofield <[email protected]> --- Changes in v2: - Add comment for replay state comparison (Fabio) - Rebase onto latest ndctl/pending - Add Fabio's Tags test/common | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/test/common b/test/common index 2eb11b7396d0..d60d9e046445 100644 --- a/test/common +++ b/test/common @@ -168,3 +168,114 @@ check_dmesg() # CXL COMMON CXL_TEST_QOS_CLASS=42 + +# CXL region replay helpers +# +# replay_regions() snapshots the current region configuration, performs +# a cxl_acpi driver unbind/bind cycle to trigger region replay, and +# verifies that the regions reconstructed during enumeration match the +# original configuration. +# +# This allows tests to create regions through the user interface and +# then replay them as auto-discovered regions during driver +# initialization. +# +# See example usage in test/cxl-region-replay.sh. + +CXL_EXPECTED_REGION_SIGS="" + +cxl_get_memdev_serial() +{ + local memdev="$1" + + "$CXL" list -m "$memdev" | jq -r '.[0].serial' +} + +cxl_emit_region_signature() +{ + local region="$1" + local region_json size type ways gran state + local entry pos memdev serial sig + + region_json=$("$CXL" list -R --targets -r "$region") + [[ -n "$region_json" && "$region_json" != "[]" ]] || return 1 + + size=$(jq -r '.[0].size' <<<"$region_json") + type=$(jq -r '.[0].type' <<<"$region_json") + ways=$(jq -r '.[0].interleave_ways' <<<"$region_json") + gran=$(jq -r '.[0].interleave_granularity' <<<"$region_json") + state=$(jq -r '.[0].decode_state' <<<"$region_json") + + sig="size=$size type=$type ways=$ways gran=$gran" + + while IFS= read -r entry; do + pos=$(jq -r '.position' <<<"$entry") + memdev=$(jq -r '.memdev' <<<"$entry") + serial=$(cxl_get_memdev_serial "$memdev") || return 1 + [[ -n "$serial" && "$serial" != "null" ]] || return 1 + sig="$sig pos=$pos serial=$serial" + done < <(jq -c '.[0].mappings | sort_by(.position)[]' <<<"$region_json") + + echo "$sig state=$state" +} + +cxl_collect_region_signatures() +{ + local region + local -a regions=() + + mapfile -t regions < <("$CXL" list -Ri | jq -r '.[].region' | sort) || return 1 + + for region in "${regions[@]}"; do + cxl_emit_region_signature "$region" || return 1 + done | sort +} + +cxl_capture_expected_region_signatures() +{ + CXL_EXPECTED_REGION_SIGS=$(cxl_collect_region_signatures) || return 1 +} + +cxl_verify_replayed_regions() +{ + local actual_region_sigs + local -a expected_lines=() + local -a actual_lines=() + local i + local expected_line actual_line + local expected_struct actual_struct + local expected_state actual_state + + actual_region_sigs=$(cxl_collect_region_signatures) || return 1 + + mapfile -t expected_lines < <(printf '%s\n' "$CXL_EXPECTED_REGION_SIGS" | sed '/^$/d') + mapfile -t actual_lines < <(printf '%s\n' "$actual_region_sigs" | sed '/^$/d') + + [ "${#expected_lines[@]}" -eq "${#actual_lines[@]}" ] || return 1 + + for ((i = 0; i < ${#expected_lines[@]}; i++)); do + expected_line=${expected_lines[i]} + actual_line=${actual_lines[i]} + + expected_struct=${expected_line% state=*} + expected_state=${expected_line##* state=} + actual_struct=${actual_line% state=*} + actual_state=${actual_line##* state=} + + # Require exact structural match for the region config. + # Only enforce state when the expected state was commit. + [ "$expected_struct" = "$actual_struct" ] || return 1 + [ "$expected_state" != "commit" ] || [ "$actual_state" = "commit" ] || return 1 + done +} + +replay_regions() +{ + echo "replaying existing regions" + cxl_capture_expected_region_signatures || return 1 + echo 1 > /sys/bus/platform/devices/cxl_acpi.0/decoder_reset_preserve_registry + echo cxl_acpi.0 > /sys/bus/platform/drivers/cxl_acpi/unbind + echo cxl_acpi.0 > /sys/bus/platform/drivers/cxl_acpi/bind + echo 0 > /sys/bus/platform/devices/cxl_acpi.0/decoder_reset_preserve_registry + cxl_verify_replayed_regions || return 1 +} -- 2.37.3
