From 48d2672519d2bfc0cb78f68bcadc7f5c68395a52 Mon Sep 17 00:00:00 2001 From: Ryan Murray Date: Fri, 30 Oct 2026 22:33:14 +1100 Subject: [PATCH 1/2] wifi: mt7932: report a connect the AP did not complete at info level A Neo boot logged mt7932-fullmac 0000:01:00.0: CONNECT_FAILED: -110; recovery-required=0 at error level while NetworkManager brought up Wi-Fi. The firmware was fine. The association timed out at the AP, cfg80211 reported the failed connect to the supplicant, and the next attempt connected. Once the request has gone to the AP, a timeout, a refusal or a reset with the firmware still healthy is how the AP answered. These are the same three outcomes the connect worker already treats as retryable for the first OWE attempt. mac80211 reports association timeouts and refusals at info level, and the supplicant logs them too. Log them at info level here as well. Everything else keeps the error level: failures before the request reaches the AP, protocol and I/O errors, and any failure that leaves the link needing recovery. A firmware command timeout sets link_failed, so it still shows as an error. Assisted-by: LLM Signed-off-by: Ryan Murray Co-Authored-By: Claude Opus 5.5 --- drivers/net/wireless/mediatek/mt7932/link.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt7932/link.c b/drivers/net/wireless/mediatek/mt7932/link.c index 538a1f15f0a3f..713d801cb1891 100644 --- a/drivers/net/wireless/mediatek/mt7932/link.c +++ b/drivers/net/wireless/mediatek/mt7932/link.c @@ -598,6 +598,20 @@ static int mt_connect_attempt(struct mt7932 *m, bool *submitted, return ret ?: READ_ONCE(m->connect_error); } +/* + * Once the request has gone to the AP, a timeout, a refusal or a reset while + * the firmware is still healthy is how the AP answered, not a driver or + * firmware fault. cfg80211 hands it to the supplicant, which retries, and + * mac80211 reports the same outcomes at info level. Keep the error level for + * failures that need recovery or point at the firmware. + */ +static bool mt_connect_failed_at_peer(struct mt7932 *m, bool auth_submitted, + int ret) +{ + return auth_submitted && !READ_ONCE(m->link_failed) && + (ret == -ETIMEDOUT || ret == -ECONNREFUSED || ret == -ECONNRESET); +} + void mt_connect_work(struct work_struct *work) { struct mt7932 *m = container_of(work, struct mt7932, connect_work); @@ -760,6 +774,9 @@ void mt_connect_work(struct work_struct *work) READ_ONCE(m->data_ready)); else if (cancelled) dev_dbg(&m->pdev->dev, "CONNECT_CANCELLED: %d\n", ret); + else if (mt_connect_failed_at_peer(m, auth_submitted, ret)) + dev_info(&m->pdev->dev, "CONNECT_FAILED: %d; recovery-required=0\n", + ret); else dev_err(&m->pdev->dev, "CONNECT_FAILED: %d; recovery-required=%u\n", ret, READ_ONCE(m->link_failed)); From 7f88d18a50e28515bc9d189a61ac7ce773e18485 Mon Sep 17 00:00:00 2001 From: Ryan Murray Date: Fri, 30 Oct 2026 23:30:56 +1100 Subject: [PATCH 2/2] tools/asahi: cover the mt7932 connect report's log level The connect worker now asks mt_connect_failed_at_peer() whether a failed connect is the AP's answer, and logs those at info level. The host test compiled the report path on its own, so it failed on the missing helper and the auth_submitted local. Extract the helper next to the report, pass auth_submitted to the test worker and give the stub a link_failed flag. Count dev_info() and dev_err() calls and check every error code with the request at the AP or not and the firmware healthy or not: only a timeout, refusal or reset of a request that reached the AP with healthy firmware is logged at info level. Assisted-by: LLM Signed-off-by: Ryan Murray --- tools/asahi/mt7932-connect-result-tests.py | 54 ++++++++++++++++------ 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/tools/asahi/mt7932-connect-result-tests.py b/tools/asahi/mt7932-connect-result-tests.py index 2f8a4bf9d4c62..87054ccfcef80 100755 --- a/tools/asahi/mt7932-connect-result-tests.py +++ b/tools/asahi/mt7932-connect-result-tests.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0-only -"""Compile the connect worker's report path and the complete nl80211 encoder.""" +"""Compile the connect worker's report path, its log-level helper and the +complete nl80211 encoder.""" from pathlib import Path import argparse import hashlib @@ -41,9 +42,9 @@ #define spin_unlock(l) ((void)(l)) #define mutex_lock(l) ((void)(l)) #define mutex_unlock(l) ((void)(l)) -#define dev_info(...) ((void)0) +#define dev_info(...) ((void)info_logs++) #define dev_dbg(...) ((void)0) -#define dev_err(...) ((void)0) +#define dev_err(...) ((void)err_logs++) #define for_each_valid_link(cr,l) for((l)=0;(l)<1;(l)++) struct sk_buff { unsigned values[32]; bool seen[32]; }; struct nlattr { int n; }; @@ -75,11 +76,11 @@ static int wiphy_net(int*w){return 0;} static void genlmsg_multicast_netns(int*f,int n,struct sk_buff*m,int p,int g,gfp_t t){} ENCODER -struct mt7932 {bool stopping,connect_open,assoc_request_seen,connecting,connected,disconnecting,connect_cancelled,connect_publishing,connect_lost,rf_ready,connect_pmk_valid; +struct mt7932 {bool link_failed,stopping,connect_open,assoc_request_seen,connecting,connected,disconnecting,connect_cancelled,connect_publishing,connect_lost,rf_ready,connect_pmk_valid; int connect_error,response_lock,command_mutex,data_lock,wiphy,power_work;u16 disconnect_reason;struct net_device *netdev;struct cfg80211_bss *connect_bss;u8 connect_bssid[6],connect_pmk[32],connect_sae_pwd[63],connect_sae_pwd_length,assoc_request_ies[512];unsigned assoc_request_ie_len; struct {struct {bool ht_supported;}ht_cap;}band2;bool power_tim,data_ready,station_signal_valid,station_rx_rate_valid,station_tx_rate_valid;unsigned long station_tx_bytes,station_rx_bytes,station_tx_packets,station_rx_packets,station_connected;}; static unsigned long jiffies=1; -static unsigned notifications,disconnections,retirements,releases,authorizations,carrier,work_count; +static unsigned info_logs,err_logs,notifications,disconnections,retirements,releases,authorizations,carrier,work_count; static struct cfg80211_connect_resp_params saved; static bool mt_rf_allowed(struct mt7932*m){return m->rf_ready;} static void mt_transport_snapshot(struct mt7932*m){} @@ -96,16 +97,22 @@ static void netif_carrier_on(struct net_device*n){carrier++;} static void netif_wake_queue(struct net_device*n){} static void cfg80211_port_authorized(struct net_device*n,const u8*b,const u8*p,size_t l,gfp_t f){authorizations++;} -static void report_worker(struct mt7932 *m,int ret,bool retirement_attempted){ +HELPER +static void report_worker(struct mt7932 *m,int ret,bool retirement_attempted,bool auth_submitted){ struct cfg80211_connect_resp_params response={};unsigned long flags;bool submitted=true,peer_owned=true,cancelled;u16 reason; REPORT int main(void){struct net_device n={1};struct cfg80211_bss b={}; int errors[]={0,-ETIMEDOUT,-ECONNREFUSED,-EPROTO,-ECANCELED,-ECONNRESET,-EIO}; - for(unsigned i=0;i