Skip to content

Commit f2829c8

Browse files
jmberg-intelMiriam-Rachel
authored andcommitted
wifi: iwlwifi: mvm/mld: use average RSSI for beacons
When connected to an AP, the PHY will typically be tuned to a higher bandwidth than the beacons are transmitted on, as they are normally only transmitted on 20 MHz. This can mean that another STA is simultaneously transmitting on another channel of the higher bandwidth, and apparently this energy may be taken into account by the PHY, resulting in elevated energy readings. To work around this, track the firmware's corrected beacon energy data and replace the RSSI in beacons by that. The replacement happens for all beacons received in the context of the current MAC or link (depending on FW version), in which case the filters will drop all else. For a scan, which is only tuning to 20 MHz channels, the MAC/link ID will be one that isn't found (the AUX ID 4), and no correction will be done (nor is it needed.) Signed-off-by: Johannes Berg <[email protected]> Signed-off-by: Miri Korenblit <[email protected]> Link: https://patch.msgid.link/20250711183056.324bfe7027ff.I160f947e7aab30e0110a7019ed46186e57c3de14@changeid
1 parent 91b9f31 commit f2829c8

File tree

11 files changed

+223
-15
lines changed

11 files changed

+223
-15
lines changed

drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@ enum iwl_data_path_subcmd_ids {
124124
*/
125125
TLC_MNG_UPDATE_NOTIF = 0xF7,
126126

127+
/**
128+
* @BEACON_FILTER_IN_NOTIF: &struct iwl_beacon_filter_notif
129+
*/
130+
BEACON_FILTER_IN_NOTIF = 0xF8,
131+
127132
/**
128133
* @STA_PM_NOTIF: &struct iwl_mvm_pm_state_notification
129134
*/

drivers/net/wireless/intel/iwlwifi/fw/api/rx.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,9 @@ enum iwl_rx_mpdu_amsdu_info {
194194
};
195195

196196
enum iwl_rx_mpdu_mac_phy_band {
197+
/* whether or not this is MAC or LINK depends on the API */
197198
IWL_RX_MPDU_MAC_PHY_BAND_MAC_MASK = 0x0f,
199+
IWL_RX_MPDU_MAC_PHY_BAND_LINK_MASK = 0x0f,
198200
IWL_RX_MPDU_MAC_PHY_BAND_PHY_MASK = 0x30,
199201
IWL_RX_MPDU_MAC_PHY_BAND_BAND_MASK = 0xc0,
200202
};
@@ -671,7 +673,7 @@ struct iwl_rx_mpdu_desc {
671673
*/
672674
__le16 phy_info;
673675
/**
674-
* @mac_phy_band: MAC ID, PHY ID, band;
676+
* @mac_phy_band: MAC/link ID, PHY ID, band;
675677
* see &enum iwl_rx_mpdu_mac_phy_band
676678
*/
677679
u8 mac_phy_band;
@@ -1019,4 +1021,24 @@ struct iwl_rfh_queue_config {
10191021
struct iwl_rfh_queue_data data[];
10201022
} __packed; /* RFH_QUEUE_CONFIG_API_S_VER_1 */
10211023

1024+
/**
1025+
* struct iwl_beacon_filter_notif_v1 - beacon filter notification
1026+
* @average_energy: average energy for the received beacon
1027+
* @mac_id: MAC ID the beacon was received for
1028+
*/
1029+
struct iwl_beacon_filter_notif_v1 {
1030+
__le32 average_energy;
1031+
__le32 mac_id;
1032+
} __packed; /* BEACON_FILTER_IN_NTFY_API_S_VER_1 */
1033+
1034+
/**
1035+
* struct iwl_beacon_filter_notif - beacon filter notification
1036+
* @average_energy: average energy for the received beacon
1037+
* @link_id: link ID the beacon was received for
1038+
*/
1039+
struct iwl_beacon_filter_notif {
1040+
__le32 average_energy;
1041+
__le32 link_id;
1042+
} __packed; /* BEACON_FILTER_IN_NTFY_API_S_VER_2 */
1043+
10221044
#endif /* __iwl_fw_api_rx_h__ */

drivers/net/wireless/intel/iwlwifi/mld/link.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,7 @@ iwl_mld_init_link(struct iwl_mld *mld, struct ieee80211_bss_conf *link,
783783
{
784784
mld_link->vif = link->vif;
785785
mld_link->link_id = link->link_id;
786+
mld_link->average_beacon_energy = 0;
786787

787788
iwl_mld_init_internal_sta(&mld_link->bcast_sta);
788789
iwl_mld_init_internal_sta(&mld_link->mcast_sta);
@@ -1216,3 +1217,22 @@ unsigned int iwl_mld_get_link_grade(struct iwl_mld *mld,
12161217
return grade;
12171218
}
12181219
EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_get_link_grade);
1220+
1221+
void iwl_mld_handle_beacon_filter_notif(struct iwl_mld *mld,
1222+
struct iwl_rx_packet *pkt)
1223+
{
1224+
const struct iwl_beacon_filter_notif *notif = (const void *)pkt->data;
1225+
u32 link_id = le32_to_cpu(notif->link_id);
1226+
struct ieee80211_bss_conf *link_conf =
1227+
iwl_mld_fw_id_to_link_conf(mld, link_id);
1228+
struct iwl_mld_link *mld_link;
1229+
1230+
if (IWL_FW_CHECK(mld, !link_conf, "invalid link ID %d\n", link_id))
1231+
return;
1232+
1233+
mld_link = iwl_mld_link_from_mac80211(link_conf);
1234+
if (WARN_ON_ONCE(!mld_link))
1235+
return;
1236+
1237+
mld_link->average_beacon_energy = le32_to_cpu(notif->average_energy);
1238+
}

drivers/net/wireless/intel/iwlwifi/mld/link.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ struct iwl_probe_resp_data {
4141
* @mcast_sta: station used for multicast packets. Used in AP, GO and IBSS.
4242
* @mon_sta: station used for TX injection in monitor interface.
4343
* @link_id: over the air link ID
44+
* @average_beacon_energy: average beacon energy for beacons received during
45+
* client connections
4446
* @ap_early_keys: The firmware cannot install keys before bcast/mcast STAs,
4547
* but higher layers work differently, so we store the keys here for
4648
* later installation.
@@ -85,6 +87,7 @@ struct iwl_mld_link {
8587

8688
/* we can only have 2 GTK + 2 IGTK + 2 BIGTK active at a time */
8789
struct ieee80211_key_conf *ap_early_keys[6];
90+
u32 average_beacon_energy;
8891
bool silent_deactivation;
8992
struct iwl_probe_resp_data __rcu *probe_resp_data;
9093
};
@@ -150,4 +153,7 @@ void iwl_mld_omi_ap_changed_bw(struct iwl_mld *mld,
150153
struct ieee80211_bss_conf *link_conf,
151154
enum ieee80211_sta_rx_bandwidth bw);
152155

156+
void iwl_mld_handle_beacon_filter_notif(struct iwl_mld *mld,
157+
struct iwl_rx_packet *pkt);
158+
153159
#endif /* __iwl_mld_link_h__ */

drivers/net/wireless/intel/iwlwifi/mld/mld.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ static const struct iwl_hcmd_names iwl_mld_data_path_names[] = {
255255
HCMD_NAME(ESR_MODE_NOTIF),
256256
HCMD_NAME(MONITOR_NOTIF),
257257
HCMD_NAME(TLC_MNG_UPDATE_NOTIF),
258+
HCMD_NAME(BEACON_FILTER_IN_NOTIF),
258259
HCMD_NAME(MU_GROUP_MGMT_NOTIF),
259260
};
260261

drivers/net/wireless/intel/iwlwifi/mld/notif.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ CMD_VERSIONS(time_sync_confirm_notif,
351351
CMD_VERSIONS(omi_status_notif,
352352
CMD_VER_ENTRY(1, iwl_omi_send_status_notif))
353353
CMD_VERSIONS(ftm_resp_notif, CMD_VER_ENTRY(10, iwl_tof_range_rsp_ntfy))
354+
CMD_VERSIONS(beacon_filter_notif, CMD_VER_ENTRY(2, iwl_beacon_filter_notif))
354355

355356
DEFINE_SIMPLE_CANCELLATION(session_prot, iwl_session_prot_notif, mac_link_id)
356357
DEFINE_SIMPLE_CANCELLATION(tlc, iwl_tlc_update_notif, sta_id)
@@ -368,6 +369,7 @@ DEFINE_SIMPLE_CANCELLATION(uapsd_misbehaving_ap, iwl_uapsd_misbehaving_ap_notif,
368369
mac_id)
369370
#define iwl_mld_cancel_omi_status_notif iwl_mld_always_cancel
370371
DEFINE_SIMPLE_CANCELLATION(ftm_resp, iwl_tof_range_rsp_ntfy, request_id)
372+
DEFINE_SIMPLE_CANCELLATION(beacon_filter, iwl_beacon_filter_notif, link_id)
371373

372374
/**
373375
* DOC: Handlers for fw notifications
@@ -460,6 +462,8 @@ const struct iwl_rx_handler iwl_mld_rx_handlers[] = {
460462
time_sync_confirm_notif, RX_HANDLER_ASYNC)
461463
RX_HANDLER_OF_LINK(DATA_PATH_GROUP, OMI_SEND_STATUS_NOTIF,
462464
omi_status_notif)
465+
RX_HANDLER_OF_LINK(DATA_PATH_GROUP, BEACON_FILTER_IN_NOTIF,
466+
beacon_filter_notif)
463467
RX_HANDLER_OF_FTM_REQ(LOCATION_GROUP, TOF_RANGE_RESPONSE_NOTIF,
464468
ftm_resp_notif)
465469
};

drivers/net/wireless/intel/iwlwifi/mld/rx.c

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,55 @@ void iwl_mld_pass_packet_to_mac80211(struct iwl_mld *mld,
143143
}
144144
EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_pass_packet_to_mac80211);
145145

146-
static void iwl_mld_fill_signal(struct iwl_mld *mld,
146+
static bool iwl_mld_used_average_energy(struct iwl_mld *mld, int link_id,
147+
struct ieee80211_hdr *hdr,
148+
struct ieee80211_rx_status *rx_status)
149+
{
150+
struct ieee80211_bss_conf *link_conf;
151+
struct iwl_mld_link *mld_link;
152+
153+
if (unlikely(!hdr || link_id < 0))
154+
return false;
155+
156+
if (likely(!ieee80211_is_beacon(hdr->frame_control)))
157+
return false;
158+
159+
/*
160+
* if link ID is >= valid ones then that means the RX
161+
* was on the AUX link and no correction is needed
162+
*/
163+
if (link_id >= mld->fw->ucode_capa.num_links)
164+
return false;
165+
166+
/* for the link conf lookup */
167+
guard(rcu)();
168+
169+
link_conf = rcu_dereference(mld->fw_id_to_bss_conf[link_id]);
170+
if (!link_conf)
171+
return false;
172+
173+
mld_link = iwl_mld_link_from_mac80211(link_conf);
174+
if (!mld_link)
175+
return false;
176+
177+
/*
178+
* If we know the link by link ID then the frame was
179+
* received for the link, so by filtering it means it
180+
* was from the AP the link is connected to.
181+
*/
182+
183+
/* skip also in case we don't have it (yet) */
184+
if (!mld_link->average_beacon_energy)
185+
return false;
186+
187+
IWL_DEBUG_STATS(mld, "energy override by average %d\n",
188+
mld_link->average_beacon_energy);
189+
rx_status->signal = -mld_link->average_beacon_energy;
190+
return true;
191+
}
192+
193+
static void iwl_mld_fill_signal(struct iwl_mld *mld, int link_id,
194+
struct ieee80211_hdr *hdr,
147195
struct ieee80211_rx_status *rx_status,
148196
struct iwl_mld_rx_phy_data *phy_data)
149197
{
@@ -159,9 +207,11 @@ static void iwl_mld_fill_signal(struct iwl_mld *mld,
159207
IWL_DEBUG_STATS(mld, "energy in A %d B %d, and max %d\n",
160208
energy_a, energy_b, max_energy);
161209

210+
if (iwl_mld_used_average_energy(mld, link_id, hdr, rx_status))
211+
return;
212+
162213
rx_status->signal = max_energy;
163-
rx_status->chains =
164-
(rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS;
214+
rx_status->chains = u32_get_bits(rate_n_flags, RATE_MCS_ANT_AB_MSK);
165215
rx_status->chain_signal[0] = energy_a;
166216
rx_status->chain_signal[1] = energy_b;
167217
}
@@ -1160,7 +1210,10 @@ static void iwl_mld_add_rtap_sniffer_config(struct iwl_mld *mld,
11601210
}
11611211
#endif
11621212

1163-
static void iwl_mld_rx_fill_status(struct iwl_mld *mld, struct sk_buff *skb,
1213+
/* Note: hdr can be NULL */
1214+
static void iwl_mld_rx_fill_status(struct iwl_mld *mld, int link_id,
1215+
struct ieee80211_hdr *hdr,
1216+
struct sk_buff *skb,
11641217
struct iwl_mld_rx_phy_data *phy_data,
11651218
int queue)
11661219
{
@@ -1182,7 +1235,7 @@ static void iwl_mld_rx_fill_status(struct iwl_mld *mld, struct sk_buff *skb,
11821235
phy_data->phy_info & IWL_RX_MPDU_PHY_SHORT_PREAMBLE)
11831236
rx_status->enc_flags |= RX_ENC_FLAG_SHORTPRE;
11841237

1185-
iwl_mld_fill_signal(mld, rx_status, phy_data);
1238+
iwl_mld_fill_signal(mld, link_id, hdr, rx_status, phy_data);
11861239

11871240
/* This may be overridden by iwl_mld_rx_he() to HE_RU */
11881241
switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) {
@@ -1733,7 +1786,7 @@ void iwl_mld_rx_mpdu(struct iwl_mld *mld, struct napi_struct *napi,
17331786
struct sk_buff *skb;
17341787
size_t mpdu_desc_size = sizeof(*mpdu_desc);
17351788
bool drop = false;
1736-
u8 crypto_len = 0, band;
1789+
u8 crypto_len = 0, band, link_id;
17371790
u32 pkt_len = iwl_rx_packet_payload_len(pkt);
17381791
u32 mpdu_len;
17391792
enum iwl_mld_reorder_result reorder_res;
@@ -1822,7 +1875,10 @@ void iwl_mld_rx_mpdu(struct iwl_mld *mld, struct napi_struct *napi,
18221875
SCHED_SCAN_PASS_ALL_STATE_FOUND;
18231876
}
18241877

1825-
iwl_mld_rx_fill_status(mld, skb, &phy_data, queue);
1878+
link_id = u8_get_bits(mpdu_desc->mac_phy_band,
1879+
IWL_RX_MPDU_MAC_PHY_BAND_LINK_MASK);
1880+
1881+
iwl_mld_rx_fill_status(mld, link_id, hdr, skb, &phy_data, queue);
18261882

18271883
if (iwl_mld_rx_crypto(mld, sta, hdr, rx_status, mpdu_desc, queue,
18281884
le32_to_cpu(pkt->len_n_flags), &crypto_len))
@@ -2035,7 +2091,8 @@ void iwl_mld_rx_monitor_no_data(struct iwl_mld *mld, struct napi_struct *napi,
20352091
rx_status->freq = ieee80211_channel_to_frequency(channel,
20362092
rx_status->band);
20372093

2038-
iwl_mld_rx_fill_status(mld, skb, &phy_data, queue);
2094+
/* link ID is ignored for NULL header */
2095+
iwl_mld_rx_fill_status(mld, -1, NULL, skb, &phy_data, queue);
20392096

20402097
/* No more radiotap info should be added after this point.
20412098
* Mark it as mac header for upper layers to know where

drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1769,6 +1769,8 @@ void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif)
17691769
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
17701770
return;
17711771

1772+
mvmvif->deflink.average_beacon_energy = 0;
1773+
17721774
INIT_DELAYED_WORK(&mvmvif->csa_work,
17731775
iwl_mvm_channel_switch_disconnect_wk);
17741776

drivers/net/wireless/intel/iwlwifi/mvm/mvm.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,8 @@ struct iwl_probe_resp_data {
304304
* @mcast_sta: multicast station
305305
* @phy_ctxt: phy context allocated to this link, if any
306306
* @bf_data: beacon filtering data
307+
* @average_beacon_energy: average beacon energy for beacons received during
308+
* client connections
307309
*/
308310
struct iwl_mvm_vif_link_info {
309311
u8 bssid[ETH_ALEN];
@@ -342,6 +344,7 @@ struct iwl_mvm_vif_link_info {
342344
u16 mgmt_queue;
343345

344346
struct iwl_mvm_link_bf_data bf_data;
347+
u32 average_beacon_energy;
345348
};
346349

347350
/**
@@ -2074,6 +2077,9 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
20742077
struct iwl_rx_cmd_buffer *rxb);
20752078
void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm,
20762079
struct iwl_rx_cmd_buffer *rxb);
2080+
void iwl_mvm_rx_beacon_filter_notif(struct iwl_mvm *mvm,
2081+
struct iwl_rx_cmd_buffer *rxb);
2082+
20772083
/* Bindings */
20782084
int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
20792085
int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);

drivers/net/wireless/intel/iwlwifi/mvm/ops.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,11 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
489489
RX_HANDLER_GRP(SCAN_GROUP, CHANNEL_SURVEY_NOTIF,
490490
iwl_mvm_rx_channel_survey_notif, RX_HANDLER_ASYNC_LOCKED,
491491
struct iwl_umac_scan_channel_survey_notif),
492+
RX_HANDLER_GRP(DATA_PATH_GROUP, BEACON_FILTER_IN_NOTIF,
493+
iwl_mvm_rx_beacon_filter_notif,
494+
RX_HANDLER_ASYNC_LOCKED,
495+
/* same size as v1 */
496+
struct iwl_beacon_filter_notif),
492497
};
493498
#undef RX_HANDLER
494499
#undef RX_HANDLER_GRP
@@ -659,6 +664,7 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
659664
HCMD_NAME(ESR_MODE_NOTIF),
660665
HCMD_NAME(MONITOR_NOTIF),
661666
HCMD_NAME(THERMAL_DUAL_CHAIN_REQUEST),
667+
HCMD_NAME(BEACON_FILTER_IN_NOTIF),
662668
HCMD_NAME(STA_PM_NOTIF),
663669
HCMD_NAME(MU_GROUP_MGMT_NOTIF),
664670
HCMD_NAME(RX_QUEUES_NOTIFICATION),

0 commit comments

Comments
 (0)