summaryrefslogtreecommitdiff
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2022-06-09 23:05:07 +0300
committerJohannes Berg <johannes.berg@intel.com>2022-06-20 13:56:04 +0300
commit69d41b5a9c9d8d24c0faeb376fc2f52fc810d855 (patch)
tree1289a38176a7b697b6f50af7b783ca4d26cf52f5 /net/mac80211
parenteef25a6679adb3cc73b611cf6c78386f54df0e0f (diff)
downloadlinux-69d41b5a9c9d8d24c0faeb376fc2f52fc810d855.tar.xz
wifi: mac80211: add MLO link ID to TX frame metadata
Take a few bits out of the control.flags to add the link ID to TX frame metadata, so drivers don't need to look it up by the address themselves. Implement that lookup where it's needed, for internal frame TX, and set it to "unspecified" for data transmissions. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/tx.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index e8a5e27a3dd1..17313954c628 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2889,7 +2889,9 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
info->flags = info_flags;
info->ack_frame_id = info_id;
info->band = band;
- info->control.flags = ctrl_flags;
+ info->control.flags = ctrl_flags |
+ u32_encode_bits(IEEE80211_LINK_UNSPECIFIED,
+ IEEE80211_TX_CTRL_MLO_LINK);
return skb;
free:
@@ -3558,7 +3560,9 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
info->flags = IEEE80211_TX_CTL_FIRST_FRAGMENT |
IEEE80211_TX_CTL_DONTFRAG |
(tid_tx ? IEEE80211_TX_CTL_AMPDU : 0);
- info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT;
+ info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT |
+ u32_encode_bits(IEEE80211_LINK_UNSPECIFIED,
+ IEEE80211_TX_CTRL_MLO_LINK);
#ifdef CONFIG_MAC80211_DEBUGFS
if (local->force_tx_status)
@@ -5668,7 +5672,9 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, int tid,
enum nl80211_band band)
{
+ const struct ieee80211_hdr *hdr = (void *)skb->data;
int ac = ieee80211_ac_from_tid(tid);
+ unsigned int link;
skb_reset_mac_header(skb);
skb_set_queue_mapping(skb, ac);
@@ -5676,6 +5682,30 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
skb->dev = sdata->dev;
+ BUILD_BUG_ON(IEEE80211_LINK_UNSPECIFIED < IEEE80211_MLD_MAX_NUM_LINKS);
+ BUILD_BUG_ON(!FIELD_FIT(IEEE80211_TX_CTRL_MLO_LINK,
+ IEEE80211_LINK_UNSPECIFIED));
+
+ if (!sdata->vif.valid_links) {
+ link = 0;
+ } else if (memcmp(sdata->vif.addr, hdr->addr2, ETH_ALEN) == 0) {
+ /* address from the MLD */
+ link = IEEE80211_LINK_UNSPECIFIED;
+ } else {
+ /* otherwise must be addressed from a link */
+ for (link = 0; link < ARRAY_SIZE(sdata->vif.link_conf); link++) {
+ if (memcmp(sdata->vif.link_conf[link]->addr,
+ hdr->addr2, ETH_ALEN) == 0)
+ break;
+ }
+
+ if (WARN_ON_ONCE(link == ARRAY_SIZE(sdata->vif.link_conf)))
+ link = ffs(sdata->vif.valid_links) - 1;
+ }
+
+ IEEE80211_SKB_CB(skb)->control.flags |=
+ u32_encode_bits(link, IEEE80211_TX_CTRL_MLO_LINK);
+
/*
* The other path calling ieee80211_xmit is from the tasklet,
* and while we can handle concurrent transmissions locking