Adding NO_STA flag and reworking RX link resolution
Subsystems (4)
cover Adding NO_STA flag and reworking RX link resolution
From: Benjamin Berg <[email protected]>
Hi,
This patchset refactors the RX link resolution a bit to fix some issues where mac80211 might accept frames on the wrong link and incorrectly translate the address. It also adds a new NL80211_ATTR_FRAME_CMD_NO_STA flag so that userspace can know whether address translation was done by the kernel on RX and can also prevent address translation for management frames during TX.
This together should be enough to fix the existing issues in hostapd where stations that are still associated try to authenticate again but hostapd for example ends up sending the frame to an old link address.
I would appreciate if you test the patches and work on the hostapd side. Note that I have not properly verified the new nl80211 API, so it could well be that I missed something.
Benjamin
Benjamin Berg (8):
wifi: iwlwifi: use link_sta internally to the driver
wifi: mac80211: change public RX API to use link stations
wifi: mac80211: refactor RX link_id and station handling
wifi: mac80211: rework RX packet handling
wifi: cfg80211: add attribute for TX/RX denoting there is no station
wifi: mac80211: report to cfg80211 when no STA is known for a frame
wifi: mac80211: pass station to ieee80211_tx_skb_tid
wifi: mac80211: pass error station if non-STA transmit was requested
drivers/net/wireless/intel/iwlwifi/mld/agg.c | 21 +- drivers/net/wireless/intel/iwlwifi/mld/agg.h | 4 +- drivers/net/wireless/intel/iwlwifi/mld/rx.c | 50 +- drivers/net/wireless/intel/iwlwifi/mld/rx.h | 2 +- .../wireless/intel/iwlwifi/mld/tests/agg.c | 7 +- drivers/net/wireless/intel/iwlwifi/mvm/rx.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 6 +- drivers/net/wireless/virtual/mac80211_hwsim.c | 3 - include/net/cfg80211.h | 4 + include/net/mac80211.h | 25 +- include/uapi/linux/nl80211.h | 7 + net/mac80211/agg-tx.c | 6 +- net/mac80211/eht.c | 3 - net/mac80211/ht.c | 4 +- net/mac80211/ieee80211_i.h | 14 +- net/mac80211/iface.c | 7 +- net/mac80211/mlme.c | 9 +- net/mac80211/offchannel.c | 13 +- net/mac80211/rx.c | 438 ++++++++++-------- net/mac80211/scan.c | 10 +- net/mac80211/tdls.c | 4 +- net/mac80211/tx.c | 8 +- net/wireless/nl80211.c | 8 +- 23 files changed, 358 insertions(+), 297 deletions(-)
Signature · 1 line
2.53.0
RFC PATCH 1/8 wifi: iwlwifi: use link_sta internally to the driver
From: Benjamin Berg <[email protected]>
Using the link_sta is a natural way to pass both the STA and the link ID information at the same time. Use that internally to the driver in preparation to mac80211 changing its API and adopting the same method.
--- drivers/net/wireless/intel/iwlwifi/mld/agg.c | 21 +++++---- drivers/net/wireless/intel/iwlwifi/mld/agg.h | 4 +- drivers/net/wireless/intel/iwlwifi/mld/rx.c | 45 ++++++++++--------- drivers/net/wireless/intel/iwlwifi/mld/rx.h | 2 +- .../wireless/intel/iwlwifi/mld/tests/agg.c | 7 +-- 5 files changed, 42 insertions(+), 37 deletions(-)
drivers/net/wireless/intel/iwlwifi/mld/agg.c +12 -9
@@ -1,13 +1,14 @@// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* -* Copyright (C) 2024-2025 Intel Corporation +* Copyright (C) 2024-2026 Intel Corporation */ #include "agg.h" #include "sta.h" #include "hcmd.h" static void -iwl_mld_reorder_release_frames(struct iwl_mld *mld, struct ieee80211_sta *sta, +iwl_mld_reorder_release_frames(struct iwl_mld *mld, + struct ieee80211_link_sta *link_sta, struct napi_struct *napi, struct iwl_mld_baid_data *baid_data, struct iwl_mld_reorder_buffer *reorder_buf,
@@ -32,7 +33,7 @@ iwl_mld_reorder_release_frames(struct iwl_mld *mld, struct ieee80211_sta *sta,while ((skb =__skb_dequeue (skb_list))) {iwl_mld_pass_packet_to_mac80211 (mld, napi, skb, reorder_buf->queue, - sta); + link_sta); reorder_buf->num_stored--; } }
@@ -71,7 +72,7 @@ static void iwl_mld_release_frames_from_notif(struct iwl_mld *mld, reorder_buf = &ba_data->reorder_buf[queue]; -iwl_mld_reorder_release_frames (mld, link_sta->sta, napi, ba_data, +iwl_mld_reorder_release_frames (mld, link_sta, napi, ba_data, reorder_buf, nssn); out_unlock:rcu_read_unlock ();
@@ -174,7 +175,7 @@ void iwl_mld_del_ba(struct iwl_mld *mld, int queue, reorder_buf = &ba_data->reorder_buf[queue];/* release all frames that are in the reorder buffer to the stack */ -iwl_mld_reorder_release_frames (mld, link_sta->sta,NULL , +iwl_mld_reorder_release_frames (mld, link_sta,NULL , ba_data, reorder_buf,ieee80211_sn_add (reorder_buf->head_sn, ba_data->buf_size));
@@ -187,14 +188,14 @@ void iwl_mld_del_ba(struct iwl_mld *mld, int queue,*/ enum iwl_mld_reorder_result iwl_mld_reorder (struct iwl_mld *mld,struct napi_struct *napi, -int queue,struct ieee80211_sta *sta, +int queue,struct ieee80211_link_sta *link_sta,struct sk_buff *skb,struct iwl_rx_mpdu_desc *desc) {struct ieee80211_hdr *hdr = (void *)skb_mac_header (skb);struct iwl_mld_baid_data *baid_data;struct iwl_mld_reorder_buffer *buffer;struct iwl_mld_reorder_buf_entry *entries; -struct iwl_mld_sta *mld_sta =iwl_mld_sta_from_mac80211 (sta); +struct iwl_mld_sta *mld_sta;struct iwl_mld_link_sta *mld_link_sta;u32 reorder =le32_to_cpu (desc->reorder_data);bool amsdu, last_subframe, is_old_sn, is_dup;
@@ -217,10 +218,12 @@ iwl_mld_reorder(struct iwl_mld *mld, struct napi_struct *napi,return IWL_MLD_PASS_SKB ;/* no sta yet */ -if (WARN_ONCE (!sta, +if (WARN_ONCE (!link_sta,"Got valid BAID without a valid station assigned\n" ))return IWL_MLD_PASS_SKB ; + mld_sta =iwl_mld_sta_from_mac80211 (link_sta->sta); +/* not a data packet */ if (!ieee80211_is_data_qos (hdr->frame_control) ||is_multicast_ether_addr (hdr->addr1))
@@ -310,7 +313,7 @@ iwl_mld_reorder(struct iwl_mld *mld, struct napi_struct *napi,* will be released when the frame release notification arrives. */ if (!amsdu || last_subframe) -iwl_mld_reorder_release_frames (mld, sta, napi, baid_data, +iwl_mld_reorder_release_frames (mld, link_sta, napi, baid_data, buffer, nssn);else if (buffer->num_stored ==1 ) buffer->head_sn = nssn;
drivers/net/wireless/intel/iwlwifi/mld/agg.h +2 -2
@@ -1,6 +1,6 @@/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* -* Copyright (C) 2024 Intel Corporation +* Copyright (C) 2024, 2026 Intel Corporation */ #ifndef __iwl_agg_h__#define __iwl_agg_h__
@@ -106,7 +106,7 @@ int iwl_mld_ampdu_rx_stop(struct iwl_mld *mld, struct ieee80211_sta *sta,enum iwl_mld_reorder_result iwl_mld_reorder (struct iwl_mld *mld,struct napi_struct *napi, -int queue,struct ieee80211_sta *sta, +int queue,struct ieee80211_link_sta *link_sta,struct sk_buff *skb,struct iwl_rx_mpdu_desc *desc); void iwl_mld_handle_frame_release_notif(struct iwl_mld *mld,
drivers/net/wireless/intel/iwlwifi/mld/rx.c +23 -22
151 lines not on this page · raw message
drivers/net/wireless/intel/iwlwifi/mld/rx.h +1 -1
@@ -64,7 +64,7 @@ void iwl_mld_handle_rx_queues_sync_notif(struct iwl_mld *mld,void iwl_mld_pass_packet_to_mac80211 (struct iwl_mld *mld,struct napi_struct *napi,struct sk_buff *skb,int queue, -struct ieee80211_sta *sta); +struct ieee80211_link_sta *link_sta); void iwl_mld_handle_phy_air_sniffer_notif(struct iwl_mld *mld, struct napi_struct *napi,
drivers/net/wireless/intel/iwlwifi/mld/tests/agg.c +4 -3
@@ -2,7 +2,7 @@/* * KUnit tests for channel helper functions * -* Copyright (C) 2024-2025 Intel Corporation +* Copyright (C) 2024-2026 Intel Corporation */ #include <kunit/test.h> #include <kunit/static_stub.h>
@@ -441,7 +441,7 @@ static void fake_iwl_mld_pass_packet_to_mac80211(struct iwl_mld *mld, struct napi_struct *napi, struct sk_buff *skb, int queue, - struct ieee80211_sta *sta) + struct ieee80211_link_sta *link_sta) { __skb_queue_tail(&g_released_skbs, skb); g_num_released_skbs++;
@@ -630,7 +630,8 @@ static void test_reorder_buffer(struct kunit *test) mpdu_desc =setup_mpdu_desc ();rcu_read_lock (); - reorder_res =iwl_mld_reorder (mld,NULL ,QUEUE , sta, skb, mpdu_desc); + reorder_res =iwl_mld_reorder (mld,NULL ,QUEUE , &sta->deflink, skb, + mpdu_desc);rcu_read_unlock ();KUNIT_ASSERT_EQ (test, reorder_res, param->expected.reorder_res);
Signature · 1 line
2.53.0
RFC PATCH 2/8 wifi: mac80211: change public RX API to use link stations
In reply to Benjamin BergFrom: Benjamin Berg <[email protected]>
If a station is passed then the link ID also needs to be known. As such, it is a more natural API to simply pass the link station directly rather than pushing the link information into the RX status.
Furthermore, having the link ID in the RX status is not actually correct because the link IDs are VIF specific and there may be multiple VIFs. In the case of a station this relationship is clear, but then one may as well use the link station.
This patch only changes the API and emulates the old (incorrect) behaviour for now. The mac80211 RX code will be updated in later patches.
---
This is obviously incomplete. Though one can adjust drivers easily by passing sta->link[status->link_id] as that information has been prepared.
--- drivers/net/wireless/intel/iwlwifi/mld/rx.c | 7 +------ drivers/net/wireless/intel/iwlwifi/mvm/rx.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 6 +++--- drivers/net/wireless/virtual/mac80211_hwsim.c | 3 --- include/net/mac80211.h | 16 +++++++++++---- net/mac80211/rx.c | 20 ++++++++++++++----- 6 files changed, 32 insertions(+), 22 deletions(-)
drivers/net/wireless/intel/iwlwifi/mld/rx.c +1 -6
@@ -131,7 +131,7 @@ void iwl_mld_pass_packet_to_mac80211(struct iwl_mld *mld,return ; } -ieee80211_rx_napi (mld->hw, link_sta->sta, skb, napi); +ieee80211_rx_napi (mld->hw, link_sta, skb, napi); }EXPORT_SYMBOL_IF_IWLWIFI_KUNIT (iwl_mld_pass_packet_to_mac80211);
@@ -1765,11 +1765,6 @@ iwl_mld_rx_with_sta(struct iwl_mld *mld, struct ieee80211_hdr *hdr, rx_status =IEEE80211_SKB_RXCB (skb); -if (link_sta && sta->valid_links) { - rx_status->link_valid = true; - rx_status->link_id = link_sta->link_id; - } -/* fill checksum */ if (ieee80211_is_data (hdr->frame_control) && pkt->len_n_flags &cpu_to_le32 (FH_RSCSR_RPA_EN )) {
drivers/net/wireless/intel/iwlwifi/mvm/rx.c +1 -1
@@ -90,7 +90,7 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm, fraglen, rxb->truesize); } -ieee80211_rx_napi (mvm->hw, sta, skb, napi); +ieee80211_rx_napi (mvm->hw, &sta->deflink, skb, napi); }/*
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +3 -3
@@ -1,6 +1,6 @@// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* -* Copyright (C) 2012-2014, 2018-2025 Intel Corporation +* Copyright (C) 2012-2014, 2018-2026 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH */
@@ -243,7 +243,7 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,return ; } -ieee80211_rx_napi (mvm->hw, sta, skb, napi); +ieee80211_rx_napi (mvm->hw, &sta->deflink, skb, napi); } static bool iwl_mvm_used_average_energy(struct iwl_mvm *mvm,
@@ -2528,7 +2528,7 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi, }rcu_read_lock (); -ieee80211_rx_napi (mvm->hw, sta, skb, napi); +ieee80211_rx_napi (mvm->hw, &sta->deflink, skb, napi);rcu_read_unlock (); }
drivers/net/wireless/virtual/mac80211_hwsim.c +0 -3
@@ -1755,9 +1755,6 @@ static void mac80211_hwsim_rx(struct mac80211_hwsim_data *data, sp->active_links_rx &= ~BIT (link_id); else sp->active_links_rx |= BIT(link_id); - - rx_status->link_valid = true; - rx_status->link_id = link_id; }rcu_read_unlock (); }
include/net/mac80211.h +12 -4
@@ -5207,14 +5207,18 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw);* mixed for a single hardware. Must not run concurrently with * ieee80211_tx_status_skb() or ieee80211_tx_status_ni(). * +* For data frames, when hardware has done address translation, a link station +* has to be provided and the frequency information may be skipped. +* * This function must be called with BHs disabled and RCU read lock * * @hw: the hardware this frame came in on -* @sta: the station the frame was received from, or %NULL +* @link_sta: the link station the data frame was received from, or %NULL * @skb: the buffer to receive, owned by mac80211 after this call * @list: the destination list */ -void ieee80211_rx_list (struct ieee80211_hw *hw,struct ieee80211_sta *sta, +void ieee80211_rx_list (struct ieee80211_hw *hw, +struct ieee80211_link_sta *link_sta,struct sk_buff *skb,struct list_head *list);/**
@@ -5232,14 +5236,18 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *sta,* mixed for a single hardware. Must not run concurrently with * ieee80211_tx_status_skb() or ieee80211_tx_status_ni(). * +* For data frames, when hardware has done address translation, a link station +* has to be provided and the frequency information may be skipped. +* * This function must be called with BHs disabled. * * @hw: the hardware this frame came in on -* @sta: the station the frame was received from, or %NULL +* @link_sta: the link station the data frame was received from, or %NULL * @skb: the buffer to receive, owned by mac80211 after this call * @napi: the NAPI context */ -void ieee80211_rx_napi (struct ieee80211_hw *hw,struct ieee80211_sta *sta, +void ieee80211_rx_napi (struct ieee80211_hw *hw, +struct ieee80211_link_sta *link_sta,struct sk_buff *skb,struct napi_struct *napi);/**
net/mac80211/rx.c +15 -5
@@ -5432,7 +5432,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,* This is the receive path handler. It is called by a low level driver when an * 802.11 MPDU is received from the hardware. */ -void ieee80211_rx_list (struct ieee80211_hw *hw,struct ieee80211_sta *pubsta, +void ieee80211_rx_list (struct ieee80211_hw *hw, +struct ieee80211_link_sta *link_pubsta,struct sk_buff *skb,struct list_head *list) {struct ieee80211_local *local =hw_to_local (hw);
@@ -5440,6 +5441,7 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,struct ieee80211_supported_band *sband;struct ieee80211_rx_status *status =IEEE80211_SKB_RXCB (skb);struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; +struct ieee80211_sta *pubsta;WARN_ON_ONCE (softirq_count () ==0 );
@@ -5562,8 +5564,15 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, } } -if (WARN_ON_ONCE (status->link_id >=IEEE80211_LINK_UNSPECIFIED )) - goto drop; +/* FIXME: Emulate the old driver behaviour for now */ +if (link_pubsta) { + status->link_valid =1 ; + status->link_id = link_pubsta->link_id; + pubsta = link_pubsta->sta; + }else { + status->link_valid =0 ; + pubsta =NULL ; + } status->rx_flags =0 ;
@@ -5595,7 +5604,8 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, }EXPORT_SYMBOL (ieee80211_rx_list); -void ieee80211_rx_napi (struct ieee80211_hw *hw,struct ieee80211_sta *pubsta, +void ieee80211_rx_napi (struct ieee80211_hw *hw, +struct ieee80211_link_sta *link_pubsta,struct sk_buff *skb,struct napi_struct *napi) {struct sk_buff *tmp;
@@ -5608,7 +5618,7 @@ void ieee80211_rx_napi(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,* receive processing */ rcu_read_lock (); -ieee80211_rx_list (hw, pubsta, skb, &list); +ieee80211_rx_list (hw, link_pubsta, skb, &list);rcu_read_unlock ();if (!napi) {
Signature · 1 line
2.53.0
kernel test robot
build botRe: [RFC PATCH 2/8] wifi: mac80211: change public RX API to use link stations
kernel test robot noticed the following build errors:
Hi Benjamin,
[This is a private test report for your RFC patch.] kernel test robot noticed the following build errors:
[auto build test ERROR on wireless-next/main]
[also build test ERROR on wireless/main linus/master v6.19 next-20260220] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Benjamin-Berg/wifi-iwlwifi-use-link_sta-internally-to-the-driver/20260220-222422 base: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git main patch link: https://lore.kernel.org/r/20260220151929.61ef722ac889.I4a2d45609e94b52654b10ec572e59a45d09c41f4%40changeid patch subject: [RFC PATCH 2/8] wifi: mac80211: change public RX API to use link stations config: nios2-allmodconfig (https://download.01.org/0day-ci/archive/20260221/[email protected]/config) compiler: nios2-linux-gcc (GCC) 11.5.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260221/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
drivers/net/wireless/ath/ath11k/dp_rx.c: In function 'ath11k_dp_rx_deliver_msdu':
>> drivers/net/wireless/ath/ath11k/dp_rx.c:2503:35: error: passing argument 2 of 'ieee80211_rx_napi' from incompatible pointer type [-Werror=incompatible-pointer-types]
2503 | ieee80211_rx_napi(ar->hw, pubsta, msdu, napi);
| ^~~~~~
| |
| struct ieee80211_sta *
In file included from drivers/net/wireless/ath/ath11k/wmi.h:10,
from drivers/net/wireless/ath/ath11k/core.h:24,
from drivers/net/wireless/ath/ath11k/dp_rx.c:11:
include/net/mac80211.h:5250:51: note: expected 'struct ieee80211_link_sta *' but argument is of type 'struct ieee80211_sta *'
5250 | struct ieee80211_link_sta *link_sta,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
cc1: some warnings being treated as errors
--
drivers/net/wireless/mediatek/mt76/mac80211.c: In function 'mt76_rx_complete':
>> drivers/net/wireless/mediatek/mt76/mac80211.c:1522:39: error: passing argument 2 of 'ieee80211_rx_list' from incompatible pointer type [-Werror=incompatible-pointer-types]
1522 | ieee80211_rx_list(hw, sta, skb, &list);
| ^~~
| |
| struct ieee80211_sta *
In file included from drivers/net/wireless/mediatek/mt76/mt76.h:18,
from drivers/net/wireless/mediatek/mt76/mac80211.c:7:
include/net/mac80211.h:5221:51: note: expected 'struct ieee80211_link_sta *' but argument is of type 'struct ieee80211_sta *'
5221 | struct ieee80211_link_sta *link_sta,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
drivers/net/wireless/mediatek/mt76/mac80211.c:1531:47: error: passing argument 2 of 'ieee80211_rx_list' from incompatible pointer type [-Werror=incompatible-pointer-types]
1531 | ieee80211_rx_list(hw, sta, skb, &list);
| ^~~
| |
| struct ieee80211_sta *
In file included from drivers/net/wireless/mediatek/mt76/mt76.h:18,
from drivers/net/wireless/mediatek/mt76/mac80211.c:7:
include/net/mac80211.h:5221:51: note: expected 'struct ieee80211_link_sta *' but argument is of type 'struct ieee80211_sta *'
5221 | struct ieee80211_link_sta *link_sta,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~cc1: some warnings being treated as errors
vim +/ieee80211_rx_napi +2503 drivers/net/wireless/ath/ath11k/dp_rx.c
d5c65159f289537 Kalle Valo 2019-11-23 2426
d5c65159f289537 Kalle Valo 2019-11-23 2427 static void ath11k_dp_rx_deliver_msdu(struct ath11k *ar, struct napi_struct *napi,
2167fa606c0f0e6 Sriram R 2021-09-28 2428 struct sk_buff *msdu,
2167fa606c0f0e6 Sriram R 2021-09-28 2429 struct ieee80211_rx_status *status)
d5c65159f289537 Kalle Valo 2019-11-23 2430 {
e4eb7b5c335ccfd John Crispin 2019-11-25 2431 static const struct ieee80211_radiotap_he known = {
93634c61056e345 John Crispin 2019-12-17 2432 .data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN |
93634c61056e345 John Crispin 2019-12-17 2433 IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN),
e4eb7b5c335ccfd John Crispin 2019-11-25 2434 .data2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN),
e4eb7b5c335ccfd John Crispin 2019-11-25 2435 };
2167fa606c0f0e6 Sriram R 2021-09-28 2436 struct ieee80211_rx_status *rx_status;
e4eb7b5c335ccfd John Crispin 2019-11-25 2437 struct ieee80211_radiotap_he *he = NULL;
2167fa606c0f0e6 Sriram R 2021-09-28 2438 struct ieee80211_sta *pubsta = NULL;
2167fa606c0f0e6 Sriram R 2021-09-28 2439 struct ath11k_peer *peer;
2167fa606c0f0e6 Sriram R 2021-09-28 2440 struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu);
2167fa606c0f0e6 Sriram R 2021-09-28 2441 u8 decap = DP_RX_DECAP_TYPE_RAW;
2167fa606c0f0e6 Sriram R 2021-09-28 2442 bool is_mcbc = rxcb->is_mcbc;
2167fa606c0f0e6 Sriram R 2021-09-28 2443 bool is_eapol = rxcb->is_eapol;
d5c65159f289537 Kalle Valo 2019-11-23 2444
2167fa606c0f0e6 Sriram R 2021-09-28 2445 if (status->encoding == RX_ENC_HE &&
2167fa606c0f0e6 Sriram R 2021-09-28 2446 !(status->flag & RX_FLAG_RADIOTAP_HE) &&
2167fa606c0f0e6 Sriram R 2021-09-28 2447 !(status->flag & RX_FLAG_SKIP_MONITOR)) {
e4eb7b5c335ccfd John Crispin 2019-11-25 2448 he = skb_push(msdu, sizeof(known));
e4eb7b5c335ccfd John Crispin 2019-11-25 2449 memcpy(he, &known, sizeof(known));
e4eb7b5c335ccfd John Crispin 2019-11-25 2450 status->flag |= RX_FLAG_RADIOTAP_HE;
e4eb7b5c335ccfd John Crispin 2019-11-25 2451 }
d5c65159f289537 Kalle Valo 2019-11-23 2452
2167fa606c0f0e6 Sriram R 2021-09-28 2453 if (!(status->flag & RX_FLAG_ONLY_MONITOR))
2167fa606c0f0e6 Sriram R 2021-09-28 2454 decap = ath11k_dp_rx_h_msdu_start_decap_type(ar->ab, rxcb->rx_desc);
2167fa606c0f0e6 Sriram R 2021-09-28 2455
2167fa606c0f0e6 Sriram R 2021-09-28 2456 spin_lock_bh(&ar->ab->base_lock);
2167fa606c0f0e6 Sriram R 2021-09-28 2457 peer = ath11k_dp_rx_h_find_peer(ar->ab, msdu);
2167fa606c0f0e6 Sriram R 2021-09-28 2458 if (peer && peer->sta)
2167fa606c0f0e6 Sriram R 2021-09-28 2459 pubsta = peer->sta;
2167fa606c0f0e6 Sriram R 2021-09-28 2460 spin_unlock_bh(&ar->ab->base_lock);
2167fa606c0f0e6 Sriram R 2021-09-28 2461
d5c65159f289537 Kalle Valo 2019-11-23 2462 ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
cf036c416e9a0a8 Kalle Valo 2023-06-09 2463 "rx skb %p len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
d5c65159f289537 Kalle Valo 2019-11-23 2464 msdu,
d5c65159f289537 Kalle Valo 2019-11-23 2465 msdu->len,
2167fa606c0f0e6 Sriram R 2021-09-28 2466 peer ? peer->addr : NULL,
2167fa606c0f0e6 Sriram R 2021-09-28 2467 rxcb->tid,
2167fa606c0f0e6 Sriram R 2021-09-28 2468 is_mcbc ? "mcast" : "ucast",
2167fa606c0f0e6 Sriram R 2021-09-28 2469 rxcb->seq_no,
d5c65159f289537 Kalle Valo 2019-11-23 2470 (status->encoding == RX_ENC_LEGACY) ? "legacy" : "",
d5c65159f289537 Kalle Valo 2019-11-23 2471 (status->encoding == RX_ENC_HT) ? "ht" : "",
d5c65159f289537 Kalle Valo 2019-11-23 2472 (status->encoding == RX_ENC_VHT) ? "vht" : "",
d5c65159f289537 Kalle Valo 2019-11-23 2473 (status->encoding == RX_ENC_HE) ? "he" : "",
d5c65159f289537 Kalle Valo 2019-11-23 2474 (status->bw == RATE_INFO_BW_40) ? "40" : "",
d5c65159f289537 Kalle Valo 2019-11-23 2475 (status->bw == RATE_INFO_BW_80) ? "80" : "",
d5c65159f289537 Kalle Valo 2019-11-23 2476 (status->bw == RATE_INFO_BW_160) ? "160" : "",
d5c65159f289537 Kalle Valo 2019-11-23 2477 status->enc_flags & RX_ENC_FLAG_SHORT_GI ? "sgi " : "",
d5c65159f289537 Kalle Valo 2019-11-23 2478 status->rate_idx,
d5c65159f289537 Kalle Valo 2019-11-23 2479 status->nss,
d5c65159f289537 Kalle Valo 2019-11-23 2480 status->freq,
d5c65159f289537 Kalle Valo 2019-11-23 2481 status->band, status->flag,
d5c65159f289537 Kalle Valo 2019-11-23 2482 !!(status->flag & RX_FLAG_FAILED_FCS_CRC),
d5c65159f289537 Kalle Valo 2019-11-23 2483 !!(status->flag & RX_FLAG_MMIC_ERROR),
d5c65159f289537 Kalle Valo 2019-11-23 2484 !!(status->flag & RX_FLAG_AMSDU_MORE));
d5c65159f289537 Kalle Valo 2019-11-23 2485
aa2092a9bab3f87 Venkateswara Naralasetty 2020-09-08 2486 ath11k_dbg_dump(ar->ab, ATH11K_DBG_DP_RX, NULL, "dp rx msdu: ",
aa2092a9bab3f87 Venkateswara Naralasetty 2020-09-08 2487 msdu->data, msdu->len);
aa2092a9bab3f87 Venkateswara Naralasetty 2020-09-08 2488
2167fa606c0f0e6 Sriram R 2021-09-28 2489 rx_status = IEEE80211_SKB_RXCB(msdu);
2167fa606c0f0e6 Sriram R 2021-09-28 2490 *rx_status = *status;
2167fa606c0f0e6 Sriram R 2021-09-28 2491
d5c65159f289537 Kalle Valo 2019-11-23 2492 /* TODO: trace rx packet */
d5c65159f289537 Kalle Valo 2019-11-23 2493
2167fa606c0f0e6 Sriram R 2021-09-28 2494 /* PN for multicast packets are not validate in HW,
2167fa606c0f0e6 Sriram R 2021-09-28 2495 * so skip 802.3 rx path
3fecca0e7de885c Jeff Johnson 2022-09-09 2496 * Also, fast_rx expects the STA to be authorized, hence
2167fa606c0f0e6 Sriram R 2021-09-28 2497 * eapol packets are sent in slow path.
2167fa606c0f0e6 Sriram R 2021-09-28 2498 */
2167fa606c0f0e6 Sriram R 2021-09-28 2499 if (decap == DP_RX_DECAP_TYPE_ETHERNET2_DIX && !is_eapol &&
2167fa606c0f0e6 Sriram R 2021-09-28 2500 !(is_mcbc && rx_status->flag & RX_FLAG_DECRYPTED))
2167fa606c0f0e6 Sriram R 2021-09-28 2501 rx_status->flag |= RX_FLAG_8023;
2167fa606c0f0e6 Sriram R 2021-09-28 2502
2167fa606c0f0e6 Sriram R 2021-09-28 @2503 ieee80211_rx_napi(ar->hw, pubsta, msdu, napi);
d5c65159f289537 Kalle Valo 2019-11-23 2504 }
d5c65159f289537 Kalle Valo 2019-11-23 2505 Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
kernel test robot
build botRe: [RFC PATCH 2/8] wifi: mac80211: change public RX API to use link stations
In reply to Benjamin Bergkernel test robot noticed the following build errors:
Hi Benjamin,
[This is a private test report for your RFC patch.] kernel test robot noticed the following build errors:
[auto build test ERROR on wireless-next/main]
[also build test ERROR on wireless/main linus/master v6.19 next-20260220] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Benjamin-Berg/wifi-iwlwifi-use-link_sta-internally-to-the-driver/20260220-222422 base: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git main patch link: https://lore.kernel.org/r/20260220151929.61ef722ac889.I4a2d45609e94b52654b10ec572e59a45d09c41f4%40changeid patch subject: [RFC PATCH 2/8] wifi: mac80211: change public RX API to use link stations config: x86_64-rhel-9.4-rust (https://download.01.org/0day-ci/archive/20260221/[email protected]/config) compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261) rustc: rustc 1.88.0 (6b00bc388 2025-06-23) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260221/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
>> drivers/net/wireless/mediatek/mt76/mac80211.c:1522:25: error: incompatible pointer types passing 'struct ieee80211_sta *' to parameter of type 'struct ieee80211_link_sta *' [-Werror,-Wincompatible-pointer-types]
1522 | ieee80211_rx_list(hw, sta, skb, &list);
| ^~~
include/net/mac80211.h:5221:37: note: passing argument to parameter 'link_sta' here
5221 | struct ieee80211_link_sta *link_sta,
| ^
drivers/net/wireless/mediatek/mt76/mac80211.c:1531:26: error: incompatible pointer types passing 'struct ieee80211_sta *' to parameter of type 'struct ieee80211_link_sta *' [-Werror,-Wincompatible-pointer-types]
1531 | ieee80211_rx_list(hw, sta, skb, &list);
| ^~~ include/net/mac80211.h:5221:37: note: passing argument to parameter 'link_sta' here
5221 | struct ieee80211_link_sta *link_sta,
| ^
2 errors generated.
--
>> drivers/net/wireless/ath/ath11k/dp_rx.c:2503:28: error: incompatible pointer types passing 'struct ieee80211_sta *' to parameter of type 'struct ieee80211_link_sta *' [-Werror,-Wincompatible-pointer-types]
2503 | ieee80211_rx_napi(ar->hw, pubsta, msdu, napi);
| ^~~~~~ include/net/mac80211.h:5250:37: note: passing argument to parameter 'link_sta' here
5250 | struct ieee80211_link_sta *link_sta,
| ^
1 error generated.
vim +1522 drivers/net/wireless/mediatek/mt76/mac80211.c
d71ef28636e435 Felix Fietkau 2018-01-27 1506
9d9d738b4b54c8 Felix Fietkau 2018-01-24 1507 void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames,
81e850ef2625cb Lorenzo Bianconi 2018-07-31 1508 struct napi_struct *napi)
17f1de56df0512 Felix Fietkau 2017-11-21 1509 {
9c68a57bc22d8c Felix Fietkau 2018-01-24 1510 struct ieee80211_sta *sta;
bfc394dd65ef47 Felix Fietkau 2019-10-11 1511 struct ieee80211_hw *hw;
3298b1f866fb41 Felix Fietkau 2020-07-25 1512 struct sk_buff *skb, *tmp;
3298b1f866fb41 Felix Fietkau 2020-07-25 1513 LIST_HEAD(list);
9d9d738b4b54c8 Felix Fietkau 2018-01-24 1514
c3d7c82a8bb017 Felix Fietkau 2018-04-25 1515 spin_lock(&dev->rx_lock);
9d9d738b4b54c8 Felix Fietkau 2018-01-24 1516 while ((skb = __skb_dequeue(frames)) != NULL) {
cc4b3c139ad308 Lorenzo Bianconi 2020-10-11 1517 struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
cc4b3c139ad308 Lorenzo Bianconi 2020-10-11 1518
3c1032e1221723 Felix Fietkau 2022-06-23 1519 mt76_check_ccmp_pn(skb);
cc4b3c139ad308 Lorenzo Bianconi 2020-10-11 1520 skb_shinfo(skb)->frag_list = NULL;
bfc394dd65ef47 Felix Fietkau 2019-10-11 1521 mt76_rx_convert(dev, skb, &hw, &sta);
3298b1f866fb41 Felix Fietkau 2020-07-25 @1522 ieee80211_rx_list(hw, sta, skb, &list);
cc4b3c139ad308 Lorenzo Bianconi 2020-10-11 1523
cc4b3c139ad308 Lorenzo Bianconi 2020-10-11 1524 /* subsequent amsdu frames */
cc4b3c139ad308 Lorenzo Bianconi 2020-10-11 1525 while (nskb) {
cc4b3c139ad308 Lorenzo Bianconi 2020-10-11 1526 skb = nskb;
cc4b3c139ad308 Lorenzo Bianconi 2020-10-11 1527 nskb = nskb->next;
cc4b3c139ad308 Lorenzo Bianconi 2020-10-11 1528 skb->next = NULL;
cc4b3c139ad308 Lorenzo Bianconi 2020-10-11 1529
cc4b3c139ad308 Lorenzo Bianconi 2020-10-11 1530 mt76_rx_convert(dev, skb, &hw, &sta);
cc4b3c139ad308 Lorenzo Bianconi 2020-10-11 1531 ieee80211_rx_list(hw, sta, skb, &list);
cc4b3c139ad308 Lorenzo Bianconi 2020-10-11 1532 }
9d9d738b4b54c8 Felix Fietkau 2018-01-24 1533 }
c3d7c82a8bb017 Felix Fietkau 2018-04-25 1534 spin_unlock(&dev->rx_lock);
3298b1f866fb41 Felix Fietkau 2020-07-25 1535
3298b1f866fb41 Felix Fietkau 2020-07-25 1536 if (!napi) {
3298b1f866fb41 Felix Fietkau 2020-07-25 1537 netif_receive_skb_list(&list);
3298b1f866fb41 Felix Fietkau 2020-07-25 1538 return;
3298b1f866fb41 Felix Fietkau 2020-07-25 1539 }
3298b1f866fb41 Felix Fietkau 2020-07-25 1540
3298b1f866fb41 Felix Fietkau 2020-07-25 1541 list_for_each_entry_safe(skb, tmp, &list, list) {
3298b1f866fb41 Felix Fietkau 2020-07-25 1542 skb_list_del_init(skb);
3298b1f866fb41 Felix Fietkau 2020-07-25 1543 napi_gro_receive(napi, skb);
3298b1f866fb41 Felix Fietkau 2020-07-25 1544 }
9d9d738b4b54c8 Felix Fietkau 2018-01-24 1545 }
9d9d738b4b54c8 Felix Fietkau 2018-01-24 1546 Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
RFC PATCH 3/8 wifi: mac80211: refactor RX link_id and station handling
In reply to Benjamin BergFrom: Benjamin Berg <[email protected]>
The link ID for one frequency may be different between VIFs. As such, the sensible thing is to set the link ID later in the flow once the SKB is duplicated for each VIF. As the link ID is not passed in from outside mac80211 it is always valid and the corresponding bit can be dropped.
Also switch a few more places to pass the link STA as that is a natural way to pass the link information around.
This fixes the per-link statistics when frames are reordered.
Note that this patch deliberately leaves some places unchanged and even incorrect as this will be addressed by further refactorings.
--- include/net/mac80211.h | 9 +- net/mac80211/eht.c | 3 - net/mac80211/iface.c | 7 +- net/mac80211/mlme.c | 9 +- net/mac80211/rx.c | 209 ++++++++++++++++++----------------------- net/mac80211/scan.c | 10 +- 6 files changed, 105 insertions(+), 142 deletions(-)
include/net/mac80211.h +4 -5
@@ -1655,10 +1655,9 @@ enum mac80211_rx_encoding {* @ampdu_reference: A-MPDU reference number, must be a different value for * each A-MPDU but the same for each subframe within one A-MPDU * @zero_length_psdu_type: radiotap type of the 0-length PSDU -* @link_valid: if the link which is identified by @link_id is valid. This flag -* is set only when connection is MLO. -* @link_id: id of the link used to receive the packet. This is used along with -* @link_valid. +* @link_id: id of the link used to receive the packet. Set and used by +* mac80211 internally, it uses @freq set by the driver to identify the +* correct link per vif. */ struct ieee80211_rx_status {u64 mactime;
@@ -1698,7 +1697,7 @@ struct ieee80211_rx_status {u8 chains;s8 chain_signal[IEEE80211_MAX_CHAINS ];u8 zero_length_psdu_type; - u8 link_valid:1, link_id:4; + u8 link_id:4; }; static inline u32
net/mac80211/eht.c +0 -3
@@ -174,9 +174,6 @@ void ieee80211_rx_eml_op_mode_notif(struct ieee80211_sub_if_data *sdata,if (!ift_ext_capa)return ; -if (!status->link_valid) -return ; - sta =sta_info_get_bss (sdata, mgmt->sa);if (!sta)return ;
net/mac80211/iface.c +2 -5
@@ -1611,11 +1611,8 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,break ; status =IEEE80211_SKB_RXCB (skb); -if (!status->link_valid) - link_sta = &sta->deflink; -else - link_sta =rcu_dereference_protected (sta->link[status->link_id], -lockdep_is_held (&local->hw.wiphy->mtx)); + link_sta =wiphy_dereference (local->hw.wiphy, + sta->link[status->link_id]);if (link_sta) ieee80211_ht_handle_chanwidth_notif(local, sdata, sta, link_sta, chanwidth,
net/mac80211/mlme.c +3 -6
@@ -8273,12 +8273,9 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, mgmt = (struct ieee80211_mgmt *) skb->data; fc =le16_to_cpu (mgmt->frame_control); -if (rx_status->link_valid) { - link =sdata_dereference (sdata->link[rx_status->link_id], - sdata); -if (!link) -return ; - } + link =sdata_dereference (sdata->link[rx_status->link_id], sdata); +if (!link) +return ;switch (fc &IEEE80211_FCTL_STYPE ) {case IEEE80211_STYPE_BEACON :
net/mac80211/rx.c +92 -117
440 lines not on this page · raw message
net/mac80211/scan.c +4 -6
@@ -9,7 +9,7 @@* Copyright 2007, Michael Wu <[email protected]> * Copyright 2013-2015 Intel Mobile Communications GmbH * Copyright 2016-2017 Intel Deutschland GmbH -* Copyright (C) 2018-2025 Intel Corporation +* Copyright (C) 2018-2026 Intel Corporation */ #include <linux/if_arp.h>
@@ -204,12 +204,10 @@ ieee80211_bss_info_update(struct ieee80211_local *local,* an indication on which of the links the frame was received */ if (ieee80211_vif_is_mld (&scan_sdata->vif)) { -if (rx_status->link_valid) { -s8 link_id = rx_status->link_id; +s8 link_id = rx_status->link_id; - link_conf = -rcu_dereference (scan_sdata->vif.link_conf[link_id]); - } + link_conf = +rcu_dereference (scan_sdata->vif.link_conf[link_id]); }else { link_conf = &scan_sdata->vif.bss_conf; }
Signature · 1 line
2.53.0
kernel test robot
build botRe: [RFC PATCH 3/8] wifi: mac80211: refactor RX link_id and station handling
kernel test robot noticed the following build errors:
Hi Benjamin,
[This is a private test report for your RFC patch.] kernel test robot noticed the following build errors:
[auto build test ERROR on wireless-next/main]
[also build test ERROR on wireless/main linus/master next-20260220] [cannot apply to v6.19]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Benjamin-Berg/wifi-iwlwifi-use-link_sta-internally-to-the-driver/20260220-222422 base: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git main patch link: https://lore.kernel.org/r/20260220151929.5b3a42e30504.I8abe3601d0335dca22d48bcee864817cfccf0de0%40changeid patch subject: [RFC PATCH 3/8] wifi: mac80211: refactor RX link_id and station handling config: nios2-allmodconfig (https://download.01.org/0day-ci/archive/20260221/[email protected]/config) compiler: nios2-linux-gcc (GCC) 11.5.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260221/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
drivers/net/wireless/mediatek/mt76/mac80211.c: In function 'mt76_rx_convert':
>> drivers/net/wireless/mediatek/mt76/mac80211.c:1282:25: error: 'struct ieee80211_rx_status' has no member named 'link_valid'; did you mean 'link_id'?
1282 | status->link_valid = mstat.wcid->link_valid;
| ^~~~~~~~~~
| link_id
drivers/net/wireless/mediatek/mt76/mac80211.c: In function 'mt76_rx_complete':
drivers/net/wireless/mediatek/mt76/mac80211.c:1522:39: error: passing argument 2 of 'ieee80211_rx_list' from incompatible pointer type [-Werror=incompatible-pointer-types]
1522 | ieee80211_rx_list(hw, sta, skb, &list);
| ^~~
| |
| struct ieee80211_sta *
In file included from drivers/net/wireless/mediatek/mt76/mt76.h:18,
from drivers/net/wireless/mediatek/mt76/mac80211.c:7:
include/net/mac80211.h:5220:51: note: expected 'struct ieee80211_link_sta *' but argument is of type 'struct ieee80211_sta *'
5220 | struct ieee80211_link_sta *link_sta,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
drivers/net/wireless/mediatek/mt76/mac80211.c:1531:47: error: passing argument 2 of 'ieee80211_rx_list' from incompatible pointer type [-Werror=incompatible-pointer-types]
1531 | ieee80211_rx_list(hw, sta, skb, &list);
| ^~~
| |
| struct ieee80211_sta *
In file included from drivers/net/wireless/mediatek/mt76/mt76.h:18,
from drivers/net/wireless/mediatek/mt76/mac80211.c:7:
include/net/mac80211.h:5220:51: note: expected 'struct ieee80211_link_sta *' but argument is of type 'struct ieee80211_sta *'
5220 | struct ieee80211_link_sta *link_sta,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
cc1: some warnings being treated as errors
--
drivers/net/wireless/realtek/rtw89/core.c: In function 'rtw89_vif_rx_stats_iter':
>> drivers/net/wireless/realtek/rtw89/core.c:2992:28: error: 'struct ieee80211_rx_status' has no member named 'link_valid'; did you mean 'link_id'?
2992 | rx_status->link_valid = true;
| ^~~~~~~~~~
| link_idvim +1282 drivers/net/wireless/mediatek/mt76/mac80211.c
4550fb9e98104f Felix Fietkau 2022-02-04 1231
bfc394dd65ef47 Felix Fietkau 2019-10-11 1232 static void
bfc394dd65ef47 Felix Fietkau 2019-10-11 1233 mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
bfc394dd65ef47 Felix Fietkau 2019-10-11 1234 struct ieee80211_hw **hw,
bfc394dd65ef47 Felix Fietkau 2019-10-11 1235 struct ieee80211_sta **sta)
4e34249e9565dc Felix Fietkau 2018-01-24 1236 {
4e34249e9565dc Felix Fietkau 2018-01-24 1237 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
abe3f3da670981 Ryder Lee 2021-08-25 1238 struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
4e34249e9565dc Felix Fietkau 2018-01-24 1239 struct mt76_rx_status mstat;
4e34249e9565dc Felix Fietkau 2018-01-24 1240
4e34249e9565dc Felix Fietkau 2018-01-24 1241 mstat = *((struct mt76_rx_status *)skb->cb);
4e34249e9565dc Felix Fietkau 2018-01-24 1242 memset(status, 0, sizeof(*status));
4e34249e9565dc Felix Fietkau 2018-01-24 1243
6855bebea8f893 Howard Hsu 2025-09-15 1244 skb->priority = mstat.qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
6855bebea8f893 Howard Hsu 2025-09-15 1245
4e34249e9565dc Felix Fietkau 2018-01-24 1246 status->flag = mstat.flag;
4e34249e9565dc Felix Fietkau 2018-01-24 1247 status->freq = mstat.freq;
4e34249e9565dc Felix Fietkau 2018-01-24 1248 status->enc_flags = mstat.enc_flags;
4e34249e9565dc Felix Fietkau 2018-01-24 1249 status->encoding = mstat.encoding;
4e34249e9565dc Felix Fietkau 2018-01-24 1250 status->bw = mstat.bw;
021af945997ffa Shayne Chen 2023-03-03 1251 if (status->encoding == RX_ENC_EHT) {
021af945997ffa Shayne Chen 2023-03-03 1252 status->eht.ru = mstat.eht.ru;
021af945997ffa Shayne Chen 2023-03-03 1253 status->eht.gi = mstat.eht.gi;
021af945997ffa Shayne Chen 2023-03-03 1254 } else {
af4a2f2fdd6fe4 Ryder Lee 2020-04-25 1255 status->he_ru = mstat.he_ru;
af4a2f2fdd6fe4 Ryder Lee 2020-04-25 1256 status->he_gi = mstat.he_gi;
af4a2f2fdd6fe4 Ryder Lee 2020-04-25 1257 status->he_dcm = mstat.he_dcm;
021af945997ffa Shayne Chen 2023-03-03 1258 }
4e34249e9565dc Felix Fietkau 2018-01-24 1259 status->rate_idx = mstat.rate_idx;
4e34249e9565dc Felix Fietkau 2018-01-24 1260 status->nss = mstat.nss;
4e34249e9565dc Felix Fietkau 2018-01-24 1261 status->band = mstat.band;
4e34249e9565dc Felix Fietkau 2018-01-24 1262 status->signal = mstat.signal;
4e34249e9565dc Felix Fietkau 2018-01-24 1263 status->chains = mstat.chains;
d515fdca46e729 Felix Fietkau 2019-08-28 1264 status->ampdu_reference = mstat.ampdu_ref;
0fda6d7bb5a29b Ryder Lee 2021-03-30 1265 status->device_timestamp = mstat.timestamp;
0fda6d7bb5a29b Ryder Lee 2021-03-30 1266 status->mactime = mstat.timestamp;
a71b648e352787 Ryder Lee 2022-10-14 1267 status->signal = mt76_rx_signal(mstat.chains, mstat.chain_signal);
4550fb9e98104f Felix Fietkau 2022-02-04 1268 if (status->signal <= -128)
4550fb9e98104f Felix Fietkau 2022-02-04 1269 status->flag |= RX_FLAG_NO_SIGNAL_VAL;
4e34249e9565dc Felix Fietkau 2018-01-24 1270
abe3f3da670981 Ryder Lee 2021-08-25 1271 if (ieee80211_is_beacon(hdr->frame_control) ||
abe3f3da670981 Ryder Lee 2021-08-25 1272 ieee80211_is_probe_resp(hdr->frame_control))
abe3f3da670981 Ryder Lee 2021-08-25 1273 status->boottime_ns = ktime_get_boottime_ns();
abe3f3da670981 Ryder Lee 2021-08-25 1274
4e34249e9565dc Felix Fietkau 2018-01-24 1275 BUILD_BUG_ON(sizeof(mstat) > sizeof(skb->cb));
13381dcdb3acad Ryder Lee 2019-08-21 1276 BUILD_BUG_ON(sizeof(status->chain_signal) !=
13381dcdb3acad Ryder Lee 2019-08-21 1277 sizeof(mstat.chain_signal));
13381dcdb3acad Ryder Lee 2019-08-21 1278 memcpy(status->chain_signal, mstat.chain_signal,
13381dcdb3acad Ryder Lee 2019-08-21 1279 sizeof(mstat.chain_signal));
9c68a57bc22d8c Felix Fietkau 2018-01-24 1280
4f0f33d2747f20 Sean Wang 2024-07-06 1281 if (mstat.wcid) {
4f0f33d2747f20 Sean Wang 2024-07-06 @1282 status->link_valid = mstat.wcid->link_valid;
4f0f33d2747f20 Sean Wang 2024-07-06 1283 status->link_id = mstat.wcid->link_id;
4f0f33d2747f20 Sean Wang 2024-07-06 1284 }
4f0f33d2747f20 Sean Wang 2024-07-06 1285
bfc394dd65ef47 Felix Fietkau 2019-10-11 1286 *sta = wcid_to_sta(mstat.wcid);
128c9b7d6235b9 Lorenzo Bianconi 2022-07-04 1287 *hw = mt76_phy_hw(dev, mstat.phy_idx);
4e34249e9565dc Felix Fietkau 2018-01-24 1288 }
4e34249e9565dc Felix Fietkau 2018-01-24 1289 Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
RFC PATCH 4/8 wifi: mac80211: rework RX packet handling
In reply to Benjamin BergFrom: Benjamin Berg <[email protected]>
The code has grown over time and it was not correctly handling all cases. Examples of issues are that for management frames we would match the received address against the MLD address even though we should not resolve the station in that case. Another issue was that for data frames we would not correctly fall back to use link addresses when the driver does not provide the pubsta already.
The new code still uses the same approach as before. For data frames, assume that we a valid station exists and interfaces do not need to be iterated. On the other hand, for non-data frames (or if a data frame without a station is received) all interfaces must be iterated.
Note that this rework makes mac80211 slightly more strict. For example, previously mac80211 would have incorrectly accepted a data frame that was transmitted on the wrong link.
--- net/mac80211/rx.c | 284 +++++++++++++++++++++++++++------------------- 1 file changed, 170 insertions(+), 114 deletions(-)
net/mac80211/rx.c +170 -114
@@ -4284,9 +4284,33 @@ static bool ieee80211_rx_is_valid_sta_link_id(struct ieee80211_sta *sta, u8 link_id) {if (sta->mlo) -return !!(sta->valid_links &BIT (link_id)); -else -return sta->deflink.link_id == link_id; +return sta->valid_links &BIT (link_id); + +return sta->deflink.link_id == link_id; +} + +static bool ieee80211_rx_data_set_link_sta (struct ieee80211_rx_data *rx, +struct link_sta_info *link_sta) +{ +struct sta_info *sta; + +if (WARN_ON_ONCE (!link_sta) || + !ieee80211_rx_is_valid_sta_link_id (&link_sta->sta->sta, + link_sta->link_id)) +return false; + + sta = link_sta->sta; + + rx->sta = sta; + rx->local = sta->sdata->local; + rx->link =rcu_dereference (sta->sdata->link[link_sta->link_id]); +if (!rx->link) +return false; + + rx->link_id = rx->link->link_id; + rx->link_sta = link_sta; + +return true; } static bool ieee80211_rx_data_set_link(struct ieee80211_rx_data *rx,
@@ -5192,53 +5216,18 @@ static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw,dev_kfree_skb (skb); } -static bool ieee80211_rx_for_interface (struct ieee80211_rx_data *rx, -struct sk_buff *skb,bool consume) +static bool ieee80211_rx_valid_freq (int freq,struct ieee80211_link_data *link) { -struct link_sta_info *link_sta; -struct ieee80211_hdr *hdr = (void *)skb->data; -struct sta_info *sta; -int link_id =-1 ; - -/* -* FIXME: Here we can assume that link addresses have not -* been translated. -* -* Look up link station first, in case there's a -* chance that they might have a link address that -* is identical to the MLD address, that way we'll -* have the link information if needed. -*/ - link_sta =link_sta_info_get_bss (rx->sdata, hdr->addr2); -if (link_sta) { - sta = link_sta->sta; - link_id = link_sta->link_id; - }else { -struct ieee80211_rx_status *status =IEEE80211_SKB_RXCB (skb); - - sta =sta_info_get_bss (rx->sdata, hdr->addr2); -if (ieee80211_vif_is_mld (&rx->sdata->vif) && - status->freq) { -struct ieee80211_link_data *link; -struct ieee80211_chanctx_conf *conf; +struct ieee80211_chanctx_conf *conf; -for_each_link_data_rcu (rx->sdata, link) { - conf =rcu_dereference (link->conf->chanctx_conf); -if (!conf || !conf->def.chan) -continue ; - -if (status->freq == conf->def.chan->center_freq) { - link_id = link->link_id; -break ; - } - } - } - } +if (!freq || link->sdata->vif.type ==NL80211_IFTYPE_NAN ) +return true; -if (!ieee80211_rx_data_set_sta (rx, sta, link_id)) + conf =rcu_dereference (link->conf->chanctx_conf); +if (!conf || !conf->def.chan)return false; -return ieee80211_prepare_and_rx_handle (rx, skb, consume); +return freq == conf->def.chan->center_freq; }/*
@@ -5252,11 +5241,14 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, {struct ieee80211_local *local =hw_to_local (hw);struct ieee80211_sub_if_data *sdata; +struct ieee80211_rx_status *status =IEEE80211_SKB_RXCB (skb);struct ieee80211_hdr *hdr; +struct link_sta_info *link_sta; +struct sta_info *sta;__le16 fc;struct ieee80211_rx_data rx; -struct ieee80211_sub_if_data *prev;struct rhlist_head *tmp; +bool rx_data_pending;int err =0 ; fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
@@ -5292,92 +5284,102 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, ieee80211_is_s1g_beacon(hdr->frame_control)))ieee80211_scan_rx (local, skb); +/* +* RX of a data frame should only happen to existing stations. +* It is therefore more efficient to use the one provided by the driver +* or search based on the station's address. +* +* Note we will fall through and handle a spurious data frame in the +* same way as a management frame. +*/ if (ieee80211_is_data (fc)) { -struct sta_info *sta, *prev_sta; -if (link_pubsta) { - sta =container_of (link_pubsta->sta, - struct sta_info, sta); -if (!ieee80211_rx_data_set_sta (&rx, sta, - link_pubsta->link_id)) - goto out; + sta = container_of(link_pubsta->sta, struct sta_info, + sta); + link_sta =rcu_dereference (sta->link[link_pubsta->link_id]); -if (ieee80211_prepare_and_rx_handle (&rx, skb, true)) + rx.sdata = sta->sdata; +if (ieee80211_rx_data_set_link_sta (&rx, link_sta) && +ieee80211_prepare_and_rx_handle (&rx, skb, true))return ; + goto out; } - prev_sta =NULL ; + rx_data_pending = false; +/* Search for stations on non-MLD interfaces */ for_each_sta_info (local, hdr->addr2, sta, tmp) { -int link_id; +struct ieee80211_link_data *link; -if (!prev_sta) { - prev_sta = sta; +if (ieee80211_vif_is_mld (&sta->sdata->vif))continue ; - } - - rx.sdata = prev_sta->sdata; - -/* -* FIXME: This is not correct as the addr2 cannot be a -* link address if the loop itself is iterated. -*/ -if (prev_sta->sta.mlo) { -struct link_sta_info *link_sta; - link_sta =link_sta_info_get_bss (rx.sdata, - hdr->addr2); -if (!link_sta) -continue ; + link = &sta->sdata->deflink; +if (!ieee80211_rx_valid_freq (status->freq, link)) +continue ; - link_id = link_sta->link_id; - }else { - link_id = sta->deflink.link_id; +if (rx_data_pending) { +ieee80211_prepare_and_rx_handle (&rx, skb, + false); + rx_data_pending = false; } -if (!ieee80211_rx_data_set_sta (&rx, prev_sta, link_id)) - goto out; - -ieee80211_prepare_and_rx_handle (&rx, skb, false); + rx.sdata = sta->sdata; +if (!ieee80211_rx_data_set_link_sta (&rx, &sta->deflink)) +continue ; - prev_sta = sta; + rx_data_pending = true; } -if (prev_sta) { -int link_id; - - rx.sdata = prev_sta->sdata; +/* And search stations on MLD interfaces */ +for_each_link_sta_info (local, hdr->addr2, link_sta, tmp) { +struct ieee80211_link_data *link; -/* -* FIXME: This is not correct as the addr2 cannot be a -* link address if the loop itself is iterated. -*/ -if (prev_sta->sta.mlo) { -struct link_sta_info *link_sta; + sta = link_sta->sta; + sdata = sta->sdata; + link =rcu_dereference (sdata->link[link_sta->link_id]); - link_sta =link_sta_info_get_bss (rx.sdata, - hdr->addr2); -if (!link_sta) - goto out; +if (!ieee80211_rx_valid_freq (status->freq, link)) +continue ; - link_id = link_sta->link_id; - }else { - link_id = sta->deflink.link_id; +if (rx_data_pending) { +ieee80211_prepare_and_rx_handle (&rx, skb, + false); + rx_data_pending = false; } -if (!ieee80211_rx_data_set_sta (&rx, prev_sta, link_id)) - goto out; + rx.sdata = sta->sdata; +if (!ieee80211_rx_data_set_link_sta (&rx, link_sta)) +continue ; + + rx_data_pending = true; + } +if (rx_data_pending) {if (ieee80211_prepare_and_rx_handle (&rx, skb, true))return ; - goto out; +else + goto out; } + +/* fall through, e.g. for spurious frame notification */ } - prev =NULL ; +/* +* This is a management frame (or a data frame without a station) and +* it will be delivered independent of whether a station exists, +* so iterate the interfaces. +*/ + rx_data_pending = false; + +/* We expect the driver to provide frequency information */ +if (WARN_ON_ONCE (!local->emulate_chanctx && !status->freq)) + goto out;list_for_each_entry_rcu (sdata, &local->interfaces, list) { +struct ieee80211_link_data *link =NULL ; +if (!ieee80211_sdata_running (sdata))continue ;
@@ -5385,30 +5387,84 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, sdata->vif.type == NL80211_IFTYPE_AP_VLAN)continue ; +/* Try to resolve the station */ +if (!ieee80211_vif_is_mld (&sdata->vif)) { + sta =sta_info_get_bss (sdata, hdr->addr2); + +if (sta) { + link_sta = &sta->deflink; + link = &sdata->deflink; + } + }else { + link_sta =link_sta_info_get_bss (sdata, hdr->addr2); + +if (link_sta) { + sta = link_sta->sta; + link =rcu_dereference (sdata->link[link_sta->link_id]); + } + } +/* -* frame is destined for this interface, but if it's -* not also for the previous one we handle that after -* the loop to avoid copying the SKB once too much +* If we found a STA and it has a valid link information, then +* RX using the station. */ +if (link_sta && link && +ieee80211_rx_valid_freq (status->freq, link)) { +if (rx_data_pending) { +ieee80211_prepare_and_rx_handle (&rx, skb, false); + rx_data_pending = false; + } + +/* No valid_links check as we need to RX beacons */ + + rx.sdata = sdata; +if (ieee80211_rx_data_set_link_sta (&rx, link_sta)) + rx_data_pending = true; -if (!prev) { - prev = sdata;continue ; } - rx.sdata = prev; -ieee80211_rx_for_interface (&rx, skb, false); +/* No station, try to resolve the link and RX */ +if (ieee80211_vif_is_mld (&sdata->vif)) { +struct ieee80211_chanctx_conf *conf; +bool found = false; - prev = sdata; - } +for_each_link_data_rcu (sdata, link) { + conf =rcu_dereference (link->conf->chanctx_conf); +if (!conf || !conf->def.chan) +continue ; -if (prev) { - rx.sdata = prev; +if (status->freq == conf->def.chan->center_freq) { + found = true; +break ; + } + } -if (ieee80211_rx_for_interface (&rx, skb, true)) -return ; +if (!found) + link = &sdata->deflink; + }else { + link = &sdata->deflink; + } + +if (rx_data_pending) { +ieee80211_prepare_and_rx_handle (&rx, skb, false); + rx_data_pending = false; + } + + rx.sdata = sdata; + rx.local = sdata->local; + rx.link = link; + rx.link_id = link->link_id; + rx.sta =NULL ; + rx.link_sta =NULL ; + + rx_data_pending = true; } +if (rx_data_pending && +ieee80211_prepare_and_rx_handle (&rx, skb, true)) +return ; + out:dev_kfree_skb (skb); }
Signature · 1 line
2.53.0
Re: [RFC PATCH 4/8] wifi: mac80211: rework RX packet handling
net/mac80211/rx.c static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, · line 5292
Quoted 10 lines · Benjamin Berg
net/mac80211/rx.c +6
-0@@ -5292,92 +5284,102 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, ieee80211_is_s1g_beacon(hdr->frame_control)))ieee80211_scan_rx (local, skb); +/* +* RX of a data frame should only happen to existing stations. +* It is therefore more efficient to use the one provided by the driver +* or search based on the station's address. +* +* Note we will fall through and handle a spurious data frame in the
Note that checkpatch doesn't like the use of "fall through" in a comment since that term is usually associated with switch code where one case does some processing and then falls through to a subsequent case instead of having a break. Should we reword so that checkpatch doesn't complain?
CHECK: Prefer 'fallthrough;' over fallthrough comment #5293: FILE: net/mac80211/rx.c:5293:
+ * Note we will fall through and handle a spurious data frame in the
Quoted 115 lines
net/mac80211/rx.c +39
-53+* same way as a management frame. +*/ if (ieee80211_is_data (fc)) { -struct sta_info *sta, *prev_sta; -if (link_pubsta) { - sta =container_of (link_pubsta->sta, - struct sta_info, sta); -if (!ieee80211_rx_data_set_sta (&rx, sta, - link_pubsta->link_id)) - goto out; + sta = container_of(link_pubsta->sta, struct sta_info, + sta); + link_sta =rcu_dereference (sta->link[link_pubsta->link_id]); -if (ieee80211_prepare_and_rx_handle (&rx, skb, true)) + rx.sdata = sta->sdata; +if (ieee80211_rx_data_set_link_sta (&rx, link_sta) && +ieee80211_prepare_and_rx_handle (&rx, skb, true))return ; + goto out; } - prev_sta =NULL ; + rx_data_pending = false; +/* Search for stations on non-MLD interfaces */ for_each_sta_info (local, hdr->addr2, sta, tmp) { -int link_id; +struct ieee80211_link_data *link; -if (!prev_sta) { - prev_sta = sta; +if (ieee80211_vif_is_mld (&sta->sdata->vif))continue ; - } - - rx.sdata = prev_sta->sdata; - -/* -* FIXME: This is not correct as the addr2 cannot be a -* link address if the loop itself is iterated. -*/ -if (prev_sta->sta.mlo) { -struct link_sta_info *link_sta; - link_sta =link_sta_info_get_bss (rx.sdata, - hdr->addr2); -if (!link_sta) -continue ; + link = &sta->sdata->deflink; +if (!ieee80211_rx_valid_freq (status->freq, link)) +continue ; - link_id = link_sta->link_id; - }else { - link_id = sta->deflink.link_id; +if (rx_data_pending) { +ieee80211_prepare_and_rx_handle (&rx, skb, + false); + rx_data_pending = false; } -if (!ieee80211_rx_data_set_sta (&rx, prev_sta, link_id)) - goto out; - -ieee80211_prepare_and_rx_handle (&rx, skb, false); + rx.sdata = sta->sdata; +if (!ieee80211_rx_data_set_link_sta (&rx, &sta->deflink)) +continue ; - prev_sta = sta; + rx_data_pending = true; } -if (prev_sta) { -int link_id; - - rx.sdata = prev_sta->sdata; +/* And search stations on MLD interfaces */ +for_each_link_sta_info (local, hdr->addr2, link_sta, tmp) { +struct ieee80211_link_data *link; -/* -* FIXME: This is not correct as the addr2 cannot be a -* link address if the loop itself is iterated. -*/ -if (prev_sta->sta.mlo) { -struct link_sta_info *link_sta; + sta = link_sta->sta; + sdata = sta->sdata; + link =rcu_dereference (sdata->link[link_sta->link_id]); - link_sta =link_sta_info_get_bss (rx.sdata, - hdr->addr2); -if (!link_sta) - goto out; +if (!ieee80211_rx_valid_freq (status->freq, link)) +continue ; - link_id = link_sta->link_id; - }else { - link_id = sta->deflink.link_id; +if (rx_data_pending) { +ieee80211_prepare_and_rx_handle (&rx, skb, + false); + rx_data_pending = false; } -if (!ieee80211_rx_data_set_sta (&rx, prev_sta, link_id)) - goto out; + rx.sdata = sta->sdata; +if (!ieee80211_rx_data_set_link_sta (&rx, link_sta)) +continue ;
net/mac80211/rx.c static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, · line 5363
Quoted 10 lines
net/mac80211/rx.c +6
-1+ + rx_data_pending = true; + } +if (rx_data_pending) {if (ieee80211_prepare_and_rx_handle (&rx, skb, true))return ; - goto out; +else + goto out;
why change this?
kernel convention is to avoid else after an if that ends in a change in flow.
WARNING: else is not generally useful after a break or return #5363: FILE: net/mac80211/rx.c:5363:
+ return;
+ else
net/mac80211/rx.c static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, · line 5366
Quoted 3 lines
net/mac80211/rx.c +2
-0} + +/* fall through, e.g. for spurious frame notification */
here again
CHECK: Prefer 'fallthrough;' over fallthrough comment #5367: FILE: net/mac80211/rx.c:5367:
+ /* fall through, e.g. for spurious frame notification */
Quoted 20 lines
net/mac80211/rx.c +12
-1} - prev =NULL ; +/* +* This is a management frame (or a data frame without a station) and +* it will be delivered independent of whether a station exists, +* so iterate the interfaces. +*/ + rx_data_pending = false; + +/* We expect the driver to provide frequency information */ +if (WARN_ON_ONCE (!local->emulate_chanctx && !status->freq)) + goto out;list_for_each_entry_rcu (sdata, &local->interfaces, list) { +struct ieee80211_link_data *link =NULL ; +if (!ieee80211_sdata_running (sdata))continue ;
Re: [RFC PATCH 4/8] wifi: mac80211: rework RX packet handling
Quoted 16 lines · Jeff Johnson
net/mac80211/rx.c static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, · line 5292
Quoted 10 lines · Benjamin Berg
net/mac80211/rx.c +0
-0@@ -5292,92 +5284,102 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, ieee80211_is_s1g_beacon(hdr->frame_control))) ieee80211_scan_rx(local, skb);net/mac80211/rx.c +6
-0+/* +* RX of a data frame should only happen to existing stations. +* It is therefore more efficient to use the one provided by the driver +* or search based on the station's address. +* +* Note we will fall through and handle a spurious data frame in the Note that checkpatch doesn't like the use of "fall through" in a comment since that term is usually associated with switch code where one case does some processing and then falls through to a subsequent case instead of having a break. Should we reword so that checkpatch doesn't complain?
I feel that "fall through" captures quite nicely what we do here and there is really no need to change the wording just to make checkpatch happy.
That said, I'll change the if/else that was also flagged.
Benjamin
Quoted 169 lines
CHECK: Prefer 'fallthrough;' over fallthrough comment
#5293: FILE:net/mac80211/rx.c:5293:
+ * Note we will fall through and handle a spurious data frame in theQuoted 122 lines
net/mac80211/rx.c +2
-0+* same way as a management frame. +*/ if (
ieee80211_is_data(fc)) {(quoted diff) +0
-2- struct sta_info *sta, *prev_sta; -if (
link_pubsta) {net/mac80211/rx.c +3
-5- sta =container_of (link_pubsta->sta, - struct sta_info, sta); -if (!ieee80211_rx_data_set_sta (&rx, sta, - link_pubsta->link_id)) - goto out; + sta = container_of(link_pubsta->sta, struct sta_info, + sta); + link_sta =rcu_dereference (sta->link[link_pubsta->link_id]);net/mac80211/rx.c +3
-1-if (ieee80211_prepare_and_rx_handle (&rx, skb, true)) + rx.sdata = sta->sdata; +if (ieee80211_rx_data_set_link_sta (&rx, link_sta) && + ieee80211_prepare_and_rx_handle(&rx, skb, true))return;
+
goto out;
}(quoted diff) +1
-1- prev_sta = NULL; + rx_data_pending = false;net/mac80211/rx.c +1
-0+/* Search for stations on non-MLD interfaces */
for_each_sta_info(local, hdr->addr2, sta, tmp){(quoted diff) +1
-1- int link_id; + struct ieee80211_link_data *link;net/mac80211/rx.c +1
-2-if (!prev_sta) { - prev_sta = sta; +if (ieee80211_vif_is_mld (&sta->sdata->vif))continue;
net/mac80211/rx.c +0
-10- } - - rx.sdata = prev_sta->sdata; - -/* -* FIXME: This is not correct as the addr2 cannot be a -* link address if the loop itself is iterated. -*/ -if (prev_sta->sta.mlo) { -struct link_sta_info *link_sta;net/mac80211/rx.c +3
-4- link_sta =link_sta_info_get_bss (rx.sdata, - hdr->addr2); -if (!link_sta) -continue ; + link = &sta->sdata->deflink; +if (!ieee80211_rx_valid_freq (status->freq, link)) +continue ;net/mac80211/rx.c +4
-3- link_id = link_sta->link_id; - }else { - link_id = sta->deflink.link_id; +if (rx_data_pending) { +ieee80211_prepare_and_rx_handle (&rx, skb, + false); + rx_data_pending = false;}
net/mac80211/rx.c +3
-4-if (!ieee80211_rx_data_set_sta (&rx, prev_sta, link_id)) - goto out; - -ieee80211_prepare_and_rx_handle (&rx, skb, false); + rx.sdata = sta->sdata; +if (!ieee80211_rx_data_set_link_sta (&rx, &sta->deflink)) +continue ;(quoted diff) +1
-1- prev_sta = sta; + rx_data_pending = true;}
net/mac80211/rx.c +3
-4-if (prev_sta) { -int link_id; - - rx.sdata = prev_sta->sdata; +/* And search stations on MLD interfaces */ +for_each_link_sta_info (local, hdr->addr2, link_sta, tmp) { +struct ieee80211_link_data *link;net/mac80211/rx.c +3
-6-/* -* FIXME: This is not correct as the addr2 cannot be a -* link address if the loop itself is iterated. -*/ -if (prev_sta->sta.mlo) { -struct link_sta_info *link_sta; + sta = link_sta->sta; + sdata = sta->sdata; + link =rcu_dereference (sdata->link[link_sta->link_id]);net/mac80211/rx.c +2
-4- link_sta =link_sta_info_get_bss (rx.sdata, - hdr->addr2); -if (!link_sta) - goto out; +if (!ieee80211_rx_valid_freq (status->freq, link)) +continue ;net/mac80211/rx.c +4
-3- link_id = link_sta->link_id; - }else { - link_id = sta->deflink.link_id; +if (rx_data_pending) { +ieee80211_prepare_and_rx_handle (&rx, skb, + false); + rx_data_pending = false;}
net/mac80211/rx.c +6
-2-if (!ieee80211_rx_data_set_sta (&rx, prev_sta, link_id)) - goto out; + rx.sdata = sta->sdata; +if (!ieee80211_rx_data_set_link_sta (&rx, link_sta)) +continue ; + + rx_data_pending = true; + }(quoted diff) +1
-0+ if (rx_data_pending) {if (
ieee80211_prepare_and_rx_handle(&rx, skb, true)) return;net/mac80211/rx.c static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, · line 5363
Quoted 3 lines
net/mac80211/rx.c +2
-1- goto out; +else + goto out;why change this?
kernel convention is to avoid else after an if that ends in a change in flow.WARNING: else is not generally useful after a break or return #5363: FILE:
net/mac80211/rx.c:5363:
+ return;
+ elseReview
Quoted 3 lines
}
(quoted diff) +2
-0+ + /* fall through, e.g. for spurious frame notification */here again
CHECK: Prefer 'fallthrough;' over fallthrough comment
#5367: FILE:net/mac80211/rx.c:5367:
+ /* fall through, e.g. for spurious frame notification */Quoted 20 lines
}
net/mac80211/rx.c +10
-1- prev =NULL ; +/* +* This is a management frame (or a data frame without a station) and +* it will be delivered independent of whether a station exists, +* so iterate the interfaces. +*/ + rx_data_pending = false; + +/* We expect the driver to provide frequency information */ +if (WARN_ON_ONCE (!local->emulate_chanctx && !status->freq)) + goto out;
list_for_each_entry_rcu(sdata, &local->interfaces, list){net/mac80211/rx.c +2
-0+struct ieee80211_link_data *link =NULL ; +if (!ieee80211_sdata_running(sdata)) continue;
RFC PATCH 5/8 wifi: cfg80211: add attribute for TX/RX denoting there is no station
In reply to Benjamin BergFrom: Benjamin Berg <[email protected]>
For MLD stations, userspace may need to explicitly transmit a frame to a specific link address. In that case, it needs to ensure that no address translation happens.
In the reverse case of an RX, userspace may need to know the link address for a frame. By passing the information whether a STA is known for the frame, userspace knows whether link translation happened and can do the reverse lookup when needed.
This is important for flows where a STA is still registered but the connection has been lost and it is returning again.
--- include/net/cfg80211.h | 4 ++++ include/uapi/linux/nl80211.h | 7 +++++++ net/wireless/nl80211.c | 8 +++++++- 3 files changed, 18 insertions(+), 1 deletion(-)
include/net/cfg80211.h +4 -0
@@ -3919,6 +3919,7 @@ struct cfg80211_update_ft_ies_params {* @link_id: for MLO, the link ID to transmit on, -1 if not given; note * that the link ID isn't validated (much), it's in range but the * link might not exist (or be used by the receiver STA) +* @no_sta: set if the frame should not be transmitted using an existing STA */ struct cfg80211_mgmt_tx_params {struct ieee80211_channel *chan;
@@ -3931,6 +3932,7 @@ struct cfg80211_mgmt_tx_params {int n_csa_offsets;const u16 *csa_offsets;int link_id; +bool no_sta; };/**
@@ -9025,6 +9027,7 @@ void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,* @flags: flags, as defined in &enum nl80211_rxmgmt_flags * @rx_tstamp: Hardware timestamp of frame RX in nanoseconds * @ack_tstamp: Hardware timestamp of ack TX in nanoseconds +* @no_sta: set if no station is known for the frame (relevant for MLD) */ struct cfg80211_rx_info {int freq;
@@ -9036,6 +9039,7 @@ struct cfg80211_rx_info {u32 flags;u64 rx_tstamp;u64 ack_tstamp; +bool no_sta; };/**
include/uapi/linux/nl80211.h +7 -0
@@ -2984,6 +2984,11 @@ enum nl80211_commands {* this feature during association. This is a flag attribute. * Currently only supported in mac80211 drivers. * +* @NL80211_ATTR_FRAME_CMD_NO_STA: Valid for NL80211_CMD_FRAME to denote that +* the kernel had no station for a received frame or should not use a +* known station to transmit a frame. This is relevant to know whether +* MLD address translation happened or to disable it when sending a frame. +* * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3557,6 +3562,8 @@ enum nl80211_attrs {NL80211_ATTR_UHR_CAPABILITY ,NL80211_ATTR_DISABLE_UHR , +NL80211_ATTR_FRAME_CMD_NO_STA , +/* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST,
net/wireless/nl80211.c +7 -1
@@ -946,6 +946,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_UHR_CAPABILITY ] = NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_uhr_capa, 255), [NL80211_ATTR_DISABLE_UHR] = { .type = NLA_FLAG }, + [NL80211_ATTR_FRAME_CMD_NO_STA] = { .type = NLA_FLAG }, };/* policy for the key attributes */
@@ -14020,6 +14021,9 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) !(wdev->valid_links & BIT(params.link_id)))return -EINVAL ; + params.no_sta = +nla_get_flag (info->attrs[NL80211_ATTR_FRAME_CMD_NO_STA ]); + params.buf =nla_data (info->attrs[NL80211_ATTR_FRAME ]); params.len =nla_len (info->attrs[NL80211_ATTR_FRAME ]);
@@ -20581,7 +20585,9 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, (info->ack_tstamp &&nla_put_u64_64bit (msg,NL80211_ATTR_TX_HW_TIMESTAMP , info->ack_tstamp, - NL80211_ATTR_PAD))) +NL80211_ATTR_PAD )) || + (info->no_sta && + nla_put_flag(msg, NL80211_ATTR_FRAME_CMD_NO_STA))) goto nla_put_failure;genlmsg_end (msg, hdr);
Signature · 1 line
2.53.0
RFC PATCH 6/8 wifi: mac80211: report to cfg80211 when no STA is known for a frame
In reply to Benjamin BergFrom: Benjamin Berg <[email protected]>
This is relevant for hostapd to know whether address translation was done on a received management frame.
--- net/mac80211/rx.c | 1 + 1 file changed, 1 insertion(+)
net/mac80211/rx.c +1 -0
@@ -3948,6 +3948,7 @@ ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx) .len = rx->skb->len, .link_id = rx->link_id, .have_link_id = rx->link_id >= 0, + .no_sta = !rx->sta, };/* skip known-bad action frames and return them in the next handler */
Signature · 1 line
2.53.0
RFC PATCH 7/8 wifi: mac80211: pass station to ieee80211_tx_skb_tid
In reply to Benjamin BergFrom: Benjamin Berg <[email protected]>
The station may be relevant for queuing and will also generally be resolved in some cases. However, we want to be able to prevent looking up the station based on the address.
Add a station parameter, which can be set to the correct station, to an error value to prevent station lookup or to NULL to get the old behaviour where the address is used to find the appropriate station.
Also disable the station lookup for ieee80211_tx_skb_tid_band already as it does not make any sense to find a station when doing an off-channel transmit.
--- net/mac80211/agg-tx.c | 6 +++--- net/mac80211/ht.c | 4 ++-- net/mac80211/ieee80211_i.h | 14 ++++++++------ net/mac80211/offchannel.c | 2 +- net/mac80211/rx.c | 2 +- net/mac80211/tdls.c | 4 ++-- net/mac80211/tx.c | 8 +++++--- 7 files changed, 22 insertions(+), 18 deletions(-)
net/mac80211/agg-tx.c +3 -3
@@ -9,7 +9,7 @@* Copyright 2007, Michael Wu <[email protected]> * Copyright 2007-2010, Intel Corporation * Copyright(c) 2015-2017 Intel Deutschland GmbH -* Copyright (C) 2018 - 2024 Intel Corporation +* Copyright (C) 2018 - 2024, 2026 Intel Corporation */ #include <linux/ieee80211.h>
@@ -97,7 +97,7 @@ static void ieee80211_send_addba_request(struct sta_info *sta, u16 tid,if (sta->sta.deflink.he_cap.has_he)ieee80211_add_addbaext (skb,0 , agg_size); -ieee80211_tx_skb_tid (sdata, skb, tid,-1 ); +ieee80211_tx_skb_tid (sdata, skb,NULL , tid,-1 ); }void ieee80211_send_bar (struct ieee80211_vif *vif,u8 *ra,u16 tid,u16 ssn)
@@ -126,7 +126,7 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)IEEE80211_SKB_CB (skb)->flags |=IEEE80211_TX_INTFL_DONT_ENCRYPT |IEEE80211_TX_CTL_REQ_TX_STATUS ; -ieee80211_tx_skb_tid (sdata, skb, tid,-1 ); +ieee80211_tx_skb_tid (sdata, skb,NULL , tid,-1 ); }EXPORT_SYMBOL (ieee80211_send_bar);
net/mac80211/ht.c +2 -2
@@ -9,7 +9,7 @@* Copyright 2007, Michael Wu <[email protected]> * Copyright 2007-2010, Intel Corporation * Copyright 2017 Intel Deutschland GmbH -* Copyright(c) 2020-2025 Intel Corporation +* Copyright(c) 2020-2026 Intel Corporation */ #include <linux/ieee80211.h>
@@ -571,7 +571,7 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, info->status_data =IEEE80211_STATUS_TYPE_SMPS |u16_encode_bits (status_link_id <<2 | smps,IEEE80211_STATUS_SUBDATA_MASK ); -ieee80211_tx_skb_tid (sdata, skb,7 , link_id); +ieee80211_tx_skb_tid (sdata, skb,NULL ,7 , link_id);return 0 ; }
net/mac80211/ieee80211_i.h +8 -6
@@ -2393,7 +2393,8 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, struct sk_buff *skb);void __ieee80211_tx_skb_tid_band (struct ieee80211_sub_if_data *sdata, -struct sk_buff *skb,int tid,int link_id, +struct sk_buff *skb,struct sta_info *sta, +int tid,int link_id,enum nl80211_band band); static inline bool ieee80211_require_encrypted_assoc(__le16 fc,
@@ -2411,22 +2412,23 @@ int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,static inline void ieee80211_tx_skb_tid_band (struct ieee80211_sub_if_data *sdata, -struct sk_buff *skb,int tid, -enum nl80211_band band) +struct sk_buff *skb,int tid,enum nl80211_band band) {rcu_read_lock (); -__ieee80211_tx_skb_tid_band (sdata, skb, tid,-1 , band); +__ieee80211_tx_skb_tid_band (sdata, skb,ERR_PTR (-ENOENT ), + tid,-1 , band);rcu_read_unlock (); }void ieee80211_tx_skb_tid (struct ieee80211_sub_if_data *sdata, -struct sk_buff *skb,int tid,int link_id); +struct sk_buff *skb,struct sta_info *sta, +int tid,int link_id);static inline void ieee80211_tx_skb (struct ieee80211_sub_if_data *sdata,struct sk_buff *skb) {/* Send all internal mgmt frames on VO. Accordingly set TID to 7. */ -ieee80211_tx_skb_tid (sdata, skb,7 ,-1 ); +ieee80211_tx_skb_tid (sdata, skb,NULL ,7 ,-1 ); }/**
net/mac80211/offchannel.c +1 -1
@@ -1026,7 +1026,7 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, }if (!need_offchan) { -ieee80211_tx_skb_tid (sdata, skb,7 , link_id); +ieee80211_tx_skb_tid (sdata, skb,NULL ,7 , link_id); ret =0 ; goto out_unlock; }
net/mac80211/rx.c +1 -1
@@ -4072,7 +4072,7 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx) local->hw.offchannel_tx_hw_queue; } -__ieee80211_tx_skb_tid_band (rx->sdata, nskb,7 ,-1 , +__ieee80211_tx_skb_tid_band (rx->sdata, nskb, rx->sta,7 ,-1 , status->band); }
net/mac80211/tdls.c +2 -2
@@ -6,7 +6,7 @@* Copyright 2014, Intel Corporation * Copyright 2014 Intel Mobile Communications GmbH * Copyright 2015 - 2016 Intel Deutschland GmbH -* Copyright (C) 2019, 2021-2025 Intel Corporation +* Copyright (C) 2019, 2021-2026 Intel Corporation */ #include <linux/ieee80211.h>
@@ -1067,7 +1067,7 @@ ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev, }if (action_code ==WLAN_PUB_ACTION_TDLS_DISCOVER_RES ) { -ieee80211_tx_skb_tid (sdata, skb,7 , link_id); +ieee80211_tx_skb_tid (sdata, skb, sta,7 , link_id);return 0 ; }
net/mac80211/tx.c +5 -3
@@ -6235,7 +6235,8 @@ void ieee80211_unreserve_tid(struct ieee80211_sta *pubsta, u8 tid)EXPORT_SYMBOL (ieee80211_unreserve_tid);void __ieee80211_tx_skb_tid_band (struct ieee80211_sub_if_data *sdata, -struct sk_buff *skb,int tid,int link_id, +struct sk_buff *skb,struct sta_info *sta, +int tid,int link_id,enum nl80211_band band) {const struct ieee80211_hdr *hdr = (void *)skb->data;
@@ -6292,7 +6293,8 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, }void ieee80211_tx_skb_tid (struct ieee80211_sub_if_data *sdata, -struct sk_buff *skb,int tid,int link_id) +struct sk_buff *skb,struct sta_info *sta, +int tid,int link_id) {struct ieee80211_chanctx_conf *chanctx_conf;enum nl80211_band band;
@@ -6317,7 +6319,7 @@ void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, band =0 ; } -__ieee80211_tx_skb_tid_band (sdata, skb, tid, link_id, band); +__ieee80211_tx_skb_tid_band (sdata, skb, sta, tid, link_id, band);rcu_read_unlock (); }
Signature · 1 line
2.53.0
RFC PATCH 8/8 wifi: mac80211: pass error station if non-STA transmit was requested
In reply to Benjamin BergFrom: Benjamin Berg <[email protected]>
When cfg80211 requested a transmit without a station, pass an error station to ieee80211_tx_skb_tid instead of the correct one.
--- net/mac80211/offchannel.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
net/mac80211/offchannel.c +9 -4
@@ -857,8 +857,10 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, need_offchan = true;rcu_read_lock (); - sta =sta_info_get_bss (sdata, mgmt->da); - mlo_sta = sta && sta->sta.mlo; +if (!params->no_sta) { + sta =sta_info_get_bss (sdata, mgmt->da); + mlo_sta = sta && sta->sta.mlo; + } if (!ieee80211_is_action(mgmt->frame_control) || mgmt->u.action.category == WLAN_CATEGORY_PUBLIC ||
@@ -887,7 +889,8 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, local->ops->remain_on_channel && memcmp(sdata->vif.cfg.ap_addr, mgmt->bssid, ETH_ALEN))) { need_offchan = true; - } else if (sdata->u.mgd.associated && + } else if (!params->no_sta && + sdata->u.mgd.associated && ether_addr_equal(sdata->vif.cfg.ap_addr, mgmt->da)) { sta =sta_info_get_bss (sdata, mgmt->da); mlo_sta = sta && sta->sta.mlo;
@@ -1026,7 +1029,9 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, }if (!need_offchan) { -ieee80211_tx_skb_tid (sdata, skb,NULL ,7 , link_id); +ieee80211_tx_skb_tid (sdata, skb, + sta ? sta :ERR_PTR (-ENOENT ), +7 , link_id); ret =0 ; goto out_unlock; }
Signature · 1 line
2.53.0
Quoted 11 lines · Benjamin Berg
From: Benjamin Berg <[email protected]>
Hi,
This patchset refactors the RX link resolution a bit to fix some issues where mac80211 might accept frames on the wrong link and incorrectly translate the address. It also adds a new
NL80211_ATTR_FRAME_CMD_NO_STAflag so that userspace can know whether address translation was done by the kernel on RX and can also prevent address translation for management frames during TX.
Quoted 7 lines
This together should be enough to fix the existing issues in hostapd where stations that are still associated try to authenticate again but hostapd for example ends up sending the frame to an old link address.
I would appreciate if you test the patches and work on the hostapd side. Note that I have not properly verified the new nl80211 API, so it could well be that I missed something.
Lack of changes for ath drivers prevents me from running this series through my automation.
drivers/net/wireless/ath/ath11k/dp_rx.c: In function 'ath11k_dp_rx_deliver_msdu':drivers/net/wireless/ath/ath11k/dp_rx.c:2503:35: error: passing argument 2 of 'ieee80211_rx_napi' from incompatible pointer type [-Wincompatible-pointer-types]
2503 | ieee80211_rx_napi(ar->hw, pubsta, msdu, napi);
| ^~~~~~
| |
| struct ieee80211_sta *
In file included from drivers/net/wireless/ath/ath11k/wmi.h:10,
from drivers/net/wireless/ath/ath11k/core.h:24,
from drivers/net/wireless/ath/ath11k/dp_rx.c:11:
./include/net/mac80211.h:5249:51: note: expected 'struct ieee80211_link_sta *' but argument is of type 'struct ieee80211_sta *'
5249 | struct ieee80211_link_sta *link_sta,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~drivers/net/wireless/ath/ath12k/dp_rx.c: In function 'ath12k_dp_rx_deliver_msdu':drivers/net/wireless/ath/ath12k/dp_rx.c:1344:25: error: 'struct ieee80211_rx_status' has no member named 'link_valid'; did you mean 'link_id'?
1344 | status->link_valid = 1;
| ^~~~~~~~~~
| link_id
drivers/net/wireless/ath/ath12k/dp_rx.c:1391:58: error: passing argument 2 of 'ieee80211_rx_napi' from incompatible pointer type [-Wincompatible-pointer-types]
1391 | ieee80211_rx_napi(ath12k_pdev_dp_to_hw(dp_pdev), pubsta, msdu, napi);
| ^~~~~~
| |
| struct ieee80211_sta *
In file included from drivers/net/wireless/ath/ath12k/wmi.h:10,
from drivers/net/wireless/ath/ath12k/core.h:24,
from drivers/net/wireless/ath/ath12k/dp_rx.c:11:
./include/net/mac80211.h:5249:51: note: expected 'struct ieee80211_link_sta *' but argument is of type 'struct ieee80211_sta *'
5249 | struct ieee80211_link_sta *link_sta,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~drivers/net/wireless/ath/ath12k/dp_mon.c: In function 'ath12k_dp_mon_rx_deliver_msdu':drivers/net/wireless/ath/ath12k/dp_mon.c:520:17: error: 'struct ieee80211_rx_status' has no member named 'link_valid'; did you mean 'link_id'?
520 | status->link_valid = 0;
| ^~~~~~~~~~
| link_id
drivers/net/wireless/ath/ath12k/dp_mon.c:538:33: error: 'struct ieee80211_rx_status' has no member named 'link_valid'; did you mean 'link_id'?
538 | status->link_valid = 1;
| ^~~~~~~~~~
| link_id
drivers/net/wireless/ath/ath12k/dp_mon.c:586:58: error: passing argument 2 of 'ieee80211_rx_napi' from incompatible pointer type [-Wincompatible-pointer-types]
586 | ieee80211_rx_napi(ath12k_pdev_dp_to_hw(dp_pdev), pubsta, msdu, napi);
| ^~~~~~
| |
| struct ieee80211_sta *
In file included from drivers/net/wireless/ath/ath12k/wmi.h:10,
from drivers/net/wireless/ath/ath12k/core.h:24,
from drivers/net/wireless/ath/ath12k/dp_mon.h:10,
from drivers/net/wireless/ath/ath12k/dp_mon.c:7:
./include/net/mac80211.h:5249:51: note: expected 'struct ieee80211_link_sta *' but argument is of type 'struct ieee80211_sta *'
5249 | struct ieee80211_link_sta *link_sta,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~