Commit eef25a66 authored by Johannes Berg's avatar Johannes Berg

wifi: mac80211: remove band from TX info in MLO

If the interface is an MLD, then we don't know which band
the frame will be transmitted on, and we don't know how to
look up the band. Set the band information to zero in that
case, the driver cannot rely on it anyway.

No longer inline ieee80211_tx_skb_tid() since it's even
bigger now.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent d8787ec6
...@@ -1029,7 +1029,9 @@ ieee80211_rate_get_vht_nss(const struct ieee80211_tx_rate *rate) ...@@ -1029,7 +1029,9 @@ ieee80211_rate_get_vht_nss(const struct ieee80211_tx_rate *rate)
* (3) TX status information - driver tells mac80211 what happened * (3) TX status information - driver tells mac80211 what happened
* *
* @flags: transmit info flags, defined above * @flags: transmit info flags, defined above
* @band: the band to transmit on (use for checking for races) * @band: the band to transmit on (use e.g. for checking for races),
* not valid if the interface is an MLD since we won't know which
* link the frame will be transmitted on
* @hw_queue: HW queue to put the frame on, skb_get_queue_mapping() gives the AC * @hw_queue: HW queue to put the frame on, skb_get_queue_mapping() gives the AC
* @ack_frame_id: internal frame ID for TX status, used internally * @ack_frame_id: internal frame ID for TX status, used internally
* @tx_time_est: TX time estimate in units of 4us, used internally * @tx_time_est: TX time estimate in units of 4us, used internally
......
...@@ -2251,23 +2251,8 @@ ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, ...@@ -2251,23 +2251,8 @@ ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
rcu_read_unlock(); rcu_read_unlock();
} }
static inline void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, int tid) struct sk_buff *skb, int tid);
{
struct ieee80211_chanctx_conf *chanctx_conf;
rcu_read_lock();
chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
if (WARN_ON(!chanctx_conf)) {
rcu_read_unlock();
kfree_skb(skb);
return;
}
__ieee80211_tx_skb_tid_band(sdata, skb, tid,
chanctx_conf->def.chan->band);
rcu_read_unlock();
}
static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb) struct sk_buff *skb)
......
...@@ -2566,8 +2566,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, ...@@ -2566,8 +2566,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
bool tdls_peer; bool tdls_peer;
bool multicast; bool multicast;
u16 info_id = 0; u16 info_id = 0;
struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_chanctx_conf *chanctx_conf = NULL;
struct ieee80211_sub_if_data *ap_sdata;
enum nl80211_band band; enum nl80211_band band;
int ret; int ret;
...@@ -2584,7 +2583,9 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, ...@@ -2584,7 +2583,9 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
ethertype = (skb->data[12] << 8) | skb->data[13]; ethertype = (skb->data[12] << 8) | skb->data[13];
fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf); if (!sdata->vif.valid_links)
chanctx_conf =
rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
switch (sdata->vif.type) { switch (sdata->vif.type) {
case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_AP_VLAN:
...@@ -2599,10 +2600,16 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, ...@@ -2599,10 +2600,16 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
wme_sta = sta->sta.wme; wme_sta = sta->sta.wme;
} }
/* override chanctx_conf from AP (we don't have one) */ if (!sdata->vif.valid_links) {
ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, struct ieee80211_sub_if_data *ap_sdata;
u.ap);
chanctx_conf = rcu_dereference(ap_sdata->vif.bss_conf.chanctx_conf); /* override chanctx_conf from AP (we don't have one) */
ap_sdata = container_of(sdata->bss,
struct ieee80211_sub_if_data,
u.ap);
chanctx_conf =
rcu_dereference(ap_sdata->vif.bss_conf.chanctx_conf);
}
if (sdata->wdev.use_4addr) if (sdata->wdev.use_4addr)
break; break;
fallthrough; fallthrough;
...@@ -2738,10 +2745,15 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, ...@@ -2738,10 +2745,15 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
} }
if (!chanctx_conf) { if (!chanctx_conf) {
ret = -ENOTCONN; if (!sdata->vif.valid_links) {
goto free; ret = -ENOTCONN;
goto free;
}
/* MLD transmissions must not rely on the band */
band = 0;
} else {
band = chanctx_conf->def.chan->band;
} }
band = chanctx_conf->def.chan->band;
multicast = is_multicast_ether_addr(hdr.addr1); multicast = is_multicast_ether_addr(hdr.addr1);
...@@ -2953,14 +2965,20 @@ void ieee80211_check_fast_xmit(struct sta_info *sta) ...@@ -2953,14 +2965,20 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG)) !ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG))
goto out; goto out;
rcu_read_lock(); if (!sdata->vif.valid_links) {
chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf); rcu_read_lock();
if (!chanctx_conf) { chanctx_conf =
rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
if (!chanctx_conf) {
rcu_read_unlock();
goto out;
}
build.band = chanctx_conf->def.chan->band;
rcu_read_unlock(); rcu_read_unlock();
goto out; } else {
/* MLD transmissions must not rely on the band */
build.band = 0;
} }
build.band = chanctx_conf->def.chan->band;
rcu_read_unlock();
fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
...@@ -4577,12 +4595,16 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, ...@@ -4577,12 +4595,16 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
sdata = vif_to_sdata(info->control.vif); sdata = vif_to_sdata(info->control.vif);
if (info->control.flags & IEEE80211_TX_INTCFL_NEED_TXPROCESSING) { if (info->control.flags & IEEE80211_TX_INTCFL_NEED_TXPROCESSING) {
chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf); /* update band only for non-MLD */
if (unlikely(!chanctx_conf)) { if (!sdata->vif.valid_links) {
dev_kfree_skb(skb); chanctx_conf =
return true; rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
if (unlikely(!chanctx_conf)) {
dev_kfree_skb(skb);
return true;
}
info->band = chanctx_conf->def.chan->band;
} }
info->band = chanctx_conf->def.chan->band;
result = ieee80211_tx(sdata, NULL, skb, true); result = ieee80211_tx(sdata, NULL, skb, true);
} else if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) { } else if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) { if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
...@@ -5665,6 +5687,31 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, ...@@ -5665,6 +5687,31 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
local_bh_enable(); local_bh_enable();
} }
void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, int tid)
{
struct ieee80211_chanctx_conf *chanctx_conf;
enum nl80211_band band;
rcu_read_lock();
if (!sdata->vif.valid_links) {
chanctx_conf =
rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
if (WARN_ON(!chanctx_conf)) {
rcu_read_unlock();
kfree_skb(skb);
return;
}
band = chanctx_conf->def.chan->band;
} else {
/* MLD transmissions must not rely on the band */
band = 0;
}
__ieee80211_tx_skb_tid_band(sdata, skb, tid, band);
rcu_read_unlock();
}
int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev, int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
const u8 *buf, size_t len, const u8 *buf, size_t len,
const u8 *dest, __be16 proto, bool unencrypted, const u8 *dest, __be16 proto, bool unencrypted,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment