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 "debug.h"
29 #include "init.h"
30 #include "wl12xx_80211.h"
31 #include "acx.h"
32 #include "cmd.h"
33 #include "reg.h"
34 #include "tx.h"
35 #include "io.h"
36 
wl1271_init_templates_config(struct wl1271 * wl)37 int wl1271_init_templates_config(struct wl1271 *wl)
38 {
39 	int ret, i;
40 	size_t max_size;
41 
42 	/* send empty templates for fw memory reservation */
43 	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
44 				      CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
45 				      WL1271_CMD_TEMPL_MAX_SIZE,
46 				      0, WL1271_RATE_AUTOMATIC);
47 	if (ret < 0)
48 		return ret;
49 
50 	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
51 				      CMD_TEMPL_CFG_PROBE_REQ_5,
52 				      NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0,
53 				      WL1271_RATE_AUTOMATIC);
54 	if (ret < 0)
55 		return ret;
56 
57 	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
58 				      CMD_TEMPL_NULL_DATA, NULL,
59 				      sizeof(struct wl12xx_null_data_template),
60 				      0, WL1271_RATE_AUTOMATIC);
61 	if (ret < 0)
62 		return ret;
63 
64 	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
65 				      CMD_TEMPL_PS_POLL, NULL,
66 				      sizeof(struct wl12xx_ps_poll_template),
67 				      0, WL1271_RATE_AUTOMATIC);
68 	if (ret < 0)
69 		return ret;
70 
71 	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
72 				      CMD_TEMPL_QOS_NULL_DATA, NULL,
73 				      sizeof
74 				      (struct ieee80211_qos_hdr),
75 				      0, WL1271_RATE_AUTOMATIC);
76 	if (ret < 0)
77 		return ret;
78 
79 	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
80 				      CMD_TEMPL_PROBE_RESPONSE, NULL,
81 				      WL1271_CMD_TEMPL_DFLT_SIZE,
82 				      0, WL1271_RATE_AUTOMATIC);
83 	if (ret < 0)
84 		return ret;
85 
86 	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
87 				      CMD_TEMPL_BEACON, NULL,
88 				      WL1271_CMD_TEMPL_DFLT_SIZE,
89 				      0, WL1271_RATE_AUTOMATIC);
90 	if (ret < 0)
91 		return ret;
92 
93 	max_size = sizeof(struct wl12xx_arp_rsp_template) +
94 		   WL1271_EXTRA_SPACE_MAX;
95 	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
96 				      CMD_TEMPL_ARP_RSP, NULL,
97 				      max_size,
98 				      0, WL1271_RATE_AUTOMATIC);
99 	if (ret < 0)
100 		return ret;
101 
102 	/*
103 	 * Put very large empty placeholders for all templates. These
104 	 * reserve memory for later.
105 	 */
106 	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
107 				      CMD_TEMPL_AP_PROBE_RESPONSE, NULL,
108 				      WL1271_CMD_TEMPL_MAX_SIZE,
109 				      0, WL1271_RATE_AUTOMATIC);
110 	if (ret < 0)
111 		return ret;
112 
113 	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
114 				      CMD_TEMPL_AP_BEACON, NULL,
115 				      WL1271_CMD_TEMPL_MAX_SIZE,
116 				      0, WL1271_RATE_AUTOMATIC);
117 	if (ret < 0)
118 		return ret;
119 
120 	ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
121 				      CMD_TEMPL_DEAUTH_AP, NULL,
122 				      sizeof
123 				      (struct wl12xx_disconn_template),
124 				      0, WL1271_RATE_AUTOMATIC);
125 	if (ret < 0)
126 		return ret;
127 
128 	for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
129 		ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
130 					      CMD_TEMPL_KLV, NULL,
131 					      sizeof(struct ieee80211_qos_hdr),
132 					      i, WL1271_RATE_AUTOMATIC);
133 		if (ret < 0)
134 			return ret;
135 	}
136 
137 	return 0;
138 }
139 
wl1271_ap_init_deauth_template(struct wl1271 * wl,struct wl12xx_vif * wlvif)140 static int wl1271_ap_init_deauth_template(struct wl1271 *wl,
141 					  struct wl12xx_vif *wlvif)
142 {
143 	struct wl12xx_disconn_template *tmpl;
144 	int ret;
145 	u32 rate;
146 
147 	tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
148 	if (!tmpl) {
149 		ret = -ENOMEM;
150 		goto out;
151 	}
152 
153 	tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
154 					     IEEE80211_STYPE_DEAUTH);
155 
156 	rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
157 	ret = wl1271_cmd_template_set(wl, wlvif->role_id,
158 				      CMD_TEMPL_DEAUTH_AP,
159 				      tmpl, sizeof(*tmpl), 0, rate);
160 
161 out:
162 	kfree(tmpl);
163 	return ret;
164 }
165 
wl1271_ap_init_null_template(struct wl1271 * wl,struct ieee80211_vif * vif)166 static int wl1271_ap_init_null_template(struct wl1271 *wl,
167 					struct ieee80211_vif *vif)
168 {
169 	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
170 	struct ieee80211_hdr_3addr *nullfunc;
171 	int ret;
172 	u32 rate;
173 
174 	nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL);
175 	if (!nullfunc) {
176 		ret = -ENOMEM;
177 		goto out;
178 	}
179 
180 	nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
181 					      IEEE80211_STYPE_NULLFUNC |
182 					      IEEE80211_FCTL_FROMDS);
183 
184 	/* nullfunc->addr1 is filled by FW */
185 
186 	memcpy(nullfunc->addr2, vif->addr, ETH_ALEN);
187 	memcpy(nullfunc->addr3, vif->addr, ETH_ALEN);
188 
189 	rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
190 	ret = wl1271_cmd_template_set(wl, wlvif->role_id,
191 				      CMD_TEMPL_NULL_DATA, nullfunc,
192 				      sizeof(*nullfunc), 0, rate);
193 
194 out:
195 	kfree(nullfunc);
196 	return ret;
197 }
198 
wl1271_ap_init_qos_null_template(struct wl1271 * wl,struct ieee80211_vif * vif)199 static int wl1271_ap_init_qos_null_template(struct wl1271 *wl,
200 					    struct ieee80211_vif *vif)
201 {
202 	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
203 	struct ieee80211_qos_hdr *qosnull;
204 	int ret;
205 	u32 rate;
206 
207 	qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL);
208 	if (!qosnull) {
209 		ret = -ENOMEM;
210 		goto out;
211 	}
212 
213 	qosnull->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
214 					     IEEE80211_STYPE_QOS_NULLFUNC |
215 					     IEEE80211_FCTL_FROMDS);
216 
217 	/* qosnull->addr1 is filled by FW */
218 
219 	memcpy(qosnull->addr2, vif->addr, ETH_ALEN);
220 	memcpy(qosnull->addr3, vif->addr, ETH_ALEN);
221 
222 	rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
223 	ret = wl1271_cmd_template_set(wl, wlvif->role_id,
224 				      CMD_TEMPL_QOS_NULL_DATA, qosnull,
225 				      sizeof(*qosnull), 0, rate);
226 
227 out:
228 	kfree(qosnull);
229 	return ret;
230 }
231 
wl12xx_init_rx_config(struct wl1271 * wl)232 static int wl12xx_init_rx_config(struct wl1271 *wl)
233 {
234 	int ret;
235 
236 	ret = wl1271_acx_rx_msdu_life_time(wl);
237 	if (ret < 0)
238 		return ret;
239 
240 	return 0;
241 }
242 
wl12xx_init_phy_vif_config(struct wl1271 * wl,struct wl12xx_vif * wlvif)243 static int wl12xx_init_phy_vif_config(struct wl1271 *wl,
244 					    struct wl12xx_vif *wlvif)
245 {
246 	int ret;
247 
248 	ret = wl1271_acx_slot(wl, wlvif, DEFAULT_SLOT_TIME);
249 	if (ret < 0)
250 		return ret;
251 
252 	ret = wl1271_acx_service_period_timeout(wl, wlvif);
253 	if (ret < 0)
254 		return ret;
255 
256 	ret = wl1271_acx_rts_threshold(wl, wlvif, wl->hw->wiphy->rts_threshold);
257 	if (ret < 0)
258 		return ret;
259 
260 	return 0;
261 }
262 
wl1271_init_sta_beacon_filter(struct wl1271 * wl,struct wl12xx_vif * wlvif)263 static int wl1271_init_sta_beacon_filter(struct wl1271 *wl,
264 					 struct wl12xx_vif *wlvif)
265 {
266 	int ret;
267 
268 	ret = wl1271_acx_beacon_filter_table(wl, wlvif);
269 	if (ret < 0)
270 		return ret;
271 
272 	/* enable beacon filtering */
273 	ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true);
274 	if (ret < 0)
275 		return ret;
276 
277 	return 0;
278 }
279 
wl1271_init_pta(struct wl1271 * wl)280 int wl1271_init_pta(struct wl1271 *wl)
281 {
282 	int ret;
283 
284 	ret = wl12xx_acx_sg_cfg(wl);
285 	if (ret < 0)
286 		return ret;
287 
288 	ret = wl1271_acx_sg_enable(wl, wl->sg_enabled);
289 	if (ret < 0)
290 		return ret;
291 
292 	return 0;
293 }
294 
wl1271_init_energy_detection(struct wl1271 * wl)295 int wl1271_init_energy_detection(struct wl1271 *wl)
296 {
297 	int ret;
298 
299 	ret = wl1271_acx_cca_threshold(wl);
300 	if (ret < 0)
301 		return ret;
302 
303 	return 0;
304 }
305 
wl1271_init_beacon_broadcast(struct wl1271 * wl,struct wl12xx_vif * wlvif)306 static int wl1271_init_beacon_broadcast(struct wl1271 *wl,
307 					struct wl12xx_vif *wlvif)
308 {
309 	int ret;
310 
311 	ret = wl1271_acx_bcn_dtim_options(wl, wlvif);
312 	if (ret < 0)
313 		return ret;
314 
315 	return 0;
316 }
317 
wl12xx_init_fwlog(struct wl1271 * wl)318 static int wl12xx_init_fwlog(struct wl1271 *wl)
319 {
320 	int ret;
321 
322 	if (wl->quirks & WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED)
323 		return 0;
324 
325 	ret = wl12xx_cmd_config_fwlog(wl);
326 	if (ret < 0)
327 		return ret;
328 
329 	return 0;
330 }
331 
332 /* generic sta initialization (non vif-specific) */
wl1271_sta_hw_init(struct wl1271 * wl,struct wl12xx_vif * wlvif)333 static int wl1271_sta_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif)
334 {
335 	int ret;
336 
337 	/* PS config */
338 	ret = wl12xx_acx_config_ps(wl, wlvif);
339 	if (ret < 0)
340 		return ret;
341 
342 	/* FM WLAN coexistence */
343 	ret = wl1271_acx_fm_coex(wl);
344 	if (ret < 0)
345 		return ret;
346 
347 	ret = wl1271_acx_sta_rate_policies(wl, wlvif);
348 	if (ret < 0)
349 		return ret;
350 
351 	return 0;
352 }
353 
wl1271_sta_hw_init_post_mem(struct wl1271 * wl,struct ieee80211_vif * vif)354 static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl,
355 				       struct ieee80211_vif *vif)
356 {
357 	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
358 	int ret, i;
359 
360 	/* disable all keep-alive templates */
361 	for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
362 		ret = wl1271_acx_keep_alive_config(wl, wlvif, i,
363 						   ACX_KEEP_ALIVE_TPL_INVALID);
364 		if (ret < 0)
365 			return ret;
366 	}
367 
368 	/* disable the keep-alive feature */
369 	ret = wl1271_acx_keep_alive_mode(wl, wlvif, false);
370 	if (ret < 0)
371 		return ret;
372 
373 	return 0;
374 }
375 
376 /* generic ap initialization (non vif-specific) */
wl1271_ap_hw_init(struct wl1271 * wl,struct wl12xx_vif * wlvif)377 static int wl1271_ap_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif)
378 {
379 	int ret;
380 
381 	ret = wl1271_init_ap_rates(wl, wlvif);
382 	if (ret < 0)
383 		return ret;
384 
385 	return 0;
386 }
387 
wl1271_ap_init_templates(struct wl1271 * wl,struct ieee80211_vif * vif)388 int wl1271_ap_init_templates(struct wl1271 *wl, struct ieee80211_vif *vif)
389 {
390 	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
391 	int ret;
392 
393 	ret = wl1271_ap_init_deauth_template(wl, wlvif);
394 	if (ret < 0)
395 		return ret;
396 
397 	ret = wl1271_ap_init_null_template(wl, vif);
398 	if (ret < 0)
399 		return ret;
400 
401 	ret = wl1271_ap_init_qos_null_template(wl, vif);
402 	if (ret < 0)
403 		return ret;
404 
405 	/*
406 	 * when operating as AP we want to receive external beacons for
407 	 * configuring ERP protection.
408 	 */
409 	ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false);
410 	if (ret < 0)
411 		return ret;
412 
413 	return 0;
414 }
415 
wl1271_ap_hw_init_post_mem(struct wl1271 * wl,struct ieee80211_vif * vif)416 static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl,
417 				      struct ieee80211_vif *vif)
418 {
419 	return wl1271_ap_init_templates(wl, vif);
420 }
421 
wl1271_init_ap_rates(struct wl1271 * wl,struct wl12xx_vif * wlvif)422 int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif)
423 {
424 	int i, ret;
425 	struct conf_tx_rate_class rc;
426 	u32 supported_rates;
427 
428 	wl1271_debug(DEBUG_AP, "AP basic rate set: 0x%x",
429 		     wlvif->basic_rate_set);
430 
431 	if (wlvif->basic_rate_set == 0)
432 		return -EINVAL;
433 
434 	rc.enabled_rates = wlvif->basic_rate_set;
435 	rc.long_retry_limit = 10;
436 	rc.short_retry_limit = 10;
437 	rc.aflags = 0;
438 	ret = wl1271_acx_ap_rate_policy(wl, &rc, wlvif->ap.mgmt_rate_idx);
439 	if (ret < 0)
440 		return ret;
441 
442 	/* use the min basic rate for AP broadcast/multicast */
443 	rc.enabled_rates = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
444 	rc.short_retry_limit = 10;
445 	rc.long_retry_limit = 10;
446 	rc.aflags = 0;
447 	ret = wl1271_acx_ap_rate_policy(wl, &rc, wlvif->ap.bcast_rate_idx);
448 	if (ret < 0)
449 		return ret;
450 
451 	/*
452 	 * If the basic rates contain OFDM rates, use OFDM only
453 	 * rates for unicast TX as well. Else use all supported rates.
454 	 */
455 	if ((wlvif->basic_rate_set & CONF_TX_OFDM_RATES))
456 		supported_rates = CONF_TX_OFDM_RATES;
457 	else
458 		supported_rates = CONF_TX_AP_ENABLED_RATES;
459 
460 	/* unconditionally enable HT rates */
461 	supported_rates |= CONF_TX_MCS_RATES;
462 
463 	/* configure unicast TX rate classes */
464 	for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
465 		rc.enabled_rates = supported_rates;
466 		rc.short_retry_limit = 10;
467 		rc.long_retry_limit = 10;
468 		rc.aflags = 0;
469 		ret = wl1271_acx_ap_rate_policy(wl, &rc,
470 						wlvif->ap.ucast_rate_idx[i]);
471 		if (ret < 0)
472 			return ret;
473 	}
474 
475 	return 0;
476 }
477 
wl1271_set_ba_policies(struct wl1271 * wl,struct wl12xx_vif * wlvif)478 static int wl1271_set_ba_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif)
479 {
480 	/* Reset the BA RX indicators */
481 	wlvif->ba_allowed = true;
482 	wl->ba_rx_session_count = 0;
483 
484 	/* BA is supported in STA/AP modes */
485 	if (wlvif->bss_type != BSS_TYPE_AP_BSS &&
486 	    wlvif->bss_type != BSS_TYPE_STA_BSS) {
487 		wlvif->ba_support = false;
488 		return 0;
489 	}
490 
491 	wlvif->ba_support = true;
492 
493 	/* 802.11n initiator BA session setting */
494 	return wl12xx_acx_set_ba_initiator_policy(wl, wlvif);
495 }
496 
wl1271_chip_specific_init(struct wl1271 * wl)497 int wl1271_chip_specific_init(struct wl1271 *wl)
498 {
499 	int ret = 0;
500 
501 	if (wl->chip.id == CHIP_ID_1283_PG20) {
502 		u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE;
503 
504 		if (!(wl->quirks & WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT))
505 			/* Enable SDIO padding */
506 			host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK;
507 
508 		/* Must be before wl1271_acx_init_mem_config() */
509 		ret = wl1271_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap);
510 		if (ret < 0)
511 			goto out;
512 	}
513 out:
514 	return ret;
515 }
516 
517 /* vif-specifc initialization */
wl12xx_init_sta_role(struct wl1271 * wl,struct wl12xx_vif * wlvif)518 static int wl12xx_init_sta_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
519 {
520 	int ret;
521 
522 	ret = wl1271_acx_group_address_tbl(wl, wlvif, true, NULL, 0);
523 	if (ret < 0)
524 		return ret;
525 
526 	/* Initialize connection monitoring thresholds */
527 	ret = wl1271_acx_conn_monit_params(wl, wlvif, false);
528 	if (ret < 0)
529 		return ret;
530 
531 	/* Beacon filtering */
532 	ret = wl1271_init_sta_beacon_filter(wl, wlvif);
533 	if (ret < 0)
534 		return ret;
535 
536 	/* Beacons and broadcast settings */
537 	ret = wl1271_init_beacon_broadcast(wl, wlvif);
538 	if (ret < 0)
539 		return ret;
540 
541 	/* Configure rssi/snr averaging weights */
542 	ret = wl1271_acx_rssi_snr_avg_weights(wl, wlvif);
543 	if (ret < 0)
544 		return ret;
545 
546 	return 0;
547 }
548 
549 /* vif-specific intialization */
wl12xx_init_ap_role(struct wl1271 * wl,struct wl12xx_vif * wlvif)550 static int wl12xx_init_ap_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
551 {
552 	int ret;
553 
554 	ret = wl1271_acx_ap_max_tx_retry(wl, wlvif);
555 	if (ret < 0)
556 		return ret;
557 
558 	/* initialize Tx power */
559 	ret = wl1271_acx_tx_power(wl, wlvif, wlvif->power_level);
560 	if (ret < 0)
561 		return ret;
562 
563 	return 0;
564 }
565 
wl1271_init_vif_specific(struct wl1271 * wl,struct ieee80211_vif * vif)566 int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif)
567 {
568 	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
569 	struct conf_tx_ac_category *conf_ac;
570 	struct conf_tx_tid *conf_tid;
571 	bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
572 	int ret, i;
573 
574 	/*
575 	 * consider all existing roles before configuring psm.
576 	 * TODO: reconfigure on interface removal.
577 	 */
578 	if (!wl->ap_count) {
579 		if (is_ap) {
580 			/* Configure for power always on */
581 			ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
582 			if (ret < 0)
583 				return ret;
584 		} else if (!wl->sta_count) {
585 			/* Configure for ELP power saving */
586 			ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
587 			if (ret < 0)
588 				return ret;
589 		}
590 	}
591 
592 	/* Mode specific init */
593 	if (is_ap) {
594 		ret = wl1271_ap_hw_init(wl, wlvif);
595 		if (ret < 0)
596 			return ret;
597 
598 		ret = wl12xx_init_ap_role(wl, wlvif);
599 		if (ret < 0)
600 			return ret;
601 	} else {
602 		ret = wl1271_sta_hw_init(wl, wlvif);
603 		if (ret < 0)
604 			return ret;
605 
606 		ret = wl12xx_init_sta_role(wl, wlvif);
607 		if (ret < 0)
608 			return ret;
609 	}
610 
611 	wl12xx_init_phy_vif_config(wl, wlvif);
612 
613 	/* Default TID/AC configuration */
614 	BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count);
615 	for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
616 		conf_ac = &wl->conf.tx.ac_conf[i];
617 		ret = wl1271_acx_ac_cfg(wl, wlvif, conf_ac->ac,
618 					conf_ac->cw_min, conf_ac->cw_max,
619 					conf_ac->aifsn, conf_ac->tx_op_limit);
620 		if (ret < 0)
621 			return ret;
622 
623 		conf_tid = &wl->conf.tx.tid_conf[i];
624 		ret = wl1271_acx_tid_cfg(wl, wlvif,
625 					 conf_tid->queue_id,
626 					 conf_tid->channel_type,
627 					 conf_tid->tsid,
628 					 conf_tid->ps_scheme,
629 					 conf_tid->ack_policy,
630 					 conf_tid->apsd_conf[0],
631 					 conf_tid->apsd_conf[1]);
632 		if (ret < 0)
633 			return ret;
634 	}
635 
636 	/* Configure HW encryption */
637 	ret = wl1271_acx_feature_cfg(wl, wlvif);
638 	if (ret < 0)
639 		return ret;
640 
641 	/* Mode specific init - post mem init */
642 	if (is_ap)
643 		ret = wl1271_ap_hw_init_post_mem(wl, vif);
644 	else
645 		ret = wl1271_sta_hw_init_post_mem(wl, vif);
646 
647 	if (ret < 0)
648 		return ret;
649 
650 	/* Configure initiator BA sessions policies */
651 	ret = wl1271_set_ba_policies(wl, wlvif);
652 	if (ret < 0)
653 		return ret;
654 
655 	return 0;
656 }
657 
wl1271_hw_init(struct wl1271 * wl)658 int wl1271_hw_init(struct wl1271 *wl)
659 {
660 	int ret;
661 
662 	if (wl->chip.id == CHIP_ID_1283_PG20) {
663 		ret = wl128x_cmd_general_parms(wl);
664 		if (ret < 0)
665 			return ret;
666 		ret = wl128x_cmd_radio_parms(wl);
667 		if (ret < 0)
668 			return ret;
669 	} else {
670 		ret = wl1271_cmd_general_parms(wl);
671 		if (ret < 0)
672 			return ret;
673 		ret = wl1271_cmd_radio_parms(wl);
674 		if (ret < 0)
675 			return ret;
676 		ret = wl1271_cmd_ext_radio_parms(wl);
677 		if (ret < 0)
678 			return ret;
679 	}
680 
681 	/* Chip-specific init */
682 	ret = wl1271_chip_specific_init(wl);
683 	if (ret < 0)
684 		return ret;
685 
686 	/* Init templates */
687 	ret = wl1271_init_templates_config(wl);
688 	if (ret < 0)
689 		return ret;
690 
691 	ret = wl12xx_acx_mem_cfg(wl);
692 	if (ret < 0)
693 		return ret;
694 
695 	/* Configure the FW logger */
696 	ret = wl12xx_init_fwlog(wl);
697 	if (ret < 0)
698 		return ret;
699 
700 	/* Bluetooth WLAN coexistence */
701 	ret = wl1271_init_pta(wl);
702 	if (ret < 0)
703 		return ret;
704 
705 	/* Default memory configuration */
706 	ret = wl1271_acx_init_mem_config(wl);
707 	if (ret < 0)
708 		return ret;
709 
710 	/* RX config */
711 	ret = wl12xx_init_rx_config(wl);
712 	if (ret < 0)
713 		goto out_free_memmap;
714 
715 	ret = wl1271_acx_dco_itrim_params(wl);
716 	if (ret < 0)
717 		goto out_free_memmap;
718 
719 	/* Configure TX patch complete interrupt behavior */
720 	ret = wl1271_acx_tx_config_options(wl);
721 	if (ret < 0)
722 		goto out_free_memmap;
723 
724 	/* RX complete interrupt pacing */
725 	ret = wl1271_acx_init_rx_interrupt(wl);
726 	if (ret < 0)
727 		goto out_free_memmap;
728 
729 	/* Energy detection */
730 	ret = wl1271_init_energy_detection(wl);
731 	if (ret < 0)
732 		goto out_free_memmap;
733 
734 	/* Default fragmentation threshold */
735 	ret = wl1271_acx_frag_threshold(wl, wl->hw->wiphy->frag_threshold);
736 	if (ret < 0)
737 		goto out_free_memmap;
738 
739 	/* Enable data path */
740 	ret = wl1271_cmd_data_path(wl, 1);
741 	if (ret < 0)
742 		goto out_free_memmap;
743 
744 	/* configure PM */
745 	ret = wl1271_acx_pm_config(wl);
746 	if (ret < 0)
747 		goto out_free_memmap;
748 
749 	ret = wl12xx_acx_set_rate_mgmt_params(wl);
750 	if (ret < 0)
751 		goto out_free_memmap;
752 
753 	/* configure hangover */
754 	ret = wl12xx_acx_config_hangover(wl);
755 	if (ret < 0)
756 		goto out_free_memmap;
757 
758 	return 0;
759 
760  out_free_memmap:
761 	kfree(wl->target_mem_map);
762 	wl->target_mem_map = NULL;
763 
764 	return ret;
765 }
766