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; |
183 ifmgd->tx_bitrate_changed = true; | 172 ifmgd->tx_bitrate_changed = true; |
184 ieee80211_queue_work(&local->hw, | 173 ieee80211_queue_work(&local->hw, |
185 &ifmgd->bitrate_notify_work); | 174 &ifmgd->bitrate_notify_work); |
186 } | 175 } |
187 } | 176 } |
177 | |
178 if ((sdata->vif.type == NL80211_IFTYPE_STATION) && | |
179 (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) | |
180 ieee80211_sta_tx_notify(sdata, (void *) skb->data); | |
188 } | 181 } |
189 | 182 |
190 void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | 183 void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) |
191 { | 184 { |
192 struct sk_buff *skb2; | 185 struct sk_buff *skb2; |
193 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 186 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
194 struct ieee80211_local *local = hw_to_local(hw); | 187 struct ieee80211_local *local = hw_to_local(hw); |
195 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 188 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
196 u16 frag, type; | 189 u16 frag, type; |
197 __le16 fc; | 190 __le16 fc; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
263 } else { | 256 } else { |
264 if (!(info->flags & IEEE80211_TX_STAT_ACK)) | 257 if (!(info->flags & IEEE80211_TX_STAT_ACK)) |
265 sta->tx_retry_failed++; | 258 sta->tx_retry_failed++; |
266 sta->tx_retry_count += retry_count; | 259 sta->tx_retry_count += retry_count; |
267 } | 260 } |
268 | 261 |
269 rate_control_tx_status(local, sband, sta, skb); | 262 rate_control_tx_status(local, sband, sta, skb); |
270 if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | 263 if (ieee80211_vif_is_mesh(&sta->sdata->vif)) |
271 ieee80211s_update_metric(local, sta, skb); | 264 ieee80211s_update_metric(local, sta, skb); |
272 | 265 |
273 » » if (!(info->flags & IEEE80211_TX_CTL_INJECTED)) | 266 » » if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && |
274 » » » ieee80211_sta_tx_status(sta, skb); | 267 » » (info->flags & IEEE80211_TX_STAT_ACK)) |
268 » » » ieee80211_frame_acked(sta, skb); | |
Sam Leffler
2010/12/01 00:23:44
these changes are wrong; you don't notify when tx
| |
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 |