-
Notifications
You must be signed in to change notification settings - Fork 25
Added UFS functional tests #220
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
base: main
Are you sure you want to change the base?
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 |
|---|---|---|
|
|
@@ -48,6 +48,16 @@ run: | |
| - $PWD/utils/send-to-lava.sh $PWD/suites/Kernel/Baseport/smmu/smmu.res || true | ||
| - $PWD/suites/Kernel/Baseport/Storage/UFS_Validation/run.sh || true | ||
| - $PWD/utils/send-to-lava.sh $PWD/suites/Kernel/Baseport/Storage/UFS_Validation/UFS_Validation.res || true | ||
| - $PWD/suites/Kernel/Baseport/Storage/ufs_gear_lane/run.sh || true | ||
| - $PWD/utils/send-to-lava.sh $PWD/suites/Kernel/Baseport/Storage/ufs_gear_lane/ufs_gear_lane.res || true | ||
| - $PWD/suites/Kernel/Baseport/Storage/ufs_hibern8/run.sh || true | ||
| - $PWD/utils/send-to-lava.sh $PWD/suites/Kernel/Baseport/Storage/ufs_hibern8/ufs_hibern8.res || true | ||
| - $PWD/suites/Kernel/Baseport/Storage/ufs_read_writes/run.sh || true | ||
| - $PWD/utils/send-to-lava.sh $PWD/suites/Kernel/Baseport/Storage/ufs_read_writes/ufs_read_writes.res || true | ||
| - $PWD/suites/Kernel/Baseport/Storage/ufs_runtime_suspend_resume/run.sh || true | ||
| - $PWD/utils/send-to-lava.sh $PWD/suites/Kernel/Baseport/Storage/ufs_runtime_suspend_resume/ufs_runtime_suspend_resume.res || true | ||
| - $PWD/suites/Kernel/Baseport/Storage/ufs_write_booster/run.sh || true | ||
| - $PWD/utils/send-to-lava.sh $PWD/suites/Kernel/Baseport/Storage/ufs_write_booster/ufs_write_booster.res || true | ||
|
Contributor
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. I suggest enabling these tests in qcom-next instead of meta-qcom. |
||
| - $PWD/suites/Kernel/Baseport/wpss_remoteproc/run.sh || true | ||
| - $PWD/utils/send-to-lava.sh $PWD/suites/Kernel/Baseport/wpss_remoteproc/wpss_remoteproc.res || true | ||
| - $PWD/suites/Kernel/DCVS/Freq_Scaling/run.sh || true | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| # UFS Gear/Lane Validation | ||
| ## Overview | ||
|
|
||
| This shell script executes on the DUT (Device-Under-Test) and verifies the UFS Gear & Lane 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`, `dmesg`, `lsmod`, `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_gear_lane.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 | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,266 @@ | ||
| #!/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 1 | ||
| fi | ||
|
|
||
| # Only source if not already loaded | ||
| if [ -z "$__INIT_ENV_LOADED" ]; then | ||
| # shellcheck disable=SC1090 | ||
| . "$INIT_ENV" | ||
|
Contributor
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. you never set __INIT_ENV_LOADED, so this guard is effectively useless if this script is ever sourced again. |
||
| fi | ||
|
|
||
| # Always source functestlib.sh | ||
| # shellcheck disable=SC1090,SC1091 | ||
| . "$TOOLS/functestlib.sh" | ||
|
|
||
| TESTNAME="ufs_gear_lane" | ||
| test_path=$(find_test_case_by_name "$TESTNAME") | ||
| cd "$test_path" || exit 1 | ||
| res_file="./$TESTNAME.res" | ||
|
|
||
| log_info "--------------------------------------------------" | ||
| log_info "------------- Starting $TESTNAME Test ------------" | ||
|
|
||
| check_dependencies dd grep cut head tail udevadm sleep | ||
|
Contributor
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. cut, head, tail, udevadm are not used anywhere in this script. You do use findmnt and awk, and rely on readlink (though that's almost always present) |
||
|
|
||
| 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 | ||
|
Contributor
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. "$MANDATORY_CONFIGS" is one arugment with a space inside, not two config names. That'll fail. |
||
| 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" | ||
|
Contributor
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. Include log_skip so it is visible to the user. |
||
| exit 0 | ||
| } | ||
|
|
||
| block_dev=$(detect_ufs_partition_block) | ||
|
Contributor
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. Never used $block_dev for the load. |
||
| 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 | ||
|
|
||
| # Function to get the first matching node path | ||
| get_dt_node_path() { | ||
|
Contributor
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. Move all functions to functestlib.sh |
||
| 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" | ||
| } | ||
|
|
||
| # 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 & Lane on load & no-load conditions" | ||
|
|
||
| # 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" | ||
|
|
||
| # Check for UFS Lane node and assign to variable | ||
| log_info "Checking for UFS Lane node..." | ||
| if ! check_dt_nodes "/sys/devices/platform/soc@0/*ufs*/power_info/lane"; then | ||
| log_skip "UFS Lane status node not found" | ||
| echo "$TESTNAME SKIP" > "$res_file" | ||
| exit 0 | ||
| fi | ||
|
|
||
| LANE_NODE=$(get_dt_node_path "/sys/devices/platform/soc@0/*ufs*/power_info/lane") | ||
| if [ -z "$LANE_NODE" ]; then | ||
| log_skip "Failed to get lane node path" | ||
| echo "$TESTNAME SKIP" > "$res_file" | ||
| exit 0 | ||
| fi | ||
| log_info "Found lane node: $LANE_NODE" | ||
|
|
||
| # Get UFS version and determine expected gear | ||
| spec_version_value=$(cat "$SPEC_VERSION" 2>/dev/null) | ||
|
Contributor
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. "No cat" polish. you can avoid shellcheck SC2002. |
||
| if [ -z "$spec_version_value" ]; then | ||
| log_fail "Failed to read specification version from $SPEC_VERSION" | ||
| echo "$TESTNAME FAIL" > "$res_file" | ||
| exit 1 | ||
| fi | ||
| log_info "UFS Specification Version: $spec_version_value" | ||
|
|
||
| EXPECTED_GEAR=$(get_ufs_gear "$spec_version_value") | ||
|
Contributor
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. on unknow spec version you do return 1 -> test FAILs. If you want to treat truly unknow future UFS versions as "cannot valiate -> SKIP". |
||
| if [ -z "$EXPECTED_GEAR" ]; then | ||
| log_fail "Failed to determine expected gear for spec version $spec_version_value" | ||
| echo "$TESTNAME FAIL" > "$res_file" | ||
| exit 1 | ||
| fi | ||
| log_info "Expected UFS Gear: HS_GEAR$EXPECTED_GEAR" | ||
|
|
||
| # Start dd command in background and check gear/lane under load | ||
| log_info "Starting I/O load test to verify UFS Gear and Lane under load..." | ||
| tmpfile="/ufs_gear_lane.tmp" | ||
|
|
||
| # Start dd in background | ||
| dd if=/dev/zero of="$tmpfile" bs=3M count=1024 >/dev/null 2>&1 & | ||
|
Contributor
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. of="$tmpfile" is on / -> whichever filesystem backs. you even skip when UFS is rootfs (resolved_block == resolved_rootfs), meaning in the common safe case, you're explicitly not touching UFS at all.
Contributor
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. 3M * 1024 = 3GiB per run is huge for CI, and on some boards will take long time. |
||
| DD_PID=$! | ||
|
|
||
| sleep 1 | ||
|
|
||
|
Contributor
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. you only sleep 1 before reading gear/ lane, if the write is still ramping up, it's fine. But there's no guarantee that I/O is heavy at exactly that moment. |
||
| # Read current gear and lane values | ||
| CURRENT_GEAR=$(cat "$GEAR_NODE" 2>/dev/null | tr -d '[:space:]') | ||
| CURRENT_LANE=$(cat "$LANE_NODE" 2>/dev/null | tr -d '[:space:]') | ||
|
|
||
| wait $DD_PID 2>/dev/null | ||
|
|
||
| # Clean up temp file | ||
| rm -f "$tmpfile" | ||
|
|
||
| log_info "Current UFS Gear under load: $CURRENT_GEAR" | ||
| log_info "Current UFS Lane under load: $CURRENT_LANE" | ||
|
|
||
| # Verify gear and lane values | ||
| if [ -z "$CURRENT_GEAR" ] || [ -z "$CURRENT_LANE" ]; then | ||
| log_fail "Failed to read current gear or lane values" | ||
| echo "$TESTNAME FAIL" > "$res_file" | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Check if gear matches expected and lane is 2 | ||
| if [ "$CURRENT_GEAR" = "HS_GEAR$EXPECTED_GEAR" ] && [ "$CURRENT_LANE" = "2" ]; then | ||
| log_pass "UFS Gear and Lane validation passed" | ||
| log_info "Gear: $CURRENT_GEAR (Expected: HS_GEAR$EXPECTED_GEAR)" | ||
| log_info "Lane: $CURRENT_LANE (Expected: 2)" | ||
| scan_dmesg_errors "ufs" "$test_path" | ||
|
Contributor
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. Called twice on the PASS path |
||
| echo "$TESTNAME PASS" > "$res_file" | ||
|
Contributor
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. .res file is written PASS twice |
||
| else | ||
| log_fail "UFS Gear and Lane validation failed" | ||
| if [ "$CURRENT_GEAR" != "HS_GEAR$EXPECTED_GEAR" ]; then | ||
| log_fail "Gear mismatch: Current=$CURRENT_GEAR, Expected=HS_GEAR$EXPECTED_GEAR" | ||
| fi | ||
| if [ "$CURRENT_LANE" != "2" ]; then | ||
| log_fail "Lane mismatch: Current=$CURRENT_LANE, Expected=2" | ||
| fi | ||
| echo "$TESTNAME FAIL" > "$res_file" | ||
| exit 1 | ||
| fi | ||
|
|
||
| scan_dmesg_errors "ufs" "$test_path" | ||
|
Contributor
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. NIT |
||
| log_pass "$TESTNAME completed successfully" | ||
| echo "$TESTNAME PASS" > "$res_file" | ||
|
Contributor
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. NIT |
||
| exit 0 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
| ``` |
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.
Are these tests validated on qcom-next?