-
Notifications
You must be signed in to change notification settings - Fork 21
adsp_remoteproc: enforce fixed 30s pre-stop #144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
#!/bin/sh | ||
|
||
# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. | ||
# SPDX-License-Identifier: BSD-3-Clause-Clear | ||
# Robustly find and source init_env | ||
|
@@ -39,42 +38,149 @@ log_info "---------------------------------------------------------------------- | |
log_info "------------------- Starting $TESTNAME Testcase ----------------------------" | ||
log_info "=== Test Initialization ===" | ||
|
||
# Tunables | ||
STOP_TO="${STOP_TO:-10}" | ||
START_TO="${START_TO:-10}" | ||
POLL_I="${POLL_I:-1}" | ||
# --- Tunables (override via env) ---------------------------------------------- | ||
STOP_TO="${STOP_TO:-10}" # remoteproc stop timeout (s) | ||
START_TO="${START_TO:-10}" # remoteproc start timeout (s) | ||
POLL_I="${POLL_I:-1}" # state poll interval (s) | ||
PRE_STOP_DELAY="${PRE_STOP_DELAY:-30}" # FIXED delay before stopping ADSP (seconds) | ||
FATAL_ON_UNSUSPENDED="${FATAL_ON_UNSUSPENDED:-0}" # 1 = abort if audio not suspended/unsupported after delay | ||
|
||
log_info "Tunables: STOP_TO=$STOP_TO START_TO=$START_TO POLL_I=$POLL_I PRE_STOP_DELAY=$PRE_STOP_DELAY FATAL_ON_UNSUSPENDED=$FATAL_ON_UNSUSPENDED" | ||
|
||
# --- Audio readiness snapshot (no hardcoding, no long wait) ------------------- | ||
# Discovers a bound snd*/snd-soc* driver, logs module once, collects nodes to check. | ||
# Sets globals: | ||
# CHECK_NODES="list of .../power/runtime_status files" | ||
# AUDIO_PM_SNAPSHOT_OK=1/0 (current sample) | ||
discover_audio_stack_and_snapshot() { | ||
DRIVERS_BASE="/sys/bus/platform/drivers" | ||
log_info "Validating audio stack readiness before ADSP test..." | ||
log_info "Scanning for platform audio driver (module -> bound -> suspend snapshot)..." | ||
|
||
platform_drv="" | ||
platform_mod="" | ||
|
||
for drvdir in "$DRIVERS_BASE"/snd-* "$DRIVERS_BASE"/snd-soc-*; do | ||
[ -d "$drvdir" ] || continue | ||
[ -L "$drvdir/sound" ] || continue | ||
platform_drv="$(basename "$drvdir")" | ||
if [ -L "$drvdir/module" ]; then | ||
platform_mod="$(basename "$(readlink -f "$drvdir/module")")" | ||
else | ||
platform_mod="" | ||
fi | ||
break | ||
done | ||
|
||
CHECK_NODES="" | ||
if [ -z "$platform_drv" ]; then | ||
log_warn "No suitable platform audio driver found (module+bound); skipping suspend snapshot" | ||
AUDIO_PM_SNAPSHOT_OK=1 | ||
return 0 | ||
fi | ||
|
||
if [ -n "$platform_mod" ]; then | ||
if check_driver_loaded "$platform_mod" >/dev/null 2>&1; then | ||
log_pass "Driver/module '$platform_mod' is loaded" | ||
elif [ -d "/sys/module/$platform_mod" ]; then | ||
log_info "Module '$platform_mod' appears built-in" | ||
else | ||
log_warn "Module '$platform_mod' not present; proceeding (driver bound)" | ||
fi | ||
else | ||
log_info "No 'module' symlink for $platform_drv; assuming built-in/platform driver" | ||
fi | ||
|
||
log_info "Using bound audio driver: $platform_drv${platform_mod:+ (module: $platform_mod)}" | ||
|
||
TARGET_PATH="$DRIVERS_BASE/$platform_drv/sound" | ||
|
||
# 1) Platform sound root + immediate children (collect runtime_status files) | ||
if [ -d "$TARGET_PATH" ]; then | ||
_rt_nodes_list="$(mktemp)" | ||
find "$TARGET_PATH" -maxdepth 2 -type f -path "*/power/runtime_status" \ | ||
-exec printf '%s\n' {} \; 2>/dev/null > "$_rt_nodes_list" | ||
while IFS= read -r f; do | ||
[ -n "$f" ] && CHECK_NODES="$CHECK_NODES $f" | ||
done < "$_rt_nodes_list" | ||
rm -f "$_rt_nodes_list" | ||
fi | ||
|
||
# 2) ALSA cards | ||
for f in /sys/class/sound/card*/device/power/runtime_status; do | ||
[ -f "$f" ] && CHECK_NODES="$CHECK_NODES $f" | ||
done | ||
|
||
# 3) SoundWire slaves | ||
for f in /sys/bus/soundwire/devices/*/power/runtime_status; do | ||
[ -f "$f" ] && CHECK_NODES="$CHECK_NODES $f" | ||
done | ||
|
||
log_info "DEBUG: STOP_TO=$STOP_TO START_TO=$START_TO POLL_I=$POLL_I" | ||
if [ -z "$CHECK_NODES" ]; then | ||
log_warn "No runtime_status nodes found for audio stack; treating snapshot as OK" | ||
AUDIO_PM_SNAPSHOT_OK=1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can u add skip so that it will show in the result There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It's the same here. We can't add SKIP, so instead we're using log_info for debugging purposes. |
||
return 0 | ||
fi | ||
|
||
# Single snapshot: OK if all nodes are 'suspended' or 'unsupported' | ||
AUDIO_PM_SNAPSHOT_OK=1 | ||
for n in $CHECK_NODES; do | ||
st="$(cat "$n" 2>/dev/null || echo "unknown")" | ||
case "$st" in | ||
suspended|unsupported) : ;; | ||
*) AUDIO_PM_SNAPSHOT_OK=0 ;; | ||
esac | ||
[ "$AUDIO_PM_SNAPSHOT_OK" -eq 0 ] && break | ||
done | ||
|
||
if [ "$AUDIO_PM_SNAPSHOT_OK" -eq 1 ]; then | ||
log_info "Audio PM snapshot: OK (suspended/unsupported)" | ||
else | ||
log_warn "Audio PM snapshot: not fully suspended; proceeding to fixed pre-stop delay" | ||
fi | ||
} | ||
|
||
# DT check for entries | ||
if dt_has_remoteproc_fw "$FW"; then | ||
log_info "DT indicates $FW is present" | ||
else | ||
# Re-check after fixed delay (if gating is enabled) | ||
audio_pm_snapshot_ok() { | ||
# Re-sample the same CHECK_NODES set; if empty, treat as OK. | ||
if [ -z "$CHECK_NODES" ]; then | ||
echo "1" | ||
return | ||
fi | ||
for n in $CHECK_NODES; do | ||
st="$(cat "$n" 2>/dev/null || echo "unknown")" | ||
case "$st" in suspended|unsupported) : ;; *) echo "0"; return ;; esac | ||
done | ||
echo "1" | ||
} | ||
|
||
discover_audio_stack_and_snapshot | ||
|
||
# --- Check DT presence for ADSP ----------------------------------------------- | ||
if ! dt_has_remoteproc_fw "$FW"; then | ||
log_skip "$TESTNAME SKIP – $FW not described in DT" | ||
echo "$TESTNAME SKIP" >"$RES_FILE" | ||
exit 0 | ||
fi | ||
log_info "DT indicates $FW is present" | ||
|
||
# Enumerate ADSP remoteproc entries | ||
# get_remoteproc_by_firmware prints: "path|state|firmware|name" | ||
entries="$(get_remoteproc_by_firmware "$FW" "" all)" || entries="" | ||
# --- Enumerate ADSP remoteproc entries ---------------------------------------- | ||
entries="$(get_remoteproc_by_firmware "$FW" "" all 2>/dev/null)" || entries="" | ||
if [ -z "$entries" ]; then | ||
log_fail "$FW present in DT but no /sys/class/remoteproc entry found" | ||
echo "$TESTNAME FAIL" >"$RES_FILE" | ||
exit 1 | ||
fi | ||
|
||
count_instances=$(printf '%s\n' "$entries" | wc -l) | ||
count_instances="$(printf '%s\n' "$entries" | wc -l)" | ||
log_info "Found $count_instances $FW instance(s)" | ||
|
||
inst_fail=0 | ||
RESULT_LINES="" | ||
|
||
tmp_list="$(mktemp)" | ||
printf '%s\n' "$entries" >"$tmp_list" | ||
|
||
# --- Iterate each instance via here-doc --------------------------------------- | ||
while IFS='|' read -r rpath rstate rfirm rname; do | ||
[ -n "$rpath" ] || continue | ||
|
||
inst_id="$(basename "$rpath")" | ||
log_info "---- $inst_id: path=$rpath state=$rstate firmware=$rfirm name=$rname ----" | ||
|
||
|
@@ -83,7 +189,6 @@ while IFS='|' read -r rpath rstate rfirm rname; do | |
start_res="NA" | ||
ping_res="SKIPPED" | ||
|
||
# Boot check | ||
if [ "$rstate" = "running" ]; then | ||
log_pass "$inst_id: boot check PASS" | ||
else | ||
|
@@ -95,12 +200,28 @@ while IFS='|' read -r rpath rstate rfirm rname; do | |
continue | ||
fi | ||
|
||
# Stop | ||
# ---- Fixed pre-stop delay (always wait PRE_STOP_DELAY seconds) ----------- | ||
log_info "$inst_id: waiting ${PRE_STOP_DELAY}s before remoteproc stop (fixed delay)" | ||
[ "$PRE_STOP_DELAY" -gt 0 ] && sleep "$PRE_STOP_DELAY" | ||
|
||
# Optional gating: after the fixed delay, ensure PM is OK before stopping | ||
if [ "$FATAL_ON_UNSUSPENDED" -eq 1 ]; then | ||
if [ "$(audio_pm_snapshot_ok)" -ne 1 ]; then | ||
log_fail "Audio not in suspended/unsupported state after ${PRE_STOP_DELAY}s (FATAL_ON_UNSUSPENDED=1); aborting before stop" | ||
echo "$TESTNAME FAIL" >"$RES_FILE" | ||
exit 1 | ||
fi | ||
fi | ||
|
||
# Helpful dmesg snapshots | ||
dmesg | tail -n 100 > "$test_path/dmesg_before_stop.log" | ||
dump_rproc_logs "$rpath" before-stop | ||
t0=$(date +%s) | ||
|
||
# ---- Stop ADSP ----------------------------------------------------------- | ||
t0="$(date +%s)" | ||
log_info "$inst_id: stopping" | ||
if stop_remoteproc "$rpath" && wait_remoteproc_state "$rpath" offline "$STOP_TO" "$POLL_I"; then | ||
t1=$(date +%s) | ||
t1="$(date +%s)" | ||
log_pass "$inst_id: stop PASS ($((t1 - t0))s)" | ||
stop_res="PASS" | ||
else | ||
|
@@ -112,14 +233,15 @@ while IFS='|' read -r rpath rstate rfirm rname; do | |
$inst_id: boot=$boot_res, stop=$stop_res, start=$start_res, ping=$ping_res" | ||
continue | ||
fi | ||
dump_rproc_logs "$rpath" after-stop | ||
|
||
# Start | ||
dump_rproc_logs "$rpath" after-stop | ||
dump_rproc_logs "$rpath" before-start | ||
t2=$(date +%s) | ||
|
||
# ---- Start ADSP ---------------------------------------------------------- | ||
t2="$(date +%s)" | ||
log_info "$inst_id: starting" | ||
if start_remoteproc "$rpath" && wait_remoteproc_state "$rpath" running "$START_TO" "$POLL_I"; then | ||
t3=$(date +%s) | ||
t3="$(date +%s)" | ||
log_pass "$inst_id: start PASS ($((t3 - t2))s)" | ||
start_res="PASS" | ||
else | ||
|
@@ -131,10 +253,12 @@ while IFS='|' read -r rpath rstate rfirm rname; do | |
$inst_id: boot=$boot_res, stop=$stop_res, start=$start_res, ping=$ping_res" | ||
continue | ||
fi | ||
|
||
dump_rproc_logs "$rpath" after-start | ||
dmesg | tail -n 100 > "$test_path/dmesg_after_restart.log" | ||
|
||
# Optional RPMsg ping | ||
if CTRL_DEV=$(find_rpmsg_ctrl_for "$FW"); then | ||
# ---- Optional RPMsg sanity ping ----------------------------------------- | ||
if CTRL_DEV="$(find_rpmsg_ctrl_for "$FW")"; then | ||
log_info "$inst_id: RPMsg ctrl dev: $CTRL_DEV" | ||
if rpmsg_ping_generic "$CTRL_DEV"; then | ||
log_pass "$inst_id: rpmsg ping PASS" | ||
|
@@ -150,11 +274,11 @@ while IFS='|' read -r rpath rstate rfirm rname; do | |
|
||
RESULT_LINES="$RESULT_LINES | ||
$inst_id: boot=$boot_res, stop=$stop_res, start=$start_res, ping=$ping_res" | ||
done <<__RPROC_LIST__ | ||
$entries | ||
__RPROC_LIST__ | ||
|
||
done <"$tmp_list" | ||
rm -f "$tmp_list" | ||
|
||
# Summary | ||
# --- Summary ------------------------------------------------------------------ | ||
log_info "Instance results:$RESULT_LINES" | ||
|
||
if [ "$inst_fail" -gt 0 ]; then | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1200,7 +1200,7 @@ dump_rproc_logs() { | |
logfile="rproc_${base}_${label}_${ts}.log" | ||
log_info "Dumping ${base} [${label}] → ${logfile}" | ||
[ -r "$rpath/trace" ] && cat "$rpath/trace" >"$logfile" | ||
dmesg --ctime | grep -i "$base" >>"$logfile" 2>/dev/null || : | ||
dmesg | grep -i "$base" >>"$logfile" 2>/dev/null || : | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why --ctime is removed here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The current dmesg utility does not include this option, so it will display a usage error. |
||
} | ||
|
||
# find_rpmsg_ctrl_for <short-name> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we append skip to result here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK, we cannot skip the test because the driver does not have the capability to display the PM stats, as it shows unsupported. The message reads:
Audio PM snapshot: OK (suspended/unsupported)
. Based on this, we are able to skip the entire test.