diff --git a/Runner/suites/Connectivity/WiFi/WiFi_OnOff/WiFi_OnOff.yaml b/Runner/suites/Connectivity/WiFi/WiFi_OnOff/WiFi_OnOff.yaml index 7502368f..1695be46 100644 --- a/Runner/suites/Connectivity/WiFi/WiFi_OnOff/WiFi_OnOff.yaml +++ b/Runner/suites/Connectivity/WiFi/WiFi_OnOff/WiFi_OnOff.yaml @@ -7,10 +7,15 @@ metadata: scope: - functional +params: + WIFI_WAIT_SECS: "60" + WIFI_WAIT_STEP_SECS: "2" + WIFI_RECOVERY_RELOAD: "1" + WIFI_RECOVERY_RELOAD_AFTER_S: "" + run: steps: - REPO_PATH=$PWD - cd Runner/suites/Connectivity/WiFi/WiFi_OnOff - - ./run.sh || true + - WIFI_WAIT_SECS="${WIFI_WAIT_SECS}" WIFI_WAIT_STEP_SECS="${WIFI_WAIT_STEP_SECS}" WIFI_RECOVERY_RELOAD="${WIFI_RECOVERY_RELOAD}" WIFI_RECOVERY_RELOAD_AFTER_S="${WIFI_RECOVERY_RELOAD_AFTER_S}" ./run.sh || true - $REPO_PATH/Runner/utils/send-to-lava.sh WiFi_OnOff.res - diff --git a/Runner/suites/Connectivity/WiFi/WiFi_OnOff/run.sh b/Runner/suites/Connectivity/WiFi/WiFi_OnOff/run.sh index 8d805898..101660b8 100755 --- a/Runner/suites/Connectivity/WiFi/WiFi_OnOff/run.sh +++ b/Runner/suites/Connectivity/WiFi/WiFi_OnOff/run.sh @@ -45,6 +45,7 @@ qcom,wcn6750 qcom,wcn3950 ath12k ath11k +ath10k wifi wlan qca @@ -67,6 +68,8 @@ EOF WIFI_WAIT_SECS="${WIFI_WAIT_SECS:-60}" WIFI_WAIT_STEP_SECS="${WIFI_WAIT_STEP_SECS:-2}" +WIFI_RECOVERY_RELOAD="${WIFI_RECOVERY_RELOAD:-1}" +WIFI_RECOVERY_RELOAD_AFTER_S="${WIFI_RECOVERY_RELOAD_AFTER_S:-}" WIFI_PROBE_LOG_DIR="${WIFI_PROBE_LOG_DIR:-./wifi_onoff_dmesg}" WIFI_PROBE_LOG_TAG="${WIFI_PROBE_LOG_TAG:-${TESTNAME}/probe}" WIFI_DT_PATTERNS="${WIFI_DT_PATTERNS:-$WIFI_DT_PATTERNS_DEFAULT}" @@ -96,6 +99,7 @@ log_info "---------------------------------------------------------------------- log_info "-------------------Starting $TESTNAME Testcase----------------------------" log_info "=== Test Initialization ===" log_info "Config: WIFI_WAIT_SECS=${WIFI_WAIT_SECS} WIFI_WAIT_STEP_SECS=${WIFI_WAIT_STEP_SECS}" +log_info "Config: WIFI_RECOVERY_RELOAD=${WIFI_RECOVERY_RELOAD} WIFI_RECOVERY_RELOAD_AFTER_S=${WIFI_RECOVERY_RELOAD_AFTER_S:-auto}" log_info "Config: WIFI_PROBE_LOG_TAG=${WIFI_PROBE_LOG_TAG}" if [ -n "${WIFI_IFACE:-}" ]; then @@ -128,9 +132,9 @@ fi log_info "=== WiFi DT Validation ===" if run_with_line_args wifi_dt_present "$WIFI_DT_PATTERNS"; then - log_pass "WiFi DT entry/compatible matched." + log_pass "WiFi/combined WCN DT entry/compatible matched." else - log_warn "No WiFi DT entry/compatible matched from configured patterns." + log_warn "No WiFi/combined WCN DT entry/compatible matched from configured patterns." fi log_info "=== WiFi Module Visibility ===" @@ -159,17 +163,21 @@ log_info "=== Waiting for WiFi Interface ===" wifi_iface="$(wait_for_wifi_interface "$WIFI_WAIT_SECS" "$WIFI_WAIT_STEP_SECS" || true)" if [ -z "$wifi_iface" ]; then - log_info "No WiFi interface detected after wait. Collecting diagnostics..." - + log_info "No WiFi interface detected after wait/recovery. Collecting diagnostics..." + run_with_line_args wifi_dump_debug_info "$WIFI_DT_PATTERNS" run_with_line_args wifi_log_module_info "$WIFI_DRIVER_MODULES" - wifi_has_probe_failures "$WIFI_PROBE_LOG_DIR" "$WIFI_PROBE_LOG_TAG" || true - + + if wifi_has_probe_failures "$WIFI_PROBE_LOG_DIR" "$WIFI_PROBE_LOG_TAG"; then + log_fail_exit "$TESTNAME" "WiFi driver probe/runtime failures detected and no usable WiFi interface was found." "" + fi + if wifi_stack_present; then - log_fail_exit "$TESTNAME" "WiFi stack present, but no usable WiFi interface was found after retries." "" + log_fail_exit "$TESTNAME" "WiFi runtime stack is present, but no usable WiFi interface was found after retries." "" fi - - log_skip_exit "$TESTNAME" "No WiFi interface found and no WiFi stack was detected. Skipping." "" + + log_warn "WiFi modules may be loaded, but no WiFi phy/netdev/runtime object is exposed." + log_skip_exit "$TESTNAME" "No usable WiFi interface or runtime WiFi phy/netdev was found. Skipping." "" fi log_pass "Detected WiFi interface: $wifi_iface" diff --git a/Runner/utils/lib_connectivity.sh b/Runner/utils/lib_connectivity.sh index d657cbd2..c744e22f 100755 --- a/Runner/utils/lib_connectivity.sh +++ b/Runner/utils/lib_connectivity.sh @@ -14,58 +14,88 @@ wifi_unblock_rfkill() { # Retry WiFi interface discovery for a bounded time while unblocking rfkill. # Prints interface name on success and returns non-zero on timeout. +# +# Optional recovery knobs: +# WIFI_RECOVERY_RELOAD=1|0 +# Enable one controlled WiFi driver reload if no interface appears. +# +# WIFI_RECOVERY_RELOAD_AFTER_S=N +# Try reload after N seconds of waiting. Default: half of max_wait. +# +# WIFI_RECOVERY_MODULES="mod1 mod2 ..." +# Leaf WiFi driver modules eligible for reload. +# +# Notes: +# - stdout is reserved only for the detected interface name. +# - diagnostics go to stderr because callers use command substitution. +# - shared modules such as cfg80211/mac80211/mhi must not be reloaded here. wait_for_wifi_interface() { max_wait="${1:-60}" sleep_step="${2:-2}" waited=0 iface="" settle_done=0 - + reload_done=0 + reload_after="" + mod="" + recovery_modules="${WIFI_RECOVERY_MODULES:-ath12k_wifi7 ath12k_pci ath12k_ahb ath11k_pci ath11k_ahb ath11k_snoc ath10k_snoc ath10k_pci ath10k_sdio}" + case "$max_wait" in ''|*[!0-9]*) max_wait=60 ;; esac - + case "$sleep_step" in ''|*[!0-9]*) sleep_step=2 ;; esac - + if [ "$max_wait" -le 0 ] 2>/dev/null; then max_wait=60 fi - + if [ "$sleep_step" -le 0 ] 2>/dev/null; then sleep_step=2 fi - + + reload_after="${WIFI_RECOVERY_RELOAD_AFTER_S:-}" + case "$reload_after" in + ''|*[!0-9]*) + reload_after=$((max_wait / 2)) + ;; + esac + + if [ "$reload_after" -le 0 ] 2>/dev/null; then + reload_after="$sleep_step" + fi + # Keep stdout reserved only for the detected interface name because callers # commonly use command substitution: - # wifi_iface="$(wait_for_wifi_interface ...)" + # wifi_iface="$(wait_for_wifi_interface ...)" # # All diagnostics must go to stderr to avoid contaminating the returned # interface name. log_info "Waiting up to ${max_wait}s for WiFi interface creation" >&2 - + while [ "$waited" -lt "$max_wait" ]; do wifi_unblock_rfkill - + iface="$(get_wifi_interface 2>/dev/null || true)" if [ -n "$iface" ]; then printf '%s\n' "$iface" return 0 fi - + if [ "$settle_done" -eq 0 ]; then settle_done=1 - + if command -v udevadm >/dev/null 2>&1; then log_info "No WiFi interface yet; triggering net add uevents and waiting for udev settle" >&2 udevadm trigger --action=add --subsystem-match=net >/dev/null 2>&1 || true udevadm settle --timeout=5 >/dev/null 2>&1 || true - + iface="$(get_wifi_interface 2>/dev/null || true)" if [ -n "$iface" ]; then printf '%s\n' "$iface" @@ -73,15 +103,60 @@ wait_for_wifi_interface() { fi fi fi - + + if [ "${WIFI_RECOVERY_RELOAD:-1}" = "1" ] && + [ "$reload_done" -eq 0 ] && + [ "$waited" -ge "$reload_after" ] && + command -v modprobe >/dev/null 2>&1; then + reload_done=1 + + for mod in $recovery_modules; do + [ -n "$mod" ] || continue + + if ! is_module_loaded "$mod"; then + continue + fi + + log_warn "No WiFi interface after ${waited}s; attempting one controlled reload of $mod" >&2 + + if modprobe -r "$mod" >/dev/null 2>&1; then + sleep 2 + + if modprobe "$mod" >/dev/null 2>&1; then + log_info "Reloaded WiFi module: $mod" >&2 + + wifi_unblock_rfkill + + if command -v udevadm >/dev/null 2>&1; then + udevadm trigger --action=add --subsystem-match=net >/dev/null 2>&1 || true + udevadm settle --timeout=5 >/dev/null 2>&1 || true + fi + + iface="$(get_wifi_interface 2>/dev/null || true)" + if [ -n "$iface" ]; then + printf '%s\n' "$iface" + return 0 + fi + else + log_warn "Reload failed for WiFi module $mod after unload" >&2 + fi + else + log_warn "Could not unload WiFi module $mod; it may be busy" >&2 + fi + + # Attempt only one loaded leaf driver module. + break + done + fi + sleep "$sleep_step" waited=$((waited + sleep_step)) - + if [ "$waited" -gt 0 ] && [ $((waited % 10)) -eq 0 ]; then log_info "Still waiting for WiFi interface... waited=${waited}s/${max_wait}s" >&2 fi done - + return 1 } @@ -115,19 +190,25 @@ wifi_log_module_info() { done } -# Return success when there is evidence that a WiFi software stack is present, -# even if no netdev has been created yet. Used to separate FAIL from SKIP. +# Return success when there is runtime evidence that WiFi registered a real +# device/phy/netdev. +# +# This intentionally does not treat generic module-only state as success. +# Modules such as cfg80211, mac80211, and mhi may be loaded even when no WiFi +# hardware has registered a phy or netdev. +# +# Used by tests to decide whether missing interface is a real runtime failure +# or a platform/no-device skip. wifi_stack_present() { - mod="" + iface="" - for mod in ath12k_wifi7 ath12k ath11k ath11k_pci ath10k_pci ath10k_snoc cfg80211 mac80211 mhi; do - if is_module_loaded "$mod"; then - return 0 - fi - done + iface="$(get_wifi_interface 2>/dev/null || true)" + if [ -n "$iface" ]; then + return 0 + fi if [ -d /sys/class/ieee80211 ]; then - if ls /sys/class/ieee80211/* >/dev/null 2>&1; then + if find /sys/class/ieee80211 -mindepth 1 -maxdepth 1 -print -quit 2>/dev/null | grep . >/dev/null 2>&1; then return 0 fi fi @@ -136,8 +217,20 @@ wifi_stack_present() { if iw phy 2>/dev/null | grep . >/dev/null 2>&1; then return 0 fi + + if iw dev 2>/dev/null | grep -E '^[[:space:]]*Interface[[:space:]]+' >/dev/null 2>&1; then + return 0 + fi fi + for n in /sys/class/net/*; do + [ -e "$n" ] || continue + + if [ -d "$n/wireless" ] || [ -e "$n/phy80211" ]; then + return 0 + fi + done + return 1 }