Add a test that reads the phase adjustment range and granularity a
pin advertises, picks the largest multiple of the granularity inside
the range, or the smallest one when that is already the current value,
sets it, reads it back and restores the original value. It skips when
the dpll tool lacks the phase-adjust keyword of pin set and when the
range is too narrow to pick a different value. A pin that reports no
phase adjustment or no range is a skip on a device provided by the user
and a failure on the device the script created, whose pins report
both.
The core refuses a value that is not a multiple of the granularity a
driver reports, the current value included, so a pin that sits at such
a value could not be put back. The test bails out on that before it
schedules the restore, which is deferred right after so that an
interrupted run restores the value too.
The granularity is only reported by drivers that have the core enforce
one. Without it the target is computed with a granularity of 1, and a
driver may refuse it for a granularity of its own or for any other
constraint the interface does not advertise. A refused set is therefore
a skip on a device provided by the user, with the reason the tool
reported, and a failure on the device the script created, whose
simulator accepts every value its range and granularity allow. The
test ends there, a value that was not set has nothing to read back.
Signed-off-by: Petr Oros <redacted>
---
.../drivers/net/dpll/dpll_features.sh | 85 +++++++++++++++++++
.../selftests/drivers/net/lib/sh/dpll_lib.sh | 10 +++
2 files changed, 95 insertions(+)
diff --git a/tools/testing/selftests/drivers/net/dpll/dpll_features.sh b/tools/testing/selftests/drivers/net/dpll/dpll_features.sh
index a39098fbf73135..1466ddd6538348 100755
--- a/tools/testing/selftests/drivers/net/dpll/dpll_features.sh
+++ b/tools/testing/selftests/drivers/net/dpll/dpll_features.sh
@@ -18,6 +18,7 @@ ALL_TESTS="
test_pin_state_transitions
test_pin_priority_get_set
test_pin_frequency_set_get
+ test_pin_phase_adjust_set_get
"
##############################################################################
@@ -166,6 +167,90 @@ test_pin_state_transitions()
log_test "DPLL pin state transitions"
}
+test_pin_phase_adjust_set_get()
+{
+ local before target after json min max gran reason
+
+ RET=0
+
+ if [ -z "$PIN_TUNE_ID" ]; then
+ dpll_log_test_skip_or_fail "DPLL pin phase-adjust set/get" \
+ "no spare input pin"
+ return
+ fi
+ if ! dpll_pin_set_supports phase-adjust; then
+ log_test_skip "DPLL pin phase-adjust set/get" \
+ "dpll tool lacks pin set phase-adjust"
+ return
+ fi
+
+ before=$(dpll_pin_get_phase_adjust "$PIN_TUNE_ID")
+ if [ -z "$before" ]; then
+ dpll_log_test_skip_or_fail "DPLL pin phase-adjust set/get" \
+ "phase adjust not reported"
+ return
+ fi
+
+ # Pick a target inside the advertised range different from the
+ # current value, a multiple of the granularity, which is taken as 1
+ # when the driver reports none.
+ json=$(dpll_pin_json "$PIN_TUNE_ID")
+ min=$(jq -r '.["phase-adjust-min"] // empty' <<< "$json")
+ max=$(jq -r '.["phase-adjust-max"] // empty' <<< "$json")
+ gran=$(jq -r '.["phase-adjust-gran"] // empty' <<< "$json")
+ if [ -z "$min" ] || [ -z "$max" ]; then
+ dpll_log_test_skip_or_fail "DPLL pin phase-adjust set/get" \
+ "no adjust range"
+ return
+ fi
+ # A current value that is not a granularity multiple could not be
+ # written back, so bail out before the restore is scheduled.
+ if [ -n "$gran" ] && [ $((before % gran)) -ne 0 ]; then
+ dpll_log_test_skip_or_fail "DPLL pin phase-adjust set/get" \
+ "current phase adjust not a granularity multiple"
+ return
+ fi
+ [ -n "$gran" ] || gran=1
+ defer dpll_pin_set_phase_adjust "$PIN_TUNE_ID" "$before"
+
+ # Shell division truncates towards zero, so round the bounds towards
+ # the inside of the range explicitly, which matters for negative ones.
+ target=$((max / gran * gran))
+ [ "$target" -gt "$max" ] && target=$((target - gran))
+ if [ "$target" = "$before" ]; then
+ target=$((min / gran * gran))
+ [ "$target" -lt "$min" ] && target=$((target + gran))
+ fi
+ if [ "$target" = "$before" ] || [ "$target" -gt "$max" ] ||
+ [ "$target" -lt "$min" ]; then
+ log_test_skip "DPLL pin phase-adjust set/get" "range too narrow"
+ return
+ fi
+
+ # A driver may enforce a granularity it does not report or another
+ # constraint, a skip on a device the user provided, the simulator
+ # accepts every value its range and granularity allow.
+ if ! dpll_pin_set_phase_adjust "$PIN_TUNE_ID" "$target"; then
+ reason=${DPLL_LAST_ERR%%$'\n'*}
+ dpll_log_test_skip_or_fail "DPLL pin phase-adjust set/get" \
+ "cannot set phase-adjust=$target${reason:+, $reason}"
+ return
+ fi
+ after=$(dpll_pin_get_phase_adjust "$PIN_TUNE_ID")
+ if [ "$after" != "$target" ]; then
+ check_err 1 "phase-adjust expected $target, got '$after'"
+ fi
+
+ dpll_pin_set_phase_adjust "$PIN_TUNE_ID" "$before"
+ check_err $? "cannot restore phase-adjust"
+ after=$(dpll_pin_get_phase_adjust "$PIN_TUNE_ID")
+ if [ "$after" != "$before" ]; then
+ check_err 1 "phase-adjust not restored, got '$after'"
+ fi
+
+ log_test "DPLL pin phase-adjust set/get"
+}
+
test_pin_frequency_set_get()
{
local before target after reasondiff --git a/tools/testing/selftests/drivers/net/lib/sh/dpll_lib.sh b/tools/testing/selftests/drivers/net/lib/sh/dpll_lib.sh
index 9718d73c60b444..8fa2a9936a0eb2 100644
--- a/tools/testing/selftests/drivers/net/lib/sh/dpll_lib.sh
+++ b/tools/testing/selftests/drivers/net/lib/sh/dpll_lib.sh
@@ -381,6 +381,11 @@ dpll_pin_get_prio()
__dpll_pin_dev_field "$1" "$2" '.prio'
}
+dpll_pin_get_phase_adjust()
+{
+ __dpll_pin_field "$1" '.["phase-adjust"]'
+}
+
##############################################################################
# Pin setters
#@@ -417,6 +422,11 @@ dpll_pin_set_frequency()
DPLL_LAST_ERR=$(dpll pin set id "$1" frequency "$2" 2>&1 >/dev/null)
}
+dpll_pin_set_phase_adjust()
+{
+ DPLL_LAST_ERR=$(dpll pin set id "$1" phase-adjust "$2" 2>&1 >/dev/null)
+}
+
##############################################################################
# dpllsim configfs interface
#--
2.56.0