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