OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2002-2005, Instant802 Networks, Inc. | 2 * Copyright 2002-2005, Instant802 Networks, Inc. |
3 * Copyright 2005-2006, Devicescape Software, Inc. | 3 * Copyright 2005-2006, Devicescape Software, Inc. |
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
5 * Copyright 2008-2010 Johannes Berg <johannes@sipsolutions.net> | 5 * Copyright 2008-2010 Johannes Berg <johannes@sipsolutions.net> |
6 * | 6 * |
7 * This program is free software; you can redistribute it and/or modify | 7 * This program is free software; you can redistribute it and/or modify |
8 * it under the terms of the GNU General Public License version 2 as | 8 * it under the terms of the GNU General Public License version 2 as |
9 * published by the Free Software Foundation. | 9 * published by the Free Software Foundation. |
10 */ | 10 */ |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 * being correct. Clear it so we don't get junk there, and | 51 * being correct. Clear it so we don't get junk there, and |
52 * indicate that it needs new processing, but must not be | 52 * indicate that it needs new processing, but must not be |
53 * modified/encrypted again. | 53 * modified/encrypted again. |
54 */ | 54 */ |
55 memset(&info->control, 0, sizeof(info->control)); | 55 memset(&info->control, 0, sizeof(info->control)); |
56 | 56 |
57 info->control.jiffies = jiffies; | 57 info->control.jiffies = jiffies; |
58 info->control.vif = &sta->sdata->vif; | 58 info->control.vif = &sta->sdata->vif; |
59 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING | | 59 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING | |
60 IEEE80211_TX_INTFL_RETRANSMISSION; | 60 IEEE80211_TX_INTFL_RETRANSMISSION; |
| 61 info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; |
61 | 62 |
62 sta->tx_filtered_count++; | 63 sta->tx_filtered_count++; |
63 | 64 |
64 /* | 65 /* |
65 * Clear the TX filter mask for this STA when sending the next | 66 * Clear the TX filter mask for this STA when sending the next |
66 * packet. If the STA went to power save mode, this will happen | 67 * packet. If the STA went to power save mode, this will happen |
67 * when it wakes up for the next time. | 68 * when it wakes up for the next time. |
68 */ | 69 */ |
69 set_sta_flags(sta, WLAN_STA_CLEAR_PS_FILT); | 70 set_sta_flags(sta, WLAN_STA_CLEAR_PS_FILT); |
70 | 71 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 if (net_ratelimit()) | 117 if (net_ratelimit()) |
117 printk(KERN_DEBUG "%s: dropped TX filtered frame, " | 118 printk(KERN_DEBUG "%s: dropped TX filtered frame, " |
118 "queue_len=%d PS=%d @%lu\n", | 119 "queue_len=%d PS=%d @%lu\n", |
119 wiphy_name(local->hw.wiphy), | 120 wiphy_name(local->hw.wiphy), |
120 skb_queue_len(&sta->tx_filtered), | 121 skb_queue_len(&sta->tx_filtered), |
121 !!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies); | 122 !!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies); |
122 #endif | 123 #endif |
123 dev_kfree_skb(skb); | 124 dev_kfree_skb(skb); |
124 } | 125 } |
125 | 126 |
126 static void ieee80211_sta_tx_status(struct sta_info *sta, struct sk_buff *skb) | 127 static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) |
127 { | 128 { |
128 struct ieee80211_mgmt *mgmt = (void *) skb->data; | 129 struct ieee80211_mgmt *mgmt = (void *) skb->data; |
129 struct ieee80211_local *local = sta->local; | 130 struct ieee80211_local *local = sta->local; |
130 struct ieee80211_sub_if_data *sdata = sta->sdata; | 131 struct ieee80211_sub_if_data *sdata = sta->sdata; |
131 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | |
132 | |
133 if (sdata->vif.type != NL80211_IFTYPE_STATION) | |
134 return; | |
135 | 132 |
136 if (ieee80211_is_action(mgmt->frame_control) && | 133 if (ieee80211_is_action(mgmt->frame_control) && |
137 » (info->flags & IEEE80211_TX_STAT_ACK) && | 134 » sdata->vif.type == NL80211_IFTYPE_STATION && |
138 mgmt->u.action.category == WLAN_CATEGORY_HT && | 135 mgmt->u.action.category == WLAN_CATEGORY_HT && |
139 mgmt->u.action.u.ht_smps.action == WLAN_HT_ACTION_SMPS) { | 136 mgmt->u.action.u.ht_smps.action == WLAN_HT_ACTION_SMPS) { |
140 /* | 137 /* |
141 * This update looks racy, but isn't -- if we come | 138 * This update looks racy, but isn't -- if we come |
142 * here we've definitely got a station that we're | 139 * here we've definitely got a station that we're |
143 * talking to, and on a managed interface that can | 140 * talking to, and on a managed interface that can |
144 * only be the AP. And the only other place updating | 141 * only be the AP. And the only other place updating |
145 * this variable is before we're associated. | 142 * this variable is before we're associated. |
146 */ | 143 */ |
147 switch (mgmt->u.action.u.ht_smps.smps_control) { | 144 switch (mgmt->u.action.u.ht_smps.smps_control) { |
148 case WLAN_HT_SMPS_CONTROL_DYNAMIC: | 145 case WLAN_HT_SMPS_CONTROL_DYNAMIC: |
149 sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_DYNAMIC; | 146 sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_DYNAMIC; |
150 break; | 147 break; |
151 case WLAN_HT_SMPS_CONTROL_STATIC: | 148 case WLAN_HT_SMPS_CONTROL_STATIC: |
152 sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_STATIC; | 149 sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_STATIC; |
153 break; | 150 break; |
154 case WLAN_HT_SMPS_CONTROL_DISABLED: | 151 case WLAN_HT_SMPS_CONTROL_DISABLED: |
155 default: /* shouldn't happen since we don't send that */ | 152 default: /* shouldn't happen since we don't send that */ |
156 sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_OFF; | 153 sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_OFF; |
157 break; | 154 break; |
158 } | 155 } |
159 | 156 |
160 ieee80211_queue_work(&local->hw, &local->recalc_smps); | 157 ieee80211_queue_work(&local->hw, &local->recalc_smps); |
161 } else if (ieee80211_is_probe_req(mgmt->frame_control) || | |
162 ieee80211_is_nullfunc(mgmt->frame_control)) { | |
163 struct ieee80211_if_managed *ifmgd = &sta->sdata->u.mgd; | |
164 | |
165 ifmgd->probe_acked = | |
166 (info->flags & IEEE80211_TX_STAT_ACK) ? true : false; | |
167 | |
168 ieee80211_queue_work(&local->hw, &ifmgd->probe_status_work); | |
169 } else if (ieee80211_is_data(mgmt->frame_control) && | 158 } else if (ieee80211_is_data(mgmt->frame_control) && |
170 » » sdata->vif.type == NL80211_IFTYPE_STATION && | 159 » » sdata->vif.type == NL80211_IFTYPE_STATION) { |
171 » (info->flags & IEEE80211_TX_STAT_ACK)) { | 160 » » struct ieee80211_if_managed *ifmgd; |
172 » » struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 161 » » ifmgd = &sta->sdata->u.mgd; |
173 if (ifmgd->cqm_bitrate_thold != 0 && | 162 if (ifmgd->cqm_bitrate_thold != 0 && |
174 (ifmgd->last_cqm_tx_rate.idx != sta->last_tx_rate.idx || | 163 (ifmgd->last_cqm_tx_rate.idx != sta->last_tx_rate.idx || |
175 (ifmgd->last_cqm_tx_rate.flags & | 164 (ifmgd->last_cqm_tx_rate.flags & |
176 (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_40_MHZ_WIDTH | | 165 (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_40_MHZ_WIDTH | |
177 IEEE80211_TX_RC_SHORT_GI)) != | 166 IEEE80211_TX_RC_SHORT_GI)) != |
178 (sta->last_tx_rate.flags & | 167 (sta->last_tx_rate.flags & |
179 (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_40_MHZ_WIDTH | | 168 (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_40_MHZ_WIDTH | |
180 IEEE80211_TX_RC_SHORT_GI)) || | 169 IEEE80211_TX_RC_SHORT_GI)) || |
181 sdata->u.mgd.last_cqm_bitrate == 0)) { | 170 sdata->u.mgd.last_cqm_bitrate == 0)) { |
182 ifmgd->last_cqm_tx_rate = sta->last_tx_rate; | 171 ifmgd->last_cqm_tx_rate = sta->last_tx_rate; |
(...skipping 13 matching lines...) Expand all Loading... |
196 u16 frag, type; | 185 u16 frag, type; |
197 __le16 fc; | 186 __le16 fc; |
198 struct ieee80211_supported_band *sband; | 187 struct ieee80211_supported_band *sband; |
199 struct ieee80211_tx_status_rtap_hdr *rthdr; | 188 struct ieee80211_tx_status_rtap_hdr *rthdr; |
200 struct ieee80211_sub_if_data *sdata; | 189 struct ieee80211_sub_if_data *sdata; |
201 struct net_device *prev_dev = NULL; | 190 struct net_device *prev_dev = NULL; |
202 struct sta_info *sta, *tmp; | 191 struct sta_info *sta, *tmp; |
203 int retry_count = -1, i; | 192 int retry_count = -1, i; |
204 int rates_idx = -1; | 193 int rates_idx = -1; |
205 bool send_to_cooked; | 194 bool send_to_cooked; |
| 195 bool acked; |
206 | 196 |
207 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 197 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
208 /* the HW cannot have attempted that rate */ | 198 /* the HW cannot have attempted that rate */ |
209 if (i >= hw->max_rates) { | 199 if (i >= hw->max_rates) { |
210 info->status.rates[i].idx = -1; | 200 info->status.rates[i].idx = -1; |
211 info->status.rates[i].count = 0; | 201 info->status.rates[i].count = 0; |
212 } else if (info->status.rates[i].idx >= 0) { | 202 } else if (info->status.rates[i].idx >= 0) { |
213 rates_idx = i; | 203 rates_idx = i; |
214 } | 204 } |
215 | 205 |
216 retry_count += info->status.rates[i].count; | 206 retry_count += info->status.rates[i].count; |
217 } | 207 } |
218 if (retry_count < 0) | 208 if (retry_count < 0) |
219 retry_count = 0; | 209 retry_count = 0; |
220 | 210 |
221 rcu_read_lock(); | 211 rcu_read_lock(); |
222 | 212 |
223 sband = local->hw.wiphy->bands[info->band]; | 213 sband = local->hw.wiphy->bands[info->band]; |
224 fc = hdr->frame_control; | 214 fc = hdr->frame_control; |
225 | 215 |
226 for_each_sta_info(local, hdr->addr1, sta, tmp) { | 216 for_each_sta_info(local, hdr->addr1, sta, tmp) { |
227 /* skip wrong virtual interface */ | 217 /* skip wrong virtual interface */ |
228 if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) | 218 if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) |
229 continue; | 219 continue; |
230 | 220 |
231 » » if (!(info->flags & IEEE80211_TX_STAT_ACK) && | 221 » » acked = !!(info->flags & IEEE80211_TX_STAT_ACK); |
232 » » test_sta_flags(sta, WLAN_STA_PS_STA)) { | 222 » » if (!acked && test_sta_flags(sta, WLAN_STA_PS_STA)) { |
233 /* | 223 /* |
234 * The STA is in power save mode, so assume | 224 * The STA is in power save mode, so assume |
235 * that this TX packet failed because of that. | 225 * that this TX packet failed because of that. |
236 */ | 226 */ |
237 ieee80211_handle_filtered_frame(local, sta, skb); | 227 ieee80211_handle_filtered_frame(local, sta, skb); |
238 rcu_read_unlock(); | 228 rcu_read_unlock(); |
239 return; | 229 return; |
240 } | 230 } |
241 | 231 |
242 if ((local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) && | 232 if ((local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) && |
(...skipping 11 matching lines...) Expand all Loading... |
254 & IEEE80211_SCTL_SEQ); | 244 & IEEE80211_SCTL_SEQ); |
255 ieee80211_send_bar(sta->sdata, hdr->addr1, | 245 ieee80211_send_bar(sta->sdata, hdr->addr1, |
256 tid, ssn); | 246 tid, ssn); |
257 } | 247 } |
258 | 248 |
259 if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { | 249 if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { |
260 ieee80211_handle_filtered_frame(local, sta, skb); | 250 ieee80211_handle_filtered_frame(local, sta, skb); |
261 rcu_read_unlock(); | 251 rcu_read_unlock(); |
262 return; | 252 return; |
263 } else { | 253 } else { |
264 » » » if (!(info->flags & IEEE80211_TX_STAT_ACK)) | 254 » » » if (!acked) |
265 sta->tx_retry_failed++; | 255 sta->tx_retry_failed++; |
266 sta->tx_retry_count += retry_count; | 256 sta->tx_retry_count += retry_count; |
267 } | 257 } |
268 | 258 |
269 rate_control_tx_status(local, sband, sta, skb); | 259 rate_control_tx_status(local, sband, sta, skb); |
270 if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | 260 if (ieee80211_vif_is_mesh(&sta->sdata->vif)) |
271 ieee80211s_update_metric(local, sta, skb); | 261 ieee80211s_update_metric(local, sta, skb); |
272 | 262 |
273 » » if (!(info->flags & IEEE80211_TX_CTL_INJECTED)) | 263 » » if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && acked) |
274 » » » ieee80211_sta_tx_status(sta, skb); | 264 » » » ieee80211_frame_acked(sta, skb); |
| 265 |
| 266 » » if ((sta->sdata->vif.type == NL80211_IFTYPE_STATION) && |
| 267 » » (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) |
| 268 » » » ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data,
acked); |
275 } | 269 } |
276 | 270 |
277 rcu_read_unlock(); | 271 rcu_read_unlock(); |
278 | 272 |
279 ieee80211_led_tx(local, 0); | 273 ieee80211_led_tx(local, 0); |
280 | 274 |
281 /* SNMP counters | 275 /* SNMP counters |
282 * Fragments are passed to low-level drivers as separate skbs, so these | 276 * Fragments are passed to low-level drivers as separate skbs, so these |
283 * are actually fragments, not frames. Update frame counters only for | 277 * are actually fragments, not frames. Update frame counters only for |
284 * the first fragment of the frame. */ | 278 * the first fragment of the frame. */ |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 continue; | 393 continue; |
400 | 394 |
401 if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && | 395 if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && |
402 !send_to_cooked) | 396 !send_to_cooked) |
403 continue; | 397 continue; |
404 | 398 |
405 if (prev_dev) { | 399 if (prev_dev) { |
406 skb2 = skb_clone(skb, GFP_ATOMIC); | 400 skb2 = skb_clone(skb, GFP_ATOMIC); |
407 if (skb2) { | 401 if (skb2) { |
408 skb2->dev = prev_dev; | 402 skb2->dev = prev_dev; |
409 » » » » » netif_receive_skb(skb2); | 403 » » » » » netif_rx(skb2); |
410 } | 404 } |
411 } | 405 } |
412 | 406 |
413 prev_dev = sdata->dev; | 407 prev_dev = sdata->dev; |
414 } | 408 } |
415 } | 409 } |
416 if (prev_dev) { | 410 if (prev_dev) { |
417 skb->dev = prev_dev; | 411 skb->dev = prev_dev; |
418 » » netif_receive_skb(skb); | 412 » » netif_rx(skb); |
419 skb = NULL; | 413 skb = NULL; |
420 } | 414 } |
421 rcu_read_unlock(); | 415 rcu_read_unlock(); |
422 dev_kfree_skb(skb); | 416 dev_kfree_skb(skb); |
423 } | 417 } |
424 EXPORT_SYMBOL(ieee80211_tx_status); | 418 EXPORT_SYMBOL(ieee80211_tx_status); |
OLD | NEW |