From c0e80ffc8ea7dc3204a985a52a5fa82e56318fad Mon Sep 17 00:00:00 2001 From: Jeevanandan Sandan Date: Mon, 5 Jan 2026 16:35:35 +0530 Subject: [PATCH] feat: added ufs functional tests - UFS Read/Writes - Verifies the UFS read/writes in the user partition - UFS Runtime Suspend/Resume - Ensure proper link_state transitions during load and no-load - UFS Clock Scaling/Gating - Ensures UFS clock is scaled and gated based on load and requirement - UFS Hibern8 - Validate active/hibern8 entry exit on-demand - UFS Write Booster - Check whether UFS Write Booster is enabled on write - UFS Gear Validation - Check gear switching on load - Fixed Review Comments Impact: These tests improve the functional coverage for UFS Signed-off-by: Jeevanandan Sandan --- .../Baseport/Storage/UFS_Validation/run.sh | 16 +- .../Baseport/Storage/eMMC_Validation/run.sh | 13 +- .../Storage/ufs_clock_scaling/README.md | 56 +++++ .../Baseport/Storage/ufs_clock_scaling/run.sh | 189 ++++++++++++++++ .../ufs_clock_scaling/ufs_clock_scaling.yaml | 15 ++ .../Baseport/Storage/ufs_gear_check/README.md | 42 ++++ .../Baseport/Storage/ufs_gear_check/run.sh | 202 ++++++++++++++++++ .../ufs_gear_check/ufs_gear_check.yaml | 15 ++ .../Baseport/Storage/ufs_hibern8/README.md | 45 ++++ .../Baseport/Storage/ufs_hibern8/run.sh | 146 +++++++++++++ .../Storage/ufs_hibern8/ufs_hibern8.yaml | 15 ++ .../Storage/ufs_read_writes/README.md | 43 ++++ .../Baseport/Storage/ufs_read_writes/run.sh | 147 +++++++++++++ .../ufs_read_writes/ufs_read_writes.yaml | 15 ++ .../ufs_runtime_suspend_resume/README.md | 45 ++++ .../Storage/ufs_runtime_suspend_resume/run.sh | 147 +++++++++++++ .../ufs_runtime_suspend_resume.yaml | 15 ++ .../Storage/ufs_write_booster/README.md | 43 ++++ .../Baseport/Storage/ufs_write_booster/run.sh | 188 ++++++++++++++++ .../ufs_write_booster/ufs_write_booster.yaml | 16 ++ Runner/utils/functestlib.sh | 56 +++++ 21 files changed, 1456 insertions(+), 13 deletions(-) create mode 100644 Runner/suites/Kernel/Baseport/Storage/ufs_clock_scaling/README.md create mode 100755 Runner/suites/Kernel/Baseport/Storage/ufs_clock_scaling/run.sh create mode 100644 Runner/suites/Kernel/Baseport/Storage/ufs_clock_scaling/ufs_clock_scaling.yaml create mode 100644 Runner/suites/Kernel/Baseport/Storage/ufs_gear_check/README.md create mode 100755 Runner/suites/Kernel/Baseport/Storage/ufs_gear_check/run.sh create mode 100644 Runner/suites/Kernel/Baseport/Storage/ufs_gear_check/ufs_gear_check.yaml create mode 100644 Runner/suites/Kernel/Baseport/Storage/ufs_hibern8/README.md create mode 100755 Runner/suites/Kernel/Baseport/Storage/ufs_hibern8/run.sh create mode 100644 Runner/suites/Kernel/Baseport/Storage/ufs_hibern8/ufs_hibern8.yaml create mode 100644 Runner/suites/Kernel/Baseport/Storage/ufs_read_writes/README.md create mode 100755 Runner/suites/Kernel/Baseport/Storage/ufs_read_writes/run.sh create mode 100644 Runner/suites/Kernel/Baseport/Storage/ufs_read_writes/ufs_read_writes.yaml create mode 100644 Runner/suites/Kernel/Baseport/Storage/ufs_runtime_suspend_resume/README.md create mode 100755 Runner/suites/Kernel/Baseport/Storage/ufs_runtime_suspend_resume/run.sh create mode 100644 Runner/suites/Kernel/Baseport/Storage/ufs_runtime_suspend_resume/ufs_runtime_suspend_resume.yaml create mode 100644 Runner/suites/Kernel/Baseport/Storage/ufs_write_booster/README.md create mode 100755 Runner/suites/Kernel/Baseport/Storage/ufs_write_booster/run.sh create mode 100644 Runner/suites/Kernel/Baseport/Storage/ufs_write_booster/ufs_write_booster.yaml diff --git a/Runner/suites/Kernel/Baseport/Storage/UFS_Validation/run.sh b/Runner/suites/Kernel/Baseport/Storage/UFS_Validation/run.sh index 168c5f68..e8da6bff 100755 --- a/Runner/suites/Kernel/Baseport/Storage/UFS_Validation/run.sh +++ b/Runner/suites/Kernel/Baseport/Storage/UFS_Validation/run.sh @@ -17,13 +17,14 @@ done if [ -z "$INIT_ENV" ]; then echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 - exit 1 + exit 0 fi # Only source if not already loaded if [ -z "$__INIT_ENV_LOADED" ]; then # shellcheck disable=SC1090 . "$INIT_ENV" + export __INIT_ENV_LOADED=1 fi # Always source functestlib.sh @@ -32,13 +33,13 @@ fi TESTNAME="UFS_Validation" test_path=$(find_test_case_by_name "$TESTNAME") -cd "$test_path" || exit 1 +cd "$test_path" || exit 0 res_file="./$TESTNAME.res" log_info "--------------------------------------------------" log_info "------------- Starting $TESTNAME Test ------------" -check_dependencies dd grep cut head tail udevadm +check_dependencies dd MANDATORY_CONFIGS="CONFIG_SCSI_UFSHCD CONFIG_SCSI_UFS_QCOM" OPTIONAL_CONFIGS="CONFIG_SCSI_UFSHCD_PLATFORM CONFIG_SCSI_UFSHCD_PCI CONFIG_SCSI_UFS_CDNS_PLATFORM CONFIG_SCSI_UFS_HISI CONFIG_SCSI_UFS_EXYNOS CONFIG_SCSI_UFS_ROCKCHIP CONFIG_SCSI_UFS_BSG" @@ -62,6 +63,7 @@ done check_dt_nodes "/sys/bus/platform/devices/*ufs*" || { echo "$TESTNAME SKIP" > "$res_file" + log_skip "UFS Device Tree nodes not found" exit 0 } @@ -103,7 +105,7 @@ else log_fail "UFS read test failed" log_info "Try manually: $DD_CMD" echo "$TESTNAME FAIL" > "$res_file" - exit 1 + exit 0 fi log_info "Running I/O stress test (64MB read+write on tmpfile)..." @@ -137,10 +139,10 @@ else rm -f "$tmpfile" fi echo "$TESTNAME FAIL" > "$res_file" - exit 1 + exit 0 fi -scan_dmesg_errors "ufs" "$test_path" +scan_dmesg_errors "$test_path" "ufs" log_pass "$TESTNAME completed successfully" echo "$TESTNAME PASS" > "$res_file" -exit 0 +exit 0 \ No newline at end of file diff --git a/Runner/suites/Kernel/Baseport/Storage/eMMC_Validation/run.sh b/Runner/suites/Kernel/Baseport/Storage/eMMC_Validation/run.sh index 8e4942c9..ce503bf6 100755 --- a/Runner/suites/Kernel/Baseport/Storage/eMMC_Validation/run.sh +++ b/Runner/suites/Kernel/Baseport/Storage/eMMC_Validation/run.sh @@ -17,13 +17,14 @@ done if [ -z "$INIT_ENV" ]; then echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 - exit 1 + exit 0 fi # Only source if not already loaded if [ -z "$__INIT_ENV_LOADED" ]; then # shellcheck disable=SC1090 . "$INIT_ENV" + export __INIT_ENV_LOADED=1 fi # Always source functestlib.sh @@ -32,13 +33,13 @@ fi TESTNAME="eMMC_Validation" test_path=$(find_test_case_by_name "$TESTNAME") -cd "$test_path" || exit 1 +cd "$test_path" || exit 0 res_file="./$TESTNAME.res" log_info "--------------------------------------------------" log_info "------------ Starting $TESTNAME Test -------------" -check_dependencies dd grep cut head tail udevadm +check_dependencies dd grep MANDATORY_CONFIGS="CONFIG_MMC CONFIG_MMC_BLOCK" OPTIONAL_CONFIGS="CONFIG_MMC_SDHCI CONFIG_MMC_SDHCI_MSM CONFIG_MMC_BLOCK_MINORS" @@ -96,7 +97,7 @@ else else log_fail "eMMC read test failed" echo "$TESTNAME FAIL" > "$res_file" - exit 1 + exit 0 fi fi fi @@ -117,7 +118,7 @@ if dd if=/dev/zero of="$tmpfile" bs=1M count=64 conv=fsync status=none 2>/dev/nu log_fail "eMMC I/O stress test failed (read)" rm -f "$tmpfile" echo "$TESTNAME FAIL" > "$res_file" - exit 1 + exit 0 fi else log_warn "'conv=fsync' not supported. Trying basic write fallback." @@ -134,7 +135,7 @@ else log_fail "eMMC I/O stress test failed (fallback)" rm -f "$tmpfile" echo "$TESTNAME FAIL" > "$res_file" - exit 1 + exit 0 fi fi diff --git a/Runner/suites/Kernel/Baseport/Storage/ufs_clock_scaling/README.md b/Runner/suites/Kernel/Baseport/Storage/ufs_clock_scaling/README.md new file mode 100644 index 00000000..ddee4ac1 --- /dev/null +++ b/Runner/suites/Kernel/Baseport/Storage/ufs_clock_scaling/README.md @@ -0,0 +1,56 @@ +# UFS Clock Scaling and Gating Validation +## Overview + +This shell script executes on the DUT (Device-Under-Test) and verifies the UFS clock scaling and clock gating functionality by monitoring clock frequency changes during I/O load and idle states. + +The test script performs these functional checks: + +1. **Kernel Configuration**: + - Validates presence of mandatory configs: `CONFIG_SCSI_UFSHCD`, `CONFIG_SCSI_UFS_QCOM` + - Checks optional configs: `CONFIG_SCSI_UFSHCD_PLATFORM`, `CONFIG_SCSI_UFSHCD_PCI`, `CONFIG_SCSI_UFS_CDNS_PLATFORM`, `CONFIG_SCSI_UFS_HISI`, `CONFIG_SCSI_UFS_EXYNOS`, `CONFIG_SCSI_UFS_ROCKCHIP`, `CONFIG_SCSI_UFS_BSG` + +2. **Device Tree Validation**: + - Verifies UFS device tree nodes exist at `/sys/bus/platform/devices/*ufs*` + - Detects UFS block device partition + +3. **Clock Frequency Node Detection**: + - Locates current frequency node: `/sys/devices/platform/soc@0/*ufs*/devfreq/*ufs*/cur_freq` + - Locates max frequency node: `/sys/devices/platform/soc@0/*ufs*/devfreq/*ufs*/max_freq` + - Locates min frequency node: `/sys/devices/platform/soc@0/*ufs*/devfreq/*ufs*/min_freq` + +4. **Clock Scaling Verification**: + - Generates I/O load using `dd` command (writes 2GB of data) + - Monitors whether UFS clock scales up to maximum frequency during load + - Validates clock frequency on application of load + +5. **Clock Gating Verification**: + - Waits for UFS driver to enter idle state + - Monitors whether UFS clock gates down to minimum frequency when idle + - Validates ufs clock is gated when no load is present + +## How to Run + +```sh +source init_env +cd suites/Kernel/Baseport/Storage/ufs_clock_scaling +./run.sh +``` + +## Prerequisites + +- `dd`, `sleep` must be available +- Root access may be required for complete validation +- Sufficient storage space for temporary test file (approximately 2GB) + +## Result Format + +Test result will be saved in `ufs_clock_scaling.res` as: +- `ufs_clock_scaling PASS` – if both clock scaling and gating validations pass +- `ufs_clock_scaling FAIL` – if either clock scaling or gating check fails +- `ufs_clock_scaling SKIP` – if required kernel configs, device tree nodes, or UFS devices are not found + +## License + +``` +Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +SPDX-License-Identifier: BSD-3-Clause-Clear diff --git a/Runner/suites/Kernel/Baseport/Storage/ufs_clock_scaling/run.sh b/Runner/suites/Kernel/Baseport/Storage/ufs_clock_scaling/run.sh new file mode 100755 index 00000000..9c7bf682 --- /dev/null +++ b/Runner/suites/Kernel/Baseport/Storage/ufs_clock_scaling/run.sh @@ -0,0 +1,189 @@ +#!/bin/sh +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# 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" + break + fi + SEARCH=$(dirname "$SEARCH") +done + +if [ -z "$INIT_ENV" ]; then + echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 + exit 0 +fi + +# Only source if not already loaded +if [ -z "$__INIT_ENV_LOADED" ]; then + # shellcheck disable=SC1090 + . "$INIT_ENV" + export __INIT_ENV_LOADED=1 +fi + +# Always source functestlib.sh +# shellcheck disable=SC1090,SC1091 +. "$TOOLS/functestlib.sh" + +TESTNAME="ufs_clock_scaling" +test_path=$(find_test_case_by_name "$TESTNAME") +cd "$test_path" || exit 0 +res_file="./$TESTNAME.res" + +log_info "--------------------------------------------------" +log_info "------------- Starting $TESTNAME Test ------------" + +check_dependencies dd sleep + +MANDATORY_CONFIGS="CONFIG_SCSI_UFSHCD CONFIG_SCSI_UFS_QCOM" +OPTIONAL_CONFIGS="CONFIG_SCSI_UFSHCD_PLATFORM CONFIG_SCSI_UFSHCD_PCI CONFIG_SCSI_UFS_CDNS_PLATFORM CONFIG_SCSI_UFS_HISI CONFIG_SCSI_UFS_EXYNOS CONFIG_SCSI_UFS_ROCKCHIP CONFIG_SCSI_UFS_BSG" + +log_info "Checking mandatory kernel configs for UFS..." +if ! check_kernel_config "$MANDATORY_CONFIGS" 2>/dev/null; then + log_skip "Missing mandatory UFS kernel configs: $MANDATORY_CONFIGS" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi + +log_info "Checking optional kernel configs for UFS..." +missing_optional="" +for cfg in $OPTIONAL_CONFIGS; do + if ! check_kernel_config "$cfg" 2>/dev/null; then + log_info "[OPTIONAL] $cfg is not enabled" + missing_optional="$missing_optional $cfg" + fi +done +[ -n "$missing_optional" ] && log_info "Optional configs not present but continuing:$missing_optional" + +check_dt_nodes "/sys/bus/platform/devices/*ufs*" || { + echo "$TESTNAME SKIP" > "$res_file" + log_skip "UFS Device Tree nodes not found" + exit 0 +} + +block_dev=$(detect_ufs_partition_block) +if [ -z "$block_dev" ]; then + log_skip "No UFS block device found." + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi +log_info "Detected UFS block: $block_dev" + +log_info "Validating UFS clock scaling & clock gating" +# Check for UFS clock freq node and assign to variable +log_info "Checking for UFS clock freq node..." +if ! check_dt_nodes "/sys/devices/platform/soc@0/*ufs*/devfreq/*ufs*/cur_freq"; then + log_skip "UFS clock frequency node not found" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi + +UFS_CLOCK_FREQ_NODE=$(get_dt_node_path "/sys/devices/platform/soc@0/*ufs*/devfreq/*ufs*/cur_freq") +if [ -z "$UFS_CLOCK_FREQ_NODE" ]; then + log_skip "Failed to get UFS clock frequency node path" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi +log_info "Found UFS clock freq node: $UFS_CLOCK_FREQ_NODE" + +# Check for UFS clock max freq node and assign to variable +log_info "Checking for UFS max clock freq node..." +if ! check_dt_nodes "/sys/devices/platform/soc@0/*ufs*/devfreq/*ufs*/max_freq"; then + log_skip "UFS max frequency node not found" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi + +UFS_MAX_FREQ_NODE=$(get_dt_node_path "/sys/devices/platform/soc@0/*ufs*/devfreq/*ufs*/max_freq") +if [ -z "$UFS_MAX_FREQ_NODE" ]; then + log_skip "Failed to get UFS max clock frequency node path" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi +log_info "Found UFS max freq node: $UFS_MAX_FREQ_NODE" + +UFS_MAX_FREQ=$(cat "$UFS_MAX_FREQ_NODE" 2>/dev/null) +if [ -z "$UFS_MAX_FREQ" ]; then + log_skip "Failed to read max frequency from $UFS_MAX_FREQ_NODE" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi +log_info "Max UFS clock frequency supported is $UFS_MAX_FREQ" + +# Generate load using dd command and check for ufs cur_freq +log_info "Starting I/O load test to verify UFS clock scaling..." +tmpfile="/ufs_clock_scaling.tmp" + +# Start dd in background +dd if=/dev/zero of="$tmpfile" bs=2M count=1024 >/dev/null 2>&1 & +DD_PID=$! + +log_info "Checking whether UFS clock is scaled during load..." +UFS_CLOCK_SCALED=0 + +# Use check_node_status to verify ufs clock scaling +if ! check_node_status "$UFS_CLOCK_FREQ_NODE" "$UFS_MAX_FREQ" 10 1; then + log_fail "UFS clock is not scaled" +else + log_pass "UFS clock is scaled to $UFS_MAX_FREQ" + UFS_CLOCK_SCALED=1 +fi + +# Wait for dd to complete if it's still running +if kill -0 $DD_PID 2>/dev/null; then + log_info "Waiting for I/O load test to complete..." + wait $DD_PID 2>/dev/null + sync +fi + +# Clean up temp file +rm -f "$tmpfile" + +# wait for 60 seconds for UFS driver to go to idle state +log_info "Waiting for 60 seconds for UFS clock to gate" +sync +sleep 60 + + +UFS_MIN_FREQ_NODE=$(get_dt_node_path "/sys/devices/platform/soc@0/*ufs*/devfreq/*ufs*/min_freq") +if [ -z "$UFS_MIN_FREQ_NODE" ]; then + log_skip "Failed to get UFS min clock frequency node path" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi +log_info "Found UFS min freq node: $UFS_MIN_FREQ_NODE" + +UFS_MIN_FREQ=$(cat "$UFS_MIN_FREQ_NODE" 2>/dev/null) +if [ -z "$UFS_MIN_FREQ" ]; then + log_skip "Failed to read min frequency from $UFS_MIN_FREQ" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi +log_info "Min UFS clock frequency supported is $UFS_MIN_FREQ" + +log_info "Checking whether UFS clock is gated when no load is applied" +UFS_CLOCK_GATED=0 + +# Use check_node_status to verify ufs clock scaling +if ! check_node_status "$UFS_CLOCK_FREQ_NODE" "$UFS_MIN_FREQ" 10 1; then + log_fail "UFS clock is not gated" +else + log_pass "UFS clock is gated to $UFS_MIN_FREQ" + UFS_CLOCK_GATED=1 +fi + +if [ "$UFS_CLOCK_SCALED" -ne 1 ] || [ "$UFS_CLOCK_GATED" -ne 1 ]; then + log_fail "UFS clock scaling & gating test failed" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + +scan_dmesg_errors "$test_path" "ufs" +log_pass "$TESTNAME completed successfully" +echo "$TESTNAME PASS" > "$res_file" +exit 0 \ No newline at end of file diff --git a/Runner/suites/Kernel/Baseport/Storage/ufs_clock_scaling/ufs_clock_scaling.yaml b/Runner/suites/Kernel/Baseport/Storage/ufs_clock_scaling/ufs_clock_scaling.yaml new file mode 100644 index 00000000..4cf0bb99 --- /dev/null +++ b/Runner/suites/Kernel/Baseport/Storage/ufs_clock_scaling/ufs_clock_scaling.yaml @@ -0,0 +1,15 @@ +metadata: + name: ufs-clock-scaling + format: "Lava-Test Test Definition 1.0" + description: "Check whether UFS clock is scaled when load is applied" + os: + - linux + scope: + - functional + +run: + steps: + - REPO_PATH=$PWD + - cd Runner/suites/Kernel/Baseport/Storage/ufs_clock_scaling + - ./run.sh || true + - $REPO_PATH/Runner/utils/send-to-lava.sh ufs_clock_scaling.res || true \ No newline at end of file diff --git a/Runner/suites/Kernel/Baseport/Storage/ufs_gear_check/README.md b/Runner/suites/Kernel/Baseport/Storage/ufs_gear_check/README.md new file mode 100644 index 00000000..ebc002da --- /dev/null +++ b/Runner/suites/Kernel/Baseport/Storage/ufs_gear_check/README.md @@ -0,0 +1,42 @@ +# UFS Gear Validation +## Overview + +This shell script executes on the DUT (Device-Under-Test) and verifies the UFS Gear based on the UFS spec supported by the device on application of load to UFS driver. + +The test script performs these functional checks: + +1. **Kernel Configuration**: + - Validates presence of `CONFIG_SCSI_UFS_QCOM`, `CONFIG_SCSI_UFSHCD` and entries in `/proc/config.gz`. + +2. **Read UFS Specification Version**: + - Reads the UFS specification version from `/sys/devices/platform/soc@0/1d84000.ufs/device_descriptor/specification_version` + - Based on the UFS specification version decides the max operating gear. + +2. **Runtime Verification**: + - Checks `/sys/devices/platform/soc@0/1d84000.ufs/power_info/gear` on application of load whether the operating gear is same as max supported gear. + +## How to Run + +```sh +source init_env +cd suites/Kernel/Baseport/Storage/ufs_gear_lane +./run.sh +``` + +## Prerequisites + +- `dd`, `grep`, `sleep`, `findmnt`, `awk` must be available +- Root access may be required for complete validation + +## Result Format + +Test result will be saved in `ufs_gear_check.res` as: +- `UFS Gear Validation Successful. Test Passed` – if all validations pass +- `UFS Gear did not reach max gear on load. Test Failed` – if any check fails + +## License + +``` +Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +SPDX-License-Identifier: BSD-3-Clause-Clear +``` \ No newline at end of file diff --git a/Runner/suites/Kernel/Baseport/Storage/ufs_gear_check/run.sh b/Runner/suites/Kernel/Baseport/Storage/ufs_gear_check/run.sh new file mode 100755 index 00000000..b2748da1 --- /dev/null +++ b/Runner/suites/Kernel/Baseport/Storage/ufs_gear_check/run.sh @@ -0,0 +1,202 @@ +#!/bin/sh + +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# 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" + break + fi + SEARCH=$(dirname "$SEARCH") +done + +if [ -z "$INIT_ENV" ]; then + echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 + exit 0 +fi + +# Only source if not already loaded +if [ -z "$__INIT_ENV_LOADED" ]; then + # shellcheck disable=SC1090 + . "$INIT_ENV" + export __INIT_ENV_LOADED=1 +fi + +# Always source functestlib.sh +# shellcheck disable=SC1090,SC1091 +. "$TOOLS/functestlib.sh" + +TESTNAME="ufs_gear_check" +test_path=$(find_test_case_by_name "$TESTNAME") +cd "$test_path" || exit 0 +res_file="./$TESTNAME.res" + +log_info "--------------------------------------------------" +log_info "------------- Starting $TESTNAME Test ------------" + +check_dependencies dd grep sleep findmnt awk + +MANDATORY_CONFIGS="CONFIG_SCSI_UFSHCD CONFIG_SCSI_UFS_QCOM" +OPTIONAL_CONFIGS="CONFIG_SCSI_UFSHCD_PLATFORM CONFIG_SCSI_UFSHCD_PCI CONFIG_SCSI_UFS_CDNS_PLATFORM CONFIG_SCSI_UFS_HISI CONFIG_SCSI_UFS_EXYNOS CONFIG_SCSI_UFS_ROCKCHIP CONFIG_SCSI_UFS_BSG" + +log_info "Checking mandatory kernel configs for UFS..." +if ! check_kernel_config "$MANDATORY_CONFIGS" 2>/dev/null; then + log_skip "Missing mandatory UFS kernel configs: $MANDATORY_CONFIGS" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi + +log_info "Checking optional kernel configs for UFS..." +missing_optional="" +for cfg in $OPTIONAL_CONFIGS; do + if ! check_kernel_config "$cfg" 2>/dev/null; then + log_info "[OPTIONAL] $cfg is not enabled" + missing_optional="$missing_optional $cfg" + fi +done +[ -n "$missing_optional" ] && log_info "Optional configs not present but continuing:$missing_optional" + +check_dt_nodes "/sys/bus/platform/devices/*ufs*" || { + echo "$TESTNAME SKIP" > "$res_file" + log_skip "UFS Device Tree nodes not found" + exit 0 +} + +# Get UFS gear based on specification version +get_ufs_gear() { + spec_version="$1" + gear="" + + case "$spec_version" in + 0x0100) # UFS 1.0 + gear="1" + ;; + 0x0110) # UFS 1.1 + gear="1" + ;; + 0x0200) # UFS 2.0 + gear="2" + ;; + 0x0210) # UFS 2.1 + gear="3" + ;; + 0x0220) # UFS 2.2 + gear="3" + ;; + 0x0300) # UFS 3.0 + gear="4" + ;; + 0x0310) # UFS 3.1 + gear="4" + ;; + 0x0400) # UFS 4.0 + gear="5" + ;; + 0x0410) # UFS 4.1 + gear="5" + ;; + *) + log_warn "Unknown UFS specification version: $spec_version" + return 1 + ;; + esac + printf "%s" "$gear" +} + +log_info "Validating UFS Gear on load" + +# Check for UFS Spec Version node and assign to variable +log_info "Checking for UFS device descriptor specification_version node..." +if ! check_dt_nodes "/sys/devices/platform/soc@0/*ufs*/device_descriptor/specification_version"; then + log_skip "UFS device descriptor specification_version node not found" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi + +SPEC_VERSION=$(get_dt_node_path "/sys/devices/platform/soc@0/*ufs*/device_descriptor/specification_version") +if [ -z "$SPEC_VERSION" ]; then + log_skip "Failed to get specification_version node path" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi +log_info "Found specification version node: $SPEC_VERSION" + +# Check for UFS Gear node and assign to variable +log_info "Checking for UFS Gear node..." +if ! check_dt_nodes "/sys/devices/platform/soc@0/*ufs*/power_info/gear"; then + log_skip "UFS Gear status node not found" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi + +GEAR_NODE=$(get_dt_node_path "/sys/devices/platform/soc@0/*ufs*/power_info/gear") +if [ -z "$GEAR_NODE" ]; then + log_skip "Failed to get gear node path" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi +log_info "Found gear node: $GEAR_NODE" + +# Get UFS version and determine expected gear +# shellcheck disable=SC3034 +spec_version_value=$(cat "$SPEC_VERSION" 2>/dev/null) +if [ -z "$spec_version_value" ]; then + log_fail "Failed to read specification version from $SPEC_VERSION" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi +log_info "UFS Specification Version: $spec_version_value" + +EXPECTED_GEAR=$(get_ufs_gear "$spec_version_value") +if [ -z "$EXPECTED_GEAR" ]; then + log_fail "Failed to determine expected gear for spec version $spec_version_value" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi +log_info "Expected UFS Gear: HS_GEAR$EXPECTED_GEAR" + +log_info "Starting I/O load test to verify UFS Gear under load..." +tmpfile="/ufs_gear_check.tmp" + +# Start dd in background +dd if=/dev/zero of="$tmpfile" bs=2M count=1024 >/dev/null 2>&1 & +DD_PID=$! + +# Check gear status during load +log_info "Checking UFS Gear status during load..." +GEAR_STATUS=0 + +# Use check_node_status to verify gear value +if ! check_node_status "$GEAR_NODE" "HS_GEAR$EXPECTED_GEAR" 10 1; then + log_fail "UFS Gear validation failed during load" + GEAR_STATUS=1 +else + log_pass "UFS Gear during load is HS_GEAR$EXPECTED_GEAR" +fi + +# Wait for dd to complete if it's still running +if kill -0 $DD_PID 2>/dev/null; then + log_info "Waiting for I/O load test to complete..." + wait $DD_PID 2>/dev/null + sync +fi + +# Clean up temp file +rm -f "$tmpfile" + +# Verify gear status +if [ "$GEAR_STATUS" -ne 0 ]; then + log_fail "UFS Gear validation failed during load" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + +scan_dmesg_errors "$test_path" "ufs" +log_pass "$TESTNAME completed successfully" +echo "$TESTNAME PASS" > "$res_file" +exit 0 \ No newline at end of file diff --git a/Runner/suites/Kernel/Baseport/Storage/ufs_gear_check/ufs_gear_check.yaml b/Runner/suites/Kernel/Baseport/Storage/ufs_gear_check/ufs_gear_check.yaml new file mode 100644 index 00000000..efec10f3 --- /dev/null +++ b/Runner/suites/Kernel/Baseport/Storage/ufs_gear_check/ufs_gear_check.yaml @@ -0,0 +1,15 @@ +metadata: + name: ufs-gear-check + format: "Lava-Test Test Definition 1.0" + description: "Test the UFS gear on load based on supported UFS specification" + os: + - linux + scope: + - functional + +run: + steps: + - REPO_PATH=$PWD + - cd Runner/suites/Kernel/Baseport/Storage/ufs_gear_check + - ./run.sh || true + - $REPO_PATH/Runner/utils/send-to-lava.sh ufs_gear_check.res || true \ No newline at end of file diff --git a/Runner/suites/Kernel/Baseport/Storage/ufs_hibern8/README.md b/Runner/suites/Kernel/Baseport/Storage/ufs_hibern8/README.md new file mode 100644 index 00000000..e205c6e4 --- /dev/null +++ b/Runner/suites/Kernel/Baseport/Storage/ufs_hibern8/README.md @@ -0,0 +1,45 @@ +# UFS Hibern8 Validation +## Overview + +This shell script executes on the DUT (Device-Under-Test) and verifies the UFS Hibern8/Active state transitions on load and no-load conditions. + +The test script performs these functional checks: + +1. **Kernel Configuration**: + - Validates presence of `CONFIG_SCSI_UFS_QCOM`, `CONFIG_SCSI_UFSHCD` and entries in `/proc/config.gz`. + +2. **UFS Link State Verification**: + - Checks the UFS link state in `/sys/bus/platform/devices/*ufs*/power_info/link_state` + - Verifies the link state is "ACTIVE" during I/O load + - Verifies the link state transitions to "HIBERN8" after an idle period + +3. **Runtime Verification**: + - Generates I/O load using `dd` command and monitors link state + - Creates an idle time to allow Hibern8 entry + - Validates proper state transitions between active and hibernation states + +## How to Run + +```sh +source init_env +cd suites/Kernel/Baseport/Storage/ufs_hibern8 +./run.sh +``` + +## Prerequisites + +- `dd`, `grep`, `dmesg`, `cut`, `head`, `tail`, `udevadm`, `sleep` must be available +- Root access may be required for complete validation + +## Result Format + +Test result will be saved in `ufs_hibern8.res` as: +- `ufs_hibern8 PASS` – if link state is ACTIVE on application of load & HIBERN8 when idle +- `ufs_hibern8 FAIL` – if any check fails + +## License + +``` +Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +SPDX-License-Identifier: BSD-3-Clause-Clear +``` \ No newline at end of file diff --git a/Runner/suites/Kernel/Baseport/Storage/ufs_hibern8/run.sh b/Runner/suites/Kernel/Baseport/Storage/ufs_hibern8/run.sh new file mode 100755 index 00000000..08a6c778 --- /dev/null +++ b/Runner/suites/Kernel/Baseport/Storage/ufs_hibern8/run.sh @@ -0,0 +1,146 @@ +#!/bin/sh +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# 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" + break + fi + SEARCH=$(dirname "$SEARCH") +done + +if [ -z "$INIT_ENV" ]; then + echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 + exit 0 +fi + +# Only source if not already loaded +if [ -z "$__INIT_ENV_LOADED" ]; then + # shellcheck disable=SC1090 + . "$INIT_ENV" + export __INIT_ENV_LOADED=1 +fi + +# Always source functestlib.sh +# shellcheck disable=SC1090,SC1091 +. "$TOOLS/functestlib.sh" + +TESTNAME="ufs_hibern8" +test_path=$(find_test_case_by_name "$TESTNAME") +cd "$test_path" || exit 0 +res_file="./$TESTNAME.res" + +log_info "--------------------------------------------------" +log_info "------------- Starting $TESTNAME Test ------------" + +check_dependencies dd sleep + +MANDATORY_CONFIGS="CONFIG_SCSI_UFSHCD CONFIG_SCSI_UFS_QCOM" +OPTIONAL_CONFIGS="CONFIG_SCSI_UFSHCD_PLATFORM CONFIG_SCSI_UFSHCD_PCI CONFIG_SCSI_UFS_CDNS_PLATFORM CONFIG_SCSI_UFS_HISI CONFIG_SCSI_UFS_EXYNOS CONFIG_SCSI_UFS_ROCKCHIP CONFIG_SCSI_UFS_BSG" + +log_info "Checking mandatory kernel configs for UFS..." +if ! check_kernel_config "$MANDATORY_CONFIGS" 2>/dev/null; then + log_skip "Missing mandatory UFS kernel configs: $MANDATORY_CONFIGS" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi + +log_info "Checking optional kernel configs for UFS..." +missing_optional="" +for cfg in $OPTIONAL_CONFIGS; do + if ! check_kernel_config "$cfg" 2>/dev/null; then + log_info "[OPTIONAL] $cfg is not enabled" + missing_optional="$missing_optional $cfg" + fi +done +[ -n "$missing_optional" ] && log_info "Optional configs not present but continuing:$missing_optional" + +check_dt_nodes "/sys/bus/platform/devices/*ufs*" || { + echo "$TESTNAME SKIP" > "$res_file" + log_skip "UFS Device Tree nodes not found" + exit 0 +} + +block_dev=$(detect_ufs_partition_block) +if [ -z "$block_dev" ]; then + log_skip "No UFS block device found." + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi +log_info "Detected UFS block: $block_dev" + +log_info "Validating UFS link state on load & no-load conditions" + +# Check for UFS link state node and assign to variable +log_info "Checking for UFS link state node..." +if ! check_dt_nodes "/sys/bus/platform/devices/*ufs*/power_info/link_state"; then + log_skip "UFS link state node not found" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi + +LINK_STATE_NODE=$(get_dt_node_path "/sys/bus/platform/devices/*ufs*/power_info/link_state") +if [ -z "$LINK_STATE_NODE" ]; then + log_skip "Failed to get UFS link state node path" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi +log_info "Found UFS link state node: $LINK_STATE_NODE" + +# Generate load using dd command and check for ACTIVE state +log_info "Starting I/O load test to verify UFS link state transitions..." +tmpfile="/ufs_hibern8_test.tmp" + +# Start dd in background +dd if=/dev/zero of="$tmpfile" bs=2M count=1024 >/dev/null 2>&1 & +DD_PID=$! + +log_info "Checking UFS link state during load..." +LINK_STATUS_CHECK_LOAD=0 + +# Use check_node_status to verify ufs link state +if ! check_node_status "$LINK_STATE_NODE" "ACTIVE" 10 1; then + log_fail "UFS link state validation failed during load" + LINK_STATUS_CHECK_LOAD=1 +else + log_pass "UFS link state during load is ACTIVE" +fi + +# Wait for dd to complete if it's still running +if kill -0 $DD_PID 2>/dev/null; then + log_info "Waiting for I/O load test to complete..." + wait $DD_PID 2>/dev/null + sync +fi + +# Clean up temp file +rm -f "$tmpfile" + +# Wait for 180 seconds for Hibern8 entry +log_info "Waiting 180 seconds for UFS to enter Hibern8 state..." +sleep 180 + +LINK_STATUS_CHECK_NO_LOAD=0 +# Use check_node_status to verify link state is HIBERN8 +if ! check_node_status "$LINK_STATE_NODE" "HIBERN8" 2 1; then + log_fail "UFS link state validation failed without load" + LINK_STATUS_CHECK_NO_LOAD=1 +else + log_pass "UFS link state without load is HIBERN8" +fi + +if [ "$LINK_STATUS_CHECK_LOAD" -ne 0 ] || [ "$LINK_STATUS_CHECK_NO_LOAD" -ne 0 ]; then + log_fail "UFS ACTIVE/HIBERN8 test failed" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + +scan_dmesg_errors "$test_path" "ufs" +log_pass "$TESTNAME completed successfully" +echo "$TESTNAME PASS" > "$res_file" +exit 0 \ No newline at end of file diff --git a/Runner/suites/Kernel/Baseport/Storage/ufs_hibern8/ufs_hibern8.yaml b/Runner/suites/Kernel/Baseport/Storage/ufs_hibern8/ufs_hibern8.yaml new file mode 100644 index 00000000..a5493d9a --- /dev/null +++ b/Runner/suites/Kernel/Baseport/Storage/ufs_hibern8/ufs_hibern8.yaml @@ -0,0 +1,15 @@ +metadata: + name: ufs-hibern8 + format: "Lava-Test Test Definition 1.0" + description: "Verify the UFS link hibern8" + os: + - linux + scope: + - functional + +run: + steps: + - REPO_PATH=$PWD + - cd Runner/suites/Kernel/Baseport/Storage/ufs_hibern8 + - ./run.sh || true + - $REPO_PATH/Runner/utils/send-to-lava.sh ufs_hibern8.res || true \ No newline at end of file diff --git a/Runner/suites/Kernel/Baseport/Storage/ufs_read_writes/README.md b/Runner/suites/Kernel/Baseport/Storage/ufs_read_writes/README.md new file mode 100644 index 00000000..55dc94c4 --- /dev/null +++ b/Runner/suites/Kernel/Baseport/Storage/ufs_read_writes/README.md @@ -0,0 +1,43 @@ +# UFS Read/Writes +## Overview + +This shell script executes on the DUT (Device-Under-Test) and verifies whether basic UFS file read writes are functional. + +The test script performs these functional checks: + +1. **Kernel Configuration**: + - Validates presence of `CONFIG_SCSI_UFS_QCOM`, `CONFIG_SCSI_UFSHCD` and entries in `/proc/config.gz`. + +2. **UFS Block Device Detection**: + - Detects UFS block devices using `detect_ufs_partition_block()` + - Verifies the detected block is not the root filesystem + +3. **Runtime Verification**: + - Performs basic read test on the UFS block device using `dd` + - Runs I/O stress test with 64MB read and write operations on a temporary file + +## How to Run + +```sh +source init_env +cd suites/Kernel/Baseport/Storage/ufs_read_writes +./run.sh +``` + +## Prerequisites + +- `dd`, `grep`, `cut`, `head`, `tail`, `udevadm` must be available +- Root access may be required for complete validation + +## Result Format + +Test result will be saved in `ufs_read_writes.res` as: +- `ufs_read_writes PASS` – if read/writes are successful +- `ufs_read_writes FAIL` – if any check fails + +## License + +``` +Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +SPDX-License-Identifier: BSD-3-Clause-Clear +``` \ No newline at end of file diff --git a/Runner/suites/Kernel/Baseport/Storage/ufs_read_writes/run.sh b/Runner/suites/Kernel/Baseport/Storage/ufs_read_writes/run.sh new file mode 100755 index 00000000..341bcdab --- /dev/null +++ b/Runner/suites/Kernel/Baseport/Storage/ufs_read_writes/run.sh @@ -0,0 +1,147 @@ +#!/bin/sh + +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# 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" + break + fi + SEARCH=$(dirname "$SEARCH") +done + +if [ -z "$INIT_ENV" ]; then + echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 + exit 0 +fi + +# Only source if not already loaded +if [ -z "$__INIT_ENV_LOADED" ]; then + # shellcheck disable=SC1090 + . "$INIT_ENV" + export __INIT_ENV_LOADED=1 +fi + +# Always source functestlib.sh +# shellcheck disable=SC1090,SC1091 +. "$TOOLS/functestlib.sh" + +TESTNAME="ufs_read_writes" +test_path=$(find_test_case_by_name "$TESTNAME") +cd "$test_path" || exit 0 +res_file="./$TESTNAME.res" + +log_info "--------------------------------------------------" +log_info "------------- Starting $TESTNAME Test ------------" + +check_dependencies dd + +MANDATORY_CONFIGS="CONFIG_SCSI_UFSHCD CONFIG_SCSI_UFS_QCOM" +OPTIONAL_CONFIGS="CONFIG_SCSI_UFSHCD_PLATFORM CONFIG_SCSI_UFSHCD_PCI CONFIG_SCSI_UFS_CDNS_PLATFORM CONFIG_SCSI_UFS_HISI CONFIG_SCSI_UFS_EXYNOS CONFIG_SCSI_UFS_ROCKCHIP CONFIG_SCSI_UFS_BSG" + +log_info "Checking mandatory kernel configs for UFS..." +if ! check_kernel_config "$MANDATORY_CONFIGS" 2>/dev/null; then + log_skip "Missing mandatory UFS kernel configs: $MANDATORY_CONFIGS" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi + +log_info "Checking optional kernel configs for UFS..." +missing_optional="" +for cfg in $OPTIONAL_CONFIGS; do + if ! check_kernel_config "$cfg" 2>/dev/null; then + log_info "[OPTIONAL] $cfg is not enabled" + missing_optional="$missing_optional $cfg" + fi +done +[ -n "$missing_optional" ] && log_info "Optional configs not present but continuing:$missing_optional" + +check_dt_nodes "/sys/bus/platform/devices/*ufs*" || { + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +} + +block_dev=$(detect_ufs_partition_block) +if [ -z "$block_dev" ]; then + log_skip "No UFS block device found." + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi +log_info "Detected UFS block: $block_dev" + +if command -v findmnt >/dev/null 2>&1; then + rootfs_dev=$(findmnt -n -o SOURCE /) +else + log_warn "findmnt not available, using fallback rootfs detection" + rootfs_dev=$(awk '$2 == "/" { print $1 }' /proc/mounts) +fi + +resolved_block=$(readlink -f "$block_dev" 2>/dev/null) +resolved_rootfs=$(readlink -f "$rootfs_dev" 2>/dev/null) + +if [ -n "$resolved_block" ] && [ -n "$resolved_rootfs" ] && [ "$resolved_block" = "$resolved_rootfs" ]; then + log_warn "Detected block ($resolved_block) is the root filesystem. Skipping read test." + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi + +log_info "Running basic read test on $block_dev (non-rootfs)..." +if echo | dd of=/dev/null iflag=direct 2>/dev/null; then + DD_CMD="dd if=$block_dev of=/dev/null bs=1M count=32 iflag=direct" +else + log_warn "'iflag=direct' not supported by dd. Falling back to standard dd." + DD_CMD="dd if=$block_dev of=/dev/null bs=1M count=32" +fi + +if $DD_CMD >/dev/null 2>&1; then + log_pass "UFS read test succeeded" +else + log_fail "UFS read test failed" + log_info "Try manually: $DD_CMD" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + +log_info "Running I/O stress test (64MB read+write on tmpfile)..." +tmpfile="$test_path/ufs_test.img" + +if echo | dd of=/dev/null conv=fsync 2>/dev/null; then + DD_WRITE="dd if=/dev/zero of=$tmpfile bs=1M count=64 conv=fsync" +else + log_warn "'conv=fsync' not supported by dd. Using basic write." + DD_WRITE="dd if=/dev/zero of=$tmpfile bs=1M count=64" +fi + +if $DD_WRITE >/dev/null 2>&1 && + dd if="$tmpfile" of=/dev/null bs=1M count=64 >/dev/null 2>&1; then + log_pass "UFS I/O stress test passed" + if command -v stat >/dev/null 2>&1; then + stat --format="[INFO] Size: %s bytes File: %n" "$tmpfile" + else + find "$tmpfile" -printf "[INFO] Size: %s bytes File: %p\n" + fi + rm -f "$tmpfile" +else + log_fail "UFS I/O stress test failed" + df -h . | sed 's/^/[INFO] /' + if [ -f "$tmpfile" ]; then + if command -v stat >/dev/null 2>&1; then + stat --format="[INFO] Size: %s bytes File: %n" "$tmpfile" + else + find "$tmpfile" -printf "[INFO] Size: %s bytes File: %p\n" + fi + rm -f "$tmpfile" + fi + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + +scan_dmesg_errors "$test_path" "ufs" +log_pass "$TESTNAME completed successfully" +echo "$TESTNAME PASS" > "$res_file" +exit 0 \ No newline at end of file diff --git a/Runner/suites/Kernel/Baseport/Storage/ufs_read_writes/ufs_read_writes.yaml b/Runner/suites/Kernel/Baseport/Storage/ufs_read_writes/ufs_read_writes.yaml new file mode 100644 index 00000000..b2e6faeb --- /dev/null +++ b/Runner/suites/Kernel/Baseport/Storage/ufs_read_writes/ufs_read_writes.yaml @@ -0,0 +1,15 @@ +metadata: + name: ufs-read-writes + format: "Lava-Test Test Definition 1.0" + description: "Test file I/O on UFS device using dd command" + os: + - linux + scope: + - functional + +run: + steps: + - REPO_PATH=$PWD + - cd Runner/suites/Kernel/Baseport/Storage/ufs_read_writes + - ./run.sh || true + - $REPO_PATH/Runner/utils/send-to-lava.sh ufs_read_writes.res || true \ No newline at end of file diff --git a/Runner/suites/Kernel/Baseport/Storage/ufs_runtime_suspend_resume/README.md b/Runner/suites/Kernel/Baseport/Storage/ufs_runtime_suspend_resume/README.md new file mode 100644 index 00000000..ce813b99 --- /dev/null +++ b/Runner/suites/Kernel/Baseport/Storage/ufs_runtime_suspend_resume/README.md @@ -0,0 +1,45 @@ +# UFS Runtime Suspend/Resume Validation +## Overview + +This shell script executes on the DUT (Device-Under-Test) and verifies the UFS Runtime Suspend/Resume functionality on load and no-load conditions. + +The test script performs these functional checks: + +1. **Kernel Configuration**: + - Validates presence of `CONFIG_SCSI_UFS_QCOM`, `CONFIG_SCSI_UFSHCD` and entries in `/proc/config.gz`. + +2. **UFS Runtime Status Verification**: + - Checks the UFS runtime status in `/sys/devices/platform/soc@0/*ufs*/power/runtime_status` + - Verifies the runtime status is "active" during I/O load + - Verifies the runtime status transitions to "suspended" after an idle period + +3. **Runtime Verification**: + - Generates I/O load using `dd` command and monitors runtime status + - Creates an idle time to allow runtime suspend + - Validates proper state transitions between active and suspended states + +## How to Run + +```sh +source init_env +cd suites/Kernel/Baseport/Storage/ufs_runtime_suspend_resume +./run.sh +``` + +## Prerequisites + +- `dd`, `grep`, `cut`, `head`, `tail`, `udevadm`, `sleep` must be available +- Root access may be required for complete validation + +## Result Format + +Test result will be saved in `ufs_runtime_suspend_resume.res` as: +- `ufs_runtime_suspend_resume PASS` – if runtime status is active on application of load & suspended when idle +- `ufs_runtime_suspend_resume FAIL` – if any check fails + +## License + +``` +Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +SPDX-License-Identifier: BSD-3-Clause-Clear +``` \ No newline at end of file diff --git a/Runner/suites/Kernel/Baseport/Storage/ufs_runtime_suspend_resume/run.sh b/Runner/suites/Kernel/Baseport/Storage/ufs_runtime_suspend_resume/run.sh new file mode 100755 index 00000000..932e244b --- /dev/null +++ b/Runner/suites/Kernel/Baseport/Storage/ufs_runtime_suspend_resume/run.sh @@ -0,0 +1,147 @@ +#!/bin/sh +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# 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" + break + fi + SEARCH=$(dirname "$SEARCH") +done + +if [ -z "$INIT_ENV" ]; then + echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 + exit 0 +fi + +# Only source if not already loaded +if [ -z "$__INIT_ENV_LOADED" ]; then + # shellcheck disable=SC1090 + . "$INIT_ENV" + export __INIT_ENV_LOADED=1 +fi + +# Always source functestlib.sh +# shellcheck disable=SC1090,SC1091 +. "$TOOLS/functestlib.sh" + +TESTNAME="ufs_runtime_suspend_resume" +test_path=$(find_test_case_by_name "$TESTNAME") +cd "$test_path" || exit 0 +res_file="./$TESTNAME.res" + +log_info "--------------------------------------------------" +log_info "------------- Starting $TESTNAME Test ------------" + +check_dependencies dd sleep + +MANDATORY_CONFIGS="CONFIG_SCSI_UFSHCD CONFIG_SCSI_UFS_QCOM" +OPTIONAL_CONFIGS="CONFIG_SCSI_UFSHCD_PLATFORM CONFIG_SCSI_UFSHCD_PCI CONFIG_SCSI_UFS_CDNS_PLATFORM CONFIG_SCSI_UFS_HISI CONFIG_SCSI_UFS_EXYNOS CONFIG_SCSI_UFS_ROCKCHIP CONFIG_SCSI_UFS_BSG" + +log_info "Checking mandatory kernel configs for UFS..." +if ! check_kernel_config "$MANDATORY_CONFIGS" 2>/dev/null; then + log_skip "Missing mandatory UFS kernel configs: $MANDATORY_CONFIGS" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi + +log_info "Checking optional kernel configs for UFS..." +missing_optional="" +for cfg in $OPTIONAL_CONFIGS; do + if ! check_kernel_config "$cfg" 2>/dev/null; then + log_info "[OPTIONAL] $cfg is not enabled" + missing_optional="$missing_optional $cfg" + fi +done +[ -n "$missing_optional" ] && log_info "Optional configs not present but continuing:$missing_optional" + +check_dt_nodes "/sys/bus/platform/devices/*ufs*" || { + echo "$TESTNAME SKIP" > "$res_file" + log_skip "UFS Device Tree nodes not found" + exit 0 +} + +block_dev=$(detect_ufs_partition_block) +if [ -z "$block_dev" ]; then + log_skip "No UFS block device found." + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi +log_info "Detected UFS block: $block_dev" + + +log_info "Validating UFS Runtime Suspend/Resume on load & no-load conditions" + +# Check for UFS runtime status node and assign to variable +log_info "Checking for UFS runtime status node..." +if ! check_dt_nodes "/sys/devices/platform/soc@0/*ufs*/power/runtime_status"; then + log_skip "UFS runtime status node not found" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi + +RUNTIME_STATUS_NODE=$(get_dt_node_path "/sys/devices/platform/soc@0/*ufs*/power/runtime_status") +if [ -z "$RUNTIME_STATUS_NODE" ]; then + log_skip "Failed to get runtime status node path" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi +log_info "Found runtime status node: $RUNTIME_STATUS_NODE" + +# Generate load using dd command and check for active state +log_info "Starting I/O load test to verify UFS runtime active state..." +tmpfile="/ufs_runtime_test.tmp" + +# Start dd in background +dd if=/dev/zero of="$tmpfile" bs=2M count=1024 >/dev/null 2>&1 & +DD_PID=$! + +log_info "Checking UFS runtime status during load..." +RUNTIME_STATUS_CHECK_LOAD=0 + +# Use check_node_status to verify ufs if ufs runtime status is active +if ! check_node_status "$RUNTIME_STATUS_NODE" "active" 10 1; then + log_fail "UFS runtime status validation failed during load" + RUNTIME_STATUS_CHECK_LOAD=1 +else + log_pass "UFS runtime status during load is active" +fi + +# Wait for dd to complete if it's still running +if kill -0 $DD_PID 2>/dev/null; then + log_info "Waiting for I/O load test to complete..." + wait $DD_PID 2>/dev/null + sync +fi + +# Clean up temp file +rm -f "$tmpfile" + +# Wait for 180 seconds for UFS to enter suspended state +log_info "Waiting 180 seconds for UFS to enter suspended state..." +sleep 180 + +RUNTIME_STATUS_CHECK_NO_LOAD=0 +# Use check_node_status to verify ufs runtime status is suspended +if ! check_node_status "$RUNTIME_STATUS_NODE" "suspended" 2 1; then + log_fail "UFS runtime status validation failed without load" + RUNTIME_STATUS_CHECK_NO_LOAD=1 +else + log_pass "UFS runtime status without load is suspended" +fi + +if [ "$RUNTIME_STATUS_CHECK_LOAD" -ne 0 ] || [ "$RUNTIME_STATUS_CHECK_NO_LOAD" -ne 0 ]; then + log_fail "UFS active/suspended test failed" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + +scan_dmesg_errors "$test_path" "ufs" +log_pass "$TESTNAME completed successfully" +echo "$TESTNAME PASS" > "$res_file" +exit 0 \ No newline at end of file diff --git a/Runner/suites/Kernel/Baseport/Storage/ufs_runtime_suspend_resume/ufs_runtime_suspend_resume.yaml b/Runner/suites/Kernel/Baseport/Storage/ufs_runtime_suspend_resume/ufs_runtime_suspend_resume.yaml new file mode 100644 index 00000000..bf25e319 --- /dev/null +++ b/Runner/suites/Kernel/Baseport/Storage/ufs_runtime_suspend_resume/ufs_runtime_suspend_resume.yaml @@ -0,0 +1,15 @@ +metadata: + name: ufs-runtime-suspend-resume + format: "Lava-Test Test Definition 1.0" + description: "Verify UFS Runtime suspend/resume during load and without load" + os: + - linux + scope: + - functional + +run: + steps: + - REPO_PATH=$PWD + - cd Runner/suites/Kernel/Baseport/Storage/ufs_runtime_suspend_resume + - ./run.sh || true + - $REPO_PATH/Runner/utils/send-to-lava.sh ufs_runtime_suspend_resume.res || true \ No newline at end of file diff --git a/Runner/suites/Kernel/Baseport/Storage/ufs_write_booster/README.md b/Runner/suites/Kernel/Baseport/Storage/ufs_write_booster/README.md new file mode 100644 index 00000000..f0b927a7 --- /dev/null +++ b/Runner/suites/Kernel/Baseport/Storage/ufs_write_booster/README.md @@ -0,0 +1,43 @@ +# UFS Write Booster Validation +## Overview + +This shell script executes on the DUT (Device-Under-Test) and verifies the UFS Write Booster feature activation on application of write load to UFS driver. + +The test script performs these functional checks: + +1. **Kernel Configuration**: + - Validates presence of `CONFIG_SCSI_UFS_QCOM`, `CONFIG_SCSI_UFSHCD` and entries in `/proc/config.gz`. + +2. **Read UFS Specification Version**: + - Reads the UFS specification version from `/sys/devices/platform/soc@0/*ufs*/device_descriptor/specification_version` + - Verifies the UFS specification version is 3.1 (0x0310) or higher, which supports Write Booster feature + +3. **Runtime Verification**: + - Checks `/sys/devices/platform/soc@0/*ufs*/devfreq/*ufs*/device/wb_on` on application of load + - Verifies Write Booster is enabled (value = 1) during write operations + +## How to Run + +```sh +source init_env +cd suites/Kernel/Baseport/Storage/ufs_write_booster +./run.sh +``` + +## Prerequisites + +- `dd`, `grep`, `cut`, `head`, `tail`, `udevadm`, `sleep` must be available +- Root access may be required for complete validation + +## Result Format + +Test result will be saved in `ufs_write_booster.res` as: +- `ufs_write_booster PASS` – if Write Booster is enabled during write operations +- `ufs_write_booster FAIL` – if any check fails + +## License + +``` +Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +SPDX-License-Identifier: BSD-3-Clause-Clear +``` \ No newline at end of file diff --git a/Runner/suites/Kernel/Baseport/Storage/ufs_write_booster/run.sh b/Runner/suites/Kernel/Baseport/Storage/ufs_write_booster/run.sh new file mode 100755 index 00000000..7e50f777 --- /dev/null +++ b/Runner/suites/Kernel/Baseport/Storage/ufs_write_booster/run.sh @@ -0,0 +1,188 @@ +#!/bin/sh +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# 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" + break + fi + SEARCH=$(dirname "$SEARCH") +done + +if [ -z "$INIT_ENV" ]; then + echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 + exit 0 +fi + +# Only source if not already loaded +if [ -z "$__INIT_ENV_LOADED" ]; then + # shellcheck disable=SC1090 + . "$INIT_ENV" + export __INIT_ENV_LOADED=1 +fi + +# Always source functestlib.sh +# shellcheck disable=SC1090,SC1091 +. "$TOOLS/functestlib.sh" + +TESTNAME="ufs_write_booster" +test_path=$(find_test_case_by_name "$TESTNAME") +cd "$test_path" || exit 0 +res_file="./$TESTNAME.res" + +log_info "--------------------------------------------------" +log_info "------------- Starting $TESTNAME Test ------------" + +check_dependencies dd + +MANDATORY_CONFIGS="CONFIG_SCSI_UFSHCD CONFIG_SCSI_UFS_QCOM" +OPTIONAL_CONFIGS="CONFIG_SCSI_UFSHCD_PLATFORM CONFIG_SCSI_UFSHCD_PCI CONFIG_SCSI_UFS_CDNS_PLATFORM CONFIG_SCSI_UFS_HISI CONFIG_SCSI_UFS_EXYNOS CONFIG_SCSI_UFS_ROCKCHIP CONFIG_SCSI_UFS_BSG" + +log_info "Checking mandatory kernel configs for UFS..." +if ! check_kernel_config "$MANDATORY_CONFIGS" 2>/dev/null; then + log_skip "Missing mandatory UFS kernel configs: $MANDATORY_CONFIGS" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi + +log_info "Checking optional kernel configs for UFS..." +missing_optional="" +for cfg in $OPTIONAL_CONFIGS; do + if ! check_kernel_config "$cfg" 2>/dev/null; then + log_info "[OPTIONAL] $cfg is not enabled" + missing_optional="$missing_optional $cfg" + fi +done +[ -n "$missing_optional" ] && log_info "Optional configs not present but continuing:$missing_optional" + +check_dt_nodes "/sys/bus/platform/devices/*ufs*" || { + echo "$TESTNAME SKIP" > "$res_file" + log_skip "UFS Device Tree nodes not found" + exit 0 +} + +block_dev=$(detect_ufs_partition_block) +if [ -z "$block_dev" ]; then + log_skip "No UFS block device found." + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi +log_info "Detected UFS block: $block_dev" + +# Function to compare UFS specification versions +# Returns 0 if version1 >= version2, 1 otherwise +compare_ufs_version() { + version1="$1" + version2="$2" + + # Convert hex to decimal for comparison + ver1_dec=$((version1)) + ver2_dec=$((version2)) + + if [ "$ver1_dec" -ge "$ver2_dec" ]; then + return 0 + else + return 1 + fi +} + +log_info "Validating UFS Write Booster feature" + +# Check for UFS Spec Version node and assign to variable +log_info "Checking for UFS device descriptor specification_version node..." +if ! check_dt_nodes "/sys/devices/platform/soc@0/*ufs*/device_descriptor/specification_version"; then + log_skip "UFS device descriptor specification_version node not found" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi + +SPEC_VERSION=$(get_dt_node_path "/sys/devices/platform/soc@0/*ufs*/device_descriptor/specification_version") +if [ -z "$SPEC_VERSION" ]; then + log_skip "Failed to get specification_version node path" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi +log_info "Found specification version node: $SPEC_VERSION" + +# Get UFS version +spec_version_value=$(cat "$SPEC_VERSION" 2>/dev/null) +if [ -z "$spec_version_value" ]; then + log_fail "Failed to read specification version from $SPEC_VERSION" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi +log_info "UFS Specification Version: $spec_version_value" + +# Check if UFS version is 3.1 or higher (0x0310) +if ! compare_ufs_version "$spec_version_value" "0x0310"; then + log_skip "Write booster feature is supported from and after UFS spec 3.1" + log_info "Current UFS spec version: $spec_version_value (Required: >= 0x0310)" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi + +log_info "UFS spec version $spec_version_value supports Write Booster feature" + +# Check for Write Booster status node +log_info "Checking for UFS Write Booster status node..." +if ! check_dt_nodes "/sys/devices/platform/soc@0/*ufs*/devfreq/*ufs*/device/wb_on"; then + log_skip "UFS Write Booster status node not found" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi + +WB_STATUS_NODE=$(get_dt_node_path "/sys/devices/platform/soc@0/*ufs*/devfreq/*ufs*/device/wb_on") +if [ -z "$WB_STATUS_NODE" ]; then + log_skip "Failed to get Write Booster status node path" + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi +log_info "Found Write Booster status node: $WB_STATUS_NODE" + +# Generate load using dd command and check Write Booster status +log_info "Starting I/O load test to verify Write Booster activation..." +tmpfile="/ufs_wb_test.tmp" + +# Start dd in background +dd if=/dev/zero of="$tmpfile" bs=2M count=1024 >/dev/null 2>&1 & +DD_PID=$! + +log_info "Checking Write Booster Activation on UFS Write" +WB_STATUS_CHECK=0 + +# Use check_node_status to verify whether UFS WB is enabled +if ! check_node_status "$WB_STATUS_NODE" "1" 5 1; then + log_fail "UFS Write Booster is disabled during write" + WB_STATUS_CHECK=1 +else + log_pass "UFS Write Booster is enabled during write" +fi + +# Wait for dd to complete if it's still running +if kill -0 $DD_PID 2>/dev/null; then + log_info "Waiting for I/O load test to complete..." + wait $DD_PID 2>/dev/null + sync +fi + +# Clean up temp file +rm -f "$tmpfile" + +if [ "$WB_STATUS_CHECK" -ne 0 ]; then + log_fail "UFS Write Booster Test Failed" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + +# Final validation +log_pass "UFS Write Booster validation passed" + +scan_dmesg_errors "$test_path" "ufs" +log_pass "$TESTNAME completed successfully" +echo "$TESTNAME PASS" > "$res_file" +exit 0 \ No newline at end of file diff --git a/Runner/suites/Kernel/Baseport/Storage/ufs_write_booster/ufs_write_booster.yaml b/Runner/suites/Kernel/Baseport/Storage/ufs_write_booster/ufs_write_booster.yaml new file mode 100644 index 00000000..da6f623e --- /dev/null +++ b/Runner/suites/Kernel/Baseport/Storage/ufs_write_booster/ufs_write_booster.yaml @@ -0,0 +1,16 @@ +metadata: + name: ufs-write-booster + format: "Lava-Test Test Definition 1.0" + description: "Check whether UFS Write Booster is enabled on UFS writes" + os: + - linux + scope: + - functional + +run: + steps: + - REPO_PATH=$PWD + - cd Runner/suites/Kernel/Baseport/Storage/ufs_write_booster + - ./run.sh || true + - $REPO_PATH/Runner/utils/send-to-lava.sh ufs_write_booster.res || true + diff --git a/Runner/utils/functestlib.sh b/Runner/utils/functestlib.sh index 55feae5e..fb52798c 100755 --- a/Runner/utils/functestlib.sh +++ b/Runner/utils/functestlib.sh @@ -4293,3 +4293,59 @@ get_pid() { return 1 fi } + +# Function to get the first matching node path +get_dt_node_path() { + node_pattern="$1" + found_node="" + + for node in $node_pattern; do + if [ -d "$node" ] || [ -f "$node" ]; then + found_node="$node" + break + fi + done + + printf "%s" "$found_node" +} + +# Function to check node status with retries by reading from a file +check_node_status() { + node_name="$1" + expected_status="$2" + retries="$3" + delay="$4" + + # Default values if not provided + [ -z "$retries" ] && retries=5 + [ -z "$delay" ] && delay=1 + + attempt=1 + + echo "Checking status of node '$node_name', expecting: '$expected_status'" + echo "Will retry up to $retries times with $delay second(s) delay between attempts" + + while [ "$attempt" -le "$retries" ]; do + echo "Attempt $attempt of $retries..." + + # Get node status by directly reading from the file with the node's name + status=$(cat "$node_name") + + if [ "$status" = "$expected_status" ]; then + echo "Success! Node '$node_name' has status: '$status'" + return 0 + else + echo "Current status: '$status', waiting for: '$expected_status'" + + if [ "$attempt" -lt "$retries" ]; then + echo "Retrying in $delay second(s)..." + sleep "$delay" + fi + fi + + attempt=$((attempt + 1)) + done + + echo "Failed after $retries attempts. Last status: '$status', expected: '$expected_status'" + return 1 +} \ No newline at end of file