struct sk_buff *skb;
struct ieee80211_local *local;
struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_link_data *link;
struct sta_info *sta;
struct ieee80211_key *key;
*/
rx->skb = skb;
+ if (WARN_ON_ONCE(!rx->link))
+ goto rxh_next;
+
CALL_RXH(ieee80211_rx_h_check_more_data);
CALL_RXH(ieee80211_rx_h_uapsd_and_pspoll);
CALL_RXH(ieee80211_rx_h_sta_process);
rx.sta = sta;
rx.sdata = sta->sdata;
+ rx.link = &rx.sdata->deflink;
rx.local = sta->local;
rcu_read_lock();
if (!ieee80211_accept_frame(rx))
return false;
+ if (rx->link_id >= 0) {
+ link = rcu_dereference(rx->sdata->link[rx->link_id]);
+
+ /* we might race link removal */
+ if (!link)
+ return true;
+ rx->link = link;
+ } else {
+ rx->link = &sdata->deflink;
+ }
+
if (unlikely(!is_multicast_ether_addr(hdr->addr1) &&
rx->link_id >= 0 && rx->sta && rx->sta->sta.mlo)) {
link_sta = rcu_dereference(rx->sta->link[rx->link_id]);
- link = rcu_dereference(rx->sdata->link[rx->link_id]);
- if (WARN_ON_ONCE(!link_sta || !link))
+ if (WARN_ON_ONCE(!link_sta))
return true;
}
rx.sta = container_of(pubsta, struct sta_info, sta);
rx.sdata = rx.sta->sdata;
+ rx.link = &rx.sdata->deflink;
fast_rx = rcu_dereference(rx.sta->fast_rx);
if (!fast_rx)