aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-02-04 11:58:14 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-04 11:58:14 -0500
commit10be7eb36b93364b98688831ee7d26f58402bb96 (patch)
treeeb13ae80fcaa8baacd804a721c5a4962a501a2a4 /net/mac80211/tx.c
parent90c30335a70e96b8b8493b7deb15e6b30e6d9fce (diff)
parent5ffaf8a361b4c9025963959a744f21d8173c7669 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r--net/mac80211/tx.c50
1 files changed, 33 insertions, 17 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index daf81048c1f7..85e382aa894e 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -529,6 +529,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
529 tx->key = NULL; 529 tx->key = NULL;
530 530
531 if (tx->key) { 531 if (tx->key) {
532 bool skip_hw = false;
533
532 tx->key->tx_rx_count++; 534 tx->key->tx_rx_count++;
533 /* TODO: add threshold stuff again */ 535 /* TODO: add threshold stuff again */
534 536
@@ -545,16 +547,32 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
545 !ieee80211_use_mfp(hdr->frame_control, tx->sta, 547 !ieee80211_use_mfp(hdr->frame_control, tx->sta,
546 tx->skb)) 548 tx->skb))
547 tx->key = NULL; 549 tx->key = NULL;
550 else
551 skip_hw = (tx->key->conf.flags &
552 IEEE80211_KEY_FLAG_SW_MGMT) &&
553 ieee80211_is_mgmt(hdr->frame_control);
548 break; 554 break;
549 case ALG_AES_CMAC: 555 case ALG_AES_CMAC:
550 if (!ieee80211_is_mgmt(hdr->frame_control)) 556 if (!ieee80211_is_mgmt(hdr->frame_control))
551 tx->key = NULL; 557 tx->key = NULL;
552 break; 558 break;
553 } 559 }
560
561 if (!skip_hw && tx->key &&
562 tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
563 info->control.hw_key = &tx->key->conf;
554 } 564 }
555 565
556 if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) 566 return TX_CONTINUE;
557 info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; 567}
568
569static ieee80211_tx_result debug_noinline
570ieee80211_tx_h_sta(struct ieee80211_tx_data *tx)
571{
572 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
573
574 if (tx->sta)
575 info->control.sta = &tx->sta->sta;
558 576
559 return TX_CONTINUE; 577 return TX_CONTINUE;
560} 578}
@@ -734,17 +752,6 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
734} 752}
735 753
736static ieee80211_tx_result debug_noinline 754static ieee80211_tx_result debug_noinline
737ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
738{
739 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
740
741 if (tx->sta)
742 info->control.sta = &tx->sta->sta;
743
744 return TX_CONTINUE;
745}
746
747static ieee80211_tx_result debug_noinline
748ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) 755ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
749{ 756{
750 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); 757 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
@@ -1101,7 +1108,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1101 tx->flags |= IEEE80211_TX_FRAGMENTED; 1108 tx->flags |= IEEE80211_TX_FRAGMENTED;
1102 1109
1103 /* process and remove the injection radiotap header */ 1110 /* process and remove the injection radiotap header */
1104 if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) { 1111 if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) {
1105 if (!__ieee80211_parse_tx_radiotap(tx, skb)) 1112 if (!__ieee80211_parse_tx_radiotap(tx, skb))
1106 return TX_DROP; 1113 return TX_DROP;
1107 1114
@@ -1110,6 +1117,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1110 * the radiotap header that was present and pre-filled 1117 * the radiotap header that was present and pre-filled
1111 * 'tx' with tx control information. 1118 * 'tx' with tx control information.
1112 */ 1119 */
1120 info->flags &= ~IEEE80211_TX_INTFL_HAS_RADIOTAP;
1113 } 1121 }
1114 1122
1115 /* 1123 /*
@@ -1125,6 +1133,8 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1125 tx->sta = rcu_dereference(sdata->u.vlan.sta); 1133 tx->sta = rcu_dereference(sdata->u.vlan.sta);
1126 if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr) 1134 if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr)
1127 return TX_DROP; 1135 return TX_DROP;
1136 } else if (info->flags & IEEE80211_TX_CTL_INJECTED) {
1137 tx->sta = sta_info_get_bss(sdata, hdr->addr1);
1128 } 1138 }
1129 if (!tx->sta) 1139 if (!tx->sta)
1130 tx->sta = sta_info_get(sdata, hdr->addr1); 1140 tx->sta = sta_info_get(sdata, hdr->addr1);
@@ -1279,6 +1289,7 @@ static int __ieee80211_tx(struct ieee80211_local *local,
1279static int invoke_tx_handlers(struct ieee80211_tx_data *tx) 1289static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
1280{ 1290{
1281 struct sk_buff *skb = tx->skb; 1291 struct sk_buff *skb = tx->skb;
1292 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1282 ieee80211_tx_result res = TX_DROP; 1293 ieee80211_tx_result res = TX_DROP;
1283 1294
1284#define CALL_TXH(txh) \ 1295#define CALL_TXH(txh) \
@@ -1292,10 +1303,14 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
1292 CALL_TXH(ieee80211_tx_h_check_assoc); 1303 CALL_TXH(ieee80211_tx_h_check_assoc);
1293 CALL_TXH(ieee80211_tx_h_ps_buf); 1304 CALL_TXH(ieee80211_tx_h_ps_buf);
1294 CALL_TXH(ieee80211_tx_h_select_key); 1305 CALL_TXH(ieee80211_tx_h_select_key);
1295 CALL_TXH(ieee80211_tx_h_michael_mic_add); 1306 CALL_TXH(ieee80211_tx_h_sta);
1296 if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)) 1307 if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
1297 CALL_TXH(ieee80211_tx_h_rate_ctrl); 1308 CALL_TXH(ieee80211_tx_h_rate_ctrl);
1298 CALL_TXH(ieee80211_tx_h_misc); 1309
1310 if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION))
1311 goto txh_done;
1312
1313 CALL_TXH(ieee80211_tx_h_michael_mic_add);
1299 CALL_TXH(ieee80211_tx_h_sequence); 1314 CALL_TXH(ieee80211_tx_h_sequence);
1300 CALL_TXH(ieee80211_tx_h_fragment); 1315 CALL_TXH(ieee80211_tx_h_fragment);
1301 /* handlers after fragment must be aware of tx info fragmentation! */ 1316 /* handlers after fragment must be aware of tx info fragmentation! */
@@ -1487,7 +1502,8 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
1487 int hdrlen; 1502 int hdrlen;
1488 u16 len_rthdr; 1503 u16 len_rthdr;
1489 1504
1490 info->flags |= IEEE80211_TX_CTL_INJECTED; 1505 info->flags |= IEEE80211_TX_CTL_INJECTED |
1506 IEEE80211_TX_INTFL_HAS_RADIOTAP;
1491 1507
1492 len_rthdr = ieee80211_get_radiotap_len(skb->data); 1508 len_rthdr = ieee80211_get_radiotap_len(skb->data);
1493 hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); 1509 hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);