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