From: Venkat Chimata <venkata@shasta.cloud> OpenWiFi's ucentral agent periodically (typically 120 seconds) issues nl80211 call to get associated client list from the WLAN driver. Somehow this operation was causing tx/rx delays sometimes and the video calls on connected clients are experiencing jitter. The associated client list was protected by a mutex lock. I saw that ieee80211_check_fast_xmit_all uses rcu_read_lock and rcu_read_unlock to iterate through sta_list. I took it as a refernce and changed the lock to rcu_read lock from mutex. Also saw this this comment just above sta_mutex declaration. /* Station data */ /* * The mutex only protects the list, hash table and * counter, reads are done with RCU. */ struct mutex sta_mtx; Hence tried changing mutex_lock(/unlock) in ieee80211_dump_station to rcu_read_lock(/unlock) and it resolved the jitter issue in the video calls. Tests: We had this issue show up consistently and the patch fixed the issue. We spent a good part of 2 weeks following up on this and with this fix, the video calls are smooth. Also tested if this could cause any crashes with below mentioned process. 1. Connect 3 clients 2. A script running dumping clients in an infinite loop 3. Continuously disconnect / connect one client to see if there is any crash. No crash was observed. --- v2: * Resolve warning net/mac80211/cfg.c:858:33: warning: unused variable 'local' [-Wunused-variable] --- Signed-off-by: Venkat Chimata <venkata@shasta.cloud> --- net/mac80211/cfg.c | 7 ++----- net/mac80211/sta_info.c | 3 +-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6a8350d..a005364 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -790,20 +790,17 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, int idx, u8 *mac, struct station_info *sinfo) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_local *local = sdata->local; struct sta_info *sta; int ret = -ENOENT; - mutex_lock(&local->sta_mtx); - + rcu_read_lock(); sta = sta_info_get_by_idx(sdata, idx); if (sta) { ret = 0; memcpy(mac, sta->sta.addr, ETH_ALEN); sta_set_sinfo(sta, sinfo, true); } - - mutex_unlock(&local->sta_mtx); + rcu_read_unlock(); return ret; } diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 550a610..af6fa75 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -231,8 +231,7 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata, struct sta_info *sta; int i = 0; - list_for_each_entry_rcu(sta, &local->sta_list, list, - lockdep_is_held(&local->sta_mtx)) { + list_for_each_entry_rcu(sta, &local->sta_list, list) { if (sdata != sta->sdata) continue; if (i < idx) { -- 2.34.1