diff options
author | David S. Miller <davem@davemloft.net> | 2010-02-04 11:58:14 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-04 11:58:14 -0500 |
commit | 10be7eb36b93364b98688831ee7d26f58402bb96 (patch) | |
tree | eb13ae80fcaa8baacd804a721c5a4962a501a2a4 /net/mac80211/tx.c | |
parent | 90c30335a70e96b8b8493b7deb15e6b30e6d9fce (diff) | |
parent | 5ffaf8a361b4c9025963959a744f21d8173c7669 (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.c | 50 |
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 | |||
569 | static ieee80211_tx_result debug_noinline | ||
570 | ieee80211_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 | ||
736 | static ieee80211_tx_result debug_noinline | 754 | static ieee80211_tx_result debug_noinline |
737 | ieee80211_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 | |||
747 | static ieee80211_tx_result debug_noinline | ||
748 | ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | 755 | ieee80211_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, | |||
1279 | static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | 1289 | static 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); |