Skip to content
Open
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
170 changes: 170 additions & 0 deletions automated/linux/remoteproc-smoke/remoteproc-smoke-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-only
# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
#
# remoteproc smoke tests
#
# Check that the remoteprocs which the kernel is expected to boot are running,
# to catch regressions where a DSP silently fails to come up, e.g. because its
# firmware could not be loaded.

# shellcheck disable=SC1091,SC2034,SC2039
. ../../lib/sh-test-lib
OUTPUT="$(pwd)/output"
RESULT_FILE="${OUTPUT}/result.txt"
export RESULT_FILE
SYSFS_REMOTEPROC="/sys/class/remoteproc"
DEVICE=""
# remoteprocs which the kernel doesn't boot on its own, either because no
# firmware is shipped for them or because another subsystem owns their
# lifecycle, e.g. ath11k for wpss; see
# https://github.com/qualcomm/fastrpc/pull/372
SKIP="modem wpss"
WAIT_TIME=0

usage() {
echo "Usage: $0 [-d <remoteprocs>] [-s <remoteprocs>] [-w <wait_time>]" 1>&2
exit 1
}

while getopts "d:s:w:" o; do
case "$o" in
d) DEVICE="${OPTARG}" ;;
s) SKIP="${OPTARG}" ;;
w) WAIT_TIME="${OPTARG}" ;;
*) usage ;;
esac
done

# list the sysfs directories of all remoteprocs, one per line
list_remoteprocs() {
for dir in "${SYSFS_REMOTEPROC}"/remoteproc*; do
[ -r "${dir}/name" ] || continue
echo "${dir}"
done
}

# list the sysfs directories of the remoteprocs named $1, one per line; a name
# is not guaranteed to be unique, e.g. some SoCs have two cdsp instances
remoteprocs_by_name() {
local name="$1"
for dir in $(list_remoteprocs); do
[ "$(cat "${dir}/name")" = "${name}" ] && echo "${dir}"
done

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should return 0

}

# whether remoteproc $1 is expected not to be running
is_skipped() {
local name="$1"
for skipped in ${SKIP}; do
[ "${name}" = "${skipped}" ] && return 0
done
return 1
}

# print the test case name for the remoteproc in sysfs directory $1; names are
# usually unique and are kept as-is so that results stay comparable across
# runs, but a SoC may have several remoteprocs sharing a name, in which case
# the sysfs name is added to tell them apart
test_case_name() {
local dir="$1"
local name
name="$(cat "${dir}/name")"
if [ "$(remoteprocs_by_name "${name}" | wc -l)" -gt 1 ]; then
echo "remoteproc-${name}-$(basename "${dir}")-running"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will the name will be stable across boots. Could we not use basename "$(readlink -f "${dir}/device")" to get a reliable name beforehand, just to be sure.

else
echo "remoteproc-${name}-running"
fi
}

# test that the remoteproc in sysfs directory $1 is running
test_remoteproc_state() {
local dir="$1"
local name
local state
local test_case

name="$(cat "${dir}/name")"
state="$(cat "${dir}/state" 2>/dev/null)"
test_case="$(test_case_name "${dir}")"
info_msg "$(basename "${dir}") ${name} state is ${state:-unreadable}"

# report the state above even for remoteprocs which are not tested, it is
# useful when triaging a job
if is_skipped "${name}"; then
info_msg "${name} is not expected to be running, skipping"
report_skip "${test_case}"
return
fi

# "running" is a remoteproc which Linux booted, "attached" one which was
# already running when Linux took over
case "${state}" in
running|attached) report_pass "${test_case}" ;;
*) report_fail "${test_case}" ;;
esac
}

# helper function to wait for remoteproc(s) to be enumerated. When DEVICE is
# unset, wait for any remoteproc to be enumerated.
wait_for_device() {
info_msg "Waiting ${WAIT_TIME} seconds for requested device to exist..."
for i in $(seq 1 "${WAIT_TIME}")
do
if [ -n "${DEVICE}" ]; then
# wait for all of the requested remoteprocs, not just the first one
missing=""
for name in ${DEVICE}; do
[ -z "$(remoteprocs_by_name "${name}")" ] && missing="${name}"
done
[ -z "${missing}" ] && break
else
[ -n "$(list_remoteprocs)" ] && break
fi
sleep 1
done
}

# Test run.
create_out_dir "${OUTPUT}"

info_msg "About to run remoteproc smoke test..."
info_msg "Output directory: ${OUTPUT}"

# remoteprocs are booted asynchronously, so they may not be enumerated yet
wait_for_device

if [ -n "${DEVICE}" ]; then

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this checks if device has remoteproc. I would use report_skip "remoteproc-device-exists" and report_pass "remoteproc-device-exists" at the top of the test.

Something like

all_dirs="$(list_remoteprocs)"
if [ -z "${all_dirs}" ]; then
report_skip "remoteproc-device-exists"
else
report_pass "remoteproc-device-exists"
fi

(and catch it at the bottom of this function). So you will get a remoteproc-device-exists skip when no remoteprocs are found

# a requested remoteproc which doesn't exist is a failure, unless it is one
# which is not expected to be running anyway
dirs=""
for name in ${DEVICE}; do

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth a cheap dedupe call here.

found="$(remoteprocs_by_name "${name}")"
if [ -z "${found}" ]; then
info_msg "No remoteproc named ${name}"
if is_skipped "${name}"; then
report_skip "remoteproc-${name}-running"
else
report_fail "remoteproc-${name}-running"
fi
continue
fi
dirs="${dirs} ${found}"
done
else
# auto-detect all of the remoteprocs present on the DUT
dirs="$(list_remoteprocs)"
if [ -z "${dirs}" ]; then
report_skip "remoteproc-device-exists"
exit 0
fi
report_pass "remoteproc-device-exists"
fi

# test case names embed the remoteproc name, so they are unique and stay
# comparable across runs
for dir in ${dirs}; do
test_remoteproc_state "${dir}"
done

exit 0
34 changes: 34 additions & 0 deletions automated/linux/remoteproc-smoke/remoteproc-smoke.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
metadata:
format: Lava-Test Test Definition 1.0
name: remoteproc-smoke
description: "Check that the remoteprocs which the kernel is expected to
boot are running. Catches regressions where a DSP silently fails to come
up, e.g. because its firmware could not be loaded."
maintainer:
- loic.minier@oss.qualcomm.com
os:
- debian
- ubuntu
- centos
- fedora
- openembedded
scope:
- functional
devices:
- qcs6490-rb3gen2

params:
# leave empty to auto-detect and test all remoteprocs present
DEVICE: ""
# remoteprocs which the kernel doesn't boot on its own, either because no
# firmware is shipped for them or because another subsystem owns their
# lifecycle, e.g. ath11k for wpss; see
# https://github.com/qualcomm/fastrpc/pull/372
SKIP: "modem wpss"
WAIT_TIME: 0

run:
steps:
- cd ./automated/linux/remoteproc-smoke
- ./remoteproc-smoke-test.sh -d "${DEVICE}" -s "${SKIP}" -w "${WAIT_TIME}"
- ../../utils/send-to-lava.sh ./output/result.txt
Loading