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
10 changes: 10 additions & 0 deletions Runner/plans/qcom-next-ci-premerge.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

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?

- $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
Copy link
Contributor

Choose a reason for hiding this comment

The 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
Expand Down
42 changes: 42 additions & 0 deletions Runner/suites/Kernel/Baseport/Storage/ufs_gear_lane/README.md
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
```
266 changes: 266 additions & 0 deletions Runner/suites/Kernel/Baseport/Storage/ufs_gear_lane/run.sh
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"
Copy link
Contributor

Choose a reason for hiding this comment

The 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
Copy link
Contributor

Choose a reason for hiding this comment

The 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
Copy link
Contributor

Choose a reason for hiding this comment

The 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"
Copy link
Contributor

Choose a reason for hiding this comment

The 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)
Copy link
Contributor

Choose a reason for hiding this comment

The 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() {
Copy link
Contributor

Choose a reason for hiding this comment

The 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)
Copy link
Contributor

Choose a reason for hiding this comment

The 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")
Copy link
Contributor

Choose a reason for hiding this comment

The 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 &
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor

Choose a reason for hiding this comment

The 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

Copy link
Contributor

Choose a reason for hiding this comment

The 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"
Copy link
Contributor

Choose a reason for hiding this comment

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

Called twice on the PASS path

echo "$TESTNAME PASS" > "$res_file"
Copy link
Contributor

Choose a reason for hiding this comment

The 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"
Copy link
Contributor

Choose a reason for hiding this comment

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

NIT

log_pass "$TESTNAME completed successfully"
echo "$TESTNAME PASS" > "$res_file"
Copy link
Contributor

Choose a reason for hiding this comment

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

NIT

exit 0
45 changes: 45 additions & 0 deletions Runner/suites/Kernel/Baseport/Storage/ufs_hibern8/README.md
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
```
Loading
Loading