^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * HT handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2002-2005, Instant802 Networks, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright 2005-2006, Devicescape Software, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright 2007-2010, Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright(c) 2015-2017 Intel Deutschland GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright (C) 2018-2021 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * DOC: RX A-MPDU aggregation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Aggregation on the RX side requires only implementing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * @ampdu_action callback that is invoked to start/stop any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * block-ack sessions for RX aggregation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * When RX aggregation is started by the peer, the driver is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * notified via @ampdu_action function, with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * %IEEE80211_AMPDU_RX_START action, and may reject the request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * in which case a negative response is sent to the peer, if it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * accepts it a positive response is sent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * While the session is active, the device/driver are required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * to de-aggregate frames and pass them up one by one to mac80211,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * which will handle the reorder buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * When the aggregation session is stopped again by the peer or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * ourselves, the driver's @ampdu_action function will be called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * with the action %IEEE80211_AMPDU_RX_STOP. In this case, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * call must not fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/ieee80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <net/mac80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include "ieee80211_i.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include "driver-ops.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static void ieee80211_free_tid_rx(struct rcu_head *h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct tid_ampdu_rx *tid_rx =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) container_of(h, struct tid_ampdu_rx, rcu_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) for (i = 0; i < tid_rx->buf_size; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) __skb_queue_purge(&tid_rx->reorder_buf[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) kfree(tid_rx->reorder_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) kfree(tid_rx->reorder_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) kfree(tid_rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) u16 initiator, u16 reason, bool tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct ieee80211_local *local = sta->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct tid_ampdu_rx *tid_rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct ieee80211_ampdu_params params = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) .sta = &sta->sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) .action = IEEE80211_AMPDU_RX_STOP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .tid = tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .amsdu = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) .timeout = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) .ssn = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) lockdep_assert_held(&sta->ampdu_mlme.mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) tid_rx = rcu_dereference_protected(sta->ampdu_mlme.tid_rx[tid],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) lockdep_is_held(&sta->ampdu_mlme.mtx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (!test_bit(tid, sta->ampdu_mlme.agg_session_valid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) __clear_bit(tid, sta->ampdu_mlme.agg_session_valid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) ht_dbg(sta->sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) "Rx BA session stop requested for %pM tid %u %s reason: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) sta->sta.addr, tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) initiator == WLAN_BACK_RECIPIENT ? "recipient" : "initiator",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) (int)reason);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (drv_ampdu_action(local, sta->sdata, ¶ms))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) sdata_info(sta->sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) "HW problem - can not stop rx aggregation for %pM tid %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) sta->sta.addr, tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* check if this is a self generated aggregation halt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (initiator == WLAN_BACK_RECIPIENT && tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ieee80211_send_delba(sta->sdata, sta->sta.addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) tid, WLAN_BACK_RECIPIENT, reason);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * return here in case tid_rx is not assigned - which will happen if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * IEEE80211_HW_SUPPORTS_REORDERING_BUFFER is set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (!tid_rx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) del_timer_sync(&tid_rx->session_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* make sure ieee80211_sta_reorder_release() doesn't re-arm the timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) spin_lock_bh(&tid_rx->reorder_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) tid_rx->removed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) spin_unlock_bh(&tid_rx->reorder_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) del_timer_sync(&tid_rx->reorder_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) u16 initiator, u16 reason, bool tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) mutex_lock(&sta->ampdu_mlme.mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) mutex_unlock(&sta->ampdu_mlme.mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) const u8 *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct sta_info *sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) sta = sta_info_get_bss(sdata, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (!sta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) for (i = 0; i < IEEE80211_NUM_TIDS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (ba_rx_bitmap & BIT(i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) set_bit(i, sta->ampdu_mlme.tid_rx_stop_requested);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) EXPORT_SYMBOL(ieee80211_stop_rx_ba_session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * After accepting the AddBA Request we activated a timer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * resetting it after each frame that arrives from the originator.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static void sta_rx_agg_session_timer_expired(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct tid_ampdu_rx *tid_rx = from_timer(tid_rx, t, session_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct sta_info *sta = tid_rx->sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) u8 tid = tid_rx->tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) timeout = tid_rx->last_rx + TU_TO_JIFFIES(tid_rx->timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (time_is_after_jiffies(timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) mod_timer(&tid_rx->session_timer, timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ht_dbg(sta->sdata, "RX session timer expired on %pM tid %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) sta->sta.addr, tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) set_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static void sta_rx_agg_reorder_timer_expired(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct tid_ampdu_rx *tid_rx = from_timer(tid_rx, t, reorder_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) ieee80211_release_reorder_timeout(tid_rx->sta, tid_rx->tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static void ieee80211_add_addbaext(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) const struct ieee80211_addba_ext_ie *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct ieee80211_addba_ext_ie *resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) const struct ieee80211_sta_he_cap *he_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) u8 frag_level, cap_frag_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) u8 *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) sband = ieee80211_get_sband(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) he_cap = ieee80211_get_he_iftype_cap(sband,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) ieee80211_vif_type_p2p(&sdata->vif));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (!he_cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) pos = skb_put_zero(skb, 2 + sizeof(struct ieee80211_addba_ext_ie));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) *pos++ = WLAN_EID_ADDBA_EXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) *pos++ = sizeof(struct ieee80211_addba_ext_ie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) resp = (struct ieee80211_addba_ext_ie *)pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) resp->data = req->data & IEEE80211_ADDBA_EXT_NO_FRAG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) frag_level = u32_get_bits(req->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) IEEE80211_ADDBA_EXT_FRAG_LEVEL_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) cap_frag_level = u32_get_bits(he_cap->he_cap_elem.mac_cap_info[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (frag_level > cap_frag_level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) frag_level = cap_frag_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) resp->data |= u8_encode_bits(frag_level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) IEEE80211_ADDBA_EXT_FRAG_LEVEL_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static void ieee80211_send_addba_resp(struct sta_info *sta, u8 *da, u16 tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) u8 dialog_token, u16 status, u16 policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) u16 buf_size, u16 timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) const struct ieee80211_addba_ext_ie *addbaext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct ieee80211_sub_if_data *sdata = sta->sdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct ieee80211_mgmt *mgmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) bool amsdu = ieee80211_hw_check(&local->hw, SUPPORTS_AMSDU_IN_AMPDU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) u16 capab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) skb = dev_alloc_skb(sizeof(*mgmt) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 2 + sizeof(struct ieee80211_addba_ext_ie) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) local->hw.extra_tx_headroom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) skb_reserve(skb, local->hw.extra_tx_headroom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) mgmt = skb_put_zero(skb, 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) memcpy(mgmt->da, da, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (sdata->vif.type == NL80211_IFTYPE_AP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) else if (sdata->vif.type == NL80211_IFTYPE_STATION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) IEEE80211_STYPE_ACTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) mgmt->u.action.category = WLAN_CATEGORY_BACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) mgmt->u.action.u.addba_resp.dialog_token = dialog_token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) capab = (u16)(amsdu << 0); /* bit 0 A-MSDU support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) capab |= (u16)(policy << 1); /* bit 1 aggregation policy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) capab |= (u16)(tid << 2); /* bit 5:2 TID number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (sta->sta.he_cap.has_he && addbaext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) ieee80211_add_addbaext(sdata, skb, addbaext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) ieee80211_tx_skb(sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) u8 dialog_token, u16 timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) u16 start_seq_num, u16 ba_policy, u16 tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) u16 buf_size, bool tx, bool auto_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) const struct ieee80211_addba_ext_ie *addbaext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct ieee80211_local *local = sta->sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) struct tid_ampdu_rx *tid_agg_rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct ieee80211_ampdu_params params = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) .sta = &sta->sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) .action = IEEE80211_AMPDU_RX_START,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) .tid = tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) .amsdu = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) .timeout = timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) .ssn = start_seq_num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) int i, ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) u16 status = WLAN_STATUS_REQUEST_DECLINED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) u16 max_buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (tid >= IEEE80211_FIRST_TSPEC_TSID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ht_dbg(sta->sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) "STA %pM requests BA session on unsupported tid %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) sta->sta.addr, tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (!sta->sta.ht_cap.ht_supported &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) sta->sdata->vif.bss_conf.chandef.chan->band != NL80211_BAND_6GHZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) ht_dbg(sta->sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) "STA %pM erroneously requests BA session on tid %d w/o QoS\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) sta->sta.addr, tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /* send a response anyway, it's an error case if we get here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ht_dbg(sta->sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) "Suspend in progress - Denying ADDBA request (%pM tid %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) sta->sta.addr, tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (sta->sta.he_cap.has_he)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) max_buf_size = IEEE80211_MAX_AMPDU_BUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) max_buf_size = IEEE80211_MAX_AMPDU_BUF_HT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /* sanity check for incoming parameters:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * check if configuration can support the BA policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * and if buffer size does not exceeds max value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /* XXX: check own ht delayed BA capability?? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (((ba_policy != 1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) (!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA))) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) (buf_size > max_buf_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) status = WLAN_STATUS_INVALID_QOS_PARAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) ht_dbg_ratelimited(sta->sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) "AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) sta->sta.addr, tid, ba_policy, buf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /* determine default buffer size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (buf_size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) buf_size = max_buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) /* make sure the size doesn't exceed the maximum supported by the hw */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (buf_size > sta->sta.max_rx_aggregation_subframes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) buf_size = sta->sta.max_rx_aggregation_subframes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) params.buf_size = buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) ht_dbg(sta->sdata, "AddBA Req buf_size=%d for %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) buf_size, sta->sta.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /* examine state machine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) lockdep_assert_held(&sta->ampdu_mlme.mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (test_bit(tid, sta->ampdu_mlme.agg_session_valid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (sta->ampdu_mlme.tid_rx_token[tid] == dialog_token) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct tid_ampdu_rx *tid_rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) ht_dbg_ratelimited(sta->sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) "updated AddBA Req from %pM on tid %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) sta->sta.addr, tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /* We have no API to update the timeout value in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * driver so reject the timeout update if the timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * changed. If it did not change, i.e., no real update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * just reply with success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (tid_rx && tid_rx->timeout == timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) status = WLAN_STATUS_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) status = WLAN_STATUS_REQUEST_DECLINED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) ht_dbg_ratelimited(sta->sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) "unexpected AddBA Req from %pM on tid %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) sta->sta.addr, tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /* delete existing Rx BA session on the same tid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) ___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) WLAN_STATUS_UNSPECIFIED_QOS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (ieee80211_hw_check(&local->hw, SUPPORTS_REORDERING_BUFFER)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) ret = drv_ampdu_action(local, sta->sdata, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) ht_dbg(sta->sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) "Rx A-MPDU request on %pM tid %d result %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) sta->sta.addr, tid, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) status = WLAN_STATUS_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) /* prepare A-MPDU MLME for Rx aggregation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) tid_agg_rx = kzalloc(sizeof(*tid_agg_rx), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (!tid_agg_rx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) spin_lock_init(&tid_agg_rx->reorder_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /* rx timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) timer_setup(&tid_agg_rx->session_timer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) sta_rx_agg_session_timer_expired, TIMER_DEFERRABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) /* rx reorder timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) timer_setup(&tid_agg_rx->reorder_timer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) sta_rx_agg_reorder_timer_expired, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* prepare reordering buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) tid_agg_rx->reorder_buf =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) kcalloc(buf_size, sizeof(struct sk_buff_head), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) tid_agg_rx->reorder_time =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) kfree(tid_agg_rx->reorder_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) kfree(tid_agg_rx->reorder_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) kfree(tid_agg_rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) for (i = 0; i < buf_size; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) ret = drv_ampdu_action(local, sta->sdata, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) sta->sta.addr, tid, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) kfree(tid_agg_rx->reorder_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) kfree(tid_agg_rx->reorder_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) kfree(tid_agg_rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) /* update data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) tid_agg_rx->ssn = start_seq_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) tid_agg_rx->head_seq_num = start_seq_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) tid_agg_rx->buf_size = buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) tid_agg_rx->timeout = timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) tid_agg_rx->stored_mpdu_num = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) tid_agg_rx->auto_seq = auto_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) tid_agg_rx->started = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) tid_agg_rx->reorder_buf_filtered = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) tid_agg_rx->tid = tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) tid_agg_rx->sta = sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) status = WLAN_STATUS_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) /* activate it for RX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) tid_agg_rx->last_rx = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (status == WLAN_STATUS_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) __set_bit(tid, sta->ampdu_mlme.agg_session_valid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) __clear_bit(tid, sta->ampdu_mlme.unexpected_agg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) sta->ampdu_mlme.tid_rx_token[tid] = dialog_token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) ieee80211_send_addba_resp(sta, sta->sta.addr, tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) dialog_token, status, 1, buf_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) timeout, addbaext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) static void __ieee80211_start_rx_ba_session(struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) u8 dialog_token, u16 timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) u16 start_seq_num, u16 ba_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) u16 tid, u16 buf_size, bool tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) bool auto_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) const struct ieee80211_addba_ext_ie *addbaext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) mutex_lock(&sta->ampdu_mlme.mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) ___ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) start_seq_num, ba_policy, tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) buf_size, tx, auto_seq, addbaext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) mutex_unlock(&sta->ampdu_mlme.mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) void ieee80211_process_addba_request(struct ieee80211_local *local,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct ieee80211_mgmt *mgmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) struct ieee802_11_elems elems = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) u8 dialog_token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) int ies_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) /* extract session parameters from addba request frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) dialog_token = mgmt->u.action.u.addba_req.dialog_token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) start_seq_num =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) ies_len = len - offsetof(struct ieee80211_mgmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) u.action.u.addba_req.variable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (ies_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) ieee802_11_parse_elems(mgmt->u.action.u.addba_req.variable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) ies_len, true, &elems, mgmt->bssid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (elems.parse_error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) __ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) start_seq_num, ba_policy, tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) buf_size, true, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) elems.addba_ext_ie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) const u8 *addr, unsigned int tid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) struct sta_info *sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) sta = sta_info_get_bss(sdata, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (!sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) set_bit(tid, sta->ampdu_mlme.tid_rx_manage_offl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) EXPORT_SYMBOL(ieee80211_manage_rx_ba_offl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) void ieee80211_rx_ba_timer_expired(struct ieee80211_vif *vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) const u8 *addr, unsigned int tid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) struct sta_info *sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) sta = sta_info_get_bss(sdata, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (!sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) set_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) EXPORT_SYMBOL(ieee80211_rx_ba_timer_expired);