1 /* 2 * HT handling 3 * 4 * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi> 5 * Copyright 2002-2005, Instant802 Networks, Inc. 6 * Copyright 2005-2006, Devicescape Software, Inc. 7 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 8 * Copyright 2007, Michael Wu <flamingice@sourmilk.net> 9 * Copyright 2007-2008, Intel Corporation 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License version 2 as 13 * published by the Free Software Foundation. 14 */ 15 16 #include <linux/ieee80211.h> 17 #include <linux/slab.h> 18 #include <net/mac80211.h> 19 #include "ieee80211_i.h" 20 #include "driver-ops.h" 21 22 void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, 23 u16 initiator, u16 reason) 24 { 25 struct ieee80211_local *local = sta->local; 26 int i; 27 28 /* check if TID is in operational state */ 29 spin_lock_bh(&sta->lock); 30 if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) { 31 spin_unlock_bh(&sta->lock); 32 return; 33 } 34 35 sta->ampdu_mlme.tid_state_rx[tid] = 36 HT_AGG_STATE_REQ_STOP_BA_MSK | 37 (initiator << HT_AGG_STATE_INITIATOR_SHIFT); 38 spin_unlock_bh(&sta->lock); 39 40 #ifdef CONFIG_MAC80211_HT_DEBUG 41 printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", 42 sta->sta.addr, tid); 43 #endif /* CONFIG_MAC80211_HT_DEBUG */ 44 45 if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, 46 &sta->sta, tid, NULL)) 47 printk(KERN_DEBUG "HW problem - can not stop rx " 48 "aggregation for tid %d\n", tid); 49 50 /* shutdown timer has not expired */ 51 if (initiator != WLAN_BACK_TIMER) 52 del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer); 53 54 /* check if this is a self generated aggregation halt */ 55 if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) 56 ieee80211_send_delba(sta->sdata, sta->sta.addr, 57 tid, 0, reason); 58 59 /* free the reordering buffer */ 60 for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { 61 if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) { 62 /* release the reordered frames */ 63 dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]); 64 sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--; 65 sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL; 66 } 67 } 68 69 spin_lock_bh(&sta->lock); 70 /* free resources */ 71 kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); 72 kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_time); 73 74 if (!sta->ampdu_mlme.tid_rx[tid]->shutdown) { 75 kfree(sta->ampdu_mlme.tid_rx[tid]); 76 sta->ampdu_mlme.tid_rx[tid] = NULL; 77 } 78 79 sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE; 80 spin_unlock_bh(&sta->lock); 81 } 82 83 void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, 84 u16 initiator, u16 reason) 85 { 86 struct sta_info *sta; 87 88 rcu_read_lock(); 89 90 sta = sta_info_get(sdata, ra); 91 if (!sta) { 92 rcu_read_unlock(); 93 return; 94 } 95 96 __ieee80211_stop_rx_ba_session(sta, tid, initiator, reason); 97 98 rcu_read_unlock(); 99 } 100 101 /* 102 * After accepting the AddBA Request we activated a timer, 103 * resetting it after each frame that arrives from the originator. 104 * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed. 105 */ 106 static void sta_rx_agg_session_timer_expired(unsigned long data) 107 { 108 /* not an elegant detour, but there is no choice as the timer passes 109 * only one argument, and various sta_info are needed here, so init 110 * flow in sta_info_create gives the TID as data, while the timer_to_id 111 * array gives the sta through container_of */ 112 u8 *ptid = (u8 *)data; 113 u8 *timer_to_id = ptid - *ptid; 114 struct sta_info *sta = container_of(timer_to_id, struct sta_info, 115 timer_to_tid[0]); 116 117 #ifdef CONFIG_MAC80211_HT_DEBUG 118 printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); 119 #endif 120 ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, 121 (u16)*ptid, WLAN_BACK_TIMER, 122 WLAN_REASON_QSTA_TIMEOUT); 123 } 124 125 static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, 126 u8 dialog_token, u16 status, u16 policy, 127 u16 buf_size, u16 timeout) 128 { 129 struct ieee80211_local *local = sdata->local; 130 struct sk_buff *skb; 131 struct ieee80211_mgmt *mgmt; 132 u16 capab; 133 134 skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); 135 136 if (!skb) { 137 printk(KERN_DEBUG "%s: failed to allocate buffer " 138 "for addba resp frame\n", sdata->name); 139 return; 140 } 141 142 skb_reserve(skb, local->hw.extra_tx_headroom); 143 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); 144 memset(mgmt, 0, 24); 145 memcpy(mgmt->da, da, ETH_ALEN); 146 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); 147 if (sdata->vif.type == NL80211_IFTYPE_AP || 148 sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 149 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); 150 else if (sdata->vif.type == NL80211_IFTYPE_STATION) 151 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); 152 153 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 154 IEEE80211_STYPE_ACTION); 155 156 skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp)); 157 mgmt->u.action.category = WLAN_CATEGORY_BACK; 158 mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP; 159 mgmt->u.action.u.addba_resp.dialog_token = dialog_token; 160 161 capab = (u16)(policy << 1); /* bit 1 aggregation policy */ 162 capab |= (u16)(tid << 2); /* bit 5:2 TID number */ 163 capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */ 164 165 mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab); 166 mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); 167 mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); 168 169 ieee80211_tx_skb(sdata, skb); 170 } 171 172 void ieee80211_process_addba_request(struct ieee80211_local *local, 173 struct sta_info *sta, 174 struct ieee80211_mgmt *mgmt, 175 size_t len) 176 { 177 struct ieee80211_hw *hw = &local->hw; 178 struct ieee80211_conf *conf = &hw->conf; 179 struct tid_ampdu_rx *tid_agg_rx; 180 u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status; 181 u8 dialog_token; 182 int ret = -EOPNOTSUPP; 183 184 /* extract session parameters from addba request frame */ 185 dialog_token = mgmt->u.action.u.addba_req.dialog_token; 186 timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout); 187 start_seq_num = 188 le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4; 189 190 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); 191 ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1; 192 tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; 193 buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; 194 195 status = WLAN_STATUS_REQUEST_DECLINED; 196 197 if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { 198 #ifdef CONFIG_MAC80211_HT_DEBUG 199 printk(KERN_DEBUG "Suspend in progress. " 200 "Denying ADDBA request\n"); 201 #endif 202 goto end_no_lock; 203 } 204 205 /* sanity check for incoming parameters: 206 * check if configuration can support the BA policy 207 * and if buffer size does not exceeds max value */ 208 /* XXX: check own ht delayed BA capability?? */ 209 if (((ba_policy != 1) && 210 (!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA))) || 211 (buf_size > IEEE80211_MAX_AMPDU_BUF)) { 212 status = WLAN_STATUS_INVALID_QOS_PARAM; 213 #ifdef CONFIG_MAC80211_HT_DEBUG 214 if (net_ratelimit()) 215 printk(KERN_DEBUG "AddBA Req with bad params from " 216 "%pM on tid %u. policy %d, buffer size %d\n", 217 mgmt->sa, tid, ba_policy, 218 buf_size); 219 #endif /* CONFIG_MAC80211_HT_DEBUG */ 220 goto end_no_lock; 221 } 222 /* determine default buffer size */ 223 if (buf_size == 0) { 224 struct ieee80211_supported_band *sband; 225 226 sband = local->hw.wiphy->bands[conf->channel->band]; 227 buf_size = IEEE80211_MIN_AMPDU_BUF; 228 buf_size = buf_size << sband->ht_cap.ampdu_factor; 229 } 230 231 232 /* examine state machine */ 233 spin_lock_bh(&sta->lock); 234 235 if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { 236 #ifdef CONFIG_MAC80211_HT_DEBUG 237 if (net_ratelimit()) 238 printk(KERN_DEBUG "unexpected AddBA Req from " 239 "%pM on tid %u\n", 240 mgmt->sa, tid); 241 #endif /* CONFIG_MAC80211_HT_DEBUG */ 242 goto end; 243 } 244 245 /* prepare A-MPDU MLME for Rx aggregation */ 246 sta->ampdu_mlme.tid_rx[tid] = 247 kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC); 248 if (!sta->ampdu_mlme.tid_rx[tid]) { 249 #ifdef CONFIG_MAC80211_HT_DEBUG 250 if (net_ratelimit()) 251 printk(KERN_ERR "allocate rx mlme to tid %d failed\n", 252 tid); 253 #endif 254 goto end; 255 } 256 /* rx timer */ 257 sta->ampdu_mlme.tid_rx[tid]->session_timer.function = 258 sta_rx_agg_session_timer_expired; 259 sta->ampdu_mlme.tid_rx[tid]->session_timer.data = 260 (unsigned long)&sta->timer_to_tid[tid]; 261 init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer); 262 263 tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; 264 265 /* prepare reordering buffer */ 266 tid_agg_rx->reorder_buf = 267 kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); 268 tid_agg_rx->reorder_time = 269 kcalloc(buf_size, sizeof(unsigned long), GFP_ATOMIC); 270 if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) { 271 #ifdef CONFIG_MAC80211_HT_DEBUG 272 if (net_ratelimit()) 273 printk(KERN_ERR "can not allocate reordering buffer " 274 "to tid %d\n", tid); 275 #endif 276 kfree(tid_agg_rx->reorder_buf); 277 kfree(tid_agg_rx->reorder_time); 278 kfree(sta->ampdu_mlme.tid_rx[tid]); 279 sta->ampdu_mlme.tid_rx[tid] = NULL; 280 goto end; 281 } 282 283 ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, 284 &sta->sta, tid, &start_seq_num); 285 #ifdef CONFIG_MAC80211_HT_DEBUG 286 printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); 287 #endif /* CONFIG_MAC80211_HT_DEBUG */ 288 289 if (ret) { 290 kfree(tid_agg_rx->reorder_buf); 291 kfree(tid_agg_rx); 292 sta->ampdu_mlme.tid_rx[tid] = NULL; 293 goto end; 294 } 295 296 /* change state and send addba resp */ 297 sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL; 298 tid_agg_rx->dialog_token = dialog_token; 299 tid_agg_rx->ssn = start_seq_num; 300 tid_agg_rx->head_seq_num = start_seq_num; 301 tid_agg_rx->buf_size = buf_size; 302 tid_agg_rx->timeout = timeout; 303 tid_agg_rx->stored_mpdu_num = 0; 304 status = WLAN_STATUS_SUCCESS; 305 end: 306 spin_unlock_bh(&sta->lock); 307 308 end_no_lock: 309 ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid, 310 dialog_token, status, 1, buf_size, timeout); 311 } 312