From e0268a5acc3756b4c71328effe478f88958de99d Mon Sep 17 00:00:00 2001 From: Srikanth Muppandam Date: Fri, 24 Apr 2026 12:50:47 +0530 Subject: [PATCH 1/2] add shared WiFi firmware and probe helpers Add reusable connectivity helpers for WiFi firmware detection, family-specific runtime handling, module visibility checks, firmware load evidence, and tagged probe-failure reporting. The new helpers support ath12k, ath11k, and ath10k based platforms, including Glymur/WCN7850 ath12k firmware layouts, while reusing existing functestlib helpers for module lookup, module state, dmesg scanning, and remoteproc checks. Signed-off-by: Srikanth Muppandam --- Runner/utils/lib_connectivity.sh | 283 ++++++++++++++++++++++++++++++- 1 file changed, 279 insertions(+), 4 deletions(-) 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 +} From 4e6df0e4816e595ad343f0f6710d744a8e66ae6e Mon Sep 17 00:00:00 2001 From: Srikanth Muppandam Date: Fri, 24 Apr 2026 12:51:04 +0530 Subject: [PATCH 2/2] fix: extend WiFi_Firmware_Driver for ath12k platforms Refactor WiFi_Firmware_Driver to use shared lib_connectivity helpers for firmware detection, family-specific driver handling, module validation, firmware load evidence, and probe-failure checks. This extends coverage to ath12k/WCN7850 platforms such as Glymur while preserving existing ath11k and ath10k validation flow. The test now reports clear stdout tags for firmware evidence and probe checks, generates dmesg artifacts, and keeps PASS/FAIL/SKIP decisions based on the full validation summary. Signed-off-by: Srikanth Muppandam --- .../WiFi/WiFi_Firmware_Driver/run.sh | 185 +++++------------- 1 file changed, 46 insertions(+), 139 deletions(-) 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"