-
Notifications
You must be signed in to change notification settings - Fork 27
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 |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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" | ||
|
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. Failing to read max_freq currently leads to FAIL (good), but elsewhere similar read failures are treated as SKIP. Rule of thumb: |
||
| 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" | ||
|
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. ufs_* run.sh: dd writes to / root by absolute tmpfile paths (very risky) Write under the test directory ($test_path) or a writable tmpfs (/tmp) with a size cap |
||
|
|
||
| # Start dd in background | ||
| dd if=/dev/zero of="$tmpfile" bs=2M 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. too big for CU and slow stroage. Use smaller writes (e.g., 64–256MB), or looped reads to avoid wear. |
||
| 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 | ||
|
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. this will fail on many valid systems. Instead of “equals max”, validate “increased from idle”: |
||
| 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" | ||
|
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. For every test using temp files: |
||
|
|
||
| # 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 | ||
|
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. Wait times: 60s/180s hardcoded, will be flaky across boards. Provide env overrides: |
||
|
|
||
|
|
||
| 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 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
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.
is too broad. Might match unreleated nodes or multiple controllers. Detect actual UFS dir once and reuse.
e.g., locate .../ufshcd* / .../ufs base and store as UFS_SYSFS.