diff --git a/Runner/suites/Connectivity/WiFi/WiFi_Firmware_Driver/run.sh b/Runner/suites/Connectivity/WiFi/WiFi_Firmware_Driver/run.sh index 720db3e7..7436a0d4 100755 --- a/Runner/suites/Connectivity/WiFi/WiFi_Firmware_Driver/run.sh +++ b/Runner/suites/Connectivity/WiFi/WiFi_Firmware_Driver/run.sh @@ -1,11 +1,14 @@ #!/bin/sh - # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. # SPDX-License-Identifier: BSD-3-Clause # Robustly find and source init_env -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +SCRIPT_DIR="$( + cd "$(dirname "$0")" || exit 1 + pwd +)" INIT_ENV="" SEARCH="$SCRIPT_DIR" + while [ "$SEARCH" != "/" ]; do if [ -f "$SEARCH/init_env" ]; then INIT_ENV="$SEARCH/init_env" @@ -19,180 +22,84 @@ if [ -z "$INIT_ENV" ]; then exit 1 fi -# Only source if not already loaded (idempotent) -if [ -z "$__INIT_ENV_LOADED" ]; then +if [ -z "${__INIT_ENV_LOADED:-}" ]; then # shellcheck disable=SC1090 . "$INIT_ENV" fi -# Always source functestlib.sh, using $TOOLS exported by init_env # shellcheck disable=SC1090,SC1091 . "$TOOLS/functestlib.sh" +# shellcheck disable=SC1090,SC1091 +. "$TOOLS/lib_connectivity.sh" TESTNAME="WiFi_Firmware_Driver" -test_path=$(find_test_case_by_name "$TESTNAME") +test_path="$(find_test_case_by_name "$TESTNAME")" cd "$test_path" || exit 1 RES_FILE="./${TESTNAME}.res" +WIFI_FW_PROBE_LOG_DIR="${WIFI_FW_PROBE_LOG_DIR:-./wifi_firmware_driver_dmesg}" +WIFI_FW_PROBE_LOG_TAG="${WIFI_FW_PROBE_LOG_TAG:-${TESTNAME}/probe}" +WIFI_FW_LOAD_LOG_TAG="${WIFI_FW_LOAD_LOG_TAG:-${TESTNAME}/firmware}" + : >"$RES_FILE" log_info "--------------------------------------------------------------------------" log_info "-------------------Starting $TESTNAME Testcase----------------------------" log_info "=== Test Initialization ===" +log_info "Probe log tag: $WIFI_FW_PROBE_LOG_TAG" +log_info "Firmware log tag: $WIFI_FW_LOAD_LOG_TAG" -if ! check_dependencies find grep modprobe lsmod cat stat; then - log_skip "$TESTNAME SKIP - required tools (find/grep/modprobe/lsmod/cat/stat) missing" +if ! check_dependencies find grep modprobe lsmod cat stat awk; then + log_skip "$TESTNAME SKIP - required tools (find/grep/modprobe/lsmod/cat/stat/awk) missing" echo "$TESTNAME SKIP" >"$RES_FILE" exit 0 fi -# Detect SoC from /proc/device-tree/model if [ -f /proc/device-tree/model ]; then - read -r soc_model < /proc/device-tree/model + read -r soc_model /dev/null | grep -q .; then - fwfile=$(find /lib/firmware/ath11k/ -type f -name "amss.bin" -print -quit 2>/dev/null) - wifi_family="ath11k" - elif find /lib/firmware/ath11k/ -type f -name "wpss.mbn" -print -quit 2>/dev/null | grep -q .; then - fwfile=$(find /lib/firmware/ath11k/ -type f -name "wpss.mbn" -print -quit 2>/dev/null) - wifi_family="ath11k" - fi -fi +log_info "Detected SoC model: $soc_model" -# If no ath11k firmware found, try ath10k (e.g. WCN3990 on RB1/QCM2290) -if [ -z "$fwfile" ] && [ -d /lib/firmware/ath10k ]; then - # Look for wlan firmware or generic firmware-*.bin - if find /lib/firmware/ath10k/ -type f -name "wlanmdsp.mbn" -print -quit 2>/dev/null | grep -q .; then - fwfile=$(find /lib/firmware/ath10k/ -type f -name "wlanmdsp.mbn" -print -quit 2>/dev/null) - wifi_family="ath10k" - elif find /lib/firmware/ath10k/ -type f -name "firmware-*.bin" -print -quit 2>/dev/null | grep -q .; then - fwfile=$(find /lib/firmware/ath10k/ -type f -name "firmware-*.bin" -print -quit 2>/dev/null) - wifi_family="ath10k" - fi -fi +suite_rc=0 -if [ -z "$fwfile" ] || [ -z "$wifi_family" ]; then - log_skip "$TESTNAME SKIP - No ath11k/ath10k WiFi firmware found under /lib/firmware (ath11k or ath10k)" +log_info "=== WiFi Firmware Detection ===" +if ! wifi_detect_firmware_info; then + log_skip "$TESTNAME SKIP - No ath12k/ath11k/ath10k WiFi firmware found under /lib/firmware" echo "$TESTNAME SKIP" >"$RES_FILE" exit 0 fi -size=$(stat -c%s "$fwfile" 2>/dev/null) -basename=$(basename "$fwfile") -log_info "Detected WiFi firmware family: $wifi_family" -log_info "Detected firmware [$basename]: $fwfile (size: $size bytes)" +log_info "Detected WiFi firmware family: $WIFI_FW_FAMILY" +log_info "Detected firmware [$WIFI_FW_BASENAME]: $WIFI_FW_FILE (size: $WIFI_FW_SIZE bytes)" -suite_rc=0 +log_info "=== Family-specific Runtime Preparation ===" +if ! wifi_handle_firmware_family "$WIFI_FW_FAMILY" "$WIFI_FW_BASENAME"; then + suite_rc=1 +fi -# --------------------------------------------------------------------------- -# Family-specific handling (load / validate) – use log_* only, decide at end -# --------------------------------------------------------------------------- -case "$wifi_family" in - ath11k) - case "$basename" in - wpss.mbn) - log_info "Platform using wpss.mbn firmware (e.g., Kodiak - WPSS via remoteproc)" - if validate_remoteproc_running "wpss"; then - log_info "Remoteproc 'wpss' is active and validated." - else - log_fail "Remoteproc 'wpss' validation failed." - suite_rc=1 - fi - log_info "No ath11k_pci module load needed for wpss-based platform." - ;; - amss.bin) - log_info "amss.bin firmware detected (e.g., WCN6855 - Lemans/Monaco via ath11k_pci)" - if ! modprobe ath11k_pci 2>/dev/null; then - log_fail "Failed to load ath11k_pci module." - suite_rc=1 - else - log_info "ath11k_pci module loaded successfully." - fi - ;; - *) - log_skip "$TESTNAME SKIP - Unsupported ath11k firmware type: $basename" - echo "$TESTNAME SKIP" >"$RES_FILE" - exit 0 - ;; - esac - ;; - ath10k) - log_info "ath10k firmware detected (e.g., WCN3990 on RB1/QCM2290)." - # Ensure ath10k_core + one of the bus drivers (snoc/pci/sdio) are loaded - if ! lsmod | grep -q '^ath10k_core\s'; then - log_info "ath10k_core not loaded yet; attempting to load ath10k bus drivers..." - bus_loaded=0 - for m in ath10k_snoc ath10k_pci ath10k_sdio; do - if modprobe "$m" 2>/dev/null; then - log_info "Loaded ath10k bus driver module: $m" - bus_loaded=1 - break - fi - done - if [ "$bus_loaded" -ne 1 ]; then - log_fail "Failed to load any ath10k bus driver (ath10k_snoc/ath10k_pci/ath10k_sdio)." - suite_rc=1 - fi - else - log_info "ath10k_core already loaded; skipping bus driver modprobe attempts." - fi - ;; - *) - log_skip "$TESTNAME SKIP - Unsupported WiFi family detected: $wifi_family" - echo "$TESTNAME SKIP" >"$RES_FILE" - exit 0 - ;; -esac - -# --------------------------------------------------------------------------- -# Module visibility checks (family-specific) – explicitly verify ath10k modules -# --------------------------------------------------------------------------- -if [ "$wifi_family" = "ath11k" ]; then - log_info "Checking active ath11k-related kernel modules via lsmod..." - if lsmod | grep -Eq '^ath11k(_.*)?\s'; then - lsmod | grep -E '^ath11k(_.*)?\s' | while read -r mod_line; do - log_info " Module loaded: $mod_line" - done - else - log_fail "No ath11k-related kernel module detected via lsmod." - suite_rc=1 - fi -elif [ "$wifi_family" = "ath10k" ]; then - log_info "Checking active ath10k-related kernel modules via lsmod..." - if lsmod | grep -q '^ath10k_core\s'; then - log_info " Core module loaded: ath10k_core" - else - log_fail "ath10k_core module is not loaded." - suite_rc=1 - fi +log_info "=== Family-specific Module Visibility ===" +if ! wifi_verify_family_modules "$WIFI_FW_FAMILY"; then + suite_rc=1 +fi - if lsmod | grep -Eq '^ath10k_(snoc|pci|sdio)\s'; then - lsmod | grep -E '^ath10k_(snoc|pci|sdio)\s' | while read -r mod_line; do - log_info " Bus driver loaded: $mod_line" - done - else - log_fail "No ath10k bus driver module (ath10k_snoc/ath10k_pci/ath10k_sdio) detected via lsmod." - suite_rc=1 - fi +log_info "=== WiFi Firmware Load Evidence ===" +if wifi_firmware_loaded "$WIFI_FW_FAMILY" "$WIFI_FW_LOAD_LOG_TAG"; then + log_pass "[$WIFI_FW_LOAD_LOG_TAG] Firmware load/use evidence found." +else + log_fail "[$WIFI_FW_LOAD_LOG_TAG] Firmware load/use evidence not found." + suite_rc=1 +fi + +log_info "=== WiFi Probe Check ===" +if wifi_has_probe_failures "$WIFI_FW_PROBE_LOG_DIR" "$WIFI_FW_PROBE_LOG_TAG"; then + suite_rc=1 +else + log_pass "[$WIFI_FW_PROBE_LOG_TAG] No WiFi probe/runtime failures detected in kernel log." fi -# --------------------------------------------------------------------------- -# Final result -# --------------------------------------------------------------------------- if [ "$suite_rc" -eq 0 ]; then log_pass "$TESTNAME: PASS - WiFi firmware and driver validation successful." echo "$TESTNAME PASS" >"$RES_FILE" diff --git a/Runner/utils/lib_connectivity.sh b/Runner/utils/lib_connectivity.sh index 4a21f951..2a32a473 100755 --- a/Runner/utils/lib_connectivity.sh +++ b/Runner/utils/lib_connectivity.sh @@ -66,19 +66,21 @@ wifi_dt_present() { wifi_log_module_info() { mod="" mod_path="" - + for mod in "$@"; do [ -n "$mod" ] || continue - + if is_module_loaded "$mod"; then log_pass "Module loaded: $mod" else log_info "Module not loaded: $mod" fi - - mod_path="$(find_kernel_module "$mod" 2>/dev/null || true)" + + mod_path="$(find_kernel_module "$mod" 2>/dev/null | awk '/^\// { print; exit }' || true)" if [ -n "$mod_path" ]; then log_info "[module-path] $mod -> $mod_path" + else + log_info "[module-path] $mod -> not found" fi done } @@ -229,3 +231,276 @@ wifi_dump_debug_info() { wifi_dt_present "$@" || true wifi_dump_runtime_info } + +# Detect WiFi firmware family and a representative firmware file under +# /lib/firmware for ath12k, ath11k, or ath10k based platforms. +wifi_detect_firmware_info() { + WIFI_FW_FILE="" + WIFI_FW_FAMILY="" + WIFI_FW_BASENAME="" + WIFI_FW_SIZE="" + + if [ -d /lib/firmware/ath12k ]; then + WIFI_FW_FILE="$(find /lib/firmware/ath12k -type f -name amss.bin -print -quit 2>/dev/null)" + if [ -n "$WIFI_FW_FILE" ]; then + WIFI_FW_FAMILY="ath12k" + fi + fi + + if [ -z "$WIFI_FW_FILE" ] && [ -d /lib/firmware/ath11k ]; then + WIFI_FW_FILE="$(find /lib/firmware/ath11k -type f -name amss.bin -print -quit 2>/dev/null)" + if [ -n "$WIFI_FW_FILE" ]; then + WIFI_FW_FAMILY="ath11k" + else + WIFI_FW_FILE="$(find /lib/firmware/ath11k -type f -name wpss.mbn -print -quit 2>/dev/null)" + if [ -n "$WIFI_FW_FILE" ]; then + WIFI_FW_FAMILY="ath11k" + fi + fi + fi + + if [ -z "$WIFI_FW_FILE" ] && [ -d /lib/firmware/ath10k ]; then + WIFI_FW_FILE="$(find /lib/firmware/ath10k -type f -name wlanmdsp.mbn -print -quit 2>/dev/null)" + if [ -n "$WIFI_FW_FILE" ]; then + WIFI_FW_FAMILY="ath10k" + else + WIFI_FW_FILE="$(find /lib/firmware/ath10k -type f -name 'firmware-*.bin' -print -quit 2>/dev/null)" + if [ -n "$WIFI_FW_FILE" ]; then + WIFI_FW_FAMILY="ath10k" + fi + fi + fi + + if [ -z "$WIFI_FW_FILE" ] || [ -z "$WIFI_FW_FAMILY" ]; then + return 1 + fi + + WIFI_FW_BASENAME="${WIFI_FW_FILE##*/}" + WIFI_FW_SIZE="$(stat -c%s "$WIFI_FW_FILE" 2>/dev/null || echo unknown)" + + # These variables are intentionally returned to callers through shell scope. + : "$WIFI_FW_BASENAME" "$WIFI_FW_SIZE" + + return 0 +} + +# Try to load the first available module from the provided list, succeeding +# if one is already loaded or modprobe succeeds for one candidate. +wifi_load_first_available_module() { + mod="" + + for mod in "$@"; do + [ -n "$mod" ] || continue + + if is_module_loaded "$mod"; then + log_info "Module already loaded: $mod" + return 0 + fi + + if modprobe "$mod" 2>/dev/null; then + log_info "Loaded WiFi module: $mod" + return 0 + fi + done + + return 1 +} + +# Perform family-specific WiFi runtime preparation for ath12k, ath11k, or +# ath10k using logging only; callers decide the final testcase result. +wifi_handle_firmware_family() { + family="$1" + basename="$2" + + case "$family" in + ath12k) + log_info "ath12k firmware detected, handling WCN7850 / Wi-Fi 7 class platform." + if wifi_load_first_available_module ath12k_wifi7 ath12k_pci ath12k_ahb ath12k; then + return 0 + fi + log_fail "Failed to load any ath12k module: ath12k_wifi7/ath12k_pci/ath12k_ahb/ath12k" + return 1 + ;; + ath11k) + case "$basename" in + wpss.mbn) + log_info "ath11k WPSS firmware detected, validating wpss remoteproc." + if validate_remoteproc_running "wpss"; then + log_info "Remoteproc 'wpss' is active and validated." + return 0 + fi + log_fail "Remoteproc 'wpss' validation failed." + return 1 + ;; + amss.bin) + log_info "ath11k amss.bin firmware detected, handling PCI/AHB/SNOC class platform." + if wifi_load_first_available_module ath11k_pci ath11k_ahb ath11k_snoc ath11k; then + return 0 + fi + log_fail "Failed to load any ath11k module: ath11k_pci/ath11k_ahb/ath11k_snoc/ath11k" + return 1 + ;; + *) + log_fail "Unsupported ath11k firmware type: $basename" + return 1 + ;; + esac + ;; + ath10k) + log_info "ath10k firmware detected, handling WCN3990/QCM2290 class platform." + if wifi_load_first_available_module ath10k_snoc ath10k_pci ath10k_sdio ath10k_core; then + return 0 + fi + log_fail "Failed to load any ath10k module: ath10k_snoc/ath10k_pci/ath10k_sdio/ath10k_core" + return 1 + ;; + *) + log_fail "Unsupported WiFi family detected: $family" + return 1 + ;; + esac +} + +# Validate family-specific module visibility and print module/path details, +# including explicit ath10k core and bus driver checks. +wifi_verify_family_modules() { + family="$1" + + case "$family" in + ath12k) + log_info "Checking active ath12k-related kernel modules." + wifi_log_module_info ath12k_wifi7 ath12k ath12k_pci ath12k_ahb cfg80211 mac80211 mhi + + ath12k_core_ok=0 + ath12k_bus_ok=0 + + if is_module_loaded ath12k; then + ath12k_core_ok=1 + else + log_fail "ath12k core module is not loaded." + fi + + if is_module_loaded ath12k_wifi7 || is_module_loaded ath12k_pci || is_module_loaded ath12k_ahb; then + ath12k_bus_ok=1 + else + log_fail "No ath12k transport/top module detected: ath12k_wifi7/ath12k_pci/ath12k_ahb" + fi + + if [ "$ath12k_core_ok" -eq 1 ] && [ "$ath12k_bus_ok" -eq 1 ]; then + return 0 + fi + + return 1 + ;; + ath11k) + log_info "Checking active ath11k-related kernel modules." + wifi_log_module_info ath11k ath11k_pci ath11k_ahb ath11k_snoc cfg80211 mac80211 + + if is_module_loaded ath11k || is_module_loaded ath11k_pci || \ + is_module_loaded ath11k_ahb || is_module_loaded ath11k_snoc; then + return 0 + fi + + log_fail "No ath11k-related kernel module detected." + return 1 + ;; + ath10k) + log_info "Checking active ath10k-related kernel modules." + wifi_log_module_info ath10k_core ath10k_snoc ath10k_pci ath10k_sdio cfg80211 mac80211 + + ath10k_core_ok=0 + ath10k_bus_ok=0 + + if is_module_loaded ath10k_core; then + ath10k_core_ok=1 + else + log_fail "ath10k_core module is not loaded." + fi + + if is_module_loaded ath10k_snoc || is_module_loaded ath10k_pci || is_module_loaded ath10k_sdio; then + ath10k_bus_ok=1 + else + log_fail "No ath10k bus driver module detected: ath10k_snoc/ath10k_pci/ath10k_sdio" + fi + + if [ "$ath10k_core_ok" -eq 1 ] && [ "$ath10k_bus_ok" -eq 1 ]; then + return 0 + fi + + return 1 + ;; + *) + log_fail "Unsupported WiFi family for module validation: $family" + return 1 + ;; + esac +} + +# Check kernel logs and runtime wireless state for evidence that WiFi firmware +# was consumed by the driver. Returns success when firmware load/use evidence exists. +wifi_firmware_loaded() { + family="$1" + tag="${2:-wifi-firmware}" + pattern="" + matches="" + phy_path="" + phy="" + phy_found=0 + + case "$family" in + ath12k) + pattern='ath12k|ath12k_wifi7|WCN7850|wcn7850|amss.bin|m3.bin|board-2.bin|Hardware name|firmware' + ;; + ath11k) + pattern='ath11k|WCN6855|WCN6750|wcn6855|wcn6750|amss.bin|wpss.mbn|board-2.bin|remoteproc|firmware' + ;; + ath10k) + pattern='ath10k|WCN3990|wcn3990|wlanmdsp.mbn|firmware-[0-9].bin|board-2.bin|firmware' + ;; + *) + log_warn "[$tag] Unsupported WiFi firmware family for load evidence check: $family" + return 1 + ;; + esac + + matches="$(get_kernel_log 2>/dev/null | grep -Ei "$pattern" | \ + grep -Eiv 'failed|failure|error|timeout|unable|crash|fatal|Modules linked in' | tail -n 40 || true)" + + if [ -n "$matches" ]; then + printf '%s\n' "$matches" | while IFS= read -r line; do + [ -n "$line" ] || continue + log_info "[$tag] $line" + done + return 0 + fi + + if [ -d /sys/class/ieee80211 ]; then + for phy_path in /sys/class/ieee80211/*; do + [ -e "$phy_path" ] || continue + phy_found=1 + break + done + + if [ "$phy_found" -eq 1 ]; then + log_info "[$tag] /sys/class/ieee80211 contains wireless phy entries." + + for phy_path in /sys/class/ieee80211/*; do + [ -e "$phy_path" ] || continue + phy="${phy_path##*/}" + log_info "[$tag] phy detected: $phy" + done + + return 0 + fi + fi + + if command -v iw >/dev/null 2>&1; then + if iw phy 2>/dev/null | grep . >/dev/null 2>&1; then + log_info "[$tag] iw phy reports wireless PHY availability." + return 0 + fi + fi + + log_warn "[$tag] No positive WiFi firmware load/use evidence found for family: $family" + return 1 +}