On Fri, 2022-02-25 at 15:28 -0800, greearb@xxxxxxxxxxxxxxx wrote: > > - if (mvmsta->avg_energy) { > - sinfo->signal_avg = -(s8)mvmsta->avg_energy; > + if (iwl_mvm_has_new_rx_api(mvm)) { /* rxmq logic */ > + /* Grab chain signal avg, mac80211 cannot do it because > + * this driver uses RSS. Grab signal_avg here too because firmware > + * appears go not do DB summing and/or has other bugs. --Ben > + */ That "--Ben" really seems inappropriate ... please take more care when sending patches to the list. > sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG); > + sinfo->signal_avg = -ewma_signal_read(&mvmsta->rx_avg_signal); > + > + if (!mvmvif->bf_data.bf_enabled) { > + /* The firmware reliably reports different signal (2db weaker in my case) dB, but I guess we'll want to fix that instead or so ... > +static inline int iwl_mvm_sum_sigs_2(int a, int b) > +{ Feels like that calls for a helper function somewhere else, and a comment explaining it :) > +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c > @@ -278,14 +278,26 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm, > static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, > struct ieee80211_rx_status *rx_status, > u32 rate_n_flags, int energy_a, > - int energy_b) > + int energy_b, struct ieee80211_sta *sta, > + bool is_beacon, bool my_beacon) > { > int max_energy; > u32 rate_flags = rate_n_flags; > + struct iwl_mvm_sta *mvmsta = NULL; > + > + if (sta && !(is_beacon && !my_beacon)) { > + mvmsta = iwl_mvm_sta_from_mac80211(sta); > + if (energy_a) > + ewma_signal_add(&mvmsta->rx_avg_chain_signal[0], energy_a); > + if (energy_b) > + ewma_signal_add(&mvmsta->rx_avg_chain_signal[1], energy_b); > + } This is obviously racy for the exact same reason that mac80211 doesn't give you averages ... you cannot do that. Without locking, you have to rely on the firmware, and I don't think we want any locking here. > @@ -295,6 +307,15 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, > (rate_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS; > rx_status->chain_signal[0] = energy_a; > rx_status->chain_signal[1] = energy_b; > + > + if (mvmsta) { > + if (is_beacon) { > + if (my_beacon) > + ewma_signal_add(&mvmsta->rx_avg_beacon_signal, -max_energy); > + } else { > + ewma_signal_add(&mvmsta->rx_avg_signal, -max_energy); > + } > + } Why would you ignore "is_beacon && !my_beacon" cases, but handle all other management frames from everyone? > @@ -1878,6 +1899,16 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, > goto out; > } > > + is_beacon = ieee80211_is_beacon(hdr->frame_control); > + if (is_beacon && sta) { > + /* see if it is beacon destined for us */ > + if (memcmp(sta->addr, hdr->addr2, ETH_ALEN) == 0) > + my_beacon = true; don't use memcmp() for that. Anyway this really needs a lot of work, it cannot work as is. johannes