Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Runner/suites/Kernel/Baseport/Interrupts/Interrupts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ metadata:
devices:
- rb3gen2

params:
INTERRUPTS_WAIT_TIMEOUT_S: "30"
INTERRUPTS_POLL_INTERVAL_S: "2"

run:
steps:
- cd Runner
- $PWD/suites/Kernel/Baseport/Interrupts/run.sh || true
- INTERRUPTS_WAIT_TIMEOUT_S="${INTERRUPTS_WAIT_TIMEOUT_S}" INTERRUPTS_POLL_INTERVAL_S="${INTERRUPTS_POLL_INTERVAL_S}" $PWD/suites/Kernel/Baseport/Interrupts/run.sh || true
- $PWD/utils/send-to-lava.sh $PWD/suites/Kernel/Baseport/Interrupts/Interrupts.res || true
107 changes: 30 additions & 77 deletions Runner/suites/Kernel/Baseport/Interrupts/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
# SPDX-License-Identifier: BSD-3-Clause

# Robustly find and source init_env
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
INIT_ENV=""
SEARCH="$SCRIPT_DIR"

while [ "$SEARCH" != "/" ]; do
if [ -f "$SEARCH/init_env" ]; then
INIT_ENV="$SEARCH/init_env"
Expand All @@ -20,106 +22,57 @@ if [ -z "$INIT_ENV" ]; then
fi

# Only source if not already loaded (idempotent)
if [ -z "$__INIT_ENV_LOADED" ]; then
if [ -z "${__INIT_ENV_LOADED:-}" ]; then
# shellcheck disable=SC1090
. "$INIT_ENV"
fi

# Always source functestlib.sh, using $TOOLS exported by init_env
# shellcheck disable=SC1090,SC1091
. "$TOOLS/functestlib.sh"

TESTNAME="Interrupts"
test_path=$(find_test_case_by_name "$TESTNAME")
cd "$test_path" || exit 1

# shellcheck disable=SC2034
res_file="./$TESTNAME.res"

INTERRUPTS_WAIT_TIMEOUT_S="${INTERRUPTS_WAIT_TIMEOUT_S:-30}"
INTERRUPTS_POLL_INTERVAL_S="${INTERRUPTS_POLL_INTERVAL_S:-2}"

log_info "-----------------------------------------------------------------------------------------"
log_info "-------------------Starting $TESTNAME Testcase----------------------------"
log_info "=== Test Initialization ==="
log_info "Config: INTERRUPTS_WAIT_TIMEOUT_S=${INTERRUPTS_WAIT_TIMEOUT_S} INTERRUPTS_POLL_INTERVAL_S=${INTERRUPTS_POLL_INTERVAL_S}"

# Function to get the timer count
get_timer_count() {
get_interrupt_line_by_name "arch_timer"
}
if ! wait_for_interrupt_cpu_count_increment "arch_timer" "$INTERRUPTS_WAIT_TIMEOUT_S" "$INTERRUPTS_POLL_INTERVAL_S"; then
log_fail "$TESTNAME : Test Failed"
echo "$TESTNAME FAIL" > "$res_file"
exit 1
fi

# Get the initial timer count
echo "Initial timer count:"
initial_count=$(get_timer_count)
echo "$initial_count"
echo "$INTERRUPT_WAIT_INITIAL_LINE"

# Wait for 2 minutes
sleep 120
echo "Timer count after polling:"
echo "$INTERRUPT_WAIT_FINAL_LINE"

# Get the timer count after 2 minutes
echo "Timer count after 2 minutes:"
final_count=$(get_timer_count)
echo "$final_count"

# Compare the initial and final counts
echo "Comparing timer counts:"
while IFS= read -r line; do
[ -n "$line" ] || continue
log_info "Detected timer counters: initial=${INTERRUPT_COMPARE_CPU_COUNT} final=${INTERRUPT_COMPARE_CPU_COUNT}"
log_info "arch_timer counters incremented on all CPUs after ${INTERRUPT_WAIT_ELAPSED_S}s"

irq_id=$(printf '%s\n' "$line" | awk '{print $1}')
final_line=$(printf '%s\n' "$final_count" | awk -v irq="$irq_id" '$1 == irq { print; exit }')
cpu_index=0
while [ "$cpu_index" -lt "$INTERRUPT_COMPARE_CPU_COUNT" ]; do
initial_value="$(printf '%s\n' "$INTERRUPT_COMPARE_INITIAL_VALUES" | sed -n "$((cpu_index + 1))p")"
final_value="$(printf '%s\n' "$INTERRUPT_COMPARE_FINAL_VALUES" | sed -n "$((cpu_index + 1))p")"

if [ -z "$final_line" ]; then
log_fail "Could not find matching final timer line for IRQ $irq_id"
log_fail "$TESTNAME : Test Failed"
echo "$TESTNAME FAIL" > "$res_file"
exit 1
fi
echo "CPU $cpu_index: Timer count has incremented. Test PASSED"
log_pass "CPU $cpu_index: Timer count has incremented. initial=${initial_value} final=${final_value}"

initial_values=$(extract_interrupt_cpu_counts "$line")
final_values=$(extract_interrupt_cpu_counts "$final_line")

initial_cpu_count=$(count_interrupt_cpu_counts "$initial_values")
final_cpu_count=$(count_interrupt_cpu_counts "$final_values")

log_info "Detected timer counters: initial=${initial_cpu_count} final=${final_cpu_count}"

if [ "$initial_cpu_count" -eq 0 ] || [ "$final_cpu_count" -eq 0 ]; then
log_fail "No per-CPU timer counters could be parsed from /proc/interrupts"
log_fail "$TESTNAME : Test Failed"
echo "$TESTNAME FAIL" > "$res_file"
exit 1
fi

if [ "$initial_cpu_count" -ne "$final_cpu_count" ]; then
log_fail "Mismatch in parsed CPU timer counters: initial=${initial_cpu_count} final=${final_cpu_count}"
log_fail "$TESTNAME : Test Failed"
echo "$TESTNAME FAIL" > "$res_file"
exit 1
fi
cpu_index=$((cpu_index + 1))
done

fail_test=false
i=0

while [ "$i" -lt "$initial_cpu_count" ]; do
initial_value=$(printf '%s\n' "$initial_values" | sed -n "$((i + 1))p")
final_value=$(printf '%s\n' "$final_values" | sed -n "$((i + 1))p")

if [ "$initial_value" -lt "$final_value" ]; then
echo "CPU $i: Timer count has incremented. Test PASSED"
log_pass "CPU $i: Timer count has incremented. Test PASSED"
else
echo "CPU $i: Timer count has not incremented. Test FAILED"
log_fail "CPU $i: Timer count has not incremented. Test FAILED"
fail_test=true
fi
i=$((i + 1))
done

if [ "$fail_test" = false ]; then
log_pass "$TESTNAME : Test Passed"
echo "$TESTNAME PASS" > "$res_file"
exit 0
else
log_fail "$TESTNAME : Test Failed"
echo "$TESTNAME FAIL" > "$res_file"
exit 1
fi
done <<EOF
$initial_count
EOF
log_pass "$TESTNAME : Test Passed"
echo "$TESTNAME PASS" > "$res_file"
exit 0
161 changes: 161 additions & 0 deletions Runner/utils/functestlib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,167 @@ interrupt_counter_delta() {
'
}

# Compare per-CPU interrupt counters from two /proc/interrupts lines.
#
# Arguments:
# $1 - initial interrupt line
# $2 - final interrupt line
#
# Return:
# 0 - all parsed per-CPU counters incremented
# 1 - fatal parse/count mismatch
# 2 - counters parsed, but one or more CPUs did not increment yet
#
# Sets globals for callers:
# INTERRUPT_COMPARE_CPU_COUNT
# INTERRUPT_COMPARE_INITIAL_VALUES
# INTERRUPT_COMPARE_FINAL_VALUES
# shellcheck disable=SC2317
interrupt_cpu_counts_incremented() {
initial_line="$1"
final_line="$2"

INTERRUPT_COMPARE_INITIAL_VALUES="$(extract_interrupt_cpu_counts "$initial_line")"
INTERRUPT_COMPARE_FINAL_VALUES="$(extract_interrupt_cpu_counts "$final_line")"

initial_cpu_count="$(count_interrupt_cpu_counts "$INTERRUPT_COMPARE_INITIAL_VALUES")"
final_cpu_count="$(count_interrupt_cpu_counts "$INTERRUPT_COMPARE_FINAL_VALUES")"

# Export result to caller, used by Interrupts/run.sh after this helper returns.
# shellcheck disable=SC2034
INTERRUPT_COMPARE_CPU_COUNT="$initial_cpu_count"

if [ "$initial_cpu_count" -eq 0 ] || [ "$final_cpu_count" -eq 0 ]; then
log_fail "No per-CPU interrupt counters could be parsed from /proc/interrupts"
return 1
fi

if [ "$initial_cpu_count" -ne "$final_cpu_count" ]; then
log_fail "Mismatch in parsed CPU interrupt counters: initial=${initial_cpu_count} final=${final_cpu_count}"
return 1
fi

cpu_index=0
while [ "$cpu_index" -lt "$initial_cpu_count" ]; do
initial_value="$(printf '%s\n' "$INTERRUPT_COMPARE_INITIAL_VALUES" | sed -n "$((cpu_index + 1))p")"
final_value="$(printf '%s\n' "$INTERRUPT_COMPARE_FINAL_VALUES" | sed -n "$((cpu_index + 1))p")"

if [ "$initial_value" -ge "$final_value" ]; then
return 2
fi

cpu_index=$((cpu_index + 1))
done

return 0
}

# Poll a named interrupt until all per-CPU counters increment.
#
# Arguments:
# $1 - interrupt name/pattern, for example arch_timer
# $2 - timeout seconds
# $3 - poll interval seconds
#
# Return:
# 0 - interrupt counters incremented on all CPUs
# 1 - fatal error / timeout
#
# Sets globals for callers:
# INTERRUPT_WAIT_INITIAL_LINE
# INTERRUPT_WAIT_FINAL_LINE
# INTERRUPT_WAIT_IRQ_ID
# INTERRUPT_WAIT_ELAPSED_S
# INTERRUPT_COMPARE_CPU_COUNT
# INTERRUPT_COMPARE_INITIAL_VALUES
# INTERRUPT_COMPARE_FINAL_VALUES
# shellcheck disable=SC2317
wait_for_interrupt_cpu_count_increment() {
irq_name="$1"
timeout_s="$2"
poll_interval_s="$3"

if ! is_unsigned_number "$timeout_s"; then
log_warn "Invalid interrupt wait timeout '${timeout_s}', using 30"
timeout_s=30
fi

if ! is_unsigned_number "$poll_interval_s"; then
log_warn "Invalid interrupt poll interval '${poll_interval_s}', using 2"
poll_interval_s=2
fi

if [ "$poll_interval_s" -eq 0 ]; then
log_warn "Interrupt poll interval cannot be 0, using 1"
poll_interval_s=1
fi

INTERRUPT_WAIT_INITIAL_LINE="$(get_first_interrupt_line_by_name "$irq_name")"
INTERRUPT_WAIT_FINAL_LINE=""
INTERRUPT_WAIT_IRQ_ID=""
INTERRUPT_WAIT_ELAPSED_S=0

if [ -z "$INTERRUPT_WAIT_INITIAL_LINE" ]; then
log_fail "Could not find interrupt line matching '${irq_name}' in /proc/interrupts"
return 1
fi

INTERRUPT_WAIT_IRQ_ID="$(printf '%s\n' "$INTERRUPT_WAIT_INITIAL_LINE" | awk '{ print $1 }')"

log_info "Initial interrupt line for '${irq_name}':"
log_info "$INTERRUPT_WAIT_INITIAL_LINE"
log_info "Polling '${irq_name}' interrupt counters, timeout=${timeout_s}s interval=${poll_interval_s}s"

waited=0

while [ "$waited" -le "$timeout_s" ]; do
current_line="$(get_interrupt_line_by_name "$irq_name" | awk -v irq="$INTERRUPT_WAIT_IRQ_ID" '$1 == irq { print; exit }')"

if [ -n "$current_line" ]; then
INTERRUPT_WAIT_FINAL_LINE="$current_line"

interrupt_cpu_counts_incremented "$INTERRUPT_WAIT_INITIAL_LINE" "$INTERRUPT_WAIT_FINAL_LINE"
compare_rc=$?

case "$compare_rc" in
0)
INTERRUPT_WAIT_ELAPSED_S="$waited"
log_info "Final interrupt line for '${irq_name}' after ${waited}s:"
log_info "$INTERRUPT_WAIT_FINAL_LINE"
return 0
;;
1)
INTERRUPT_WAIT_ELAPSED_S="$waited"
return 1
;;
2)
:
;;
esac
else
log_warn "Interrupt line '${irq_name}' with IRQ ${INTERRUPT_WAIT_IRQ_ID} not found while polling"
fi

if [ "$waited" -ge "$timeout_s" ]; then
break
fi

sleep "$poll_interval_s"
waited=$((waited + poll_interval_s))
done

# Export result to caller, used by Interrupts/run.sh after this helper returns.
# shellcheck disable=SC2034
INTERRUPT_WAIT_ELAPSED_S="$waited"

if [ -n "$INTERRUPT_WAIT_FINAL_LINE" ]; then
log_info "Last interrupt line for '${irq_name}' after timeout:"
log_info "$INTERRUPT_WAIT_FINAL_LINE"
fi

log_fail "Interrupt counters for '${irq_name}' did not increment on all CPUs within ${timeout_s}s"
return 1
}

# Run bounded workload pinned to one CPU.
#
Expand Down
Loading