Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: allow to transmit A-MSDU within A-MPDU

Advertise the capability to send A-MSDU within A-MPDU
in the AddBA request sent by mac80211. Let the driver
know about the peer's capabilities.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Emmanuel Grumbach and committed by
Johannes Berg
e3abc8ff 1b09b556

+52 -35
+1 -1
drivers/net/wireless/ath/ath10k/mac.c
··· 6144 6144 struct ieee80211_vif *vif, 6145 6145 enum ieee80211_ampdu_mlme_action action, 6146 6146 struct ieee80211_sta *sta, u16 tid, u16 *ssn, 6147 - u8 buf_size) 6147 + u8 buf_size, bool amsdu) 6148 6148 { 6149 6149 struct ath10k *ar = hw->priv; 6150 6150 struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+1 -1
drivers/net/wireless/ath/ath9k/htc_drv_main.c
··· 1659 1659 struct ieee80211_vif *vif, 1660 1660 enum ieee80211_ampdu_mlme_action action, 1661 1661 struct ieee80211_sta *sta, 1662 - u16 tid, u16 *ssn, u8 buf_size) 1662 + u16 tid, u16 *ssn, u8 buf_size, bool amsdu) 1663 1663 { 1664 1664 struct ath9k_htc_priv *priv = hw->priv; 1665 1665 struct ath9k_htc_sta *ista;
+1 -1
drivers/net/wireless/ath/ath9k/main.c
··· 1856 1856 struct ieee80211_vif *vif, 1857 1857 enum ieee80211_ampdu_mlme_action action, 1858 1858 struct ieee80211_sta *sta, 1859 - u16 tid, u16 *ssn, u8 buf_size) 1859 + u16 tid, u16 *ssn, u8 buf_size, bool amsdu) 1860 1860 { 1861 1861 struct ath_softc *sc = hw->priv; 1862 1862 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+1 -1
drivers/net/wireless/ath/carl9170/main.c
··· 1415 1415 struct ieee80211_vif *vif, 1416 1416 enum ieee80211_ampdu_mlme_action action, 1417 1417 struct ieee80211_sta *sta, 1418 - u16 tid, u16 *ssn, u8 buf_size) 1418 + u16 tid, u16 *ssn, u8 buf_size, bool amsdu) 1419 1419 { 1420 1420 struct ar9170 *ar = hw->priv; 1421 1421 struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
+1 -1
drivers/net/wireless/ath/wcn36xx/main.c
··· 859 859 struct ieee80211_vif *vif, 860 860 enum ieee80211_ampdu_mlme_action action, 861 861 struct ieee80211_sta *sta, u16 tid, u16 *ssn, 862 - u8 buf_size) 862 + u8 buf_size, bool amsdu) 863 863 { 864 864 struct wcn36xx *wcn = hw->priv; 865 865 struct wcn36xx_sta *sta_priv = NULL;
+1 -1
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
··· 820 820 struct ieee80211_vif *vif, 821 821 enum ieee80211_ampdu_mlme_action action, 822 822 struct ieee80211_sta *sta, u16 tid, u16 *ssn, 823 - u8 buf_size) 823 + u8 buf_size, bool amsdu) 824 824 { 825 825 struct brcms_info *wl = hw->priv; 826 826 struct scb *scb = &wl->wlc->pri_scb;
+1 -1
drivers/net/wireless/cw1200/sta.c
··· 2137 2137 struct ieee80211_vif *vif, 2138 2138 enum ieee80211_ampdu_mlme_action action, 2139 2139 struct ieee80211_sta *sta, u16 tid, u16 *ssn, 2140 - u8 buf_size) 2140 + u8 buf_size, bool amsdu) 2141 2141 { 2142 2142 /* Aggregation is implemented fully in firmware, 2143 2143 * including block ack negotiation. Do not allow
+1 -1
drivers/net/wireless/cw1200/sta.h
··· 111 111 struct ieee80211_vif *vif, 112 112 enum ieee80211_ampdu_mlme_action action, 113 113 struct ieee80211_sta *sta, u16 tid, u16 *ssn, 114 - u8 buf_size); 114 + u8 buf_size, bool amsdu); 115 115 116 116 void cw1200_suspend_resume(struct cw1200_common *priv, 117 117 struct wsm_suspend_resume *arg);
+1 -1
drivers/net/wireless/iwlegacy/4965-mac.c
··· 5984 5984 il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 5985 5985 enum ieee80211_ampdu_mlme_action action, 5986 5986 struct ieee80211_sta *sta, u16 tid, u16 * ssn, 5987 - u8 buf_size) 5987 + u8 buf_size, bool amsdu) 5988 5988 { 5989 5989 struct il_priv *il = hw->priv; 5990 5990 int ret = -EINVAL;
+1 -1
drivers/net/wireless/iwlegacy/4965.h
··· 184 184 int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 185 185 enum ieee80211_ampdu_mlme_action action, 186 186 struct ieee80211_sta *sta, u16 tid, u16 * ssn, 187 - u8 buf_size); 187 + u8 buf_size, bool amsdu); 188 188 int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 189 189 struct ieee80211_sta *sta); 190 190 void
+1 -1
drivers/net/wireless/iwlwifi/dvm/mac80211.c
··· 731 731 struct ieee80211_vif *vif, 732 732 enum ieee80211_ampdu_mlme_action action, 733 733 struct ieee80211_sta *sta, u16 tid, u16 *ssn, 734 - u8 buf_size) 734 + u8 buf_size, bool amsdu) 735 735 { 736 736 struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); 737 737 int ret = -EINVAL;
+1 -1
drivers/net/wireless/iwlwifi/mvm/mac80211.c
··· 820 820 struct ieee80211_vif *vif, 821 821 enum ieee80211_ampdu_mlme_action action, 822 822 struct ieee80211_sta *sta, u16 tid, 823 - u16 *ssn, u8 buf_size) 823 + u16 *ssn, u8 buf_size, bool amsdu) 824 824 { 825 825 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 826 826 int ret;
+1 -1
drivers/net/wireless/mac80211_hwsim.c
··· 1819 1819 struct ieee80211_vif *vif, 1820 1820 enum ieee80211_ampdu_mlme_action action, 1821 1821 struct ieee80211_sta *sta, u16 tid, u16 *ssn, 1822 - u8 buf_size) 1822 + u8 buf_size, bool amsdu) 1823 1823 { 1824 1824 switch (action) { 1825 1825 case IEEE80211_AMPDU_TX_START:
+2 -1
drivers/net/wireless/mediatek/mt7601u/main.c
··· 335 335 static int 336 336 mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 337 337 enum ieee80211_ampdu_mlme_action action, 338 - struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size) 338 + struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, 339 + bool amsdu) 339 340 { 340 341 struct mt7601u_dev *dev = hw->priv; 341 342 struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
+1 -1
drivers/net/wireless/mwl8k.c
··· 5423 5423 mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 5424 5424 enum ieee80211_ampdu_mlme_action action, 5425 5425 struct ieee80211_sta *sta, u16 tid, u16 *ssn, 5426 - u8 buf_size) 5426 + u8 buf_size, bool amsdu) 5427 5427 { 5428 5428 5429 5429 int i, rc = 0;
+3 -1
drivers/net/wireless/rsi/rsi_91x_mac80211.c
··· 664 664 * @tid: Traffic identifier. 665 665 * @ssn: Pointer to ssn value. 666 666 * @buf_size: Buffer size (for kernel version > 2.6.38). 667 + * @amsdu: is AMSDU in AMPDU allowed 667 668 * 668 669 * Return: status: 0 on success, negative error code on failure. 669 670 */ ··· 674 673 struct ieee80211_sta *sta, 675 674 unsigned short tid, 676 675 unsigned short *ssn, 677 - unsigned char buf_size) 676 + unsigned char buf_size, 677 + bool amsdu) 678 678 { 679 679 int status = -EOPNOTSUPP; 680 680 struct rsi_hw *adapter = hw->priv;
+1 -1
drivers/net/wireless/rt2x00/rt2800lib.c
··· 7937 7937 int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 7938 7938 enum ieee80211_ampdu_mlme_action action, 7939 7939 struct ieee80211_sta *sta, u16 tid, u16 *ssn, 7940 - u8 buf_size) 7940 + u8 buf_size, bool amsdu) 7941 7941 { 7942 7942 struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv; 7943 7943 int ret = 0;
+1 -1
drivers/net/wireless/rt2x00/rt2800lib.h
··· 220 220 int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 221 221 enum ieee80211_ampdu_mlme_action action, 222 222 struct ieee80211_sta *sta, u16 tid, u16 *ssn, 223 - u8 buf_size); 223 + u8 buf_size, bool amsdu); 224 224 int rt2800_get_survey(struct ieee80211_hw *hw, int idx, 225 225 struct survey_info *survey); 226 226 void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
+1 -1
drivers/net/wireless/rtlwifi/core.c
··· 1373 1373 struct ieee80211_vif *vif, 1374 1374 enum ieee80211_ampdu_mlme_action action, 1375 1375 struct ieee80211_sta *sta, u16 tid, u16 *ssn, 1376 - u8 buf_size) 1376 + u8 buf_size, bool amsdu) 1377 1377 { 1378 1378 struct rtl_priv *rtlpriv = rtl_priv(hw); 1379 1379
+1 -1
drivers/net/wireless/ti/wlcore/main.c
··· 5263 5263 struct ieee80211_vif *vif, 5264 5264 enum ieee80211_ampdu_mlme_action action, 5265 5265 struct ieee80211_sta *sta, u16 tid, u16 *ssn, 5266 - u8 buf_size) 5266 + u8 buf_size, bool amsdu) 5267 5267 { 5268 5268 struct wl1271 *wl = hw->priv; 5269 5269 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+1
include/linux/ieee80211.h
··· 1379 1379 1380 1380 1381 1381 /* block-ack parameters */ 1382 + #define IEEE80211_ADDBA_PARAM_AMSDU_MASK 0x0001 1382 1383 #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 1383 1384 #define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C 1384 1385 #define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFC0
+4 -1
include/net/mac80211.h
··· 3026 3026 * buffer size of 8. Correct ways to retransmit #1 would be: 3027 3027 * - TX: 1 or 18 or 81 3028 3028 * Even "189" would be wrong since 1 could be lost again. 3029 + * The @amsdu parameter is valid when the action is set to 3030 + * %IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's ability 3031 + * to receive A-MSDU within A-MPDU. 3029 3032 * 3030 3033 * Returns a negative error code on failure. 3031 3034 * The callback can sleep. ··· 3366 3363 struct ieee80211_vif *vif, 3367 3364 enum ieee80211_ampdu_mlme_action action, 3368 3365 struct ieee80211_sta *sta, u16 tid, u16 *ssn, 3369 - u8 buf_size); 3366 + u8 buf_size, bool amsdu); 3370 3367 int (*get_survey)(struct ieee80211_hw *hw, int idx, 3371 3368 struct survey_info *survey); 3372 3369 void (*rfkill_poll)(struct ieee80211_hw *hw);
+2 -2
net/mac80211/agg-rx.c
··· 79 79 (int)reason); 80 80 81 81 if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, 82 - &sta->sta, tid, NULL, 0)) 82 + &sta->sta, tid, NULL, 0, false)) 83 83 sdata_info(sta->sdata, 84 84 "HW problem - can not stop rx aggregation for %pM tid %d\n", 85 85 sta->sta.addr, tid); ··· 321 321 __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]); 322 322 323 323 ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, 324 - &sta->sta, tid, &start_seq_num, 0); 324 + &sta->sta, tid, &start_seq_num, 0, false); 325 325 ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n", 326 326 sta->sta.addr, tid, ret); 327 327 if (ret) {
+10 -5
net/mac80211/agg-tx.c
··· 97 97 mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ; 98 98 99 99 mgmt->u.action.u.addba_req.dialog_token = dialog_token; 100 - capab = (u16)(1 << 1); /* bit 1 aggregation policy */ 100 + capab = (u16)(1 << 0); /* bit 0 A-MSDU support */ 101 + capab |= (u16)(1 << 1); /* bit 1 aggregation policy */ 101 102 capab |= (u16)(tid << 2); /* bit 5:2 TID number */ 102 103 capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */ 103 104 ··· 332 331 return -EALREADY; 333 332 ret = drv_ampdu_action(local, sta->sdata, 334 333 IEEE80211_AMPDU_TX_STOP_FLUSH_CONT, 335 - &sta->sta, tid, NULL, 0); 334 + &sta->sta, tid, NULL, 0, false); 336 335 WARN_ON_ONCE(ret); 337 336 return 0; 338 337 } ··· 382 381 tid_tx->tx_stop = reason == AGG_STOP_LOCAL_REQUEST; 383 382 384 383 ret = drv_ampdu_action(local, sta->sdata, action, 385 - &sta->sta, tid, NULL, 0); 384 + &sta->sta, tid, NULL, 0, false); 386 385 387 386 /* HW shall not deny going back to legacy */ 388 387 if (WARN_ON(ret)) { ··· 470 469 start_seq_num = sta->tid_seq[tid] >> 4; 471 470 472 471 ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, 473 - &sta->sta, tid, &start_seq_num, 0); 472 + &sta->sta, tid, &start_seq_num, 0, false); 474 473 if (ret) { 475 474 ht_dbg(sdata, 476 475 "BA request denied - HW unavailable for %pM tid %d\n", ··· 694 693 695 694 drv_ampdu_action(local, sta->sdata, 696 695 IEEE80211_AMPDU_TX_OPERATIONAL, 697 - &sta->sta, tid, NULL, tid_tx->buf_size); 696 + &sta->sta, tid, NULL, tid_tx->buf_size, 697 + tid_tx->amsdu); 698 698 699 699 /* 700 700 * synchronize with TX path, while splicing the TX path ··· 920 918 struct tid_ampdu_tx *tid_tx; 921 919 u16 capab, tid; 922 920 u8 buf_size; 921 + bool amsdu; 923 922 924 923 capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); 924 + amsdu = capab & IEEE80211_ADDBA_PARAM_AMSDU_MASK; 925 925 tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; 926 926 buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; 927 927 ··· 972 968 } 973 969 974 970 tid_tx->buf_size = buf_size; 971 + tid_tx->amsdu = amsdu; 975 972 976 973 if (test_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)) 977 974 ieee80211_agg_tx_operational(local, sta, tid);
+4 -3
net/mac80211/driver-ops.h
··· 734 734 struct ieee80211_sub_if_data *sdata, 735 735 enum ieee80211_ampdu_mlme_action action, 736 736 struct ieee80211_sta *sta, u16 tid, 737 - u16 *ssn, u8 buf_size) 737 + u16 *ssn, u8 buf_size, bool amsdu) 738 738 { 739 739 int ret = -EOPNOTSUPP; 740 740 ··· 744 744 if (!check_sdata_in_driver(sdata)) 745 745 return -EIO; 746 746 747 - trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size); 747 + trace_drv_ampdu_action(local, sdata, action, sta, tid, 748 + ssn, buf_size, amsdu); 748 749 749 750 if (local->ops->ampdu_action) 750 751 ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, 751 - sta, tid, ssn, buf_size); 752 + sta, tid, ssn, buf_size, amsdu); 752 753 753 754 trace_drv_return_int(local, ret); 754 755
+2
net/mac80211/sta_info.h
··· 133 133 * @buf_size: reorder buffer size at receiver 134 134 * @failed_bar_ssn: ssn of the last failed BAR tx attempt 135 135 * @bar_pending: BAR needs to be re-sent 136 + * @amsdu: support A-MSDU withing A-MDPU 136 137 * 137 138 * This structure's lifetime is managed by RCU, assignments to 138 139 * the array holding it must hold the aggregation mutex. ··· 159 158 160 159 u16 failed_bar_ssn; 161 160 bool bar_pending; 161 + bool amsdu; 162 162 }; 163 163 164 164 /**
+6 -4
net/mac80211/trace.h
··· 974 974 struct ieee80211_sub_if_data *sdata, 975 975 enum ieee80211_ampdu_mlme_action action, 976 976 struct ieee80211_sta *sta, u16 tid, 977 - u16 *ssn, u8 buf_size), 977 + u16 *ssn, u8 buf_size, bool amsdu), 978 978 979 - TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size), 979 + TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size, amsdu), 980 980 981 981 TP_STRUCT__entry( 982 982 LOCAL_ENTRY ··· 985 985 __field(u16, tid) 986 986 __field(u16, ssn) 987 987 __field(u8, buf_size) 988 + __field(bool, amsdu) 988 989 VIF_ENTRY 989 990 ), 990 991 ··· 997 996 __entry->tid = tid; 998 997 __entry->ssn = ssn ? *ssn : 0; 999 998 __entry->buf_size = buf_size; 999 + __entry->amsdu = amsdu; 1000 1000 ), 1001 1001 1002 1002 TP_printk( 1003 - LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d", 1003 + LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d amsdu:%d", 1004 1004 LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, 1005 - __entry->tid, __entry->buf_size 1005 + __entry->tid, __entry->buf_size, __entry->amsdu 1006 1006 ) 1007 1007 ); 1008 1008