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