xref: /openbmc/linux/drivers/net/wireless/ti/wlcore/init.c (revision 66340e5b)
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 "tx.h"
34 #include "io.h"
35 #include "hw_ops.h"
36 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
318 static int wl12xx_init_fwlog(struct wl1271 *wl)
319 {
320 	int ret;
321 
322 	if (wl->quirks & WLCORE_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) */
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 
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) */
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 
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 
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 
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 	/* get extra MIMO or wide-chan rates where the HW supports it */
464 	supported_rates |= wlcore_hw_ap_get_mimo_wide_rate_mask(wl, wlvif);
465 
466 	/* configure unicast TX rate classes */
467 	for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
468 		rc.enabled_rates = supported_rates;
469 		rc.short_retry_limit = 10;
470 		rc.long_retry_limit = 10;
471 		rc.aflags = 0;
472 		ret = wl1271_acx_ap_rate_policy(wl, &rc,
473 						wlvif->ap.ucast_rate_idx[i]);
474 		if (ret < 0)
475 			return ret;
476 	}
477 
478 	return 0;
479 }
480 
481 static int wl1271_set_ba_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif)
482 {
483 	/* Reset the BA RX indicators */
484 	wlvif->ba_allowed = true;
485 	wl->ba_rx_session_count = 0;
486 
487 	/* BA is supported in STA/AP modes */
488 	if (wlvif->bss_type != BSS_TYPE_AP_BSS &&
489 	    wlvif->bss_type != BSS_TYPE_STA_BSS) {
490 		wlvif->ba_support = false;
491 		return 0;
492 	}
493 
494 	wlvif->ba_support = true;
495 
496 	/* 802.11n initiator BA session setting */
497 	return wl12xx_acx_set_ba_initiator_policy(wl, wlvif);
498 }
499 
500 /* vif-specifc initialization */
501 static int wl12xx_init_sta_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
502 {
503 	int ret;
504 
505 	ret = wl1271_acx_group_address_tbl(wl, wlvif, true, NULL, 0);
506 	if (ret < 0)
507 		return ret;
508 
509 	/* Initialize connection monitoring thresholds */
510 	ret = wl1271_acx_conn_monit_params(wl, wlvif, false);
511 	if (ret < 0)
512 		return ret;
513 
514 	/* Beacon filtering */
515 	ret = wl1271_init_sta_beacon_filter(wl, wlvif);
516 	if (ret < 0)
517 		return ret;
518 
519 	/* Beacons and broadcast settings */
520 	ret = wl1271_init_beacon_broadcast(wl, wlvif);
521 	if (ret < 0)
522 		return ret;
523 
524 	/* Configure rssi/snr averaging weights */
525 	ret = wl1271_acx_rssi_snr_avg_weights(wl, wlvif);
526 	if (ret < 0)
527 		return ret;
528 
529 	return 0;
530 }
531 
532 /* vif-specific intialization */
533 static int wl12xx_init_ap_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
534 {
535 	int ret;
536 
537 	ret = wl1271_acx_ap_max_tx_retry(wl, wlvif);
538 	if (ret < 0)
539 		return ret;
540 
541 	/* initialize Tx power */
542 	ret = wl1271_acx_tx_power(wl, wlvif, wlvif->power_level);
543 	if (ret < 0)
544 		return ret;
545 
546 	return 0;
547 }
548 
549 int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif)
550 {
551 	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
552 	struct conf_tx_ac_category *conf_ac;
553 	struct conf_tx_tid *conf_tid;
554 	bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
555 	int ret, i;
556 
557 	/*
558 	 * consider all existing roles before configuring psm.
559 	 * TODO: reconfigure on interface removal.
560 	 */
561 	if (!wl->ap_count) {
562 		if (is_ap) {
563 			/* Configure for power always on */
564 			ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
565 			if (ret < 0)
566 				return ret;
567 		} else if (!wl->sta_count) {
568 			u8 sta_auth = wl->conf.conn.sta_sleep_auth;
569 			if (sta_auth != WL1271_PSM_ILLEGAL) {
570 				/* Configure for power according to debugfs */
571 				ret = wl1271_acx_sleep_auth(wl, sta_auth);
572 				if (ret < 0)
573 					return ret;
574 			} else if (wl->quirks & WLCORE_QUIRK_NO_ELP) {
575 				/* Configure for power always on */
576 				ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
577 				if (ret < 0)
578 					return ret;
579 			} else {
580 				/* Configure for ELP power saving */
581 				ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
582 				if (ret < 0)
583 					return ret;
584 			}
585 		}
586 	}
587 
588 	/* Mode specific init */
589 	if (is_ap) {
590 		ret = wl1271_ap_hw_init(wl, wlvif);
591 		if (ret < 0)
592 			return ret;
593 
594 		ret = wl12xx_init_ap_role(wl, wlvif);
595 		if (ret < 0)
596 			return ret;
597 	} else {
598 		ret = wl1271_sta_hw_init(wl, wlvif);
599 		if (ret < 0)
600 			return ret;
601 
602 		ret = wl12xx_init_sta_role(wl, wlvif);
603 		if (ret < 0)
604 			return ret;
605 	}
606 
607 	wl12xx_init_phy_vif_config(wl, wlvif);
608 
609 	/* Default TID/AC configuration */
610 	BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count);
611 	for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
612 		conf_ac = &wl->conf.tx.ac_conf[i];
613 		ret = wl1271_acx_ac_cfg(wl, wlvif, conf_ac->ac,
614 					conf_ac->cw_min, conf_ac->cw_max,
615 					conf_ac->aifsn, conf_ac->tx_op_limit);
616 		if (ret < 0)
617 			return ret;
618 
619 		conf_tid = &wl->conf.tx.tid_conf[i];
620 		ret = wl1271_acx_tid_cfg(wl, wlvif,
621 					 conf_tid->queue_id,
622 					 conf_tid->channel_type,
623 					 conf_tid->tsid,
624 					 conf_tid->ps_scheme,
625 					 conf_tid->ack_policy,
626 					 conf_tid->apsd_conf[0],
627 					 conf_tid->apsd_conf[1]);
628 		if (ret < 0)
629 			return ret;
630 	}
631 
632 	/* Configure HW encryption */
633 	ret = wl1271_acx_feature_cfg(wl, wlvif);
634 	if (ret < 0)
635 		return ret;
636 
637 	/* Mode specific init - post mem init */
638 	if (is_ap)
639 		ret = wl1271_ap_hw_init_post_mem(wl, vif);
640 	else
641 		ret = wl1271_sta_hw_init_post_mem(wl, vif);
642 
643 	if (ret < 0)
644 		return ret;
645 
646 	/* Configure initiator BA sessions policies */
647 	ret = wl1271_set_ba_policies(wl, wlvif);
648 	if (ret < 0)
649 		return ret;
650 
651 	ret = wlcore_hw_init_vif(wl, wlvif);
652 	if (ret < 0)
653 		return ret;
654 
655 	return 0;
656 }
657 
658 int wl1271_hw_init(struct wl1271 *wl)
659 {
660 	int ret;
661 
662 	/* Chip-specific hw init */
663 	ret = wl->ops->hw_init(wl);
664 	if (ret < 0)
665 		return ret;
666 
667 	/* Init templates */
668 	ret = wl1271_init_templates_config(wl);
669 	if (ret < 0)
670 		return ret;
671 
672 	ret = wl12xx_acx_mem_cfg(wl);
673 	if (ret < 0)
674 		return ret;
675 
676 	/* Configure the FW logger */
677 	ret = wl12xx_init_fwlog(wl);
678 	if (ret < 0)
679 		return ret;
680 
681 	/* Bluetooth WLAN coexistence */
682 	ret = wl1271_init_pta(wl);
683 	if (ret < 0)
684 		return ret;
685 
686 	/* Default memory configuration */
687 	ret = wl1271_acx_init_mem_config(wl);
688 	if (ret < 0)
689 		return ret;
690 
691 	/* RX config */
692 	ret = wl12xx_init_rx_config(wl);
693 	if (ret < 0)
694 		goto out_free_memmap;
695 
696 	ret = wl1271_acx_dco_itrim_params(wl);
697 	if (ret < 0)
698 		goto out_free_memmap;
699 
700 	/* Configure TX patch complete interrupt behavior */
701 	ret = wl1271_acx_tx_config_options(wl);
702 	if (ret < 0)
703 		goto out_free_memmap;
704 
705 	/* RX complete interrupt pacing */
706 	ret = wl1271_acx_init_rx_interrupt(wl);
707 	if (ret < 0)
708 		goto out_free_memmap;
709 
710 	/* Energy detection */
711 	ret = wl1271_init_energy_detection(wl);
712 	if (ret < 0)
713 		goto out_free_memmap;
714 
715 	/* Default fragmentation threshold */
716 	ret = wl1271_acx_frag_threshold(wl, wl->hw->wiphy->frag_threshold);
717 	if (ret < 0)
718 		goto out_free_memmap;
719 
720 	/* Enable data path */
721 	ret = wl1271_cmd_data_path(wl, 1);
722 	if (ret < 0)
723 		goto out_free_memmap;
724 
725 	/* configure PM */
726 	ret = wl1271_acx_pm_config(wl);
727 	if (ret < 0)
728 		goto out_free_memmap;
729 
730 	ret = wl12xx_acx_set_rate_mgmt_params(wl);
731 	if (ret < 0)
732 		goto out_free_memmap;
733 
734 	/* configure hangover */
735 	ret = wl12xx_acx_config_hangover(wl);
736 	if (ret < 0)
737 		goto out_free_memmap;
738 
739 	return 0;
740 
741  out_free_memmap:
742 	kfree(wl->target_mem_map);
743 	wl->target_mem_map = NULL;
744 
745 	return ret;
746 }
747