00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <linux/export.h>
00013 #include <linux/etherdevice.h>
00014 #include <net/mac80211.h>
00015 #include <asm/unaligned.h>
00016 #include "ieee80211_i.h"
00017 #include "rate.h"
00018 #include "mesh.h"
00019 #include "led.h"
00020 #include "wme.h"
00021
00022
00023 void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
00024 struct sk_buff *skb)
00025 {
00026 struct ieee80211_local *local = hw_to_local(hw);
00027 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
00028 int tmp;
00029
00030 skb->pkt_type = IEEE80211_TX_STATUS_MSG;
00031 skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ?
00032 &local->skb_queue : &local->skb_queue_unreliable, skb);
00033 tmp = skb_queue_len(&local->skb_queue) +
00034 skb_queue_len(&local->skb_queue_unreliable);
00035 while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT &&
00036 (skb = skb_dequeue(&local->skb_queue_unreliable))) {
00037 dev_kfree_skb_irq(skb);
00038 tmp--;
00039 I802_DEBUG_INC(local->tx_status_drop);
00040 }
00041 tasklet_schedule(&local->tasklet);
00042 }
00043 EXPORT_SYMBOL(ieee80211_tx_status_irqsafe);
00044
00045 static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
00046 struct sta_info *sta,
00047 struct sk_buff *skb)
00048 {
00049 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
00050 struct ieee80211_hdr *hdr = (void *)skb->data;
00051 int ac;
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 memset(&info->control, 0, sizeof(info->control));
00062
00063 info->control.jiffies = jiffies;
00064 info->control.vif = &sta->sdata->vif;
00065 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING |
00066 IEEE80211_TX_INTFL_RETRANSMISSION;
00067 info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
00068
00069 sta->tx_filtered_count++;
00070
00071
00072
00073
00074
00075
00076
00077
00078 if (hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_MOREDATA))
00079 hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_MOREDATA);
00080
00081 if (ieee80211_is_data_qos(hdr->frame_control)) {
00082 u8 *p = ieee80211_get_qos_ctl(hdr);
00083 int tid = *p & IEEE80211_QOS_CTL_TID_MASK;
00084
00085
00086
00087
00088
00089
00090 if (*p & IEEE80211_QOS_CTL_EOSP)
00091 *p &= ~IEEE80211_QOS_CTL_EOSP;
00092 ac = ieee802_1d_to_ac[tid & 7];
00093 } else {
00094 ac = IEEE80211_AC_BE;
00095 }
00096
00097
00098
00099
00100
00101
00102 set_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT);
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 if (test_sta_flag(sta, WLAN_STA_PS_STA) &&
00139 skb_queue_len(&sta->tx_filtered[ac]) < STA_MAX_TX_BUFFER) {
00140 skb_queue_tail(&sta->tx_filtered[ac], skb);
00141 sta_info_recalc_tim(sta);
00142
00143 if (!timer_pending(&local->sta_cleanup))
00144 mod_timer(&local->sta_cleanup,
00145 round_jiffies(jiffies +
00146 STA_INFO_CLEANUP_INTERVAL));
00147 return;
00148 }
00149
00150 if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
00151 !(info->flags & IEEE80211_TX_INTFL_RETRIED)) {
00152
00153 info->flags |= IEEE80211_TX_INTFL_RETRIED;
00154 ieee80211_add_pending_skb(local, skb);
00155 return;
00156 }
00157
00158 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
00159 if (net_ratelimit())
00160 wiphy_debug(local->hw.wiphy,
00161 "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n",
00162 skb_queue_len(&sta->tx_filtered[ac]),
00163 !!test_sta_flag(sta, WLAN_STA_PS_STA), jiffies);
00164 #endif
00165 dev_kfree_skb(skb);
00166 }
00167
00168 static void ieee80211_check_pending_bar(struct sta_info *sta, u8 *addr, u8 tid)
00169 {
00170 struct tid_ampdu_tx *tid_tx;
00171
00172 tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
00173 if (!tid_tx || !tid_tx->bar_pending)
00174 return;
00175
00176 tid_tx->bar_pending = false;
00177 ieee80211_send_bar(&sta->sdata->vif, addr, tid, tid_tx->failed_bar_ssn);
00178 }
00179
00180 static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
00181 {
00182 struct ieee80211_mgmt *mgmt = (void *) skb->data;
00183 struct ieee80211_local *local = sta->local;
00184 struct ieee80211_sub_if_data *sdata = sta->sdata;
00185
00186 if (ieee80211_is_data_qos(mgmt->frame_control)) {
00187 struct ieee80211_hdr *hdr = (void *) skb->data;
00188 u8 *qc = ieee80211_get_qos_ctl(hdr);
00189 u16 tid = qc[0] & 0xf;
00190
00191 ieee80211_check_pending_bar(sta, hdr->addr1, tid);
00192 }
00193
00194 if (ieee80211_is_action(mgmt->frame_control) &&
00195 sdata->vif.type == NL80211_IFTYPE_STATION &&
00196 mgmt->u.action.category == WLAN_CATEGORY_HT &&
00197 mgmt->u.action.u.ht_smps.action == WLAN_HT_ACTION_SMPS) {
00198
00199
00200
00201
00202
00203
00204
00205 switch (mgmt->u.action.u.ht_smps.smps_control) {
00206 case WLAN_HT_SMPS_CONTROL_DYNAMIC:
00207 sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_DYNAMIC;
00208 break;
00209 case WLAN_HT_SMPS_CONTROL_STATIC:
00210 sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_STATIC;
00211 break;
00212 case WLAN_HT_SMPS_CONTROL_DISABLED:
00213 default:
00214 sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_OFF;
00215 break;
00216 }
00217
00218 ieee80211_queue_work(&local->hw, &local->recalc_smps);
00219 }
00220 }
00221
00222 static void ieee80211_set_bar_pending(struct sta_info *sta, u8 tid, u16 ssn)
00223 {
00224 struct tid_ampdu_tx *tid_tx;
00225
00226 tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
00227 if (!tid_tx)
00228 return;
00229
00230 tid_tx->failed_bar_ssn = ssn;
00231 tid_tx->bar_pending = true;
00232 }
00233
00234 static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info)
00235 {
00236 int len = sizeof(struct ieee80211_radiotap_header);
00237
00238
00239 if (info->status.rates[0].idx >= 0 &&
00240 !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS))
00241 len += 2;
00242
00243
00244 len += 2;
00245
00246
00247 len += 1;
00248
00249
00250 if (info->status.rates[0].idx >= 0 &&
00251 info->status.rates[0].flags & IEEE80211_TX_RC_MCS)
00252 len += 3;
00253
00254 return len;
00255 }
00256
00257 static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band
00258 *sband, struct sk_buff *skb,
00259 int retry_count, int rtap_len)
00260 {
00261 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
00262 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
00263 struct ieee80211_radiotap_header *rthdr;
00264 unsigned char *pos;
00265 u16 txflags;
00266
00267 rthdr = (struct ieee80211_radiotap_header *) skb_push(skb, rtap_len);
00268
00269 memset(rthdr, 0, rtap_len);
00270 rthdr->it_len = cpu_to_le16(rtap_len);
00271 rthdr->it_present =
00272 cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
00273 (1 << IEEE80211_RADIOTAP_DATA_RETRIES));
00274 pos = (unsigned char *)(rthdr + 1);
00275
00276
00277
00278
00279
00280
00281
00282
00283 if (info->status.rates[0].idx >= 0 &&
00284 !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) {
00285 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
00286 *pos = sband->bitrates[info->status.rates[0].idx].bitrate / 5;
00287
00288 pos += 2;
00289 }
00290
00291
00292 txflags = 0;
00293 if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
00294 !is_multicast_ether_addr(hdr->addr1))
00295 txflags |= IEEE80211_RADIOTAP_F_TX_FAIL;
00296
00297 if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
00298 (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
00299 txflags |= IEEE80211_RADIOTAP_F_TX_CTS;
00300 else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
00301 txflags |= IEEE80211_RADIOTAP_F_TX_RTS;
00302
00303 put_unaligned_le16(txflags, pos);
00304 pos += 2;
00305
00306
00307
00308 *pos = retry_count;
00309 pos++;
00310
00311
00312 if (info->status.rates[0].idx >= 0 &&
00313 info->status.rates[0].flags & IEEE80211_TX_RC_MCS) {
00314 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
00315 pos[0] = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
00316 IEEE80211_RADIOTAP_MCS_HAVE_GI |
00317 IEEE80211_RADIOTAP_MCS_HAVE_BW;
00318 if (info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
00319 pos[1] |= IEEE80211_RADIOTAP_MCS_SGI;
00320 if (info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
00321 pos[1] |= IEEE80211_RADIOTAP_MCS_BW_40;
00322 if (info->status.rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD)
00323 pos[1] |= IEEE80211_RADIOTAP_MCS_FMT_GF;
00324 pos[2] = info->status.rates[0].idx;
00325 pos += 3;
00326 }
00327
00328 }
00329
00330
00331
00332
00333
00334
00335
00336
00337 #define STA_LOST_PKT_THRESHOLD 50
00338
00339 void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
00340 {
00341 struct sk_buff *skb2;
00342 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
00343 struct ieee80211_local *local = hw_to_local(hw);
00344 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
00345 __le16 fc;
00346 struct ieee80211_supported_band *sband;
00347 struct ieee80211_sub_if_data *sdata;
00348 struct net_device *prev_dev = NULL;
00349 struct sta_info *sta, *tmp;
00350 int retry_count = -1, i;
00351 int rates_idx = -1;
00352 bool send_to_cooked;
00353 bool acked;
00354 struct ieee80211_bar *bar;
00355 int rtap_len;
00356
00357 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
00358 if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
00359 !(info->flags & IEEE80211_TX_STAT_AMPDU)) {
00360
00361 info->status.rates[i].idx = -1;
00362 info->status.rates[i].count = 0;
00363 break;
00364 } else if (info->status.rates[i].idx < 0) {
00365 break;
00366 } else if (i >= hw->max_report_rates) {
00367
00368 info->status.rates[i].idx = -1;
00369 info->status.rates[i].count = 0;
00370 break;
00371 }
00372
00373 retry_count += info->status.rates[i].count;
00374 }
00375 rates_idx = i - 1;
00376
00377 if (retry_count < 0)
00378 retry_count = 0;
00379
00380 rcu_read_lock();
00381
00382 sband = local->hw.wiphy->bands[info->band];
00383 fc = hdr->frame_control;
00384
00385 for_each_sta_info(local, hdr->addr1, sta, tmp) {
00386
00387 if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr))
00388 continue;
00389
00390 if (info->flags & IEEE80211_TX_STATUS_EOSP)
00391 clear_sta_flag(sta, WLAN_STA_SP);
00392
00393 acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
00394 if (!acked && test_sta_flag(sta, WLAN_STA_PS_STA)) {
00395
00396
00397
00398
00399 ieee80211_handle_filtered_frame(local, sta, skb);
00400 rcu_read_unlock();
00401 return;
00402 }
00403
00404 if ((local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) &&
00405 (rates_idx != -1))
00406 sta->last_tx_rate = info->status.rates[rates_idx];
00407
00408 if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) &&
00409 (ieee80211_is_data_qos(fc))) {
00410 u16 tid, ssn;
00411 u8 *qc;
00412
00413 qc = ieee80211_get_qos_ctl(hdr);
00414 tid = qc[0] & 0xf;
00415 ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10)
00416 & IEEE80211_SCTL_SEQ);
00417 ieee80211_send_bar(&sta->sdata->vif, hdr->addr1,
00418 tid, ssn);
00419 }
00420
00421 if (!acked && ieee80211_is_back_req(fc)) {
00422 u16 tid, control;
00423
00424
00425
00426
00427
00428
00429 bar = (struct ieee80211_bar *) skb->data;
00430 control = le16_to_cpu(bar->control);
00431 if (!(control & IEEE80211_BAR_CTRL_MULTI_TID)) {
00432 u16 ssn = le16_to_cpu(bar->start_seq_num);
00433
00434 tid = (control &
00435 IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
00436 IEEE80211_BAR_CTRL_TID_INFO_SHIFT;
00437
00438 ieee80211_set_bar_pending(sta, tid, ssn);
00439 }
00440 }
00441
00442 if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
00443 ieee80211_handle_filtered_frame(local, sta, skb);
00444 rcu_read_unlock();
00445 return;
00446 } else {
00447 if (!acked)
00448 sta->tx_retry_failed++;
00449 sta->tx_retry_count += retry_count;
00450 }
00451
00452 rate_control_tx_status(local, sband, sta, skb);
00453 if (ieee80211_vif_is_mesh(&sta->sdata->vif))
00454 ieee80211s_update_metric(local, sta, skb);
00455
00456 if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && acked)
00457 ieee80211_frame_acked(sta, skb);
00458
00459 if ((sta->sdata->vif.type == NL80211_IFTYPE_STATION) &&
00460 (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS))
00461 ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data, acked);
00462
00463 if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
00464 if (info->flags & IEEE80211_TX_STAT_ACK) {
00465 if (sta->lost_packets)
00466 sta->lost_packets = 0;
00467 } else if (++sta->lost_packets >= STA_LOST_PKT_THRESHOLD) {
00468 cfg80211_cqm_pktloss_notify(sta->sdata->dev,
00469 sta->sta.addr,
00470 sta->lost_packets,
00471 GFP_ATOMIC);
00472 sta->lost_packets = 0;
00473 }
00474 }
00475 }
00476
00477 rcu_read_unlock();
00478
00479 ieee80211_led_tx(local, 0);
00480
00481
00482
00483
00484
00485 if (info->flags & IEEE80211_TX_STAT_ACK) {
00486 if (ieee80211_is_first_frag(hdr->seq_ctrl)) {
00487 local->dot11TransmittedFrameCount++;
00488 if (is_multicast_ether_addr(hdr->addr1))
00489 local->dot11MulticastTransmittedFrameCount++;
00490 if (retry_count > 0)
00491 local->dot11RetryCount++;
00492 if (retry_count > 1)
00493 local->dot11MultipleRetryCount++;
00494 }
00495
00496
00497
00498
00499
00500 if (!is_multicast_ether_addr(hdr->addr1) ||
00501 ieee80211_is_data(fc) ||
00502 ieee80211_is_mgmt(fc))
00503 local->dot11TransmittedFragmentCount++;
00504 } else {
00505 if (ieee80211_is_first_frag(hdr->seq_ctrl))
00506 local->dot11FailedCount++;
00507 }
00508
00509 if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc) &&
00510 (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) &&
00511 !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
00512 local->ps_sdata && !(local->scanning)) {
00513 if (info->flags & IEEE80211_TX_STAT_ACK) {
00514 local->ps_sdata->u.mgd.flags |=
00515 IEEE80211_STA_NULLFUNC_ACKED;
00516 } else
00517 mod_timer(&local->dynamic_ps_timer, jiffies +
00518 msecs_to_jiffies(10));
00519 }
00520
00521 if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) {
00522 u64 cookie = (unsigned long)skb;
00523
00524 if (ieee80211_is_nullfunc(hdr->frame_control) ||
00525 ieee80211_is_qos_nullfunc(hdr->frame_control)) {
00526 acked = info->flags & IEEE80211_TX_STAT_ACK;
00527
00528 cfg80211_probe_status(skb->dev, hdr->addr1,
00529 cookie, acked, GFP_ATOMIC);
00530 } else {
00531 struct ieee80211_work *wk;
00532
00533 rcu_read_lock();
00534 list_for_each_entry_rcu(wk, &local->work_list, list) {
00535 if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX)
00536 continue;
00537 if (wk->offchan_tx.frame != skb)
00538 continue;
00539 wk->offchan_tx.status = true;
00540 break;
00541 }
00542 rcu_read_unlock();
00543 if (local->hw_roc_skb_for_status == skb) {
00544 cookie = local->hw_roc_cookie ^ 2;
00545 local->hw_roc_skb_for_status = NULL;
00546 }
00547
00548 cfg80211_mgmt_tx_status(
00549 skb->dev, cookie, skb->data, skb->len,
00550 !!(info->flags & IEEE80211_TX_STAT_ACK),
00551 GFP_ATOMIC);
00552 }
00553 }
00554
00555 if (unlikely(info->ack_frame_id)) {
00556 struct sk_buff *ack_skb;
00557 unsigned long flags;
00558
00559 spin_lock_irqsave(&local->ack_status_lock, flags);
00560 ack_skb = idr_find(&local->ack_status_frames,
00561 info->ack_frame_id);
00562 if (ack_skb)
00563 idr_remove(&local->ack_status_frames,
00564 info->ack_frame_id);
00565 spin_unlock_irqrestore(&local->ack_status_lock, flags);
00566
00567
00568 if (ack_skb)
00569 skb_complete_wifi_ack(ack_skb,
00570 info->flags & IEEE80211_TX_STAT_ACK);
00571 }
00572
00573
00574 skb_orphan(skb);
00575
00576
00577 send_to_cooked = !!(info->flags & IEEE80211_TX_CTL_INJECTED) ||
00578 !(ieee80211_is_data(fc));
00579
00580
00581
00582
00583
00584 if (!local->monitors && (!send_to_cooked || !local->cooked_mntrs)) {
00585 dev_kfree_skb(skb);
00586 return;
00587 }
00588
00589
00590 rtap_len = ieee80211_tx_radiotap_len(info);
00591 if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
00592 printk(KERN_ERR "ieee80211_tx_status: headroom too small\n");
00593 dev_kfree_skb(skb);
00594 return;
00595 }
00596 ieee80211_add_tx_radiotap_header(sband, skb, retry_count, rtap_len);
00597
00598
00599 skb_set_mac_header(skb, 0);
00600 skb->ip_summed = CHECKSUM_UNNECESSARY;
00601 skb->pkt_type = PACKET_OTHERHOST;
00602 skb->protocol = htons(ETH_P_802_2);
00603 memset(skb->cb, 0, sizeof(skb->cb));
00604
00605 rcu_read_lock();
00606 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
00607 if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
00608 if (!ieee80211_sdata_running(sdata))
00609 continue;
00610
00611 if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) &&
00612 !send_to_cooked)
00613 continue;
00614
00615 if (prev_dev) {
00616 skb2 = skb_clone(skb, GFP_ATOMIC);
00617 if (skb2) {
00618 skb2->dev = prev_dev;
00619 netif_rx(skb2);
00620 }
00621 }
00622
00623 prev_dev = sdata->dev;
00624 }
00625 }
00626 if (prev_dev) {
00627 skb->dev = prev_dev;
00628 netif_rx(skb);
00629 skb = NULL;
00630 }
00631 rcu_read_unlock();
00632 dev_kfree_skb(skb);
00633 }
00634 EXPORT_SYMBOL(ieee80211_tx_status);
00635
00636 void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets)
00637 {
00638 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
00639 cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr,
00640 num_packets, GFP_ATOMIC);
00641 }
00642 EXPORT_SYMBOL(ieee80211_report_low_ack);
00643
00644 void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb)
00645 {
00646 struct ieee80211_local *local = hw_to_local(hw);
00647 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
00648
00649 if (unlikely(info->ack_frame_id)) {
00650 struct sk_buff *ack_skb;
00651 unsigned long flags;
00652
00653 spin_lock_irqsave(&local->ack_status_lock, flags);
00654 ack_skb = idr_find(&local->ack_status_frames,
00655 info->ack_frame_id);
00656 if (ack_skb)
00657 idr_remove(&local->ack_status_frames,
00658 info->ack_frame_id);
00659 spin_unlock_irqrestore(&local->ack_status_lock, flags);
00660
00661
00662 if (ack_skb)
00663 dev_kfree_skb_any(ack_skb);
00664 }
00665
00666 dev_kfree_skb_any(skb);
00667 }
00668 EXPORT_SYMBOL(ieee80211_free_txskb);