aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2010-10-16 12:19:53 -0400
committerLuciano Coelho <coelho@ti.com>2011-01-24 15:11:48 -0500
commite0fe371b74326a85029fe8720506e021fe73905a (patch)
tree0eb9864739ae8c876560598aefb410e7c7bec3e6
parent05285cf9b581af05813cfaa60e23227b009b7754 (diff)
wl12xx: AP mode - init sequence
Split HW init sequence into AP/STA specific parts The AP specific init sequence includes configuration of templates, rate classes, power mode, etc. Also unmask AP specific events in the event mbox. Separate the differences between AP and STA init into mode specific functions called from wl1271_hw_init. The first is called after radio configuration and the second after memory configuration. Signed-off-by: Arik Nemtsov <arik@wizery.com> Reviewed-by: Luciano Coelho <coelho@ti.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
-rw-r--r--drivers/net/wireless/wl12xx/cmd.h7
-rw-r--r--drivers/net/wireless/wl12xx/init.c352
-rw-r--r--drivers/net/wireless/wl12xx/init.h2
-rw-r--r--drivers/net/wireless/wl12xx/main.c32
-rw-r--r--drivers/net/wireless/wl12xx/tx.c18
-rw-r--r--drivers/net/wireless/wl12xx/tx.h1
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx_80211.h5
7 files changed, 317 insertions, 100 deletions
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 072bf3c2f24..c9909e09cd9 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -140,6 +140,13 @@ enum cmd_templ {
140 * For CTS-to-self (FastCTS) mechanism 140 * For CTS-to-self (FastCTS) mechanism
141 * for BT/WLAN coexistence (SoftGemini). */ 141 * for BT/WLAN coexistence (SoftGemini). */
142 CMD_TEMPL_ARP_RSP, 142 CMD_TEMPL_ARP_RSP,
143
144 /* AP-mode specific */
145 CMD_TEMPL_AP_BEACON = 13,
146 CMD_TEMPL_AP_PROBE_RESPONSE,
147 CMD_TEMPL_AP_ARP_RSP,
148 CMD_TEMPL_DEAUTH_AP,
149
143 CMD_TEMPL_MAX = 0xff 150 CMD_TEMPL_MAX = 0xff
144}; 151};
145 152
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 799c3691473..bdb61232f80 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -30,27 +30,9 @@
30#include "acx.h" 30#include "acx.h"
31#include "cmd.h" 31#include "cmd.h"
32#include "reg.h" 32#include "reg.h"
33#include "tx.h"
33 34
34static int wl1271_init_hwenc_config(struct wl1271 *wl) 35int wl1271_sta_init_templates_config(struct wl1271 *wl)
35{
36 int ret;
37
38 ret = wl1271_acx_feature_cfg(wl);
39 if (ret < 0) {
40 wl1271_warning("couldn't set feature config");
41 return ret;
42 }
43
44 ret = wl1271_cmd_set_sta_default_wep_key(wl, wl->default_key);
45 if (ret < 0) {
46 wl1271_warning("couldn't set default key");
47 return ret;
48 }
49
50 return 0;
51}
52
53int wl1271_init_templates_config(struct wl1271 *wl)
54{ 36{
55 int ret, i; 37 int ret, i;
56 38
@@ -118,6 +100,132 @@ int wl1271_init_templates_config(struct wl1271 *wl)
118 return 0; 100 return 0;
119} 101}
120 102
103static int wl1271_ap_init_deauth_template(struct wl1271 *wl)
104{
105 struct wl12xx_disconn_template *tmpl;
106 int ret;
107
108 tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
109 if (!tmpl) {
110 ret = -ENOMEM;
111 goto out;
112 }
113
114 tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
115 IEEE80211_STYPE_DEAUTH);
116
117 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP,
118 tmpl, sizeof(*tmpl), 0,
119 wl1271_tx_min_rate_get(wl));
120
121out:
122 kfree(tmpl);
123 return ret;
124}
125
126static int wl1271_ap_init_null_template(struct wl1271 *wl)
127{
128 struct ieee80211_hdr_3addr *nullfunc;
129 int ret;
130
131 nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL);
132 if (!nullfunc) {
133 ret = -ENOMEM;
134 goto out;
135 }
136
137 nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
138 IEEE80211_STYPE_NULLFUNC |
139 IEEE80211_FCTL_FROMDS);
140
141 /* nullfunc->addr1 is filled by FW */
142
143 memcpy(nullfunc->addr2, wl->mac_addr, ETH_ALEN);
144 memcpy(nullfunc->addr3, wl->mac_addr, ETH_ALEN);
145
146 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc,
147 sizeof(*nullfunc), 0,
148 wl1271_tx_min_rate_get(wl));
149
150out:
151 kfree(nullfunc);
152 return ret;
153}
154
155static int wl1271_ap_init_qos_null_template(struct wl1271 *wl)
156{
157 struct ieee80211_qos_hdr *qosnull;
158 int ret;
159
160 qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL);
161 if (!qosnull) {
162 ret = -ENOMEM;
163 goto out;
164 }
165
166 qosnull->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
167 IEEE80211_STYPE_QOS_NULLFUNC |
168 IEEE80211_FCTL_FROMDS);
169
170 /* qosnull->addr1 is filled by FW */
171
172 memcpy(qosnull->addr2, wl->mac_addr, ETH_ALEN);
173 memcpy(qosnull->addr3, wl->mac_addr, ETH_ALEN);
174
175 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull,
176 sizeof(*qosnull), 0,
177 wl1271_tx_min_rate_get(wl));
178
179out:
180 kfree(qosnull);
181 return ret;
182}
183
184static int wl1271_ap_init_templates_config(struct wl1271 *wl)
185{
186 int ret;
187
188 /*
189 * Put very large empty placeholders for all templates. These
190 * reserve memory for later.
191 */
192 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL,
193 sizeof
194 (struct wl12xx_probe_resp_template),
195 0, WL1271_RATE_AUTOMATIC);
196 if (ret < 0)
197 return ret;
198
199 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL,
200 sizeof
201 (struct wl12xx_beacon_template),
202 0, WL1271_RATE_AUTOMATIC);
203 if (ret < 0)
204 return ret;
205
206 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, NULL,
207 sizeof
208 (struct wl12xx_disconn_template),
209 0, WL1271_RATE_AUTOMATIC);
210 if (ret < 0)
211 return ret;
212
213 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
214 sizeof(struct wl12xx_null_data_template),
215 0, WL1271_RATE_AUTOMATIC);
216 if (ret < 0)
217 return ret;
218
219 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL,
220 sizeof
221 (struct wl12xx_qos_null_data_template),
222 0, WL1271_RATE_AUTOMATIC);
223 if (ret < 0)
224 return ret;
225
226 return 0;
227}
228
121static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter) 229static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
122{ 230{
123 int ret; 231 int ret;
@@ -145,10 +253,6 @@ int wl1271_init_phy_config(struct wl1271 *wl)
145 if (ret < 0) 253 if (ret < 0)
146 return ret; 254 return ret;
147 255
148 ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0);
149 if (ret < 0)
150 return ret;
151
152 ret = wl1271_acx_service_period_timeout(wl); 256 ret = wl1271_acx_service_period_timeout(wl);
153 if (ret < 0) 257 if (ret < 0)
154 return ret; 258 return ret;
@@ -213,11 +317,150 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
213 return 0; 317 return 0;
214} 318}
215 319
320static int wl1271_sta_hw_init(struct wl1271 *wl)
321{
322 int ret;
323
324 ret = wl1271_cmd_ext_radio_parms(wl);
325 if (ret < 0)
326 return ret;
327
328 ret = wl1271_sta_init_templates_config(wl);
329 if (ret < 0)
330 return ret;
331
332 ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0);
333 if (ret < 0)
334 return ret;
335
336 /* Initialize connection monitoring thresholds */
337 ret = wl1271_acx_conn_monit_params(wl, false);
338 if (ret < 0)
339 return ret;
340
341 /* Beacon filtering */
342 ret = wl1271_init_beacon_filter(wl);
343 if (ret < 0)
344 return ret;
345
346 /* Bluetooth WLAN coexistence */
347 ret = wl1271_init_pta(wl);
348 if (ret < 0)
349 return ret;
350
351 /* Beacons and broadcast settings */
352 ret = wl1271_init_beacon_broadcast(wl);
353 if (ret < 0)
354 return ret;
355
356 /* Configure for ELP power saving */
357 ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
358 if (ret < 0)
359 return ret;
360
361 /* Configure rssi/snr averaging weights */
362 ret = wl1271_acx_rssi_snr_avg_weights(wl);
363 if (ret < 0)
364 return ret;
365
366 ret = wl1271_acx_sta_rate_policies(wl);
367 if (ret < 0)
368 return ret;
369
370 return 0;
371}
372
373static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl)
374{
375 int ret, i;
376
377 ret = wl1271_cmd_set_sta_default_wep_key(wl, wl->default_key);
378 if (ret < 0) {
379 wl1271_warning("couldn't set default key");
380 return ret;
381 }
382
383 /* disable all keep-alive templates */
384 for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
385 ret = wl1271_acx_keep_alive_config(wl, i,
386 ACX_KEEP_ALIVE_TPL_INVALID);
387 if (ret < 0)
388 return ret;
389 }
390
391 /* disable the keep-alive feature */
392 ret = wl1271_acx_keep_alive_mode(wl, false);
393 if (ret < 0)
394 return ret;
395
396 return 0;
397}
398
399static int wl1271_ap_hw_init(struct wl1271 *wl)
400{
401 int ret, i;
402
403 ret = wl1271_ap_init_templates_config(wl);
404 if (ret < 0)
405 return ret;
406
407 /* Configure for power always on */
408 ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
409 if (ret < 0)
410 return ret;
411
412 /* Configure initial TX rate classes */
413 for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
414 ret = wl1271_acx_ap_rate_policy(wl,
415 &wl->conf.tx.ap_rc_conf[i], i);
416 if (ret < 0)
417 return ret;
418 }
419
420 ret = wl1271_acx_ap_rate_policy(wl,
421 &wl->conf.tx.ap_mgmt_conf,
422 ACX_TX_AP_MODE_MGMT_RATE);
423 if (ret < 0)
424 return ret;
425
426 ret = wl1271_acx_ap_rate_policy(wl,
427 &wl->conf.tx.ap_bcst_conf,
428 ACX_TX_AP_MODE_BCST_RATE);
429 if (ret < 0)
430 return ret;
431
432 ret = wl1271_acx_max_tx_retry(wl);
433 if (ret < 0)
434 return ret;
435
436 return 0;
437}
438
439static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl)
440{
441 int ret;
442
443 ret = wl1271_ap_init_deauth_template(wl);
444 if (ret < 0)
445 return ret;
446
447 ret = wl1271_ap_init_null_template(wl);
448 if (ret < 0)
449 return ret;
450
451 ret = wl1271_ap_init_qos_null_template(wl);
452 if (ret < 0)
453 return ret;
454
455 return 0;
456}
457
216int wl1271_hw_init(struct wl1271 *wl) 458int wl1271_hw_init(struct wl1271 *wl)
217{ 459{
218 struct conf_tx_ac_category *conf_ac; 460 struct conf_tx_ac_category *conf_ac;
219 struct conf_tx_tid *conf_tid; 461 struct conf_tx_tid *conf_tid;
220 int ret, i; 462 int ret, i;
463 bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
221 464
222 ret = wl1271_cmd_general_parms(wl); 465 ret = wl1271_cmd_general_parms(wl);
223 if (ret < 0) 466 if (ret < 0)
@@ -227,12 +470,12 @@ int wl1271_hw_init(struct wl1271 *wl)
227 if (ret < 0) 470 if (ret < 0)
228 return ret; 471 return ret;
229 472
230 ret = wl1271_cmd_ext_radio_parms(wl); 473 /* Mode specific init */
231 if (ret < 0) 474 if (is_ap)
232 return ret; 475 ret = wl1271_ap_hw_init(wl);
476 else
477 ret = wl1271_sta_hw_init(wl);
233 478
234 /* Template settings */
235 ret = wl1271_init_templates_config(wl);
236 if (ret < 0) 479 if (ret < 0)
237 return ret; 480 return ret;
238 481
@@ -259,16 +502,6 @@ int wl1271_hw_init(struct wl1271 *wl)
259 if (ret < 0) 502 if (ret < 0)
260 goto out_free_memmap; 503 goto out_free_memmap;
261 504
262 /* Initialize connection monitoring thresholds */
263 ret = wl1271_acx_conn_monit_params(wl, false);
264 if (ret < 0)
265 goto out_free_memmap;
266
267 /* Beacon filtering */
268 ret = wl1271_init_beacon_filter(wl);
269 if (ret < 0)
270 goto out_free_memmap;
271
272 /* Configure TX patch complete interrupt behavior */ 505 /* Configure TX patch complete interrupt behavior */
273 ret = wl1271_acx_tx_config_options(wl); 506 ret = wl1271_acx_tx_config_options(wl);
274 if (ret < 0) 507 if (ret < 0)
@@ -279,21 +512,11 @@ int wl1271_hw_init(struct wl1271 *wl)
279 if (ret < 0) 512 if (ret < 0)
280 goto out_free_memmap; 513 goto out_free_memmap;
281 514
282 /* Bluetooth WLAN coexistence */
283 ret = wl1271_init_pta(wl);
284 if (ret < 0)
285 goto out_free_memmap;
286
287 /* Energy detection */ 515 /* Energy detection */
288 ret = wl1271_init_energy_detection(wl); 516 ret = wl1271_init_energy_detection(wl);
289 if (ret < 0) 517 if (ret < 0)
290 goto out_free_memmap; 518 goto out_free_memmap;
291 519
292 /* Beacons and boradcast settings */
293 ret = wl1271_init_beacon_broadcast(wl);
294 if (ret < 0)
295 goto out_free_memmap;
296
297 /* Default fragmentation threshold */ 520 /* Default fragmentation threshold */
298 ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold); 521 ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold);
299 if (ret < 0) 522 if (ret < 0)
@@ -321,23 +544,13 @@ int wl1271_hw_init(struct wl1271 *wl)
321 goto out_free_memmap; 544 goto out_free_memmap;
322 } 545 }
323 546
324 /* Configure TX rate classes */
325 ret = wl1271_acx_sta_rate_policies(wl);
326 if (ret < 0)
327 goto out_free_memmap;
328
329 /* Enable data path */ 547 /* Enable data path */
330 ret = wl1271_cmd_data_path(wl, 1); 548 ret = wl1271_cmd_data_path(wl, 1);
331 if (ret < 0) 549 if (ret < 0)
332 goto out_free_memmap; 550 goto out_free_memmap;
333 551
334 /* Configure for ELP power saving */
335 ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
336 if (ret < 0)
337 goto out_free_memmap;
338
339 /* Configure HW encryption */ 552 /* Configure HW encryption */
340 ret = wl1271_init_hwenc_config(wl); 553 ret = wl1271_acx_feature_cfg(wl);
341 if (ret < 0) 554 if (ret < 0)
342 goto out_free_memmap; 555 goto out_free_memmap;
343 556
@@ -346,21 +559,12 @@ int wl1271_hw_init(struct wl1271 *wl)
346 if (ret < 0) 559 if (ret < 0)
347 goto out_free_memmap; 560 goto out_free_memmap;
348 561
349 /* disable all keep-alive templates */ 562 /* Mode specific init - post mem init */
350 for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { 563 if (is_ap)
351 ret = wl1271_acx_keep_alive_config(wl, i, 564 ret = wl1271_ap_hw_init_post_mem(wl);
352 ACX_KEEP_ALIVE_TPL_INVALID); 565 else
353 if (ret < 0) 566 ret = wl1271_sta_hw_init_post_mem(wl);
354 goto out_free_memmap;
355 }
356 567
357 /* disable the keep-alive feature */
358 ret = wl1271_acx_keep_alive_mode(wl, false);
359 if (ret < 0)
360 goto out_free_memmap;
361
362 /* Configure rssi/snr averaging weights */
363 ret = wl1271_acx_rssi_snr_avg_weights(wl);
364 if (ret < 0) 568 if (ret < 0)
365 goto out_free_memmap; 569 goto out_free_memmap;
366 570
diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/init.h
index 7762421f860..3a8bd3f426d 100644
--- a/drivers/net/wireless/wl12xx/init.h
+++ b/drivers/net/wireless/wl12xx/init.h
@@ -27,7 +27,7 @@
27#include "wl12xx.h" 27#include "wl12xx.h"
28 28
29int wl1271_hw_init_power_auth(struct wl1271 *wl); 29int wl1271_hw_init_power_auth(struct wl1271 *wl);
30int wl1271_init_templates_config(struct wl1271 *wl); 30int wl1271_sta_init_templates_config(struct wl1271 *wl);
31int wl1271_init_phy_config(struct wl1271 *wl); 31int wl1271_init_phy_config(struct wl1271 *wl);
32int wl1271_init_pta(struct wl1271 *wl); 32int wl1271_init_pta(struct wl1271 *wl);
33int wl1271_init_energy_detection(struct wl1271 *wl); 33int wl1271_init_energy_detection(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 9785b4c43c8..67f6db4354f 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -434,7 +434,7 @@ static int wl1271_plt_init(struct wl1271 *wl)
434 if (ret < 0) 434 if (ret < 0)
435 return ret; 435 return ret;
436 436
437 ret = wl1271_init_templates_config(wl); 437 ret = wl1271_sta_init_templates_config(wl);
438 if (ret < 0) 438 if (ret < 0)
439 return ret; 439 return ret;
440 440
@@ -1363,24 +1363,6 @@ static void wl1271_set_band_rate(struct wl1271 *wl)
1363 wl->basic_rate_set = wl->conf.tx.basic_rate_5; 1363 wl->basic_rate_set = wl->conf.tx.basic_rate_5;
1364} 1364}
1365 1365
1366static u32 wl1271_min_rate_get(struct wl1271 *wl)
1367{
1368 int i;
1369 u32 rate = 0;
1370
1371 if (!wl->basic_rate_set) {
1372 WARN_ON(1);
1373 wl->basic_rate_set = wl->conf.tx.basic_rate;
1374 }
1375
1376 for (i = 0; !rate; i++) {
1377 if ((wl->basic_rate_set >> i) & 0x1)
1378 rate = 1 << i;
1379 }
1380
1381 return rate;
1382}
1383
1384static int wl1271_handle_idle(struct wl1271 *wl, bool idle) 1366static int wl1271_handle_idle(struct wl1271 *wl, bool idle)
1385{ 1367{
1386 int ret; 1368 int ret;
@@ -1391,7 +1373,7 @@ static int wl1271_handle_idle(struct wl1271 *wl, bool idle)
1391 if (ret < 0) 1373 if (ret < 0)
1392 goto out; 1374 goto out;
1393 } 1375 }
1394 wl->rate_set = wl1271_min_rate_get(wl); 1376 wl->rate_set = wl1271_tx_min_rate_get(wl);
1395 wl->sta_rate_set = 0; 1377 wl->sta_rate_set = 0;
1396 ret = wl1271_acx_sta_rate_policies(wl); 1378 ret = wl1271_acx_sta_rate_policies(wl);
1397 if (ret < 0) 1379 if (ret < 0)
@@ -1467,7 +1449,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
1467 if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) 1449 if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
1468 wl1271_set_band_rate(wl); 1450 wl1271_set_band_rate(wl);
1469 1451
1470 wl->basic_rate = wl1271_min_rate_get(wl); 1452 wl->basic_rate = wl1271_tx_min_rate_get(wl);
1471 ret = wl1271_acx_sta_rate_policies(wl); 1453 ret = wl1271_acx_sta_rate_policies(wl);
1472 if (ret < 0) 1454 if (ret < 0)
1473 wl1271_warning("rate policy for update channel " 1455 wl1271_warning("rate policy for update channel "
@@ -1927,7 +1909,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
1927 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, 1909 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON,
1928 beacon->data, 1910 beacon->data,
1929 beacon->len, 0, 1911 beacon->len, 0,
1930 wl1271_min_rate_get(wl)); 1912 wl1271_tx_min_rate_get(wl));
1931 1913
1932 if (ret < 0) { 1914 if (ret < 0) {
1933 dev_kfree_skb(beacon); 1915 dev_kfree_skb(beacon);
@@ -1943,7 +1925,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
1943 CMD_TEMPL_PROBE_RESPONSE, 1925 CMD_TEMPL_PROBE_RESPONSE,
1944 beacon->data, 1926 beacon->data,
1945 beacon->len, 0, 1927 beacon->len, 0,
1946 wl1271_min_rate_get(wl)); 1928 wl1271_tx_min_rate_get(wl));
1947 dev_kfree_skb(beacon); 1929 dev_kfree_skb(beacon);
1948 if (ret < 0) 1930 if (ret < 0)
1949 goto out_sleep; 1931 goto out_sleep;
@@ -2016,7 +1998,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
2016 rates = bss_conf->basic_rates; 1998 rates = bss_conf->basic_rates;
2017 wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, 1999 wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,
2018 rates); 2000 rates);
2019 wl->basic_rate = wl1271_min_rate_get(wl); 2001 wl->basic_rate = wl1271_tx_min_rate_get(wl);
2020 ret = wl1271_acx_sta_rate_policies(wl); 2002 ret = wl1271_acx_sta_rate_policies(wl);
2021 if (ret < 0) 2003 if (ret < 0)
2022 goto out_sleep; 2004 goto out_sleep;
@@ -2070,7 +2052,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
2070 2052
2071 /* revert back to minimum rates for the current band */ 2053 /* revert back to minimum rates for the current band */
2072 wl1271_set_band_rate(wl); 2054 wl1271_set_band_rate(wl);
2073 wl->basic_rate = wl1271_min_rate_get(wl); 2055 wl->basic_rate = wl1271_tx_min_rate_get(wl);
2074 ret = wl1271_acx_sta_rate_policies(wl); 2056 ret = wl1271_acx_sta_rate_policies(wl);
2075 if (ret < 0) 2057 if (ret < 0)
2076 goto out_sleep; 2058 goto out_sleep;
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 442a7bd956e..a93fc4702f3 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -521,3 +521,21 @@ void wl1271_tx_flush(struct wl1271 *wl)
521 521
522 wl1271_warning("Unable to flush all TX buffers, timed out."); 522 wl1271_warning("Unable to flush all TX buffers, timed out.");
523} 523}
524
525u32 wl1271_tx_min_rate_get(struct wl1271 *wl)
526{
527 int i;
528 u32 rate = 0;
529
530 if (!wl->basic_rate_set) {
531 WARN_ON(1);
532 wl->basic_rate_set = wl->conf.tx.basic_rate;
533 }
534
535 for (i = 0; !rate; i++) {
536 if ((wl->basic_rate_set >> i) & 0x1)
537 rate = 1 << i;
538 }
539
540 return rate;
541}
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index 903e5dc69b7..5ccd22eaf07 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -146,5 +146,6 @@ void wl1271_tx_reset(struct wl1271 *wl);
146void wl1271_tx_flush(struct wl1271 *wl); 146void wl1271_tx_flush(struct wl1271 *wl);
147u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); 147u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
148u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); 148u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set);
149u32 wl1271_tx_min_rate_get(struct wl1271 *wl);
149 150
150#endif 151#endif
diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h
index e2b26fbf68c..67dcf8f28cd 100644
--- a/drivers/net/wireless/wl12xx/wl12xx_80211.h
+++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h
@@ -160,4 +160,9 @@ struct wl12xx_probe_resp_template {
160 struct wl12xx_ie_country country; 160 struct wl12xx_ie_country country;
161} __packed; 161} __packed;
162 162
163struct wl12xx_disconn_template {
164 struct ieee80211_header header;
165 __le16 disconn_reason;
166} __packed;
167
163#endif 168#endif