1 /*
2  * This file is part of wl1271
3  *
4  * Copyright (C) 2009 Nokia Corporation
5  *
6  * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  *
22  */
23 
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/slab.h>
27 
28 #include "init.h"
29 #include "wl12xx_80211.h"
30 #include "acx.h"
31 #include "cmd.h"
32 #include "reg.h"
33 #include "tx.h"
34 
wl1271_sta_init_templates_config(struct wl1271 * wl)35 int wl1271_sta_init_templates_config(struct wl1271 *wl)
36 {
37 	int ret, i;
38 
39 	/* send empty templates for fw memory reservation */
40 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
41 				      WL1271_CMD_TEMPL_MAX_SIZE,
42 				      0, WL1271_RATE_AUTOMATIC);
43 	if (ret < 0)
44 		return ret;
45 
46 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
47 				      NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0,
48 				      WL1271_RATE_AUTOMATIC);
49 	if (ret < 0)
50 		return ret;
51 
52 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
53 				      sizeof(struct wl12xx_null_data_template),
54 				      0, WL1271_RATE_AUTOMATIC);
55 	if (ret < 0)
56 		return ret;
57 
58 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL,
59 				      sizeof(struct wl12xx_ps_poll_template),
60 				      0, WL1271_RATE_AUTOMATIC);
61 	if (ret < 0)
62 		return ret;
63 
64 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL,
65 				      sizeof
66 				      (struct wl12xx_qos_null_data_template),
67 				      0, WL1271_RATE_AUTOMATIC);
68 	if (ret < 0)
69 		return ret;
70 
71 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL,
72 				      sizeof
73 				      (struct wl12xx_probe_resp_template),
74 				      0, WL1271_RATE_AUTOMATIC);
75 	if (ret < 0)
76 		return ret;
77 
78 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL,
79 				      sizeof
80 				      (struct wl12xx_beacon_template),
81 				      0, WL1271_RATE_AUTOMATIC);
82 	if (ret < 0)
83 		return ret;
84 
85 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, NULL,
86 				      sizeof
87 				      (struct wl12xx_arp_rsp_template),
88 				      0, WL1271_RATE_AUTOMATIC);
89 	if (ret < 0)
90 		return ret;
91 
92 	for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
93 		ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL,
94 					      WL1271_CMD_TEMPL_MAX_SIZE, i,
95 					      WL1271_RATE_AUTOMATIC);
96 		if (ret < 0)
97 			return ret;
98 	}
99 
100 	return 0;
101 }
102 
wl1271_ap_init_deauth_template(struct wl1271 * wl)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 
wl1271_ap_init_null_template(struct wl1271 * wl)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 
wl1271_ap_init_qos_null_template(struct wl1271 * wl)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 
wl1271_ap_init_templates_config(struct wl1271 * wl)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 
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)
230 {
231 	int ret;
232 
233 	ret = wl1271_acx_rx_msdu_life_time(wl);
234 	if (ret < 0)
235 		return ret;
236 
237 	ret = wl1271_acx_rx_config(wl, config, filter);
238 	if (ret < 0)
239 		return ret;
240 
241 	return 0;
242 }
243 
wl1271_init_phy_config(struct wl1271 * wl)244 int wl1271_init_phy_config(struct wl1271 *wl)
245 {
246 	int ret;
247 
248 	ret = wl1271_acx_pd_threshold(wl);
249 	if (ret < 0)
250 		return ret;
251 
252 	ret = wl1271_acx_slot(wl, DEFAULT_SLOT_TIME);
253 	if (ret < 0)
254 		return ret;
255 
256 	ret = wl1271_acx_service_period_timeout(wl);
257 	if (ret < 0)
258 		return ret;
259 
260 	ret = wl1271_acx_rts_threshold(wl, wl->conf.rx.rts_threshold);
261 	if (ret < 0)
262 		return ret;
263 
264 	return 0;
265 }
266 
wl1271_init_beacon_filter(struct wl1271 * wl)267 static int wl1271_init_beacon_filter(struct wl1271 *wl)
268 {
269 	int ret;
270 
271 	/* disable beacon filtering at this stage */
272 	ret = wl1271_acx_beacon_filter_opt(wl, false);
273 	if (ret < 0)
274 		return ret;
275 
276 	ret = wl1271_acx_beacon_filter_table(wl);
277 	if (ret < 0)
278 		return ret;
279 
280 	return 0;
281 }
282 
wl1271_init_pta(struct wl1271 * wl)283 int wl1271_init_pta(struct wl1271 *wl)
284 {
285 	int ret;
286 
287 	ret = wl1271_acx_sg_cfg(wl);
288 	if (ret < 0)
289 		return ret;
290 
291 	ret = wl1271_acx_sg_enable(wl, wl->sg_enabled);
292 	if (ret < 0)
293 		return ret;
294 
295 	return 0;
296 }
297 
wl1271_init_energy_detection(struct wl1271 * wl)298 int wl1271_init_energy_detection(struct wl1271 *wl)
299 {
300 	int ret;
301 
302 	ret = wl1271_acx_cca_threshold(wl);
303 	if (ret < 0)
304 		return ret;
305 
306 	return 0;
307 }
308 
wl1271_init_beacon_broadcast(struct wl1271 * wl)309 static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
310 {
311 	int ret;
312 
313 	ret = wl1271_acx_bcn_dtim_options(wl);
314 	if (ret < 0)
315 		return ret;
316 
317 	return 0;
318 }
319 
wl1271_sta_hw_init(struct wl1271 * wl)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 	/* PS config */
329 	ret = wl1271_acx_config_ps(wl);
330 	if (ret < 0)
331 		return ret;
332 
333 	ret = wl1271_sta_init_templates_config(wl);
334 	if (ret < 0)
335 		return ret;
336 
337 	ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0);
338 	if (ret < 0)
339 		return ret;
340 
341 	/* Initialize connection monitoring thresholds */
342 	ret = wl1271_acx_conn_monit_params(wl, false);
343 	if (ret < 0)
344 		return ret;
345 
346 	/* Beacon filtering */
347 	ret = wl1271_init_beacon_filter(wl);
348 	if (ret < 0)
349 		return ret;
350 
351 	/* Bluetooth WLAN coexistence */
352 	ret = wl1271_init_pta(wl);
353 	if (ret < 0)
354 		return ret;
355 
356 	/* Beacons and broadcast settings */
357 	ret = wl1271_init_beacon_broadcast(wl);
358 	if (ret < 0)
359 		return ret;
360 
361 	/* Configure for ELP power saving */
362 	ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
363 	if (ret < 0)
364 		return ret;
365 
366 	/* Configure rssi/snr averaging weights */
367 	ret = wl1271_acx_rssi_snr_avg_weights(wl);
368 	if (ret < 0)
369 		return ret;
370 
371 	ret = wl1271_acx_sta_rate_policies(wl);
372 	if (ret < 0)
373 		return ret;
374 
375 	ret = wl1271_acx_sta_mem_cfg(wl);
376 	if (ret < 0)
377 		return ret;
378 
379 	return 0;
380 }
381 
wl1271_sta_hw_init_post_mem(struct wl1271 * wl)382 static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl)
383 {
384 	int ret, i;
385 
386 	ret = wl1271_cmd_set_sta_default_wep_key(wl, wl->default_key);
387 	if (ret < 0) {
388 		wl1271_warning("couldn't set default key");
389 		return ret;
390 	}
391 
392 	/* disable all keep-alive templates */
393 	for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
394 		ret = wl1271_acx_keep_alive_config(wl, i,
395 						   ACX_KEEP_ALIVE_TPL_INVALID);
396 		if (ret < 0)
397 			return ret;
398 	}
399 
400 	/* disable the keep-alive feature */
401 	ret = wl1271_acx_keep_alive_mode(wl, false);
402 	if (ret < 0)
403 		return ret;
404 
405 	return 0;
406 }
407 
wl1271_ap_hw_init(struct wl1271 * wl)408 static int wl1271_ap_hw_init(struct wl1271 *wl)
409 {
410 	int ret, i;
411 
412 	ret = wl1271_ap_init_templates_config(wl);
413 	if (ret < 0)
414 		return ret;
415 
416 	/* Configure for power always on */
417 	ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
418 	if (ret < 0)
419 		return ret;
420 
421 	/* Configure initial TX rate classes */
422 	for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
423 		ret = wl1271_acx_ap_rate_policy(wl,
424 				&wl->conf.tx.ap_rc_conf[i], i);
425 		if (ret < 0)
426 			return ret;
427 	}
428 
429 	ret = wl1271_acx_ap_rate_policy(wl,
430 					&wl->conf.tx.ap_mgmt_conf,
431 					ACX_TX_AP_MODE_MGMT_RATE);
432 	if (ret < 0)
433 		return ret;
434 
435 	ret = wl1271_acx_ap_rate_policy(wl,
436 					&wl->conf.tx.ap_bcst_conf,
437 					ACX_TX_AP_MODE_BCST_RATE);
438 	if (ret < 0)
439 		return ret;
440 
441 	ret = wl1271_acx_max_tx_retry(wl);
442 	if (ret < 0)
443 		return ret;
444 
445 	ret = wl1271_acx_ap_mem_cfg(wl);
446 	if (ret < 0)
447 		return ret;
448 
449 	return 0;
450 }
451 
wl1271_ap_hw_init_post_mem(struct wl1271 * wl)452 static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl)
453 {
454 	int ret;
455 
456 	ret = wl1271_ap_init_deauth_template(wl);
457 	if (ret < 0)
458 		return ret;
459 
460 	ret = wl1271_ap_init_null_template(wl);
461 	if (ret < 0)
462 		return ret;
463 
464 	ret = wl1271_ap_init_qos_null_template(wl);
465 	if (ret < 0)
466 		return ret;
467 
468 	return 0;
469 }
470 
wl1271_check_ba_support(struct wl1271 * wl)471 static void wl1271_check_ba_support(struct wl1271 *wl)
472 {
473 	/* validate FW cose ver x.x.x.50-60.x */
474 	if ((wl->chip.fw_ver[3] >= WL12XX_BA_SUPPORT_FW_COST_VER2_START) &&
475 	    (wl->chip.fw_ver[3] < WL12XX_BA_SUPPORT_FW_COST_VER2_END)) {
476 		wl->ba_support = true;
477 		return;
478 	}
479 
480 	wl->ba_support = false;
481 }
482 
wl1271_set_ba_policies(struct wl1271 * wl)483 static int wl1271_set_ba_policies(struct wl1271 *wl)
484 {
485 	u8 tid_index;
486 	int ret = 0;
487 
488 	/* Reset the BA RX indicators */
489 	wl->ba_rx_bitmap = 0;
490 
491 	/* validate that FW support BA */
492 	wl1271_check_ba_support(wl);
493 
494 	if (wl->ba_support)
495 		/* 802.11n initiator BA session setting */
496 		for (tid_index = 0; tid_index < CONF_TX_MAX_TID_COUNT;
497 		     ++tid_index) {
498 			ret = wl1271_acx_set_ba_session(wl, WLAN_BACK_INITIATOR,
499 							tid_index, true);
500 			if (ret < 0)
501 				break;
502 		}
503 
504 	return ret;
505 }
506 
wl1271_hw_init(struct wl1271 * wl)507 int wl1271_hw_init(struct wl1271 *wl)
508 {
509 	struct conf_tx_ac_category *conf_ac;
510 	struct conf_tx_tid *conf_tid;
511 	int ret, i;
512 	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
513 
514 	ret = wl1271_cmd_general_parms(wl);
515 	if (ret < 0)
516 		return ret;
517 
518 	ret = wl1271_cmd_radio_parms(wl);
519 	if (ret < 0)
520 		return ret;
521 
522 	/* Mode specific init */
523 	if (is_ap)
524 		ret = wl1271_ap_hw_init(wl);
525 	else
526 		ret = wl1271_sta_hw_init(wl);
527 
528 	if (ret < 0)
529 		return ret;
530 
531 	/* Default memory configuration */
532 	ret = wl1271_acx_init_mem_config(wl);
533 	if (ret < 0)
534 		return ret;
535 
536 	/* RX config */
537 	ret = wl1271_init_rx_config(wl,
538 				    RX_CFG_PROMISCUOUS | RX_CFG_TSF,
539 				    RX_FILTER_OPTION_DEF);
540 	/* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
541 	   RX_FILTER_OPTION_FILTER_ALL); */
542 	if (ret < 0)
543 		goto out_free_memmap;
544 
545 	/* PHY layer config */
546 	ret = wl1271_init_phy_config(wl);
547 	if (ret < 0)
548 		goto out_free_memmap;
549 
550 	ret = wl1271_acx_dco_itrim_params(wl);
551 	if (ret < 0)
552 		goto out_free_memmap;
553 
554 	/* Configure TX patch complete interrupt behavior */
555 	ret = wl1271_acx_tx_config_options(wl);
556 	if (ret < 0)
557 		goto out_free_memmap;
558 
559 	/* RX complete interrupt pacing */
560 	ret = wl1271_acx_init_rx_interrupt(wl);
561 	if (ret < 0)
562 		goto out_free_memmap;
563 
564 	/* Energy detection */
565 	ret = wl1271_init_energy_detection(wl);
566 	if (ret < 0)
567 		goto out_free_memmap;
568 
569 	/* Default fragmentation threshold */
570 	ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold);
571 	if (ret < 0)
572 		goto out_free_memmap;
573 
574 	/* Default TID/AC configuration */
575 	BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count);
576 	for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
577 		conf_ac = &wl->conf.tx.ac_conf[i];
578 		ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
579 					conf_ac->cw_max, conf_ac->aifsn,
580 					conf_ac->tx_op_limit);
581 		if (ret < 0)
582 			goto out_free_memmap;
583 
584 		conf_tid = &wl->conf.tx.tid_conf[i];
585 		ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id,
586 					 conf_tid->channel_type,
587 					 conf_tid->tsid,
588 					 conf_tid->ps_scheme,
589 					 conf_tid->ack_policy,
590 					 conf_tid->apsd_conf[0],
591 					 conf_tid->apsd_conf[1]);
592 		if (ret < 0)
593 			goto out_free_memmap;
594 	}
595 
596 	/* Enable data path */
597 	ret = wl1271_cmd_data_path(wl, 1);
598 	if (ret < 0)
599 		goto out_free_memmap;
600 
601 	/* Configure HW encryption */
602 	ret = wl1271_acx_feature_cfg(wl);
603 	if (ret < 0)
604 		goto out_free_memmap;
605 
606 	/* configure PM */
607 	ret = wl1271_acx_pm_config(wl);
608 	if (ret < 0)
609 		goto out_free_memmap;
610 
611 	/* Mode specific init - post mem init */
612 	if (is_ap)
613 		ret = wl1271_ap_hw_init_post_mem(wl);
614 	else
615 		ret = wl1271_sta_hw_init_post_mem(wl);
616 
617 	if (ret < 0)
618 		goto out_free_memmap;
619 
620 	/* Configure initiator BA sessions policies */
621 	ret = wl1271_set_ba_policies(wl);
622 	if (ret < 0)
623 		goto out_free_memmap;
624 
625 	return 0;
626 
627  out_free_memmap:
628 	kfree(wl->target_mem_map);
629 	wl->target_mem_map = NULL;
630 
631 	return ret;
632 }
633