summaryrefslogtreecommitdiff
path: root/net/mac80211
diff options
context:
space:
mode:
authorBenjamin Berg <benjamin.berg@intel.com>2022-09-02 16:12:54 +0200
committerJohannes Berg <johannes.berg@intel.com>2022-09-06 10:17:08 +0200
commit4c51541ddb78cef2da9c4c30006c0d9d06ea9a77 (patch)
treec76070fbd0a5c2e02dd62d8dcdc74197818edb3f /net/mac80211
parent189a0c52f3104d93ac40c3d5b2dcb96cf283d4fd (diff)
wifi: mac80211: keep A-MSDU data in sta and per-link
The A-MSDU data needs to be stored per-link and aggregated into a single value for the station. Add a new struct ieee_80211_sta_aggregates in order to store this data and a new function ieee80211_sta_recalc_aggregates to update the current data for the STA. Note that in the non MLO case the pointer in ieee80211_sta will directly reference the data in deflink.agg, which means that recalculation may be skipped in that case. Signed-off-by: Benjamin Berg <benjamin.berg@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/he.c8
-rw-r--r--net/mac80211/ht.c6
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c3
-rw-r--r--net/mac80211/sta_info.c50
-rw-r--r--net/mac80211/sta_info.h3
-rw-r--r--net/mac80211/tx.c10
-rw-r--r--net/mac80211/vht.c8
7 files changed, 72 insertions, 16 deletions
diff --git a/net/mac80211/he.c b/net/mac80211/he.c
index e73899fd4bbb..729f261520c7 100644
--- a/net/mac80211/he.c
+++ b/net/mac80211/he.c
@@ -39,17 +39,19 @@ ieee80211_update_from_he_6ghz_capa(const struct ieee80211_he_6ghz_capa *he_6ghz_
switch (le16_get_bits(he_6ghz_capa->capa,
IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN)) {
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
- sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454;
+ link_sta->pub->agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454;
break;
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
- sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_7991;
+ link_sta->pub->agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_7991;
break;
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895:
default:
- sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_3895;
+ link_sta->pub->agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_3895;
break;
}
+ ieee80211_sta_recalc_aggregates(&sta->sta);
+
link_sta->pub->he_6ghz_capa = *he_6ghz_capa;
}
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 12a233ba5031..83bc41346ae7 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -241,9 +241,11 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
ht_cap.mcs.rx_highest = ht_cap_ie->mcs.rx_highest;
if (ht_cap.cap & IEEE80211_HT_CAP_MAX_AMSDU)
- sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_7935;
+ link_sta->pub->agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_7935;
else
- sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_3839;
+ link_sta->pub->agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_3839;
+
+ ieee80211_sta_recalc_aggregates(&sta->sta);
apply:
changed = memcmp(&link_sta->pub->ht_cap, &ht_cap, sizeof(ht_cap));
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 8c41a545a8b7..24c3c055db6d 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -1568,7 +1568,8 @@ minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
if (i < IEEE80211_TX_RATE_TABLE_SIZE)
rates->rate[i].idx = -1;
- mi->sta->max_rc_amsdu_len = minstrel_ht_get_max_amsdu_len(mi);
+ mi->sta->deflink.agg.max_rc_amsdu_len = minstrel_ht_get_max_amsdu_len(mi);
+ ieee80211_sta_recalc_aggregates(mi->sta);
rate_control_set_rates(mp->hw, mi->sta, rates);
}
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 4875bd8af67c..cebfd148bb40 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -376,6 +376,8 @@ static void sta_remove_link(struct sta_info *sta, unsigned int link_id,
sta_info_free_link(&alloc->info);
kfree_rcu(alloc, rcu_head);
}
+
+ ieee80211_sta_recalc_aggregates(&sta->sta);
}
/**
@@ -514,6 +516,7 @@ static void sta_info_add_link(struct sta_info *sta,
rcu_assign_pointer(sta->sta.link[link_id], link_sta);
link_sta->smps_mode = IEEE80211_SMPS_OFF;
+ link_sta->agg.max_rc_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_BA;
}
static struct sta_info *
@@ -544,6 +547,8 @@ __sta_info_alloc(struct ieee80211_sub_if_data *sdata,
sta_info_add_link(sta, 0, &sta->deflink, &sta->sta.deflink);
}
+ sta->sta.cur = &sta->sta.deflink.agg;
+
spin_lock_init(&sta->lock);
spin_lock_init(&sta->ps_lock);
INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
@@ -667,8 +672,6 @@ __sta_info_alloc(struct ieee80211_sub_if_data *sdata,
}
}
- sta->sta.max_rc_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_BA;
-
sta->cparams.ce_threshold = CODEL_DISABLED_THRESHOLD;
sta->cparams.target = MS2TIME(20);
sta->cparams.interval = MS2TIME(100);
@@ -2124,6 +2127,44 @@ void ieee80211_sta_register_airtime(struct ieee80211_sta *pubsta, u8 tid,
}
EXPORT_SYMBOL(ieee80211_sta_register_airtime);
+void ieee80211_sta_recalc_aggregates(struct ieee80211_sta *pubsta)
+{
+ struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
+ struct ieee80211_link_sta *link_sta;
+ int link_id, i;
+ bool first = true;
+
+ if (!pubsta->valid_links || !pubsta->mlo) {
+ pubsta->cur = &pubsta->deflink.agg;
+ return;
+ }
+
+ rcu_read_lock();
+ for_each_sta_active_link(&sta->sdata->vif, pubsta, link_sta, link_id) {
+ if (first) {
+ sta->cur = pubsta->deflink.agg;
+ first = false;
+ continue;
+ }
+
+ sta->cur.max_amsdu_len =
+ min(sta->cur.max_amsdu_len,
+ link_sta->agg.max_amsdu_len);
+ sta->cur.max_rc_amsdu_len =
+ min(sta->cur.max_rc_amsdu_len,
+ link_sta->agg.max_rc_amsdu_len);
+
+ for (i = 0; i < ARRAY_SIZE(sta->cur.max_tid_amsdu_len); i++)
+ sta->cur.max_tid_amsdu_len[i] =
+ min(sta->cur.max_tid_amsdu_len[i],
+ link_sta->agg.max_tid_amsdu_len[i]);
+ }
+ rcu_read_unlock();
+
+ pubsta->cur = &sta->cur;
+}
+EXPORT_SYMBOL(ieee80211_sta_recalc_aggregates);
+
void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
struct sta_info *sta, u8 ac,
u16 tx_airtime, bool tx_completed)
@@ -2819,6 +2860,11 @@ int ieee80211_sta_activate_link(struct sta_info *sta, unsigned int link_id)
if (!test_sta_flag(sta, WLAN_STA_INSERTED))
goto hash;
+ /* Ensure the values are updated for the driver,
+ * redone by sta_remove_link on failure.
+ */
+ ieee80211_sta_recalc_aggregates(&sta->sta);
+
ret = drv_change_sta_links(sdata->local, sdata, &sta->sta,
old_links, new_links);
if (ret) {
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 2eb3a9452e07..2517ea714dc4 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -622,6 +622,8 @@ struct link_sta_info {
* @tdls_chandef: a TDLS peer can have a wider chandef that is compatible to
* the BSS one.
* @frags: fragment cache
+ * @cur: storage for aggregation data
+ * &struct ieee80211_sta points either here or to deflink.agg.
* @deflink: This is the default link STA information, for non MLO STA all link
* specific STA information is accessed through @deflink or through
* link[0] which points to address of @deflink. For MLO Link STA
@@ -705,6 +707,7 @@ struct sta_info {
struct ieee80211_fragment_cache frags;
+ struct ieee80211_sta_aggregates cur;
struct link_sta_info deflink;
struct link_sta_info __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index a09673117565..24c0a1706b92 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -3387,7 +3387,7 @@ static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata,
int subframe_len = skb->len - ETH_ALEN;
u8 max_subframes = sta->sta.max_amsdu_subframes;
int max_frags = local->hw.max_tx_fragments;
- int max_amsdu_len = sta->sta.max_amsdu_len;
+ int max_amsdu_len = sta->sta.cur->max_amsdu_len;
int orig_truesize;
u32 flow_idx;
__be16 len;
@@ -3413,13 +3413,13 @@ static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata,
if (test_bit(IEEE80211_TXQ_NO_AMSDU, &txqi->flags))
return false;
- if (sta->sta.max_rc_amsdu_len)
+ if (sta->sta.cur->max_rc_amsdu_len)
max_amsdu_len = min_t(int, max_amsdu_len,
- sta->sta.max_rc_amsdu_len);
+ sta->sta.cur->max_rc_amsdu_len);
- if (sta->sta.max_tid_amsdu_len[tid])
+ if (sta->sta.cur->max_tid_amsdu_len[tid])
max_amsdu_len = min_t(int, max_amsdu_len,
- sta->sta.max_tid_amsdu_len[tid]);
+ sta->sta.cur->max_tid_amsdu_len[tid]);
flow_idx = fq_flow_idx(fq, skb);
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index b2b09d421e8b..803de5881485 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -323,16 +323,18 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
*/
switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
- link_sta->sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454;
+ link_sta->pub->agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454;
break;
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
- link_sta->sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_7991;
+ link_sta->pub->agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_7991;
break;
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895:
default:
- link_sta->sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_3895;
+ link_sta->pub->agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_3895;
break;
}
+
+ ieee80211_sta_recalc_aggregates(&link_sta->sta->sta);
}
/* FIXME: move this to some better location - parses HE/EHT now */