Chromium Code Reviews| 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 |