1*44d414dbSJohannes Berg /* 2*44d414dbSJohannes Berg * HT handling 3*44d414dbSJohannes Berg * 4*44d414dbSJohannes Berg * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi> 5*44d414dbSJohannes Berg * Copyright 2004, Instant802 Networks, Inc. 6*44d414dbSJohannes Berg * Copyright 2005, Devicescape Software, Inc. 7*44d414dbSJohannes Berg * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 8*44d414dbSJohannes Berg * Copyright 2007, Michael Wu <flamingice@sourmilk.net> 9*44d414dbSJohannes Berg * Copyright 2007-2008, Intel Corporation 10*44d414dbSJohannes Berg * 11*44d414dbSJohannes Berg * This program is free software; you can redistribute it and/or modify 12*44d414dbSJohannes Berg * it under the terms of the GNU General Public License version 2 as 13*44d414dbSJohannes Berg * published by the Free Software Foundation. 14*44d414dbSJohannes Berg */ 15*44d414dbSJohannes Berg 16*44d414dbSJohannes Berg #include <linux/ieee80211.h> 17*44d414dbSJohannes Berg #include <net/wireless.h> 18*44d414dbSJohannes Berg #include <net/mac80211.h> 19*44d414dbSJohannes Berg #include "ieee80211_i.h" 20*44d414dbSJohannes Berg #include "sta_info.h" 21*44d414dbSJohannes Berg 22*44d414dbSJohannes Berg int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, 23*44d414dbSJohannes Berg struct ieee80211_ht_info *ht_info) 24*44d414dbSJohannes Berg { 25*44d414dbSJohannes Berg 26*44d414dbSJohannes Berg if (ht_info == NULL) 27*44d414dbSJohannes Berg return -EINVAL; 28*44d414dbSJohannes Berg 29*44d414dbSJohannes Berg memset(ht_info, 0, sizeof(*ht_info)); 30*44d414dbSJohannes Berg 31*44d414dbSJohannes Berg if (ht_cap_ie) { 32*44d414dbSJohannes Berg u8 ampdu_info = ht_cap_ie->ampdu_params_info; 33*44d414dbSJohannes Berg 34*44d414dbSJohannes Berg ht_info->ht_supported = 1; 35*44d414dbSJohannes Berg ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info); 36*44d414dbSJohannes Berg ht_info->ampdu_factor = 37*44d414dbSJohannes Berg ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR; 38*44d414dbSJohannes Berg ht_info->ampdu_density = 39*44d414dbSJohannes Berg (ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2; 40*44d414dbSJohannes Berg memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16); 41*44d414dbSJohannes Berg } else 42*44d414dbSJohannes Berg ht_info->ht_supported = 0; 43*44d414dbSJohannes Berg 44*44d414dbSJohannes Berg return 0; 45*44d414dbSJohannes Berg } 46*44d414dbSJohannes Berg 47*44d414dbSJohannes Berg int ieee80211_ht_addt_info_ie_to_ht_bss_info( 48*44d414dbSJohannes Berg struct ieee80211_ht_addt_info *ht_add_info_ie, 49*44d414dbSJohannes Berg struct ieee80211_ht_bss_info *bss_info) 50*44d414dbSJohannes Berg { 51*44d414dbSJohannes Berg if (bss_info == NULL) 52*44d414dbSJohannes Berg return -EINVAL; 53*44d414dbSJohannes Berg 54*44d414dbSJohannes Berg memset(bss_info, 0, sizeof(*bss_info)); 55*44d414dbSJohannes Berg 56*44d414dbSJohannes Berg if (ht_add_info_ie) { 57*44d414dbSJohannes Berg u16 op_mode; 58*44d414dbSJohannes Berg op_mode = le16_to_cpu(ht_add_info_ie->operation_mode); 59*44d414dbSJohannes Berg 60*44d414dbSJohannes Berg bss_info->primary_channel = ht_add_info_ie->control_chan; 61*44d414dbSJohannes Berg bss_info->bss_cap = ht_add_info_ie->ht_param; 62*44d414dbSJohannes Berg bss_info->bss_op_mode = (u8)(op_mode & 0xff); 63*44d414dbSJohannes Berg } 64*44d414dbSJohannes Berg 65*44d414dbSJohannes Berg return 0; 66*44d414dbSJohannes Berg } 67*44d414dbSJohannes Berg 68*44d414dbSJohannes Berg void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, const u8 *da, 69*44d414dbSJohannes Berg u16 tid, u8 dialog_token, u16 start_seq_num, 70*44d414dbSJohannes Berg u16 agg_size, u16 timeout) 71*44d414dbSJohannes Berg { 72*44d414dbSJohannes Berg struct ieee80211_local *local = sdata->local; 73*44d414dbSJohannes Berg struct ieee80211_if_sta *ifsta = &sdata->u.sta; 74*44d414dbSJohannes Berg struct sk_buff *skb; 75*44d414dbSJohannes Berg struct ieee80211_mgmt *mgmt; 76*44d414dbSJohannes Berg u16 capab; 77*44d414dbSJohannes Berg 78*44d414dbSJohannes Berg skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); 79*44d414dbSJohannes Berg 80*44d414dbSJohannes Berg if (!skb) { 81*44d414dbSJohannes Berg printk(KERN_ERR "%s: failed to allocate buffer " 82*44d414dbSJohannes Berg "for addba request frame\n", sdata->dev->name); 83*44d414dbSJohannes Berg return; 84*44d414dbSJohannes Berg } 85*44d414dbSJohannes Berg skb_reserve(skb, local->hw.extra_tx_headroom); 86*44d414dbSJohannes Berg mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); 87*44d414dbSJohannes Berg memset(mgmt, 0, 24); 88*44d414dbSJohannes Berg memcpy(mgmt->da, da, ETH_ALEN); 89*44d414dbSJohannes Berg memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 90*44d414dbSJohannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_AP) 91*44d414dbSJohannes Berg memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); 92*44d414dbSJohannes Berg else 93*44d414dbSJohannes Berg memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); 94*44d414dbSJohannes Berg 95*44d414dbSJohannes Berg mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 96*44d414dbSJohannes Berg IEEE80211_STYPE_ACTION); 97*44d414dbSJohannes Berg 98*44d414dbSJohannes Berg skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req)); 99*44d414dbSJohannes Berg 100*44d414dbSJohannes Berg mgmt->u.action.category = WLAN_CATEGORY_BACK; 101*44d414dbSJohannes Berg mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ; 102*44d414dbSJohannes Berg 103*44d414dbSJohannes Berg mgmt->u.action.u.addba_req.dialog_token = dialog_token; 104*44d414dbSJohannes Berg capab = (u16)(1 << 1); /* bit 1 aggregation policy */ 105*44d414dbSJohannes Berg capab |= (u16)(tid << 2); /* bit 5:2 TID number */ 106*44d414dbSJohannes Berg capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */ 107*44d414dbSJohannes Berg 108*44d414dbSJohannes Berg mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab); 109*44d414dbSJohannes Berg 110*44d414dbSJohannes Berg mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout); 111*44d414dbSJohannes Berg mgmt->u.action.u.addba_req.start_seq_num = 112*44d414dbSJohannes Berg cpu_to_le16(start_seq_num << 4); 113*44d414dbSJohannes Berg 114*44d414dbSJohannes Berg ieee80211_sta_tx(sdata, skb, 0); 115*44d414dbSJohannes Berg } 116*44d414dbSJohannes Berg 117*44d414dbSJohannes Berg void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, 118*44d414dbSJohannes Berg u16 initiator, u16 reason_code) 119*44d414dbSJohannes Berg { 120*44d414dbSJohannes Berg struct ieee80211_local *local = sdata->local; 121*44d414dbSJohannes Berg struct ieee80211_if_sta *ifsta = &sdata->u.sta; 122*44d414dbSJohannes Berg struct sk_buff *skb; 123*44d414dbSJohannes Berg struct ieee80211_mgmt *mgmt; 124*44d414dbSJohannes Berg u16 params; 125*44d414dbSJohannes Berg 126*44d414dbSJohannes Berg skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); 127*44d414dbSJohannes Berg 128*44d414dbSJohannes Berg if (!skb) { 129*44d414dbSJohannes Berg printk(KERN_ERR "%s: failed to allocate buffer " 130*44d414dbSJohannes Berg "for delba frame\n", sdata->dev->name); 131*44d414dbSJohannes Berg return; 132*44d414dbSJohannes Berg } 133*44d414dbSJohannes Berg 134*44d414dbSJohannes Berg skb_reserve(skb, local->hw.extra_tx_headroom); 135*44d414dbSJohannes Berg mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); 136*44d414dbSJohannes Berg memset(mgmt, 0, 24); 137*44d414dbSJohannes Berg memcpy(mgmt->da, da, ETH_ALEN); 138*44d414dbSJohannes Berg memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 139*44d414dbSJohannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_AP) 140*44d414dbSJohannes Berg memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); 141*44d414dbSJohannes Berg else 142*44d414dbSJohannes Berg memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); 143*44d414dbSJohannes Berg mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 144*44d414dbSJohannes Berg IEEE80211_STYPE_ACTION); 145*44d414dbSJohannes Berg 146*44d414dbSJohannes Berg skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba)); 147*44d414dbSJohannes Berg 148*44d414dbSJohannes Berg mgmt->u.action.category = WLAN_CATEGORY_BACK; 149*44d414dbSJohannes Berg mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA; 150*44d414dbSJohannes Berg params = (u16)(initiator << 11); /* bit 11 initiator */ 151*44d414dbSJohannes Berg params |= (u16)(tid << 12); /* bit 15:12 TID number */ 152*44d414dbSJohannes Berg 153*44d414dbSJohannes Berg mgmt->u.action.u.delba.params = cpu_to_le16(params); 154*44d414dbSJohannes Berg mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); 155*44d414dbSJohannes Berg 156*44d414dbSJohannes Berg ieee80211_sta_tx(sdata, skb, 0); 157*44d414dbSJohannes Berg } 158*44d414dbSJohannes Berg 159*44d414dbSJohannes Berg void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn) 160*44d414dbSJohannes Berg { 161*44d414dbSJohannes Berg struct ieee80211_local *local = sdata->local; 162*44d414dbSJohannes Berg struct sk_buff *skb; 163*44d414dbSJohannes Berg struct ieee80211_bar *bar; 164*44d414dbSJohannes Berg u16 bar_control = 0; 165*44d414dbSJohannes Berg 166*44d414dbSJohannes Berg skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); 167*44d414dbSJohannes Berg if (!skb) { 168*44d414dbSJohannes Berg printk(KERN_ERR "%s: failed to allocate buffer for " 169*44d414dbSJohannes Berg "bar frame\n", sdata->dev->name); 170*44d414dbSJohannes Berg return; 171*44d414dbSJohannes Berg } 172*44d414dbSJohannes Berg skb_reserve(skb, local->hw.extra_tx_headroom); 173*44d414dbSJohannes Berg bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); 174*44d414dbSJohannes Berg memset(bar, 0, sizeof(*bar)); 175*44d414dbSJohannes Berg bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | 176*44d414dbSJohannes Berg IEEE80211_STYPE_BACK_REQ); 177*44d414dbSJohannes Berg memcpy(bar->ra, ra, ETH_ALEN); 178*44d414dbSJohannes Berg memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN); 179*44d414dbSJohannes Berg bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; 180*44d414dbSJohannes Berg bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; 181*44d414dbSJohannes Berg bar_control |= (u16)(tid << 12); 182*44d414dbSJohannes Berg bar->control = cpu_to_le16(bar_control); 183*44d414dbSJohannes Berg bar->start_seq_num = cpu_to_le16(ssn); 184*44d414dbSJohannes Berg 185*44d414dbSJohannes Berg ieee80211_sta_tx(sdata, skb, 0); 186*44d414dbSJohannes Berg } 187*44d414dbSJohannes Berg 188*44d414dbSJohannes Berg void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, 189*44d414dbSJohannes Berg u16 initiator, u16 reason) 190*44d414dbSJohannes Berg { 191*44d414dbSJohannes Berg struct ieee80211_local *local = sdata->local; 192*44d414dbSJohannes Berg struct ieee80211_hw *hw = &local->hw; 193*44d414dbSJohannes Berg struct sta_info *sta; 194*44d414dbSJohannes Berg int ret, i; 195*44d414dbSJohannes Berg DECLARE_MAC_BUF(mac); 196*44d414dbSJohannes Berg 197*44d414dbSJohannes Berg rcu_read_lock(); 198*44d414dbSJohannes Berg 199*44d414dbSJohannes Berg sta = sta_info_get(local, ra); 200*44d414dbSJohannes Berg if (!sta) { 201*44d414dbSJohannes Berg rcu_read_unlock(); 202*44d414dbSJohannes Berg return; 203*44d414dbSJohannes Berg } 204*44d414dbSJohannes Berg 205*44d414dbSJohannes Berg /* check if TID is in operational state */ 206*44d414dbSJohannes Berg spin_lock_bh(&sta->lock); 207*44d414dbSJohannes Berg if (sta->ampdu_mlme.tid_state_rx[tid] 208*44d414dbSJohannes Berg != HT_AGG_STATE_OPERATIONAL) { 209*44d414dbSJohannes Berg spin_unlock_bh(&sta->lock); 210*44d414dbSJohannes Berg rcu_read_unlock(); 211*44d414dbSJohannes Berg return; 212*44d414dbSJohannes Berg } 213*44d414dbSJohannes Berg sta->ampdu_mlme.tid_state_rx[tid] = 214*44d414dbSJohannes Berg HT_AGG_STATE_REQ_STOP_BA_MSK | 215*44d414dbSJohannes Berg (initiator << HT_AGG_STATE_INITIATOR_SHIFT); 216*44d414dbSJohannes Berg spin_unlock_bh(&sta->lock); 217*44d414dbSJohannes Berg 218*44d414dbSJohannes Berg /* stop HW Rx aggregation. ampdu_action existence 219*44d414dbSJohannes Berg * already verified in session init so we add the BUG_ON */ 220*44d414dbSJohannes Berg BUG_ON(!local->ops->ampdu_action); 221*44d414dbSJohannes Berg 222*44d414dbSJohannes Berg #ifdef CONFIG_MAC80211_HT_DEBUG 223*44d414dbSJohannes Berg printk(KERN_DEBUG "Rx BA session stop requested for %s tid %u\n", 224*44d414dbSJohannes Berg print_mac(mac, ra), tid); 225*44d414dbSJohannes Berg #endif /* CONFIG_MAC80211_HT_DEBUG */ 226*44d414dbSJohannes Berg 227*44d414dbSJohannes Berg ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP, 228*44d414dbSJohannes Berg ra, tid, NULL); 229*44d414dbSJohannes Berg if (ret) 230*44d414dbSJohannes Berg printk(KERN_DEBUG "HW problem - can not stop rx " 231*44d414dbSJohannes Berg "aggregation for tid %d\n", tid); 232*44d414dbSJohannes Berg 233*44d414dbSJohannes Berg /* shutdown timer has not expired */ 234*44d414dbSJohannes Berg if (initiator != WLAN_BACK_TIMER) 235*44d414dbSJohannes Berg del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer); 236*44d414dbSJohannes Berg 237*44d414dbSJohannes Berg /* check if this is a self generated aggregation halt */ 238*44d414dbSJohannes Berg if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) 239*44d414dbSJohannes Berg ieee80211_send_delba(sdata, ra, tid, 0, reason); 240*44d414dbSJohannes Berg 241*44d414dbSJohannes Berg /* free the reordering buffer */ 242*44d414dbSJohannes Berg for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { 243*44d414dbSJohannes Berg if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) { 244*44d414dbSJohannes Berg /* release the reordered frames */ 245*44d414dbSJohannes Berg dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]); 246*44d414dbSJohannes Berg sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--; 247*44d414dbSJohannes Berg sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL; 248*44d414dbSJohannes Berg } 249*44d414dbSJohannes Berg } 250*44d414dbSJohannes Berg /* free resources */ 251*44d414dbSJohannes Berg kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); 252*44d414dbSJohannes Berg kfree(sta->ampdu_mlme.tid_rx[tid]); 253*44d414dbSJohannes Berg sta->ampdu_mlme.tid_rx[tid] = NULL; 254*44d414dbSJohannes Berg sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE; 255*44d414dbSJohannes Berg 256*44d414dbSJohannes Berg rcu_read_unlock(); 257*44d414dbSJohannes Berg } 258*44d414dbSJohannes Berg 259*44d414dbSJohannes Berg 260*44d414dbSJohannes Berg /* 261*44d414dbSJohannes Berg * After sending add Block Ack request we activated a timer until 262*44d414dbSJohannes Berg * add Block Ack response will arrive from the recipient. 263*44d414dbSJohannes Berg * If this timer expires sta_addba_resp_timer_expired will be executed. 264*44d414dbSJohannes Berg */ 265*44d414dbSJohannes Berg void sta_addba_resp_timer_expired(unsigned long data) 266*44d414dbSJohannes Berg { 267*44d414dbSJohannes Berg /* not an elegant detour, but there is no choice as the timer passes 268*44d414dbSJohannes Berg * only one argument, and both sta_info and TID are needed, so init 269*44d414dbSJohannes Berg * flow in sta_info_create gives the TID as data, while the timer_to_id 270*44d414dbSJohannes Berg * array gives the sta through container_of */ 271*44d414dbSJohannes Berg u16 tid = *(u8 *)data; 272*44d414dbSJohannes Berg struct sta_info *temp_sta = container_of((void *)data, 273*44d414dbSJohannes Berg struct sta_info, timer_to_tid[tid]); 274*44d414dbSJohannes Berg 275*44d414dbSJohannes Berg struct ieee80211_local *local = temp_sta->local; 276*44d414dbSJohannes Berg struct ieee80211_hw *hw = &local->hw; 277*44d414dbSJohannes Berg struct sta_info *sta; 278*44d414dbSJohannes Berg u8 *state; 279*44d414dbSJohannes Berg 280*44d414dbSJohannes Berg rcu_read_lock(); 281*44d414dbSJohannes Berg 282*44d414dbSJohannes Berg sta = sta_info_get(local, temp_sta->addr); 283*44d414dbSJohannes Berg if (!sta) { 284*44d414dbSJohannes Berg rcu_read_unlock(); 285*44d414dbSJohannes Berg return; 286*44d414dbSJohannes Berg } 287*44d414dbSJohannes Berg 288*44d414dbSJohannes Berg state = &sta->ampdu_mlme.tid_state_tx[tid]; 289*44d414dbSJohannes Berg /* check if the TID waits for addBA response */ 290*44d414dbSJohannes Berg spin_lock_bh(&sta->lock); 291*44d414dbSJohannes Berg if (!(*state & HT_ADDBA_REQUESTED_MSK)) { 292*44d414dbSJohannes Berg spin_unlock_bh(&sta->lock); 293*44d414dbSJohannes Berg *state = HT_AGG_STATE_IDLE; 294*44d414dbSJohannes Berg #ifdef CONFIG_MAC80211_HT_DEBUG 295*44d414dbSJohannes Berg printk(KERN_DEBUG "timer expired on tid %d but we are not " 296*44d414dbSJohannes Berg "expecting addBA response there", tid); 297*44d414dbSJohannes Berg #endif 298*44d414dbSJohannes Berg goto timer_expired_exit; 299*44d414dbSJohannes Berg } 300*44d414dbSJohannes Berg 301*44d414dbSJohannes Berg #ifdef CONFIG_MAC80211_HT_DEBUG 302*44d414dbSJohannes Berg printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid); 303*44d414dbSJohannes Berg #endif 304*44d414dbSJohannes Berg 305*44d414dbSJohannes Berg /* go through the state check in stop_BA_session */ 306*44d414dbSJohannes Berg *state = HT_AGG_STATE_OPERATIONAL; 307*44d414dbSJohannes Berg spin_unlock_bh(&sta->lock); 308*44d414dbSJohannes Berg ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid, 309*44d414dbSJohannes Berg WLAN_BACK_INITIATOR); 310*44d414dbSJohannes Berg 311*44d414dbSJohannes Berg timer_expired_exit: 312*44d414dbSJohannes Berg rcu_read_unlock(); 313*44d414dbSJohannes Berg } 314*44d414dbSJohannes Berg 315*44d414dbSJohannes Berg void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr) 316*44d414dbSJohannes Berg { 317*44d414dbSJohannes Berg struct ieee80211_local *local = sdata->local; 318*44d414dbSJohannes Berg int i; 319*44d414dbSJohannes Berg 320*44d414dbSJohannes Berg for (i = 0; i < STA_TID_NUM; i++) { 321*44d414dbSJohannes Berg ieee80211_stop_tx_ba_session(&local->hw, addr, i, 322*44d414dbSJohannes Berg WLAN_BACK_INITIATOR); 323*44d414dbSJohannes Berg ieee80211_sta_stop_rx_ba_session(sdata, addr, i, 324*44d414dbSJohannes Berg WLAN_BACK_RECIPIENT, 325*44d414dbSJohannes Berg WLAN_REASON_QSTA_LEAVE_QBSS); 326*44d414dbSJohannes Berg } 327*44d414dbSJohannes Berg } 328*44d414dbSJohannes Berg 329