diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/ieee80211_i.h | 7 | ||||
-rw-r--r-- | net/mac80211/tx.c | 322 | ||||
-rw-r--r-- | net/mac80211/util.c | 19 | ||||
-rw-r--r-- | net/mac80211/wep.c | 21 | ||||
-rw-r--r-- | net/mac80211/wpa.c | 28 |
5 files changed, 173 insertions, 224 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index acba78e1a5ca..785f6363a6fc 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -149,11 +149,6 @@ struct ieee80211_tx_data { | |||
149 | 149 | ||
150 | struct ieee80211_channel *channel; | 150 | struct ieee80211_channel *channel; |
151 | 151 | ||
152 | /* Extra fragments (in addition to the first fragment | ||
153 | * in skb) */ | ||
154 | struct sk_buff **extra_frag; | ||
155 | int num_extra_frag; | ||
156 | |||
157 | u16 ethertype; | 152 | u16 ethertype; |
158 | unsigned int flags; | 153 | unsigned int flags; |
159 | }; | 154 | }; |
@@ -191,8 +186,6 @@ struct ieee80211_rx_data { | |||
191 | 186 | ||
192 | struct ieee80211_tx_stored_packet { | 187 | struct ieee80211_tx_stored_packet { |
193 | struct sk_buff *skb; | 188 | struct sk_buff *skb; |
194 | struct sk_buff **extra_frag; | ||
195 | int num_extra_frag; | ||
196 | }; | 189 | }; |
197 | 190 | ||
198 | struct beacon_data { | 191 | struct beacon_data { |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index f3f240c69018..51bf49cc75bc 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -34,8 +34,7 @@ | |||
34 | 34 | ||
35 | #define IEEE80211_TX_OK 0 | 35 | #define IEEE80211_TX_OK 0 |
36 | #define IEEE80211_TX_AGAIN 1 | 36 | #define IEEE80211_TX_AGAIN 1 |
37 | #define IEEE80211_TX_FRAG_AGAIN 2 | 37 | #define IEEE80211_TX_PENDING 2 |
38 | #define IEEE80211_TX_PENDING 3 | ||
39 | 38 | ||
40 | /* misc utils */ | 39 | /* misc utils */ |
41 | 40 | ||
@@ -702,17 +701,62 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | |||
702 | return TX_CONTINUE; | 701 | return TX_CONTINUE; |
703 | } | 702 | } |
704 | 703 | ||
704 | static int ieee80211_fragment(struct ieee80211_local *local, | ||
705 | struct sk_buff *skb, int hdrlen, | ||
706 | int frag_threshold) | ||
707 | { | ||
708 | struct sk_buff *tail = skb, *tmp; | ||
709 | int per_fragm = frag_threshold - hdrlen - FCS_LEN; | ||
710 | int pos = hdrlen + per_fragm; | ||
711 | int rem = skb->len - hdrlen - per_fragm; | ||
712 | |||
713 | if (WARN_ON(rem < 0)) | ||
714 | return -EINVAL; | ||
715 | |||
716 | while (rem) { | ||
717 | int fraglen = per_fragm; | ||
718 | |||
719 | if (fraglen > rem) | ||
720 | fraglen = rem; | ||
721 | rem -= fraglen; | ||
722 | tmp = dev_alloc_skb(local->tx_headroom + | ||
723 | frag_threshold + | ||
724 | IEEE80211_ENCRYPT_HEADROOM + | ||
725 | IEEE80211_ENCRYPT_TAILROOM); | ||
726 | if (!tmp) | ||
727 | return -ENOMEM; | ||
728 | tail->next = tmp; | ||
729 | tail = tmp; | ||
730 | skb_reserve(tmp, local->tx_headroom + | ||
731 | IEEE80211_ENCRYPT_HEADROOM); | ||
732 | /* copy control information */ | ||
733 | memcpy(tmp->cb, skb->cb, sizeof(tmp->cb)); | ||
734 | skb_copy_queue_mapping(tmp, skb); | ||
735 | tmp->priority = skb->priority; | ||
736 | tmp->do_not_encrypt = skb->do_not_encrypt; | ||
737 | tmp->dev = skb->dev; | ||
738 | tmp->iif = skb->iif; | ||
739 | |||
740 | /* copy header and data */ | ||
741 | memcpy(skb_put(tmp, hdrlen), skb->data, hdrlen); | ||
742 | memcpy(skb_put(tmp, fraglen), skb->data + pos, fraglen); | ||
743 | |||
744 | pos += fraglen; | ||
745 | } | ||
746 | |||
747 | skb->len = hdrlen + per_fragm; | ||
748 | return 0; | ||
749 | } | ||
750 | |||
705 | static ieee80211_tx_result debug_noinline | 751 | static ieee80211_tx_result debug_noinline |
706 | ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | 752 | ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) |
707 | { | 753 | { |
708 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 754 | struct sk_buff *skb = tx->skb; |
709 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 755 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
710 | size_t hdrlen, per_fragm, num_fragm, payload_len, left; | 756 | struct ieee80211_hdr *hdr = (void *)skb->data; |
711 | struct sk_buff **frags, *first, *frag; | ||
712 | int i; | ||
713 | u16 seq; | ||
714 | u8 *pos; | ||
715 | int frag_threshold = tx->local->fragmentation_threshold; | 757 | int frag_threshold = tx->local->fragmentation_threshold; |
758 | int hdrlen; | ||
759 | int fragnum; | ||
716 | 760 | ||
717 | if (!(tx->flags & IEEE80211_TX_FRAGMENTED)) | 761 | if (!(tx->flags & IEEE80211_TX_FRAGMENTED)) |
718 | return TX_CONTINUE; | 762 | return TX_CONTINUE; |
@@ -725,58 +769,35 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
725 | if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) | 769 | if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) |
726 | return TX_DROP; | 770 | return TX_DROP; |
727 | 771 | ||
728 | first = tx->skb; | ||
729 | |||
730 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 772 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
731 | payload_len = first->len - hdrlen; | ||
732 | per_fragm = frag_threshold - hdrlen - FCS_LEN; | ||
733 | num_fragm = DIV_ROUND_UP(payload_len, per_fragm); | ||
734 | |||
735 | frags = kzalloc(num_fragm * sizeof(struct sk_buff *), GFP_ATOMIC); | ||
736 | if (!frags) | ||
737 | goto fail; | ||
738 | |||
739 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); | ||
740 | seq = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ; | ||
741 | pos = first->data + hdrlen + per_fragm; | ||
742 | left = payload_len - per_fragm; | ||
743 | for (i = 0; i < num_fragm - 1; i++) { | ||
744 | struct ieee80211_hdr *fhdr; | ||
745 | size_t copylen; | ||
746 | |||
747 | if (left <= 0) | ||
748 | goto fail; | ||
749 | 773 | ||
750 | /* reserve enough extra head and tail room for possible | 774 | /* internal error, why is TX_FRAGMENTED set? */ |
751 | * encryption */ | 775 | if (WARN_ON(skb->len <= frag_threshold)) |
752 | frag = frags[i] = | 776 | return TX_DROP; |
753 | dev_alloc_skb(tx->local->tx_headroom + | ||
754 | frag_threshold + | ||
755 | IEEE80211_ENCRYPT_HEADROOM + | ||
756 | IEEE80211_ENCRYPT_TAILROOM); | ||
757 | if (!frag) | ||
758 | goto fail; | ||
759 | |||
760 | /* Make sure that all fragments use the same priority so | ||
761 | * that they end up using the same TX queue */ | ||
762 | frag->priority = first->priority; | ||
763 | 777 | ||
764 | skb_reserve(frag, tx->local->tx_headroom + | 778 | /* |
765 | IEEE80211_ENCRYPT_HEADROOM); | 779 | * Now fragment the frame. This will allocate all the fragments and |
780 | * chain them (using skb as the first fragment) to skb->next. | ||
781 | * During transmission, we will remove the successfully transmitted | ||
782 | * fragments from this list. When the low-level driver rejects one | ||
783 | * of the fragments then we will simply pretend to accept the skb | ||
784 | * but store it away as pending. | ||
785 | */ | ||
786 | if (ieee80211_fragment(tx->local, skb, hdrlen, frag_threshold)) | ||
787 | return TX_DROP; | ||
766 | 788 | ||
767 | /* copy TX information */ | 789 | /* update duration/seq/flags of fragments */ |
768 | info = IEEE80211_SKB_CB(frag); | 790 | fragnum = 0; |
769 | memcpy(info, first->cb, sizeof(frag->cb)); | 791 | do { |
792 | int next_len; | ||
793 | const __le16 morefrags = cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); | ||
770 | 794 | ||
771 | /* copy/fill in 802.11 header */ | 795 | hdr = (void *)skb->data; |
772 | fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen); | 796 | info = IEEE80211_SKB_CB(skb); |
773 | memcpy(fhdr, first->data, hdrlen); | ||
774 | fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG)); | ||
775 | 797 | ||
776 | if (i == num_fragm - 2) { | 798 | if (skb->next) { |
777 | /* clear MOREFRAGS bit for the last fragment */ | 799 | hdr->frame_control |= morefrags; |
778 | fhdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREFRAGS); | 800 | next_len = skb->next->len; |
779 | } else { | ||
780 | /* | 801 | /* |
781 | * No multi-rate retries for fragmented frames, that | 802 | * No multi-rate retries for fragmented frames, that |
782 | * would completely throw off the NAV at other STAs. | 803 | * would completely throw off the NAV at other STAs. |
@@ -787,37 +808,16 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
787 | info->control.rates[4].idx = -1; | 808 | info->control.rates[4].idx = -1; |
788 | BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5); | 809 | BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5); |
789 | info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; | 810 | info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
811 | } else { | ||
812 | hdr->frame_control &= ~morefrags; | ||
813 | next_len = 0; | ||
790 | } | 814 | } |
791 | 815 | hdr->duration_id = ieee80211_duration(tx, 0, next_len); | |
792 | /* copy data */ | 816 | hdr->seq_ctrl |= cpu_to_le16(fragnum & IEEE80211_SCTL_FRAG); |
793 | copylen = left > per_fragm ? per_fragm : left; | 817 | fragnum++; |
794 | memcpy(skb_put(frag, copylen), pos, copylen); | 818 | } while ((skb = skb->next)); |
795 | |||
796 | skb_copy_queue_mapping(frag, first); | ||
797 | |||
798 | frag->do_not_encrypt = first->do_not_encrypt; | ||
799 | frag->dev = first->dev; | ||
800 | frag->iif = first->iif; | ||
801 | |||
802 | pos += copylen; | ||
803 | left -= copylen; | ||
804 | } | ||
805 | skb_trim(first, hdrlen + per_fragm); | ||
806 | |||
807 | tx->num_extra_frag = num_fragm - 1; | ||
808 | tx->extra_frag = frags; | ||
809 | 819 | ||
810 | return TX_CONTINUE; | 820 | return TX_CONTINUE; |
811 | |||
812 | fail: | ||
813 | if (frags) { | ||
814 | for (i = 0; i < num_fragm - 1; i++) | ||
815 | if (frags[i]) | ||
816 | dev_kfree_skb(frags[i]); | ||
817 | kfree(frags); | ||
818 | } | ||
819 | I802_DEBUG_INC(tx->local->tx_handlers_drop_fragment); | ||
820 | return TX_DROP; | ||
821 | } | 821 | } |
822 | 822 | ||
823 | static ieee80211_tx_result debug_noinline | 823 | static ieee80211_tx_result debug_noinline |
@@ -845,27 +845,19 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) | |||
845 | static ieee80211_tx_result debug_noinline | 845 | static ieee80211_tx_result debug_noinline |
846 | ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) | 846 | ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) |
847 | { | 847 | { |
848 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 848 | struct sk_buff *skb = tx->skb; |
849 | int next_len, i; | 849 | struct ieee80211_hdr *hdr; |
850 | int group_addr = is_multicast_ether_addr(hdr->addr1); | 850 | int next_len; |
851 | 851 | bool group_addr; | |
852 | if (!(tx->flags & IEEE80211_TX_FRAGMENTED)) { | ||
853 | hdr->duration_id = ieee80211_duration(tx, group_addr, 0); | ||
854 | return TX_CONTINUE; | ||
855 | } | ||
856 | |||
857 | hdr->duration_id = ieee80211_duration(tx, group_addr, | ||
858 | tx->extra_frag[0]->len); | ||
859 | 852 | ||
860 | for (i = 0; i < tx->num_extra_frag; i++) { | 853 | do { |
861 | if (i + 1 < tx->num_extra_frag) | 854 | hdr = (void *) skb->data; |
862 | next_len = tx->extra_frag[i + 1]->len; | 855 | next_len = skb->next ? skb->next->len : 0; |
863 | else | 856 | group_addr = is_multicast_ether_addr(hdr->addr1); |
864 | next_len = 0; | ||
865 | 857 | ||
866 | hdr = (struct ieee80211_hdr *)tx->extra_frag[i]->data; | 858 | hdr->duration_id = |
867 | hdr->duration_id = ieee80211_duration(tx, 0, next_len); | 859 | ieee80211_duration(tx, group_addr, next_len); |
868 | } | 860 | } while ((skb = skb->next)); |
869 | 861 | ||
870 | return TX_CONTINUE; | 862 | return TX_CONTINUE; |
871 | } | 863 | } |
@@ -873,19 +865,16 @@ ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) | |||
873 | static ieee80211_tx_result debug_noinline | 865 | static ieee80211_tx_result debug_noinline |
874 | ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) | 866 | ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) |
875 | { | 867 | { |
876 | int i; | 868 | struct sk_buff *skb = tx->skb; |
877 | 869 | ||
878 | if (!tx->sta) | 870 | if (!tx->sta) |
879 | return TX_CONTINUE; | 871 | return TX_CONTINUE; |
880 | 872 | ||
881 | tx->sta->tx_packets++; | 873 | tx->sta->tx_packets++; |
882 | tx->sta->tx_fragments++; | 874 | do { |
883 | tx->sta->tx_bytes += tx->skb->len; | 875 | tx->sta->tx_fragments++; |
884 | if (tx->extra_frag) { | 876 | tx->sta->tx_bytes += skb->len; |
885 | tx->sta->tx_fragments += tx->num_extra_frag; | 877 | } while ((skb = skb->next)); |
886 | for (i = 0; i < tx->num_extra_frag; i++) | ||
887 | tx->sta->tx_bytes += tx->extra_frag[i]->len; | ||
888 | } | ||
889 | 878 | ||
890 | return TX_CONTINUE; | 879 | return TX_CONTINUE; |
891 | } | 880 | } |
@@ -1099,45 +1088,36 @@ static int ieee80211_tx_prepare(struct ieee80211_local *local, | |||
1099 | return 0; | 1088 | return 0; |
1100 | } | 1089 | } |
1101 | 1090 | ||
1102 | static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, | 1091 | static int __ieee80211_tx(struct ieee80211_local *local, |
1103 | struct ieee80211_tx_data *tx) | 1092 | struct ieee80211_tx_data *tx) |
1104 | { | 1093 | { |
1094 | struct sk_buff *skb = tx->skb, *next; | ||
1105 | struct ieee80211_tx_info *info; | 1095 | struct ieee80211_tx_info *info; |
1106 | int ret, i; | 1096 | int ret; |
1097 | bool fragm = false; | ||
1107 | 1098 | ||
1108 | if (skb) { | 1099 | local->mdev->trans_start = jiffies; |
1100 | |||
1101 | while (skb) { | ||
1109 | if (ieee80211_queue_stopped(&local->hw, | 1102 | if (ieee80211_queue_stopped(&local->hw, |
1110 | skb_get_queue_mapping(skb))) | 1103 | skb_get_queue_mapping(skb))) |
1111 | return IEEE80211_TX_PENDING; | 1104 | return IEEE80211_TX_PENDING; |
1112 | 1105 | ||
1113 | ret = local->ops->tx(local_to_hw(local), skb); | 1106 | if (fragm) { |
1114 | if (ret) | 1107 | info = IEEE80211_SKB_CB(skb); |
1115 | return IEEE80211_TX_AGAIN; | ||
1116 | local->mdev->trans_start = jiffies; | ||
1117 | ieee80211_led_tx(local, 1); | ||
1118 | } | ||
1119 | if (tx->extra_frag) { | ||
1120 | for (i = 0; i < tx->num_extra_frag; i++) { | ||
1121 | if (!tx->extra_frag[i]) | ||
1122 | continue; | ||
1123 | info = IEEE80211_SKB_CB(tx->extra_frag[i]); | ||
1124 | info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT | | 1108 | info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT | |
1125 | IEEE80211_TX_CTL_FIRST_FRAGMENT); | 1109 | IEEE80211_TX_CTL_FIRST_FRAGMENT); |
1126 | if (ieee80211_queue_stopped(&local->hw, | ||
1127 | skb_get_queue_mapping(tx->extra_frag[i]))) | ||
1128 | return IEEE80211_TX_FRAG_AGAIN; | ||
1129 | |||
1130 | ret = local->ops->tx(local_to_hw(local), | ||
1131 | tx->extra_frag[i]); | ||
1132 | if (ret) | ||
1133 | return IEEE80211_TX_FRAG_AGAIN; | ||
1134 | local->mdev->trans_start = jiffies; | ||
1135 | ieee80211_led_tx(local, 1); | ||
1136 | tx->extra_frag[i] = NULL; | ||
1137 | } | 1110 | } |
1138 | kfree(tx->extra_frag); | 1111 | |
1139 | tx->extra_frag = NULL; | 1112 | next = skb->next; |
1113 | ret = local->ops->tx(local_to_hw(local), skb); | ||
1114 | if (ret != NETDEV_TX_OK) | ||
1115 | return IEEE80211_TX_AGAIN; | ||
1116 | tx->skb = skb = next; | ||
1117 | ieee80211_led_tx(local, 1); | ||
1118 | fragm = true; | ||
1140 | } | 1119 | } |
1120 | |||
1141 | return IEEE80211_TX_OK; | 1121 | return IEEE80211_TX_OK; |
1142 | } | 1122 | } |
1143 | 1123 | ||
@@ -1149,7 +1129,6 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | |||
1149 | { | 1129 | { |
1150 | struct sk_buff *skb = tx->skb; | 1130 | struct sk_buff *skb = tx->skb; |
1151 | ieee80211_tx_result res = TX_DROP; | 1131 | ieee80211_tx_result res = TX_DROP; |
1152 | int i; | ||
1153 | 1132 | ||
1154 | #define CALL_TXH(txh) \ | 1133 | #define CALL_TXH(txh) \ |
1155 | res = txh(tx); \ | 1134 | res = txh(tx); \ |
@@ -1173,11 +1152,13 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | |||
1173 | txh_done: | 1152 | txh_done: |
1174 | if (unlikely(res == TX_DROP)) { | 1153 | if (unlikely(res == TX_DROP)) { |
1175 | I802_DEBUG_INC(tx->local->tx_handlers_drop); | 1154 | I802_DEBUG_INC(tx->local->tx_handlers_drop); |
1176 | dev_kfree_skb(skb); | 1155 | while (skb) { |
1177 | for (i = 0; i < tx->num_extra_frag; i++) | 1156 | struct sk_buff *next; |
1178 | if (tx->extra_frag[i]) | 1157 | |
1179 | dev_kfree_skb(tx->extra_frag[i]); | 1158 | next = skb->next; |
1180 | kfree(tx->extra_frag); | 1159 | dev_kfree_skb(skb); |
1160 | skb = next; | ||
1161 | } | ||
1181 | return -1; | 1162 | return -1; |
1182 | } else if (unlikely(res == TX_QUEUED)) { | 1163 | } else if (unlikely(res == TX_QUEUED)) { |
1183 | I802_DEBUG_INC(tx->local->tx_handlers_queued); | 1164 | I802_DEBUG_INC(tx->local->tx_handlers_queued); |
@@ -1194,7 +1175,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) | |||
1194 | struct ieee80211_tx_data tx; | 1175 | struct ieee80211_tx_data tx; |
1195 | ieee80211_tx_result res_prepare; | 1176 | ieee80211_tx_result res_prepare; |
1196 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1177 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1197 | int ret, i; | 1178 | int ret; |
1198 | u16 queue; | 1179 | u16 queue; |
1199 | 1180 | ||
1200 | queue = skb_get_queue_mapping(skb); | 1181 | queue = skb_get_queue_mapping(skb); |
@@ -1225,7 +1206,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) | |||
1225 | goto out; | 1206 | goto out; |
1226 | 1207 | ||
1227 | retry: | 1208 | retry: |
1228 | ret = __ieee80211_tx(local, skb, &tx); | 1209 | ret = __ieee80211_tx(local, &tx); |
1229 | if (ret) { | 1210 | if (ret) { |
1230 | struct ieee80211_tx_stored_packet *store; | 1211 | struct ieee80211_tx_stored_packet *store; |
1231 | 1212 | ||
@@ -1240,9 +1221,6 @@ retry: | |||
1240 | 1221 | ||
1241 | store = &local->pending_packet[queue]; | 1222 | store = &local->pending_packet[queue]; |
1242 | 1223 | ||
1243 | if (ret == IEEE80211_TX_FRAG_AGAIN) | ||
1244 | skb = NULL; | ||
1245 | |||
1246 | set_bit(queue, local->queues_pending); | 1224 | set_bit(queue, local->queues_pending); |
1247 | smp_mb(); | 1225 | smp_mb(); |
1248 | /* | 1226 | /* |
@@ -1260,22 +1238,23 @@ retry: | |||
1260 | clear_bit(queue, local->queues_pending); | 1238 | clear_bit(queue, local->queues_pending); |
1261 | goto retry; | 1239 | goto retry; |
1262 | } | 1240 | } |
1263 | store->skb = skb; | 1241 | store->skb = tx.skb; |
1264 | store->extra_frag = tx.extra_frag; | ||
1265 | store->num_extra_frag = tx.num_extra_frag; | ||
1266 | } | 1242 | } |
1267 | out: | 1243 | out: |
1268 | rcu_read_unlock(); | 1244 | rcu_read_unlock(); |
1269 | return 0; | 1245 | return 0; |
1270 | 1246 | ||
1271 | drop: | 1247 | drop: |
1272 | if (skb) | ||
1273 | dev_kfree_skb(skb); | ||
1274 | for (i = 0; i < tx.num_extra_frag; i++) | ||
1275 | if (tx.extra_frag[i]) | ||
1276 | dev_kfree_skb(tx.extra_frag[i]); | ||
1277 | kfree(tx.extra_frag); | ||
1278 | rcu_read_unlock(); | 1248 | rcu_read_unlock(); |
1249 | |||
1250 | skb = tx.skb; | ||
1251 | while (skb) { | ||
1252 | struct sk_buff *next; | ||
1253 | |||
1254 | next = skb->next; | ||
1255 | dev_kfree_skb(skb); | ||
1256 | skb = next; | ||
1257 | } | ||
1279 | return 0; | 1258 | return 0; |
1280 | } | 1259 | } |
1281 | 1260 | ||
@@ -1810,17 +1789,21 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1810 | */ | 1789 | */ |
1811 | void ieee80211_clear_tx_pending(struct ieee80211_local *local) | 1790 | void ieee80211_clear_tx_pending(struct ieee80211_local *local) |
1812 | { | 1791 | { |
1813 | int i, j; | 1792 | struct sk_buff *skb; |
1814 | struct ieee80211_tx_stored_packet *store; | 1793 | int i; |
1815 | 1794 | ||
1816 | for (i = 0; i < local->hw.queues; i++) { | 1795 | for (i = 0; i < local->hw.queues; i++) { |
1817 | if (!test_bit(i, local->queues_pending)) | 1796 | if (!test_bit(i, local->queues_pending)) |
1818 | continue; | 1797 | continue; |
1819 | store = &local->pending_packet[i]; | 1798 | |
1820 | kfree_skb(store->skb); | 1799 | skb = local->pending_packet[i].skb; |
1821 | for (j = 0; j < store->num_extra_frag; j++) | 1800 | while (skb) { |
1822 | kfree_skb(store->extra_frag[j]); | 1801 | struct sk_buff *next; |
1823 | kfree(store->extra_frag); | 1802 | |
1803 | next = skb->next; | ||
1804 | dev_kfree_skb(skb); | ||
1805 | skb = next; | ||
1806 | } | ||
1824 | clear_bit(i, local->queues_pending); | 1807 | clear_bit(i, local->queues_pending); |
1825 | } | 1808 | } |
1826 | } | 1809 | } |
@@ -1854,14 +1837,11 @@ void ieee80211_tx_pending(unsigned long data) | |||
1854 | netif_start_subqueue(local->mdev, i); | 1837 | netif_start_subqueue(local->mdev, i); |
1855 | 1838 | ||
1856 | store = &local->pending_packet[i]; | 1839 | store = &local->pending_packet[i]; |
1857 | tx.extra_frag = store->extra_frag; | ||
1858 | tx.num_extra_frag = store->num_extra_frag; | ||
1859 | tx.flags = 0; | 1840 | tx.flags = 0; |
1860 | ret = __ieee80211_tx(local, store->skb, &tx); | 1841 | tx.skb = store->skb; |
1861 | if (ret) { | 1842 | ret = __ieee80211_tx(local, &tx); |
1862 | if (ret == IEEE80211_TX_FRAG_AGAIN) | 1843 | store->skb = tx.skb; |
1863 | store->skb = NULL; | 1844 | if (!ret) { |
1864 | } else { | ||
1865 | clear_bit(i, local->queues_pending); | 1845 | clear_bit(i, local->queues_pending); |
1866 | ieee80211_wake_queue(&local->hw, i); | 1846 | ieee80211_wake_queue(&local->hw, i); |
1867 | } | 1847 | } |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 444bb14c95e1..021166c8cce2 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -166,18 +166,13 @@ int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) | |||
166 | 166 | ||
167 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) | 167 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) |
168 | { | 168 | { |
169 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; | 169 | struct sk_buff *skb = tx->skb; |
170 | 170 | struct ieee80211_hdr *hdr; | |
171 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | 171 | |
172 | if (tx->extra_frag) { | 172 | do { |
173 | struct ieee80211_hdr *fhdr; | 173 | hdr = (struct ieee80211_hdr *) skb->data; |
174 | int i; | 174 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
175 | for (i = 0; i < tx->num_extra_frag; i++) { | 175 | } while ((skb = skb->next)); |
176 | fhdr = (struct ieee80211_hdr *) | ||
177 | tx->extra_frag[i]->data; | ||
178 | fhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | ||
179 | } | ||
180 | } | ||
181 | } | 176 | } |
182 | 177 | ||
183 | int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, | 178 | int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 7043ddc75498..ef73105b3061 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -329,24 +329,17 @@ static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
329 | ieee80211_tx_result | 329 | ieee80211_tx_result |
330 | ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx) | 330 | ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx) |
331 | { | 331 | { |
332 | int i; | 332 | struct sk_buff *skb; |
333 | 333 | ||
334 | ieee80211_tx_set_protected(tx); | 334 | ieee80211_tx_set_protected(tx); |
335 | 335 | ||
336 | if (wep_encrypt_skb(tx, tx->skb) < 0) { | 336 | skb = tx->skb; |
337 | I802_DEBUG_INC(tx->local->tx_handlers_drop_wep); | 337 | do { |
338 | return TX_DROP; | 338 | if (wep_encrypt_skb(tx, skb) < 0) { |
339 | } | 339 | I802_DEBUG_INC(tx->local->tx_handlers_drop_wep); |
340 | 340 | return TX_DROP; | |
341 | if (tx->extra_frag) { | ||
342 | for (i = 0; i < tx->num_extra_frag; i++) { | ||
343 | if (wep_encrypt_skb(tx, tx->extra_frag[i])) { | ||
344 | I802_DEBUG_INC(tx->local-> | ||
345 | tx_handlers_drop_wep); | ||
346 | return TX_DROP; | ||
347 | } | ||
348 | } | 341 | } |
349 | } | 342 | } while ((skb = skb->next)); |
350 | 343 | ||
351 | return TX_CONTINUE; | 344 | return TX_CONTINUE; |
352 | } | 345 | } |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 9101b48ec2ae..4f8bfea278f2 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -196,19 +196,13 @@ ieee80211_tx_result | |||
196 | ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx) | 196 | ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx) |
197 | { | 197 | { |
198 | struct sk_buff *skb = tx->skb; | 198 | struct sk_buff *skb = tx->skb; |
199 | int i; | ||
200 | 199 | ||
201 | ieee80211_tx_set_protected(tx); | 200 | ieee80211_tx_set_protected(tx); |
202 | 201 | ||
203 | if (tkip_encrypt_skb(tx, skb) < 0) | 202 | do { |
204 | return TX_DROP; | 203 | if (tkip_encrypt_skb(tx, skb) < 0) |
205 | 204 | return TX_DROP; | |
206 | if (tx->extra_frag) { | 205 | } while ((skb = skb->next)); |
207 | for (i = 0; i < tx->num_extra_frag; i++) { | ||
208 | if (tkip_encrypt_skb(tx, tx->extra_frag[i])) | ||
209 | return TX_DROP; | ||
210 | } | ||
211 | } | ||
212 | 206 | ||
213 | return TX_CONTINUE; | 207 | return TX_CONTINUE; |
214 | } | 208 | } |
@@ -428,19 +422,13 @@ ieee80211_tx_result | |||
428 | ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) | 422 | ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) |
429 | { | 423 | { |
430 | struct sk_buff *skb = tx->skb; | 424 | struct sk_buff *skb = tx->skb; |
431 | int i; | ||
432 | 425 | ||
433 | ieee80211_tx_set_protected(tx); | 426 | ieee80211_tx_set_protected(tx); |
434 | 427 | ||
435 | if (ccmp_encrypt_skb(tx, skb) < 0) | 428 | do { |
436 | return TX_DROP; | 429 | if (ccmp_encrypt_skb(tx, skb) < 0) |
437 | 430 | return TX_DROP; | |
438 | if (tx->extra_frag) { | 431 | } while ((skb = skb->next)); |
439 | for (i = 0; i < tx->num_extra_frag; i++) { | ||
440 | if (ccmp_encrypt_skb(tx, tx->extra_frag[i])) | ||
441 | return TX_DROP; | ||
442 | } | ||
443 | } | ||
444 | 432 | ||
445 | return TX_CONTINUE; | 433 | return TX_CONTINUE; |
446 | } | 434 | } |