aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-11-16 09:28:55 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-11-21 16:20:42 -0500
commit252b86c43225d067468dd182e9ae616ad2532bc8 (patch)
treed584ef11ebd143960c1890e361a89653fb9812c9
parent83c76570961573e56a238d84ba18f2581ef1e6b5 (diff)
mac80211: use skb list for fragments
We are currently linking the skbs by using skb->next directly. This works, but the preferred way is to use a struct sk_buff_head instead. That also prepares for passing that to drivers directly. While at it I noticed we calculate the duration for fragments twice -- remove one of them. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/tx.c116
-rw-r--r--net/mac80211/util.c6
-rw-r--r--net/mac80211/wep.c5
-rw-r--r--net/mac80211/wpa.c25
5 files changed, 82 insertions, 71 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 068cc92d16aa..f2785056d8d9 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -142,6 +142,7 @@ typedef unsigned __bitwise__ ieee80211_tx_result;
142 142
143struct ieee80211_tx_data { 143struct ieee80211_tx_data {
144 struct sk_buff *skb; 144 struct sk_buff *skb;
145 struct sk_buff_head skbs;
145 struct ieee80211_local *local; 146 struct ieee80211_local *local;
146 struct ieee80211_sub_if_data *sdata; 147 struct ieee80211_sub_if_data *sdata;
147 struct sta_info *sta; 148 struct sta_info *sta;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 431988361553..26a7cfb80b7c 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -35,7 +35,8 @@
35 35
36/* misc utils */ 36/* misc utils */
37 37
38static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, 38static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
39 struct sk_buff *skb, int group_addr,
39 int next_frag_len) 40 int next_frag_len)
40{ 41{
41 int rate, mrate, erp, dur, i; 42 int rate, mrate, erp, dur, i;
@@ -43,7 +44,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
43 struct ieee80211_local *local = tx->local; 44 struct ieee80211_local *local = tx->local;
44 struct ieee80211_supported_band *sband; 45 struct ieee80211_supported_band *sband;
45 struct ieee80211_hdr *hdr; 46 struct ieee80211_hdr *hdr;
46 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); 47 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
47 48
48 /* assume HW handles this */ 49 /* assume HW handles this */
49 if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS) 50 if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
@@ -75,7 +76,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
75 * at the highest possible rate belonging to the PHY rates in the 76 * at the highest possible rate belonging to the PHY rates in the
76 * BSSBasicRateSet 77 * BSSBasicRateSet
77 */ 78 */
78 hdr = (struct ieee80211_hdr *)tx->skb->data; 79 hdr = (struct ieee80211_hdr *)skb->data;
79 if (ieee80211_is_ctl(hdr->frame_control)) { 80 if (ieee80211_is_ctl(hdr->frame_control)) {
80 /* TODO: These control frames are not currently sent by 81 /* TODO: These control frames are not currently sent by
81 * mac80211, but should they be implemented, this function 82 * mac80211, but should they be implemented, this function
@@ -841,11 +842,12 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
841 return TX_CONTINUE; 842 return TX_CONTINUE;
842} 843}
843 844
844static int ieee80211_fragment(struct ieee80211_local *local, 845static int ieee80211_fragment(struct ieee80211_tx_data *tx,
845 struct sk_buff *skb, int hdrlen, 846 struct sk_buff *skb, int hdrlen,
846 int frag_threshold) 847 int frag_threshold)
847{ 848{
848 struct sk_buff *tail = skb, *tmp; 849 struct ieee80211_local *local = tx->local;
850 struct sk_buff *tmp;
849 int per_fragm = frag_threshold - hdrlen - FCS_LEN; 851 int per_fragm = frag_threshold - hdrlen - FCS_LEN;
850 int pos = hdrlen + per_fragm; 852 int pos = hdrlen + per_fragm;
851 int rem = skb->len - hdrlen - per_fragm; 853 int rem = skb->len - hdrlen - per_fragm;
@@ -853,6 +855,8 @@ static int ieee80211_fragment(struct ieee80211_local *local,
853 if (WARN_ON(rem < 0)) 855 if (WARN_ON(rem < 0))
854 return -EINVAL; 856 return -EINVAL;
855 857
858 /* first fragment was already added to queue by caller */
859
856 while (rem) { 860 while (rem) {
857 int fraglen = per_fragm; 861 int fraglen = per_fragm;
858 862
@@ -865,8 +869,9 @@ static int ieee80211_fragment(struct ieee80211_local *local,
865 IEEE80211_ENCRYPT_TAILROOM); 869 IEEE80211_ENCRYPT_TAILROOM);
866 if (!tmp) 870 if (!tmp)
867 return -ENOMEM; 871 return -ENOMEM;
868 tail->next = tmp; 872
869 tail = tmp; 873 __skb_queue_tail(&tx->skbs, tmp);
874
870 skb_reserve(tmp, local->tx_headroom + 875 skb_reserve(tmp, local->tx_headroom +
871 IEEE80211_ENCRYPT_HEADROOM); 876 IEEE80211_ENCRYPT_HEADROOM);
872 /* copy control information */ 877 /* copy control information */
@@ -882,6 +887,7 @@ static int ieee80211_fragment(struct ieee80211_local *local,
882 pos += fraglen; 887 pos += fraglen;
883 } 888 }
884 889
890 /* adjust first fragment's length */
885 skb->len = hdrlen + per_fragm; 891 skb->len = hdrlen + per_fragm;
886 return 0; 892 return 0;
887} 893}
@@ -896,6 +902,10 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
896 int hdrlen; 902 int hdrlen;
897 int fragnum; 903 int fragnum;
898 904
905 /* no matter what happens, tx->skb moves to tx->skbs */
906 __skb_queue_tail(&tx->skbs, skb);
907 tx->skb = NULL;
908
899 if (info->flags & IEEE80211_TX_CTL_DONTFRAG) 909 if (info->flags & IEEE80211_TX_CTL_DONTFRAG)
900 return TX_CONTINUE; 910 return TX_CONTINUE;
901 911
@@ -924,21 +934,21 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
924 * of the fragments then we will simply pretend to accept the skb 934 * of the fragments then we will simply pretend to accept the skb
925 * but store it away as pending. 935 * but store it away as pending.
926 */ 936 */
927 if (ieee80211_fragment(tx->local, skb, hdrlen, frag_threshold)) 937 if (ieee80211_fragment(tx, skb, hdrlen, frag_threshold))
928 return TX_DROP; 938 return TX_DROP;
929 939
930 /* update duration/seq/flags of fragments */ 940 /* update duration/seq/flags of fragments */
931 fragnum = 0; 941 fragnum = 0;
932 do { 942
943 skb_queue_walk(&tx->skbs, skb) {
933 int next_len; 944 int next_len;
934 const __le16 morefrags = cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); 945 const __le16 morefrags = cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
935 946
936 hdr = (void *)skb->data; 947 hdr = (void *)skb->data;
937 info = IEEE80211_SKB_CB(skb); 948 info = IEEE80211_SKB_CB(skb);
938 949
939 if (skb->next) { 950 if (!skb_queue_is_last(&tx->skbs, skb)) {
940 hdr->frame_control |= morefrags; 951 hdr->frame_control |= morefrags;
941 next_len = skb->next->len;
942 /* 952 /*
943 * No multi-rate retries for fragmented frames, that 953 * No multi-rate retries for fragmented frames, that
944 * would completely throw off the NAV at other STAs. 954 * would completely throw off the NAV at other STAs.
@@ -953,10 +963,9 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
953 hdr->frame_control &= ~morefrags; 963 hdr->frame_control &= ~morefrags;
954 next_len = 0; 964 next_len = 0;
955 } 965 }
956 hdr->duration_id = ieee80211_duration(tx, 0, next_len);
957 hdr->seq_ctrl |= cpu_to_le16(fragnum & IEEE80211_SCTL_FRAG); 966 hdr->seq_ctrl |= cpu_to_le16(fragnum & IEEE80211_SCTL_FRAG);
958 fragnum++; 967 fragnum++;
959 } while ((skb = skb->next)); 968 }
960 969
961 return TX_CONTINUE; 970 return TX_CONTINUE;
962} 971}
@@ -964,16 +973,16 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
964static ieee80211_tx_result debug_noinline 973static ieee80211_tx_result debug_noinline
965ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) 974ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
966{ 975{
967 struct sk_buff *skb = tx->skb; 976 struct sk_buff *skb;
968 977
969 if (!tx->sta) 978 if (!tx->sta)
970 return TX_CONTINUE; 979 return TX_CONTINUE;
971 980
972 tx->sta->tx_packets++; 981 tx->sta->tx_packets++;
973 do { 982 skb_queue_walk(&tx->skbs, skb) {
974 tx->sta->tx_fragments++; 983 tx->sta->tx_fragments++;
975 tx->sta->tx_bytes += skb->len; 984 tx->sta->tx_bytes += skb->len;
976 } while ((skb = skb->next)); 985 }
977 986
978 return TX_CONTINUE; 987 return TX_CONTINUE;
979} 988}
@@ -1012,21 +1021,25 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
1012static ieee80211_tx_result debug_noinline 1021static ieee80211_tx_result debug_noinline
1013ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) 1022ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx)
1014{ 1023{
1015 struct sk_buff *skb = tx->skb; 1024 struct sk_buff *skb;
1016 struct ieee80211_hdr *hdr; 1025 struct ieee80211_hdr *hdr;
1017 int next_len; 1026 int next_len;
1018 bool group_addr; 1027 bool group_addr;
1019 1028
1020 do { 1029 skb_queue_walk(&tx->skbs, skb) {
1021 hdr = (void *) skb->data; 1030 hdr = (void *) skb->data;
1022 if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) 1031 if (unlikely(ieee80211_is_pspoll(hdr->frame_control)))
1023 break; /* must not overwrite AID */ 1032 break; /* must not overwrite AID */
1024 next_len = skb->next ? skb->next->len : 0; 1033 if (!skb_queue_is_last(&tx->skbs, skb)) {
1034 struct sk_buff *next = skb_queue_next(&tx->skbs, skb);
1035 next_len = next->len;
1036 } else
1037 next_len = 0;
1025 group_addr = is_multicast_ether_addr(hdr->addr1); 1038 group_addr = is_multicast_ether_addr(hdr->addr1);
1026 1039
1027 hdr->duration_id = 1040 hdr->duration_id =
1028 ieee80211_duration(tx, group_addr, next_len); 1041 ieee80211_duration(tx, skb, group_addr, next_len);
1029 } while ((skb = skb->next)); 1042 }
1030 1043
1031 return TX_CONTINUE; 1044 return TX_CONTINUE;
1032} 1045}
@@ -1105,6 +1118,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1105 tx->local = local; 1118 tx->local = local;
1106 tx->sdata = sdata; 1119 tx->sdata = sdata;
1107 tx->channel = local->hw.conf.channel; 1120 tx->channel = local->hw.conf.channel;
1121 __skb_queue_head_init(&tx->skbs);
1108 1122
1109 /* 1123 /*
1110 * If this flag is set to true anywhere, and we get here, 1124 * If this flag is set to true anywhere, and we get here,
@@ -1180,17 +1194,18 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1180/* 1194/*
1181 * Returns false if the frame couldn't be transmitted but was queued instead. 1195 * Returns false if the frame couldn't be transmitted but was queued instead.
1182 */ 1196 */
1183static bool __ieee80211_tx(struct ieee80211_local *local, struct sk_buff **skbp, 1197static bool __ieee80211_tx(struct ieee80211_local *local,
1198 struct sk_buff_head *skbs,
1184 struct sta_info *sta, bool txpending) 1199 struct sta_info *sta, bool txpending)
1185{ 1200{
1186 struct sk_buff *skb = *skbp, *next; 1201 struct sk_buff *skb, *tmp;
1187 struct ieee80211_tx_info *info; 1202 struct ieee80211_tx_info *info;
1188 struct ieee80211_sub_if_data *sdata; 1203 struct ieee80211_sub_if_data *sdata;
1189 unsigned long flags; 1204 unsigned long flags;
1190 int len; 1205 int len;
1191 bool fragm = false; 1206 bool fragm = false;
1192 1207
1193 while (skb) { 1208 skb_queue_walk_safe(skbs, skb, tmp) {
1194 int q = skb_get_queue_mapping(skb); 1209 int q = skb_get_queue_mapping(skb);
1195 __le16 fc; 1210 __le16 fc;
1196 1211
@@ -1202,24 +1217,10 @@ static bool __ieee80211_tx(struct ieee80211_local *local, struct sk_buff **skbp,
1202 * transmission from the tx-pending tasklet when the 1217 * transmission from the tx-pending tasklet when the
1203 * queue is woken again. 1218 * queue is woken again.
1204 */ 1219 */
1205 1220 if (txpending)
1206 do { 1221 skb_queue_splice(skbs, &local->pending[q]);
1207 next = skb->next; 1222 else
1208 skb->next = NULL; 1223 skb_queue_splice_tail(skbs, &local->pending[q]);
1209 /*
1210 * NB: If txpending is true, next must already
1211 * be NULL since we must've gone through this
1212 * loop before already; therefore we can just
1213 * queue the frame to the head without worrying
1214 * about reordering of fragments.
1215 */
1216 if (unlikely(txpending))
1217 __skb_queue_head(&local->pending[q],
1218 skb);
1219 else
1220 __skb_queue_tail(&local->pending[q],
1221 skb);
1222 } while ((skb = next));
1223 1224
1224 spin_unlock_irqrestore(&local->queue_stop_reason_lock, 1225 spin_unlock_irqrestore(&local->queue_stop_reason_lock,
1225 flags); 1226 flags);
@@ -1233,10 +1234,9 @@ static bool __ieee80211_tx(struct ieee80211_local *local, struct sk_buff **skbp,
1233 info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT | 1234 info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT |
1234 IEEE80211_TX_CTL_FIRST_FRAGMENT); 1235 IEEE80211_TX_CTL_FIRST_FRAGMENT);
1235 1236
1236 next = skb->next;
1237 len = skb->len; 1237 len = skb->len;
1238 1238
1239 if (next) 1239 if (!skb_queue_is_last(skbs, skb))
1240 info->flags |= IEEE80211_TX_CTL_MORE_FRAMES; 1240 info->flags |= IEEE80211_TX_CTL_MORE_FRAMES;
1241 1241
1242 sdata = vif_to_sdata(info->control.vif); 1242 sdata = vif_to_sdata(info->control.vif);
@@ -1260,14 +1260,17 @@ static bool __ieee80211_tx(struct ieee80211_local *local, struct sk_buff **skbp,
1260 info->control.sta = NULL; 1260 info->control.sta = NULL;
1261 1261
1262 fc = ((struct ieee80211_hdr *)skb->data)->frame_control; 1262 fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
1263
1264 __skb_unlink(skb, skbs);
1263 drv_tx(local, skb); 1265 drv_tx(local, skb);
1264 1266
1265 ieee80211_tpt_led_trig_tx(local, fc, len); 1267 ieee80211_tpt_led_trig_tx(local, fc, len);
1266 *skbp = skb = next;
1267 ieee80211_led_tx(local, 1); 1268 ieee80211_led_tx(local, 1);
1268 fragm = true; 1269 fragm = true;
1269 } 1270 }
1270 1271
1272 WARN_ON(!skb_queue_empty(skbs));
1273
1271 return true; 1274 return true;
1272} 1275}
1273 1276
@@ -1277,8 +1280,7 @@ static bool __ieee80211_tx(struct ieee80211_local *local, struct sk_buff **skbp,
1277 */ 1280 */
1278static int invoke_tx_handlers(struct ieee80211_tx_data *tx) 1281static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
1279{ 1282{
1280 struct sk_buff *skb = tx->skb; 1283 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
1281 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1282 ieee80211_tx_result res = TX_DROP; 1284 ieee80211_tx_result res = TX_DROP;
1283 1285
1284#define CALL_TXH(txh) \ 1286#define CALL_TXH(txh) \
@@ -1312,13 +1314,10 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
1312 txh_done: 1314 txh_done:
1313 if (unlikely(res == TX_DROP)) { 1315 if (unlikely(res == TX_DROP)) {
1314 I802_DEBUG_INC(tx->local->tx_handlers_drop); 1316 I802_DEBUG_INC(tx->local->tx_handlers_drop);
1315 while (skb) { 1317 if (tx->skb)
1316 struct sk_buff *next; 1318 dev_kfree_skb(tx->skb);
1317 1319 else
1318 next = skb->next; 1320 __skb_queue_purge(&tx->skbs);
1319 dev_kfree_skb(skb);
1320 skb = next;
1321 }
1322 return -1; 1321 return -1;
1323 } else if (unlikely(res == TX_QUEUED)) { 1322 } else if (unlikely(res == TX_QUEUED)) {
1324 I802_DEBUG_INC(tx->local->tx_handlers_queued); 1323 I802_DEBUG_INC(tx->local->tx_handlers_queued);
@@ -1361,7 +1360,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
1361 info->band = tx.channel->band; 1360 info->band = tx.channel->band;
1362 1361
1363 if (!invoke_tx_handlers(&tx)) 1362 if (!invoke_tx_handlers(&tx))
1364 result = __ieee80211_tx(local, &tx.skb, tx.sta, txpending); 1363 result = __ieee80211_tx(local, &tx.skbs, tx.sta, txpending);
1365 out: 1364 out:
1366 rcu_read_unlock(); 1365 rcu_read_unlock();
1367 return result; 1366 return result;
@@ -2109,10 +2108,15 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
2109 if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) { 2108 if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) {
2110 result = ieee80211_tx(sdata, skb, true); 2109 result = ieee80211_tx(sdata, skb, true);
2111 } else { 2110 } else {
2111 struct sk_buff_head skbs;
2112
2113 __skb_queue_head_init(&skbs);
2114 __skb_queue_tail(&skbs, skb);
2115
2112 hdr = (struct ieee80211_hdr *)skb->data; 2116 hdr = (struct ieee80211_hdr *)skb->data;
2113 sta = sta_info_get(sdata, hdr->addr1); 2117 sta = sta_info_get(sdata, hdr->addr1);
2114 2118
2115 result = __ieee80211_tx(local, &skb, sta, true); 2119 result = __ieee80211_tx(local, &skbs, sta, true);
2116 } 2120 }
2117 2121
2118 return result; 2122 return result;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 4cf25b0eea74..939bf248ec73 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -95,13 +95,13 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
95 95
96void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) 96void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx)
97{ 97{
98 struct sk_buff *skb = tx->skb; 98 struct sk_buff *skb;
99 struct ieee80211_hdr *hdr; 99 struct ieee80211_hdr *hdr;
100 100
101 do { 101 skb_queue_walk(&tx->skbs, skb) {
102 hdr = (struct ieee80211_hdr *) skb->data; 102 hdr = (struct ieee80211_hdr *) skb->data;
103 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); 103 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
104 } while ((skb = skb->next)); 104 }
105} 105}
106 106
107int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, 107int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index a1c6bfd55f0f..68ad351479df 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -330,13 +330,12 @@ ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx)
330 330
331 ieee80211_tx_set_protected(tx); 331 ieee80211_tx_set_protected(tx);
332 332
333 skb = tx->skb; 333 skb_queue_walk(&tx->skbs, skb) {
334 do {
335 if (wep_encrypt_skb(tx, skb) < 0) { 334 if (wep_encrypt_skb(tx, skb) < 0) {
336 I802_DEBUG_INC(tx->local->tx_handlers_drop_wep); 335 I802_DEBUG_INC(tx->local->tx_handlers_drop_wep);
337 return TX_DROP; 336 return TX_DROP;
338 } 337 }
339 } while ((skb = skb->next)); 338 }
340 339
341 return TX_CONTINUE; 340 return TX_CONTINUE;
342} 341}
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 106e15a4649f..93aab0715e8a 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -223,14 +223,14 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
223ieee80211_tx_result 223ieee80211_tx_result
224ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx) 224ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx)
225{ 225{
226 struct sk_buff *skb = tx->skb; 226 struct sk_buff *skb;
227 227
228 ieee80211_tx_set_protected(tx); 228 ieee80211_tx_set_protected(tx);
229 229
230 do { 230 skb_queue_walk(&tx->skbs, skb) {
231 if (tkip_encrypt_skb(tx, skb) < 0) 231 if (tkip_encrypt_skb(tx, skb) < 0)
232 return TX_DROP; 232 return TX_DROP;
233 } while ((skb = skb->next)); 233 }
234 234
235 return TX_CONTINUE; 235 return TX_CONTINUE;
236} 236}
@@ -449,14 +449,14 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
449ieee80211_tx_result 449ieee80211_tx_result
450ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) 450ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx)
451{ 451{
452 struct sk_buff *skb = tx->skb; 452 struct sk_buff *skb;
453 453
454 ieee80211_tx_set_protected(tx); 454 ieee80211_tx_set_protected(tx);
455 455
456 do { 456 skb_queue_walk(&tx->skbs, skb) {
457 if (ccmp_encrypt_skb(tx, skb) < 0) 457 if (ccmp_encrypt_skb(tx, skb) < 0)
458 return TX_DROP; 458 return TX_DROP;
459 } while ((skb = skb->next)); 459 }
460 460
461 return TX_CONTINUE; 461 return TX_CONTINUE;
462} 462}
@@ -554,15 +554,22 @@ static inline void bip_ipn_swap(u8 *d, const u8 *s)
554ieee80211_tx_result 554ieee80211_tx_result
555ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx) 555ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
556{ 556{
557 struct sk_buff *skb = tx->skb; 557 struct sk_buff *skb;
558 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 558 struct ieee80211_tx_info *info;
559 struct ieee80211_key *key = tx->key; 559 struct ieee80211_key *key = tx->key;
560 struct ieee80211_mmie *mmie; 560 struct ieee80211_mmie *mmie;
561 u8 aad[20]; 561 u8 aad[20];
562 u64 pn64; 562 u64 pn64;
563 563
564 if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
565 return TX_DROP;
566
567 skb = skb_peek(&tx->skbs);
568
569 info = IEEE80211_SKB_CB(skb);
570
564 if (info->control.hw_key) 571 if (info->control.hw_key)
565 return 0; 572 return TX_CONTINUE;
566 573
567 if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) 574 if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
568 return TX_DROP; 575 return TX_DROP;