Skip to content

Commit

Permalink
wifi: mac80211: keep A-MSDU data in sta and per-link
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Benjamin Berg authored and Johannes Berg committed Sep 6, 2022
1 parent 189a0c5 commit 4c51541
Show file tree
Hide file tree
Showing 18 changed files with 152 additions and 65 deletions.
14 changes: 8 additions & 6 deletions drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,14 +430,16 @@ static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_sta *sta,
return -EBUSY;

if (amsdu_len) {
mvmsta->orig_amsdu_len = sta->max_amsdu_len;
sta->max_amsdu_len = amsdu_len;
for (i = 0; i < ARRAY_SIZE(sta->max_tid_amsdu_len); i++)
sta->max_tid_amsdu_len[i] = amsdu_len;
mvmsta->orig_amsdu_len = sta->cur->max_amsdu_len;
sta->deflink.agg.max_amsdu_len = amsdu_len;
sta->deflink.agg.max_amsdu_len = amsdu_len;
for (i = 0; i < ARRAY_SIZE(sta->deflink.agg.max_tid_amsdu_len); i++)
sta->deflink.agg.max_tid_amsdu_len[i] = amsdu_len;
} else {
sta->max_amsdu_len = mvmsta->orig_amsdu_len;
sta->deflink.agg.max_amsdu_len = mvmsta->orig_amsdu_len;
mvmsta->orig_amsdu_len = 0;
}

return count;
}

Expand All @@ -451,7 +453,7 @@ static ssize_t iwl_dbgfs_amsdu_len_read(struct file *file,
char buf[32];
int pos;

pos = scnprintf(buf, sizeof(buf), "current %d ", sta->max_amsdu_len);
pos = scnprintf(buf, sizeof(buf), "current %d ", sta->cur->max_amsdu_len);
pos += scnprintf(buf + pos, sizeof(buf) - pos, "stored %d\n",
mvmsta->orig_amsdu_len);

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -3193,7 +3193,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
NL80211_TDLS_SETUP);
}

sta->max_rc_amsdu_len = 1;
sta->deflink.agg.max_rc_amsdu_len = 1;
} else if (old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_AUTH) {
/*
Expand Down
12 changes: 6 additions & 6 deletions drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,9 +340,9 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
u16 size = le32_to_cpu(notif->amsdu_size);
int i;

if (sta->max_amsdu_len < size) {
if (sta->deflink.agg.max_amsdu_len < size) {
/*
* In debug sta->max_amsdu_len < size
* In debug sta->deflink.agg.max_amsdu_len < size
* so also check with orig_amsdu_len which holds the
* original data before debugfs changed the value
*/
Expand All @@ -352,18 +352,18 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,

mvmsta->amsdu_enabled = le32_to_cpu(notif->amsdu_enabled);
mvmsta->max_amsdu_len = size;
sta->max_rc_amsdu_len = mvmsta->max_amsdu_len;
sta->deflink.agg.max_rc_amsdu_len = mvmsta->max_amsdu_len;

for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
if (mvmsta->amsdu_enabled & BIT(i))
sta->max_tid_amsdu_len[i] =
sta->deflink.agg.max_tid_amsdu_len[i] =
iwl_mvm_max_amsdu_size(mvm, sta, i);
else
/*
* Not so elegant, but this will effectively
* prevent AMSDU on this TID
*/
sta->max_tid_amsdu_len[i] = 1;
sta->deflink.agg.max_tid_amsdu_len[i] = 1;
}

IWL_DEBUG_RATE(mvm,
Expand Down Expand Up @@ -450,7 +450,7 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
* since TLC offload works with one mode we can assume
* that only vht/ht is used and also set it as station max amsdu
*/
sta->max_amsdu_len = max_amsdu_len;
sta->deflink.agg.max_amsdu_len = max_amsdu_len;

cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
WIDE_ID(DATA_PATH_GROUP,
Expand Down
15 changes: 8 additions & 7 deletions drivers/net/wireless/intel/iwlwifi/mvm/rs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1491,7 +1491,7 @@ static void rs_set_amsdu_len(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
int i;

sta->max_amsdu_len = rs_fw_get_max_amsdu_len(sta);
sta->deflink.agg.max_amsdu_len = rs_fw_get_max_amsdu_len(sta);

/*
* In case TLC offload is not active amsdu_enabled is either 0xFFFF
Expand All @@ -1506,22 +1506,23 @@ static void rs_set_amsdu_len(struct iwl_mvm *mvm, struct ieee80211_sta *sta,

if (mvmsta->vif->bss_conf.he_support &&
!iwlwifi_mod_params.disable_11ax)
mvmsta->max_amsdu_len = sta->max_amsdu_len;
mvmsta->max_amsdu_len = sta->deflink.agg.max_amsdu_len;
else
mvmsta->max_amsdu_len = min_t(int, sta->max_amsdu_len, 8500);
mvmsta->max_amsdu_len =
min_t(int, sta->deflink.agg.max_amsdu_len, 8500);

sta->max_rc_amsdu_len = mvmsta->max_amsdu_len;
sta->deflink.agg.max_rc_amsdu_len = mvmsta->max_amsdu_len;

for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
if (mvmsta->amsdu_enabled)
sta->max_tid_amsdu_len[i] =
sta->deflink.agg.max_tid_amsdu_len[i] =
iwl_mvm_max_amsdu_size(mvm, sta, i);
else
/*
* Not so elegant, but this will effectively
* prevent AMSDU on this TID
*/
sta->max_tid_amsdu_len[i] = 1;
sta->deflink.agg.max_tid_amsdu_len[i] = 1;
}
}

Expand Down Expand Up @@ -2933,7 +2934,7 @@ static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,

lq_sta->lq.sta_id = mvmsta->sta_id;
mvmsta->amsdu_enabled = 0;
mvmsta->max_amsdu_len = sta->max_amsdu_len;
mvmsta->max_amsdu_len = sta->cur->max_amsdu_len;

for (j = 0; j < LQ_SIZE; j++)
rs_rate_scale_clear_tbl_windows(mvm, &lq_sta->lq_info[j]);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/intel/iwlwifi/mvm/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -926,7 +926,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
* Take the min of ieee80211 station and mvm station
*/
max_amsdu_len =
min_t(unsigned int, sta->max_amsdu_len,
min_t(unsigned int, sta->cur->max_amsdu_len,
iwl_mvm_max_amsdu_size(mvm, sta, tid));

/*
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,14 +594,14 @@ mt76_connac_mcu_sta_amsdu_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
vif->type != NL80211_IFTYPE_STATION)
return;

if (!sta->max_amsdu_len)
if (!sta->deflink.agg.max_amsdu_len)
return;

tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HW_AMSDU, sizeof(*amsdu));
amsdu = (struct sta_rec_amsdu *)tlv;
amsdu->max_amsdu_num = 8;
amsdu->amsdu_en = true;
amsdu->max_mpdu_size = sta->max_amsdu_len >=
amsdu->max_mpdu_size = sta->deflink.agg.max_amsdu_len >=
IEEE80211_MAX_MPDU_LEN_VHT_7991;

wcid->amsdu = true;
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ mt7915_mcu_sta_amsdu_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
vif->type != NL80211_IFTYPE_AP)
return;

if (!sta->max_amsdu_len)
if (!sta->deflink.agg.max_amsdu_len)
return;

tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HW_AMSDU, sizeof(*amsdu));
Expand All @@ -934,7 +934,7 @@ mt7915_mcu_sta_amsdu_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
amsdu->amsdu_en = true;
msta->wcid.amsdu = true;

switch (sta->max_amsdu_len) {
switch (sta->deflink.agg.max_amsdu_len) {
case IEEE80211_MAX_MPDU_LEN_VHT_11454:
if (!is_mt7915(&dev->mt76)) {
amsdu->max_mpdu_size =
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/realtek/rtw88/fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ static void rtw_fw_ra_report_iter(void *data, struct ieee80211_sta *sta)
si->ra_report.desc_rate = rate;
si->ra_report.bit_rate = bit_rate;

sta->max_rc_amsdu_len = get_max_amsdu_len(bit_rate);
sta->deflink.agg.max_rc_amsdu_len = get_max_amsdu_len(bit_rate);
}

static void rtw_fw_ra_report_handle(struct rtw_dev *rtwdev, u8 *payload,
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/realtek/rtw89/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -2309,7 +2309,7 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
seq_printf(m, "%s", rtwsta->ra_report.might_fallback_legacy ? " FB_G" : "");
seq_printf(m, "\t(hw_rate=0x%x)", rtwsta->ra_report.hw_rate);
seq_printf(m, "\t==> agg_wait=%d (%d)\n", rtwsta->max_agg_wait,
sta->max_rc_amsdu_len);
sta->deflink.agg.max_rc_amsdu_len);

seq_printf(m, "RX rate [%d]: ", rtwsta->mac_id);

Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/realtek/rtw89/phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -2031,8 +2031,8 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
ra_report->hw_rate = FIELD_PREP(RTW89_HW_RATE_MASK_MOD, mode) |
FIELD_PREP(RTW89_HW_RATE_MASK_VAL, rate);
ra_report->might_fallback_legacy = mcs <= 2;
sta->max_rc_amsdu_len = get_max_amsdu_len(rtwdev, ra_report);
rtwsta->max_agg_wait = sta->max_rc_amsdu_len / 1500 - 1;
sta->deflink.agg.max_rc_amsdu_len = get_max_amsdu_len(rtwdev, ra_report);
rtwsta->max_agg_wait = sta->deflink.agg.max_rc_amsdu_len / 1500 - 1;
}

static void
Expand Down
68 changes: 48 additions & 20 deletions include/net/mac80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -2143,6 +2143,34 @@ struct ieee80211_sta_txpwr {
enum nl80211_tx_power_setting type;
};

/**
* struct ieee80211_sta_aggregates - info that is aggregated from active links
*
* Used for any per-link data that needs to be aggregated and updated in the
* main &struct ieee80211_sta when updated or the active links change.
*
* @max_amsdu_len: indicates the maximal length of an A-MSDU in bytes.
* This field is always valid for packets with a VHT preamble.
* For packets with a HT preamble, additional limits apply:
*
* * If the skb is transmitted as part of a BA agreement, the
* A-MSDU maximal size is min(max_amsdu_len, 4065) bytes.
* * If the skb is not part of a BA agreement, the A-MSDU maximal
* size is min(max_amsdu_len, 7935) bytes.
*
* Both additional HT limits must be enforced by the low level
* driver. This is defined by the spec (IEEE 802.11-2012 section
* 8.3.2.2 NOTE 2).
* @max_rc_amsdu_len: Maximum A-MSDU size in bytes recommended by rate control.
* @max_tid_amsdu_len: Maximum A-MSDU size in bytes for this TID
*/
struct ieee80211_sta_aggregates {
u16 max_amsdu_len;

u16 max_rc_amsdu_len;
u16 max_tid_amsdu_len[IEEE80211_NUM_TIDS];
};

/**
* struct ieee80211_link_sta - station Link specific info
* All link specific info for a STA link for a non MLD STA(single)
Expand Down Expand Up @@ -2179,6 +2207,8 @@ struct ieee80211_link_sta {
struct ieee80211_he_6ghz_capa he_6ghz_capa;
struct ieee80211_sta_eht_cap eht_cap;

struct ieee80211_sta_aggregates agg;

u8 rx_nss;
enum ieee80211_sta_rx_bandwidth bandwidth;
struct ieee80211_sta_txpwr txpwr;
Expand Down Expand Up @@ -2218,9 +2248,10 @@ struct ieee80211_link_sta {
* @max_amsdu_subframes: indicates the maximal number of MSDUs in a single
* A-MSDU. Taken from the Extended Capabilities element. 0 means
* unlimited.
* @cur: currently valid data as aggregated from the active links
* For non MLO STA it will point to the deflink data. For MLO STA
* ieee80211_sta_recalc_aggregates() must be called to update it.
* @support_p2p_ps: indicates whether the STA supports P2P PS mechanism or not.
* @max_rc_amsdu_len: Maximum A-MSDU size in bytes recommended by rate control.
* @max_tid_amsdu_len: Maximum A-MSDU size in bytes for this TID
* @txq: per-TID data TX queues (if driver uses the TXQ abstraction); note that
* the last entry (%IEEE80211_NUM_TIDS) is used for non-data frames
* @deflink: This holds the default link STA information, for non MLO STA all link
Expand Down Expand Up @@ -2250,25 +2281,9 @@ struct ieee80211_sta {
bool mlo;
u8 max_amsdu_subframes;

/**
* @max_amsdu_len:
* indicates the maximal length of an A-MSDU in bytes.
* This field is always valid for packets with a VHT preamble.
* For packets with a HT preamble, additional limits apply:
*
* * If the skb is transmitted as part of a BA agreement, the
* A-MSDU maximal size is min(max_amsdu_len, 4065) bytes.
* * If the skb is not part of a BA agreement, the A-MSDU maximal
* size is min(max_amsdu_len, 7935) bytes.
*
* Both additional HT limits must be enforced by the low level
* driver. This is defined by the spec (IEEE 802.11-2012 section
* 8.3.2.2 NOTE 2).
*/
u16 max_amsdu_len;
struct ieee80211_sta_aggregates *cur;

bool support_p2p_ps;
u16 max_rc_amsdu_len;
u16 max_tid_amsdu_len[IEEE80211_NUM_TIDS];

struct ieee80211_txq *txq[IEEE80211_NUM_TIDS + 1];

Expand Down Expand Up @@ -6105,6 +6120,19 @@ void ieee80211_sta_eosp(struct ieee80211_sta *pubsta);
*/
void ieee80211_send_eosp_nullfunc(struct ieee80211_sta *pubsta, int tid);

/**
* ieee80211_sta_recalc_aggregates - recalculate aggregate data after a change
* @pubsta: the station
*
* Call this function after changing a per-link aggregate data as referenced in
* &struct ieee80211_sta_aggregates by accessing the agg field of
* &struct ieee80211_link_sta.
*
* With non MLO the data in deflink will be referenced directly. In that case
* there is no need to call this function.
*/
void ieee80211_sta_recalc_aggregates(struct ieee80211_sta *pubsta);

/**
* ieee80211_sta_register_airtime - register airtime usage for a sta/tid
*
Expand Down
8 changes: 5 additions & 3 deletions net/mac80211/he.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
6 changes: 4 additions & 2 deletions net/mac80211/ht.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
3 changes: 2 additions & 1 deletion net/mac80211/rc80211_minstrel_ht.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
Loading

0 comments on commit 4c51541

Please sign in to comment.