aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/Kconfig13
-rw-r--r--net/mac80211/Makefile4
-rw-r--r--net/mac80211/key.c14
-rw-r--r--net/mac80211/main.c5
-rw-r--r--net/mac80211/mlme.c47
-rw-r--r--net/mac80211/rate.h14
-rw-r--r--net/mac80211/rc80211_minstrel.c583
-rw-r--r--net/mac80211/rc80211_minstrel.h85
-rw-r--r--net/mac80211/rc80211_minstrel_debugfs.c164
-rw-r--r--net/mac80211/tx.c36
-rw-r--r--net/mac80211/wep.c3
-rw-r--r--net/mac80211/wpa.c6
12 files changed, 938 insertions, 36 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 8427518e4f20..7f710a27e91c 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -22,6 +22,11 @@ config MAC80211_RC_PID
22 mac80211 that uses a PID controller to select the TX 22 mac80211 that uses a PID controller to select the TX
23 rate. 23 rate.
24 24
25config MAC80211_RC_MINSTREL
26 bool "Minstrel"
27 ---help---
28 This option enables the 'minstrel' TX rate control algorithm
29
25choice 30choice
26 prompt "Default rate control algorithm" 31 prompt "Default rate control algorithm"
27 default MAC80211_RC_DEFAULT_PID 32 default MAC80211_RC_DEFAULT_PID
@@ -39,11 +44,19 @@ config MAC80211_RC_DEFAULT_PID
39 default rate control algorithm. You should choose 44 default rate control algorithm. You should choose
40 this unless you know what you are doing. 45 this unless you know what you are doing.
41 46
47config MAC80211_RC_DEFAULT_MINSTREL
48 bool "Minstrel"
49 depends on MAC80211_RC_MINSTREL
50 ---help---
51 Select Minstrel as the default rate control algorithm.
52
53
42endchoice 54endchoice
43 55
44config MAC80211_RC_DEFAULT 56config MAC80211_RC_DEFAULT
45 string 57 string
46 default "pid" if MAC80211_RC_DEFAULT_PID 58 default "pid" if MAC80211_RC_DEFAULT_PID
59 default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL
47 default "" 60 default ""
48 61
49endmenu 62endmenu
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 2dc8f2bff27b..31cfd1f89a72 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -41,4 +41,8 @@ mac80211-$(CONFIG_MAC80211_MESH) += \
41rc80211_pid-y := rc80211_pid_algo.o 41rc80211_pid-y := rc80211_pid_algo.o
42rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o 42rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o
43 43
44rc80211_minstrel-y := rc80211_minstrel.o
45rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o
46
44mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc80211_pid-y) 47mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc80211_pid-y)
48mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y)
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 57afcd38cd9e..a5b06fe71980 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -281,6 +281,20 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
281 key->conf.alg = alg; 281 key->conf.alg = alg;
282 key->conf.keyidx = idx; 282 key->conf.keyidx = idx;
283 key->conf.keylen = key_len; 283 key->conf.keylen = key_len;
284 switch (alg) {
285 case ALG_WEP:
286 key->conf.iv_len = WEP_IV_LEN;
287 key->conf.icv_len = WEP_ICV_LEN;
288 break;
289 case ALG_TKIP:
290 key->conf.iv_len = TKIP_IV_LEN;
291 key->conf.icv_len = TKIP_ICV_LEN;
292 break;
293 case ALG_CCMP:
294 key->conf.iv_len = CCMP_HDR_LEN;
295 key->conf.icv_len = CCMP_MIC_LEN;
296 break;
297 }
284 memcpy(key->conf.key, key_data, key_len); 298 memcpy(key->conf.key, key_data, key_len);
285 INIT_LIST_HEAD(&key->list); 299 INIT_LIST_HEAD(&key->list);
286 INIT_LIST_HEAD(&key->todo); 300 INIT_LIST_HEAD(&key->todo);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index d608c44047c0..ae62ad40ad63 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1015,6 +1015,10 @@ static int __init ieee80211_init(void)
1015 BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) + 1015 BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) +
1016 IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb)); 1016 IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb));
1017 1017
1018 ret = rc80211_minstrel_init();
1019 if (ret)
1020 return ret;
1021
1018 ret = rc80211_pid_init(); 1022 ret = rc80211_pid_init();
1019 if (ret) 1023 if (ret)
1020 return ret; 1024 return ret;
@@ -1027,6 +1031,7 @@ static int __init ieee80211_init(void)
1027static void __exit ieee80211_exit(void) 1031static void __exit ieee80211_exit(void)
1028{ 1032{
1029 rc80211_pid_exit(); 1033 rc80211_pid_exit();
1034 rc80211_minstrel_exit();
1030 1035
1031 /* 1036 /*
1032 * For key todo, it'll be empty by now but the work 1037 * For key todo, it'll be empty by now but the work
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index e859a0ab6162..49f86fa56bff 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -650,20 +650,53 @@ static void ieee80211_sta_send_apinfo(struct ieee80211_sub_if_data *sdata,
650static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata, 650static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata,
651 struct ieee80211_if_sta *ifsta) 651 struct ieee80211_if_sta *ifsta)
652{ 652{
653 char *buf;
654 size_t len;
655 int i;
653 union iwreq_data wrqu; 656 union iwreq_data wrqu;
654 657
658 if (!ifsta->assocreq_ies && !ifsta->assocresp_ies)
659 return;
660
661 buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len +
662 ifsta->assocresp_ies_len), GFP_KERNEL);
663 if (!buf)
664 return;
665
666 len = sprintf(buf, "ASSOCINFO(");
655 if (ifsta->assocreq_ies) { 667 if (ifsta->assocreq_ies) {
656 memset(&wrqu, 0, sizeof(wrqu)); 668 len += sprintf(buf + len, "ReqIEs=");
657 wrqu.data.length = ifsta->assocreq_ies_len; 669 for (i = 0; i < ifsta->assocreq_ies_len; i++) {
658 wireless_send_event(sdata->dev, IWEVASSOCREQIE, &wrqu, 670 len += sprintf(buf + len, "%02x",
659 ifsta->assocreq_ies); 671 ifsta->assocreq_ies[i]);
672 }
660 } 673 }
661 if (ifsta->assocresp_ies) { 674 if (ifsta->assocresp_ies) {
675 if (ifsta->assocreq_ies)
676 len += sprintf(buf + len, " ");
677 len += sprintf(buf + len, "RespIEs=");
678 for (i = 0; i < ifsta->assocresp_ies_len; i++) {
679 len += sprintf(buf + len, "%02x",
680 ifsta->assocresp_ies[i]);
681 }
682 }
683 len += sprintf(buf + len, ")");
684
685 if (len > IW_CUSTOM_MAX) {
686 len = sprintf(buf, "ASSOCRESPIE=");
687 for (i = 0; i < ifsta->assocresp_ies_len; i++) {
688 len += sprintf(buf + len, "%02x",
689 ifsta->assocresp_ies[i]);
690 }
691 }
692
693 if (len <= IW_CUSTOM_MAX) {
662 memset(&wrqu, 0, sizeof(wrqu)); 694 memset(&wrqu, 0, sizeof(wrqu));
663 wrqu.data.length = ifsta->assocresp_ies_len; 695 wrqu.data.length = len;
664 wireless_send_event(sdata->dev, IWEVASSOCRESPIE, &wrqu, 696 wireless_send_event(sdata->dev, IWEVCUSTOM, &wrqu, buf);
665 ifsta->assocresp_ies);
666 } 697 }
698
699 kfree(buf);
667} 700}
668 701
669 702
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index eb94e584d24e..d0092f847f82 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -125,4 +125,18 @@ static inline void rc80211_pid_exit(void)
125} 125}
126#endif 126#endif
127 127
128#ifdef CONFIG_MAC80211_RC_MINSTREL
129extern int rc80211_minstrel_init(void);
130extern void rc80211_minstrel_exit(void);
131#else
132static inline int rc80211_minstrel_init(void)
133{
134 return 0;
135}
136static inline void rc80211_minstrel_exit(void)
137{
138}
139#endif
140
141
128#endif /* IEEE80211_RATE_H */ 142#endif /* IEEE80211_RATE_H */
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
new file mode 100644
index 000000000000..f6d69dab07a3
--- /dev/null
+++ b/net/mac80211/rc80211_minstrel.c
@@ -0,0 +1,583 @@
1/*
2 * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Based on minstrel.c:
9 * Copyright (C) 2005-2007 Derek Smithies <derek@indranet.co.nz>
10 * Sponsored by Indranet Technologies Ltd
11 *
12 * Based on sample.c:
13 * Copyright (c) 2005 John Bicket
14 * All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer,
21 * without modification.
22 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
23 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
24 * redistribution must be conditioned upon including a substantially
25 * similar Disclaimer requirement for further binary redistribution.
26 * 3. Neither the names of the above-listed copyright holders nor the names
27 * of any contributors may be used to endorse or promote products derived
28 * from this software without specific prior written permission.
29 *
30 * Alternatively, this software may be distributed under the terms of the
31 * GNU General Public License ("GPL") version 2 as published by the Free
32 * Software Foundation.
33 *
34 * NO WARRANTY
35 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
38 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
39 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
40 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
41 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
42 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
43 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
44 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
45 * THE POSSIBILITY OF SUCH DAMAGES.
46 */
47#include <linux/netdevice.h>
48#include <linux/types.h>
49#include <linux/skbuff.h>
50#include <linux/debugfs.h>
51#include <linux/random.h>
52#include <linux/ieee80211.h>
53#include <net/mac80211.h>
54#include "rate.h"
55#include "rc80211_minstrel.h"
56
57#define SAMPLE_COLUMNS 10
58#define SAMPLE_TBL(_mi, _idx, _col) \
59 _mi->sample_table[(_idx * SAMPLE_COLUMNS) + _col]
60
61/* convert mac80211 rate index to local array index */
62static inline int
63rix_to_ndx(struct minstrel_sta_info *mi, int rix)
64{
65 int i = rix;
66 for (i = rix; i >= 0; i--)
67 if (mi->r[i].rix == rix)
68 break;
69 WARN_ON(mi->r[i].rix != rix);
70 return i;
71}
72
73static inline bool
74use_low_rate(struct sk_buff *skb)
75{
76 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
77 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
78 u16 fc;
79
80 fc = le16_to_cpu(hdr->frame_control);
81
82 return ((info->flags & IEEE80211_TX_CTL_NO_ACK) ||
83 (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
84 is_multicast_ether_addr(hdr->addr1));
85}
86
87
88static void
89minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
90{
91 u32 max_tp = 0, index_max_tp = 0, index_max_tp2 = 0;
92 u32 max_prob = 0, index_max_prob = 0;
93 u32 usecs;
94 u32 p;
95 int i;
96
97 mi->stats_update = jiffies;
98 for (i = 0; i < mi->n_rates; i++) {
99 struct minstrel_rate *mr = &mi->r[i];
100
101 usecs = mr->perfect_tx_time;
102 if (!usecs)
103 usecs = 1000000;
104
105 /* To avoid rounding issues, probabilities scale from 0 (0%)
106 * to 18000 (100%) */
107 if (mr->attempts) {
108 p = (mr->success * 18000) / mr->attempts;
109 mr->succ_hist += mr->success;
110 mr->att_hist += mr->attempts;
111 mr->cur_prob = p;
112 p = ((p * (100 - mp->ewma_level)) + (mr->probability *
113 mp->ewma_level)) / 100;
114 mr->probability = p;
115 mr->cur_tp = p * (1000000 / usecs);
116 }
117
118 mr->last_success = mr->success;
119 mr->last_attempts = mr->attempts;
120 mr->success = 0;
121 mr->attempts = 0;
122
123 /* Sample less often below the 10% chance of success.
124 * Sample less often above the 95% chance of success. */
125 if ((mr->probability > 17100) || (mr->probability < 1800)) {
126 mr->adjusted_retry_count = mr->retry_count >> 1;
127 if (mr->adjusted_retry_count > 2)
128 mr->adjusted_retry_count = 2;
129 } else {
130 mr->adjusted_retry_count = mr->retry_count;
131 }
132 if (!mr->adjusted_retry_count)
133 mr->adjusted_retry_count = 2;
134 }
135
136 for (i = 0; i < mi->n_rates; i++) {
137 struct minstrel_rate *mr = &mi->r[i];
138 if (max_tp < mr->cur_tp) {
139 index_max_tp = i;
140 max_tp = mr->cur_tp;
141 }
142 if (max_prob < mr->probability) {
143 index_max_prob = i;
144 max_prob = mr->probability;
145 }
146 }
147
148 max_tp = 0;
149 for (i = 0; i < mi->n_rates; i++) {
150 struct minstrel_rate *mr = &mi->r[i];
151
152 if (i == index_max_tp)
153 continue;
154
155 if (max_tp < mr->cur_tp) {
156 index_max_tp2 = i;
157 max_tp = mr->cur_tp;
158 }
159 }
160 mi->max_tp_rate = index_max_tp;
161 mi->max_tp_rate2 = index_max_tp2;
162 mi->max_prob_rate = index_max_prob;
163}
164
165static void
166minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
167 struct ieee80211_sta *sta, void *priv_sta,
168 struct sk_buff *skb)
169{
170 struct minstrel_sta_info *mi = priv_sta;
171 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
172 struct ieee80211_tx_altrate *ar = info->status.retries;
173 struct minstrel_priv *mp = priv;
174 int i, ndx, tries;
175 int success = 0;
176
177 if (!info->status.excessive_retries)
178 success = 1;
179
180 if (!mp->has_mrr || (ar[0].rate_idx < 0)) {
181 ndx = rix_to_ndx(mi, info->tx_rate_idx);
182 tries = info->status.retry_count + 1;
183 mi->r[ndx].success += success;
184 mi->r[ndx].attempts += tries;
185 return;
186 }
187
188 for (i = 0; i < 4; i++) {
189 if (ar[i].rate_idx < 0)
190 break;
191
192 ndx = rix_to_ndx(mi, ar[i].rate_idx);
193 mi->r[ndx].attempts += ar[i].limit + 1;
194
195 if ((i != 3) && (ar[i + 1].rate_idx < 0))
196 mi->r[ndx].success += success;
197 }
198
199 if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0))
200 mi->sample_count++;
201
202 if (mi->sample_deferred > 0)
203 mi->sample_deferred--;
204}
205
206
207static inline unsigned int
208minstrel_get_retry_count(struct minstrel_rate *mr,
209 struct ieee80211_tx_info *info)
210{
211 unsigned int retry = mr->adjusted_retry_count;
212
213 if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
214 retry = max(2U, min(mr->retry_count_rtscts, retry));
215 else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
216 retry = max(2U, min(mr->retry_count_cts, retry));
217 return retry;
218}
219
220
221static int
222minstrel_get_next_sample(struct minstrel_sta_info *mi)
223{
224 unsigned int sample_ndx;
225 sample_ndx = SAMPLE_TBL(mi, mi->sample_idx, mi->sample_column);
226 mi->sample_idx++;
227 if (mi->sample_idx > (mi->n_rates - 2)) {
228 mi->sample_idx = 0;
229 mi->sample_column++;
230 if (mi->sample_column >= SAMPLE_COLUMNS)
231 mi->sample_column = 0;
232 }
233 return sample_ndx;
234}
235
236void
237minstrel_get_rate(void *priv, struct ieee80211_supported_band *sband,
238 struct ieee80211_sta *sta, void *priv_sta,
239 struct sk_buff *skb, struct rate_selection *sel)
240{
241 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
242 struct minstrel_sta_info *mi = priv_sta;
243 struct minstrel_priv *mp = priv;
244 struct ieee80211_tx_altrate *ar = info->control.retries;
245 unsigned int ndx, sample_ndx = 0;
246 bool mrr;
247 bool sample_slower = false;
248 bool sample = false;
249 int i, delta;
250 int mrr_ndx[3];
251 int sample_rate;
252
253 if (!sta || !mi || use_low_rate(skb)) {
254 sel->rate_idx = rate_lowest_index(sband, sta);
255 return;
256 }
257
258 mrr = mp->has_mrr;
259
260 /* mac80211 does not allow mrr for RTS/CTS */
261 if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) ||
262 (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT))
263 mrr = false;
264
265 if (time_after(jiffies, mi->stats_update + (mp->update_interval *
266 HZ) / 1000))
267 minstrel_update_stats(mp, mi);
268
269 ndx = mi->max_tp_rate;
270
271 if (mrr)
272 sample_rate = mp->lookaround_rate_mrr;
273 else
274 sample_rate = mp->lookaround_rate;
275
276 mi->packet_count++;
277 delta = (mi->packet_count * sample_rate / 100) -
278 (mi->sample_count + mi->sample_deferred / 2);
279
280 /* delta > 0: sampling required */
281 if (delta > 0) {
282 if (mi->packet_count >= 10000) {
283 mi->sample_deferred = 0;
284 mi->sample_count = 0;
285 mi->packet_count = 0;
286 } else if (delta > mi->n_rates * 2) {
287 /* With multi-rate retry, not every planned sample
288 * attempt actually gets used, due to the way the retry
289 * chain is set up - [max_tp,sample,prob,lowest] for
290 * sample_rate < max_tp.
291 *
292 * If there's too much sampling backlog and the link
293 * starts getting worse, minstrel would start bursting
294 * out lots of sampling frames, which would result
295 * in a large throughput loss. */
296 mi->sample_count += (delta - mi->n_rates * 2);
297 }
298
299 sample_ndx = minstrel_get_next_sample(mi);
300 sample = true;
301 sample_slower = mrr && (mi->r[sample_ndx].perfect_tx_time >
302 mi->r[ndx].perfect_tx_time);
303
304 if (!sample_slower) {
305 ndx = sample_ndx;
306 mi->sample_count++;
307 } else {
308 /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark
309 * packets that have the sampling rate deferred to the
310 * second MRR stage. Increase the sample counter only
311 * if the deferred sample rate was actually used.
312 * Use the sample_deferred counter to make sure that
313 * the sampling is not done in large bursts */
314 info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
315 mi->sample_deferred++;
316 }
317 }
318 sel->rate_idx = mi->r[ndx].rix;
319 info->control.retry_limit = minstrel_get_retry_count(&mi->r[ndx], info);
320
321 if (!mrr) {
322 ar[0].rate_idx = mi->lowest_rix;
323 ar[0].limit = mp->max_retry;
324 ar[1].rate_idx = -1;
325 return;
326 }
327
328 /* MRR setup */
329 if (sample) {
330 if (sample_slower)
331 mrr_ndx[0] = sample_ndx;
332 else
333 mrr_ndx[0] = mi->max_tp_rate;
334 } else {
335 mrr_ndx[0] = mi->max_tp_rate2;
336 }
337 mrr_ndx[1] = mi->max_prob_rate;
338 mrr_ndx[2] = 0;
339 for (i = 0; i < 3; i++) {
340 ar[i].rate_idx = mi->r[mrr_ndx[i]].rix;
341 ar[i].limit = mi->r[mrr_ndx[i]].adjusted_retry_count;
342 }
343}
344
345
346static void
347calc_rate_durations(struct minstrel_sta_info *mi, struct ieee80211_local *local,
348 struct minstrel_rate *d, struct ieee80211_rate *rate)
349{
350 int erp = !!(rate->flags & IEEE80211_RATE_ERP_G);
351
352 d->perfect_tx_time = ieee80211_frame_duration(local, 1200,
353 rate->bitrate, erp, 1);
354 d->ack_time = ieee80211_frame_duration(local, 10,
355 rate->bitrate, erp, 1);
356}
357
358static void
359init_sample_table(struct minstrel_sta_info *mi)
360{
361 unsigned int i, col, new_idx;
362 unsigned int n_srates = mi->n_rates - 1;
363 u8 rnd[8];
364
365 mi->sample_column = 0;
366 mi->sample_idx = 0;
367 memset(mi->sample_table, 0, SAMPLE_COLUMNS * mi->n_rates);
368
369 for (col = 0; col < SAMPLE_COLUMNS; col++) {
370 for (i = 0; i < n_srates; i++) {
371 get_random_bytes(rnd, sizeof(rnd));
372 new_idx = (i + rnd[i & 7]) % n_srates;
373
374 while (SAMPLE_TBL(mi, new_idx, col) != 0)
375 new_idx = (new_idx + 1) % n_srates;
376
377 /* Don't sample the slowest rate (i.e. slowest base
378 * rate). We must presume that the slowest rate works
379 * fine, or else other management frames will also be
380 * failing and the link will break */
381 SAMPLE_TBL(mi, new_idx, col) = i + 1;
382 }
383 }
384}
385
386static void
387minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
388 struct ieee80211_sta *sta, void *priv_sta)
389{
390 struct minstrel_sta_info *mi = priv_sta;
391 struct minstrel_priv *mp = priv;
392 struct minstrel_rate *mr_ctl;
393 unsigned int i, n = 0;
394 unsigned int t_slot = 9; /* FIXME: get real slot time */
395
396 mi->lowest_rix = rate_lowest_index(sband, sta);
397 mr_ctl = &mi->r[rix_to_ndx(mi, mi->lowest_rix)];
398 mi->sp_ack_dur = mr_ctl->ack_time;
399
400 for (i = 0; i < sband->n_bitrates; i++) {
401 struct minstrel_rate *mr = &mi->r[n];
402 unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0;
403 unsigned int tx_time_single;
404 unsigned int cw = mp->cw_min;
405
406 if (!rate_supported(sta, sband->band, i))
407 continue;
408 n++;
409 memset(mr, 0, sizeof(*mr));
410
411 mr->rix = i;
412 mr->bitrate = sband->bitrates[i].bitrate / 5;
413 calc_rate_durations(mi, hw_to_local(mp->hw), mr,
414 &sband->bitrates[i]);
415
416 /* calculate maximum number of retransmissions before
417 * fallback (based on maximum segment size) */
418 mr->retry_count = 1;
419 mr->retry_count_cts = 1;
420 mr->retry_count_rtscts = 1;
421 tx_time = mr->perfect_tx_time + mi->sp_ack_dur;
422 do {
423 /* add one retransmission */
424 tx_time_single = mr->ack_time + mr->perfect_tx_time;
425
426 /* contention window */
427 tx_time_single += t_slot + min(cw, mp->cw_max);
428 cw = (cw + 1) << 1;
429
430 tx_time += tx_time_single;
431 tx_time_cts += tx_time_single + mi->sp_ack_dur;
432 tx_time_rtscts += tx_time_single + 2 * mi->sp_ack_dur;
433 if ((tx_time_cts < mp->segment_size) &&
434 (mr->retry_count_cts < mp->max_retry))
435 mr->retry_count_cts++;
436 if ((tx_time_rtscts < mp->segment_size) &&
437 (mr->retry_count_rtscts < mp->max_retry))
438 mr->retry_count_rtscts++;
439 } while ((tx_time < mp->segment_size) &&
440 (++mr->retry_count < mp->max_retry));
441 mr->adjusted_retry_count = mr->retry_count;
442 }
443
444 for (i = n; i < sband->n_bitrates; i++) {
445 struct minstrel_rate *mr = &mi->r[i];
446 mr->rix = -1;
447 }
448
449 mi->n_rates = n;
450 mi->stats_update = jiffies;
451
452 init_sample_table(mi);
453}
454
455static void *
456minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
457{
458 struct ieee80211_supported_band *sband;
459 struct minstrel_sta_info *mi;
460 struct minstrel_priv *mp = priv;
461 struct ieee80211_hw *hw = mp->hw;
462 int max_rates = 0;
463 int i;
464
465 mi = kzalloc(sizeof(struct minstrel_sta_info), gfp);
466 if (!mi)
467 return NULL;
468
469 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
470 sband = hw->wiphy->bands[hw->conf.channel->band];
471 if (sband->n_bitrates > max_rates)
472 max_rates = sband->n_bitrates;
473 }
474
475 mi->r = kzalloc(sizeof(struct minstrel_rate) * max_rates, gfp);
476 if (!mi->r)
477 goto error;
478
479 mi->sample_table = kmalloc(SAMPLE_COLUMNS * max_rates, gfp);
480 if (!mi->sample_table)
481 goto error1;
482
483 mi->stats_update = jiffies;
484 return mi;
485
486error1:
487 kfree(mi->r);
488error:
489 kfree(mi);
490 return NULL;
491}
492
493static void
494minstrel_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta)
495{
496 struct minstrel_sta_info *mi = priv_sta;
497
498 kfree(mi->sample_table);
499 kfree(mi->r);
500 kfree(mi);
501}
502
503static void
504minstrel_clear(void *priv)
505{
506}
507
508static void *
509minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
510{
511 struct minstrel_priv *mp;
512
513 mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC);
514 if (!mp)
515 return NULL;
516
517 /* contention window settings
518 * Just an approximation. Using the per-queue values would complicate
519 * the calculations and is probably unnecessary */
520 mp->cw_min = 15;
521 mp->cw_max = 1023;
522
523 /* number of packets (in %) to use for sampling other rates
524 * sample less often for non-mrr packets, because the overhead
525 * is much higher than with mrr */
526 mp->lookaround_rate = 5;
527 mp->lookaround_rate_mrr = 10;
528
529 /* moving average weight for EWMA */
530 mp->ewma_level = 75;
531
532 /* maximum time that the hw is allowed to stay in one MRR segment */
533 mp->segment_size = 6000;
534
535 if (hw->max_altrate_tries > 0)
536 mp->max_retry = hw->max_altrate_tries;
537 else
538 /* safe default, does not necessarily have to match hw properties */
539 mp->max_retry = 7;
540
541 if (hw->max_altrates >= 3)
542 mp->has_mrr = true;
543
544 mp->hw = hw;
545 mp->update_interval = 100;
546
547 return mp;
548}
549
550static void
551minstrel_free(void *priv)
552{
553 kfree(priv);
554}
555
556static struct rate_control_ops mac80211_minstrel = {
557 .name = "minstrel",
558 .tx_status = minstrel_tx_status,
559 .get_rate = minstrel_get_rate,
560 .rate_init = minstrel_rate_init,
561 .clear = minstrel_clear,
562 .alloc = minstrel_alloc,
563 .free = minstrel_free,
564 .alloc_sta = minstrel_alloc_sta,
565 .free_sta = minstrel_free_sta,
566#ifdef CONFIG_MAC80211_DEBUGFS
567 .add_sta_debugfs = minstrel_add_sta_debugfs,
568 .remove_sta_debugfs = minstrel_remove_sta_debugfs,
569#endif
570};
571
572int __init
573rc80211_minstrel_init(void)
574{
575 return ieee80211_rate_control_register(&mac80211_minstrel);
576}
577
578void
579rc80211_minstrel_exit(void)
580{
581 ieee80211_rate_control_unregister(&mac80211_minstrel);
582}
583
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
new file mode 100644
index 000000000000..9a90a6aee043
--- /dev/null
+++ b/net/mac80211/rc80211_minstrel.h
@@ -0,0 +1,85 @@
1/*
2 * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef __RC_MINSTREL_H
10#define __RC_MINSTREL_H
11
12struct minstrel_rate {
13 int bitrate;
14 int rix;
15
16 unsigned int perfect_tx_time;
17 unsigned int ack_time;
18
19 unsigned int retry_count;
20 unsigned int retry_count_cts;
21 unsigned int retry_count_rtscts;
22 unsigned int adjusted_retry_count;
23
24 u32 success;
25 u32 attempts;
26 u32 last_attempts;
27 u32 last_success;
28
29 /* parts per thousand */
30 u32 cur_prob;
31 u32 probability;
32
33 /* per-rate throughput */
34 u32 cur_tp;
35 u32 throughput;
36
37 u64 succ_hist;
38 u64 att_hist;
39};
40
41struct minstrel_sta_info {
42 unsigned long stats_update;
43 unsigned int sp_ack_dur;
44 unsigned int rate_avg;
45
46 unsigned int lowest_rix;
47
48 unsigned int max_tp_rate;
49 unsigned int max_tp_rate2;
50 unsigned int max_prob_rate;
51 unsigned int packet_count;
52 unsigned int sample_count;
53 int sample_deferred;
54
55 unsigned int sample_idx;
56 unsigned int sample_column;
57
58 int n_rates;
59 struct minstrel_rate *r;
60
61 /* sampling table */
62 u8 *sample_table;
63
64#ifdef CONFIG_MAC80211_DEBUGFS
65 struct dentry *dbg_stats;
66#endif
67};
68
69struct minstrel_priv {
70 struct ieee80211_hw *hw;
71 bool has_mrr;
72 unsigned int cw_min;
73 unsigned int cw_max;
74 unsigned int max_retry;
75 unsigned int ewma_level;
76 unsigned int segment_size;
77 unsigned int update_interval;
78 unsigned int lookaround_rate;
79 unsigned int lookaround_rate_mrr;
80};
81
82void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
83void minstrel_remove_sta_debugfs(void *priv, void *priv_sta);
84
85#endif
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
new file mode 100644
index 000000000000..0b024cd6b809
--- /dev/null
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -0,0 +1,164 @@
1/*
2 * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Based on minstrel.c:
9 * Copyright (C) 2005-2007 Derek Smithies <derek@indranet.co.nz>
10 * Sponsored by Indranet Technologies Ltd
11 *
12 * Based on sample.c:
13 * Copyright (c) 2005 John Bicket
14 * All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer,
21 * without modification.
22 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
23 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
24 * redistribution must be conditioned upon including a substantially
25 * similar Disclaimer requirement for further binary redistribution.
26 * 3. Neither the names of the above-listed copyright holders nor the names
27 * of any contributors may be used to endorse or promote products derived
28 * from this software without specific prior written permission.
29 *
30 * Alternatively, this software may be distributed under the terms of the
31 * GNU General Public License ("GPL") version 2 as published by the Free
32 * Software Foundation.
33 *
34 * NO WARRANTY
35 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
38 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
39 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
40 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
41 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
42 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
43 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
44 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
45 * THE POSSIBILITY OF SUCH DAMAGES.
46 */
47#include <linux/netdevice.h>
48#include <linux/types.h>
49#include <linux/skbuff.h>
50#include <linux/debugfs.h>
51#include <linux/ieee80211.h>
52#include <net/mac80211.h>
53#include "rc80211_minstrel.h"
54
55struct minstrel_stats_info {
56 struct minstrel_sta_info *mi;
57 char buf[4096];
58 size_t len;
59};
60
61static int
62minstrel_stats_open(struct inode *inode, struct file *file)
63{
64 struct minstrel_sta_info *mi = inode->i_private;
65 struct minstrel_stats_info *ms;
66 unsigned int i, tp, prob, eprob;
67 char *p;
68
69 ms = kmalloc(sizeof(*ms), GFP_KERNEL);
70 if (!ms)
71 return -ENOMEM;
72
73 file->private_data = ms;
74 p = ms->buf;
75 p += sprintf(p, "rate throughput ewma prob this prob "
76 "this succ/attempt success attempts\n");
77 for (i = 0; i < mi->n_rates; i++) {
78 struct minstrel_rate *mr = &mi->r[i];
79
80 *(p++) = (i == mi->max_tp_rate) ? 'T' : ' ';
81 *(p++) = (i == mi->max_tp_rate2) ? 't' : ' ';
82 *(p++) = (i == mi->max_prob_rate) ? 'P' : ' ';
83 p += sprintf(p, "%3u%s", mr->bitrate / 2,
84 (mr->bitrate & 1 ? ".5" : " "));
85
86 tp = ((mr->cur_tp * 96) / 18000) >> 10;
87 prob = mr->cur_prob / 18;
88 eprob = mr->probability / 18;
89
90 p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u "
91 "%3u(%3u) %8llu %8llu\n",
92 tp / 10, tp % 10,
93 eprob / 10, eprob % 10,
94 prob / 10, prob % 10,
95 mr->last_success,
96 mr->last_attempts,
97 mr->succ_hist,
98 mr->att_hist);
99 }
100 p += sprintf(p, "\nTotal packet count:: ideal %d "
101 "lookaround %d\n\n",
102 mi->packet_count - mi->sample_count,
103 mi->sample_count);
104 ms->len = p - ms->buf;
105
106 return 0;
107}
108
109static int
110minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *o)
111{
112 struct minstrel_stats_info *ms;
113 char *src;
114
115 ms = file->private_data;
116 src = ms->buf;
117
118 len = min(len, ms->len);
119 if (len <= *o)
120 return 0;
121
122 src += *o;
123 len -= *o;
124 *o += len;
125
126 if (copy_to_user(buf, src, len))
127 return -EFAULT;
128
129 return len;
130}
131
132static int
133minstrel_stats_release(struct inode *inode, struct file *file)
134{
135 struct minstrel_stats_info *ms = file->private_data;
136
137 kfree(ms);
138
139 return 0;
140}
141
142static struct file_operations minstrel_stat_fops = {
143 .owner = THIS_MODULE,
144 .open = minstrel_stats_open,
145 .read = minstrel_stats_read,
146 .release = minstrel_stats_release,
147};
148
149void
150minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir)
151{
152 struct minstrel_sta_info *mi = priv_sta;
153
154 mi->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, mi,
155 &minstrel_stat_fops);
156}
157
158void
159minstrel_remove_sta_debugfs(void *priv, void *priv_sta)
160{
161 struct minstrel_sta_info *mi = priv_sta;
162
163 debugfs_remove(mi->dbg_stats);
164}
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 0cc2e23f082c..1460537faf33 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -454,15 +454,16 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
454 if (unlikely(rsel.probe_idx >= 0)) { 454 if (unlikely(rsel.probe_idx >= 0)) {
455 info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; 455 info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
456 tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG; 456 tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
457 info->control.alt_retry_rate_idx = tx->rate_idx; 457 info->control.retries[0].rate_idx = tx->rate_idx;
458 info->control.retries[0].limit = tx->local->hw.max_altrate_tries;
458 tx->rate_idx = rsel.probe_idx; 459 tx->rate_idx = rsel.probe_idx;
459 } else 460 } else if (info->control.retries[0].limit == 0)
460 info->control.alt_retry_rate_idx = -1; 461 info->control.retries[0].rate_idx = -1;
461 462
462 if (unlikely(tx->rate_idx < 0)) 463 if (unlikely(tx->rate_idx < 0))
463 return TX_DROP; 464 return TX_DROP;
464 } else 465 } else
465 info->control.alt_retry_rate_idx = -1; 466 info->control.retries[0].rate_idx = -1;
466 467
467 if (tx->sdata->bss_conf.use_cts_prot && 468 if (tx->sdata->bss_conf.use_cts_prot &&
468 (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) { 469 (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) {
@@ -521,7 +522,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
521 * frames. 522 * frames.
522 * TODO: The last fragment could still use multiple retry 523 * TODO: The last fragment could still use multiple retry
523 * rates. */ 524 * rates. */
524 info->control.alt_retry_rate_idx = -1; 525 info->control.retries[0].rate_idx = -1;
525 } 526 }
526 527
527 /* Use CTS protection for unicast frames sent using extended rates if 528 /* Use CTS protection for unicast frames sent using extended rates if
@@ -551,7 +552,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
551 int idx; 552 int idx;
552 553
553 /* Do not use multiple retry rates when using RTS/CTS */ 554 /* Do not use multiple retry rates when using RTS/CTS */
554 info->control.alt_retry_rate_idx = -1; 555 info->control.retries[0].rate_idx = -1;
555 556
556 /* Use min(data rate, max base rate) as CTS/RTS rate */ 557 /* Use min(data rate, max base rate) as CTS/RTS rate */
557 rate = &sband->bitrates[tx->rate_idx]; 558 rate = &sband->bitrates[tx->rate_idx];
@@ -1255,8 +1256,7 @@ static int ieee80211_skb_resize(struct ieee80211_local *local,
1255 return 0; 1256 return 0;
1256} 1257}
1257 1258
1258int ieee80211_master_start_xmit(struct sk_buff *skb, 1259int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
1259 struct net_device *dev)
1260{ 1260{
1261 struct ieee80211_master_priv *mpriv = netdev_priv(dev); 1261 struct ieee80211_master_priv *mpriv = netdev_priv(dev);
1262 struct ieee80211_local *local = mpriv->local; 1262 struct ieee80211_local *local = mpriv->local;
@@ -1296,20 +1296,16 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
1296 1296
1297 if (ieee80211_vif_is_mesh(&osdata->vif) && 1297 if (ieee80211_vif_is_mesh(&osdata->vif) &&
1298 ieee80211_is_data(hdr->frame_control)) { 1298 ieee80211_is_data(hdr->frame_control)) {
1299 if (ieee80211_is_data(hdr->frame_control)) { 1299 if (is_multicast_ether_addr(hdr->addr3))
1300 if (is_multicast_ether_addr(hdr->addr3)) 1300 memcpy(hdr->addr1, hdr->addr3, ETH_ALEN);
1301 memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); 1301 else
1302 else 1302 if (mesh_nexthop_lookup(skb, osdata))
1303 if (mesh_nexthop_lookup(skb, osdata)) 1303 return 0;
1304 return 0; 1304 if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0)
1305 if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) 1305 IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh,
1306 IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, 1306 fwded_frames);
1307 fwded_frames);
1308 }
1309 } else if (unlikely(osdata->vif.type == NL80211_IFTYPE_MONITOR)) { 1307 } else if (unlikely(osdata->vif.type == NL80211_IFTYPE_MONITOR)) {
1310 struct ieee80211_sub_if_data *sdata; 1308 struct ieee80211_sub_if_data *sdata;
1311 struct ieee80211_local *local = osdata->local;
1312 struct ieee80211_hdr *hdr;
1313 int hdrlen; 1309 int hdrlen;
1314 u16 len_rthdr; 1310 u16 len_rthdr;
1315 1311
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index 376c84987e4f..f0e2d3ecb5c4 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -313,9 +313,6 @@ static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
313{ 313{
314 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 314 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
315 315
316 info->control.iv_len = WEP_IV_LEN;
317 info->control.icv_len = WEP_ICV_LEN;
318
319 if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { 316 if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
320 if (ieee80211_wep_encrypt(tx->local, skb, tx->key)) 317 if (ieee80211_wep_encrypt(tx->local, skb, tx->key))
321 return -1; 318 return -1;
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 37ae9a959f63..6db649480e8f 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -152,9 +152,6 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
152 int len, tail; 152 int len, tail;
153 u8 *pos; 153 u8 *pos;
154 154
155 info->control.icv_len = TKIP_ICV_LEN;
156 info->control.iv_len = TKIP_IV_LEN;
157
158 if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && 155 if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
159 !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { 156 !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
160 /* hwaccel - with no need for preallocated room for IV/ICV */ 157 /* hwaccel - with no need for preallocated room for IV/ICV */
@@ -374,9 +371,6 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
374 u8 *pos, *pn; 371 u8 *pos, *pn;
375 int i; 372 int i;
376 373
377 info->control.icv_len = CCMP_MIC_LEN;
378 info->control.iv_len = CCMP_HDR_LEN;
379
380 if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && 374 if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
381 !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { 375 !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
382 /* hwaccel - with no need for preallocated room for CCMP " 376 /* hwaccel - with no need for preallocated room for CCMP "