diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/wl12xx/cmd.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/init.c | 352 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/init.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 32 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl12xx_80211.h | 5 |
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 | ||
34 | static int wl1271_init_hwenc_config(struct wl1271 *wl) | 35 | int 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 | |||
53 | int 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 | ||
103 | static 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 | |||
121 | out: | ||
122 | kfree(tmpl); | ||
123 | return ret; | ||
124 | } | ||
125 | |||
126 | static 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 | |||
150 | out: | ||
151 | kfree(nullfunc); | ||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | static 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 | |||
179 | out: | ||
180 | kfree(qosnull); | ||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | static 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 | |||
121 | static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter) | 229 | static 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 | ||
320 | static 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 | |||
373 | static 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 | |||
399 | static 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 | |||
439 | static 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 | |||
216 | int wl1271_hw_init(struct wl1271 *wl) | 458 | int 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 | ||
29 | int wl1271_hw_init_power_auth(struct wl1271 *wl); | 29 | int wl1271_hw_init_power_auth(struct wl1271 *wl); |
30 | int wl1271_init_templates_config(struct wl1271 *wl); | 30 | int wl1271_sta_init_templates_config(struct wl1271 *wl); |
31 | int wl1271_init_phy_config(struct wl1271 *wl); | 31 | int wl1271_init_phy_config(struct wl1271 *wl); |
32 | int wl1271_init_pta(struct wl1271 *wl); | 32 | int wl1271_init_pta(struct wl1271 *wl); |
33 | int wl1271_init_energy_detection(struct wl1271 *wl); | 33 | int 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 | ||
1366 | static 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 | |||
1384 | static int wl1271_handle_idle(struct wl1271 *wl, bool idle) | 1366 | static 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 | |||
525 | u32 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); | |||
146 | void wl1271_tx_flush(struct wl1271 *wl); | 146 | void wl1271_tx_flush(struct wl1271 *wl); |
147 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); | 147 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); |
148 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); | 148 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); |
149 | u32 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 | ||
163 | struct wl12xx_disconn_template { | ||
164 | struct ieee80211_header header; | ||
165 | __le16 disconn_reason; | ||
166 | } __packed; | ||
167 | |||
163 | #endif | 168 | #endif |