| 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 |