]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/net/wireless/wl12xx/init.c
wl12xx: keep beacon-filtering enabled during STA operation
[mirror_ubuntu-bionic-kernel.git] / drivers / net / wireless / wl12xx / 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 "reg.h"
34 #include "tx.h"
35 #include "io.h"
36
37 int wl1271_init_templates_config(struct wl1271 *wl)
38 {
39 int ret, i;
40
41 /* send empty templates for fw memory reservation */
42 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
43 WL1271_CMD_TEMPL_DFLT_SIZE,
44 0, WL1271_RATE_AUTOMATIC);
45 if (ret < 0)
46 return ret;
47
48 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
49 NULL, WL1271_CMD_TEMPL_DFLT_SIZE, 0,
50 WL1271_RATE_AUTOMATIC);
51 if (ret < 0)
52 return ret;
53
54 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
55 sizeof(struct wl12xx_null_data_template),
56 0, WL1271_RATE_AUTOMATIC);
57 if (ret < 0)
58 return ret;
59
60 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL,
61 sizeof(struct wl12xx_ps_poll_template),
62 0, WL1271_RATE_AUTOMATIC);
63 if (ret < 0)
64 return ret;
65
66 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL,
67 sizeof
68 (struct wl12xx_qos_null_data_template),
69 0, WL1271_RATE_AUTOMATIC);
70 if (ret < 0)
71 return ret;
72
73 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL,
74 WL1271_CMD_TEMPL_DFLT_SIZE,
75 0, WL1271_RATE_AUTOMATIC);
76 if (ret < 0)
77 return ret;
78
79 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL,
80 WL1271_CMD_TEMPL_DFLT_SIZE,
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 /*
93 * Put very large empty placeholders for all templates. These
94 * reserve memory for later.
95 */
96 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL,
97 WL1271_CMD_TEMPL_MAX_SIZE,
98 0, WL1271_RATE_AUTOMATIC);
99 if (ret < 0)
100 return ret;
101
102 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL,
103 WL1271_CMD_TEMPL_MAX_SIZE,
104 0, WL1271_RATE_AUTOMATIC);
105 if (ret < 0)
106 return ret;
107
108 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, NULL,
109 sizeof
110 (struct wl12xx_disconn_template),
111 0, WL1271_RATE_AUTOMATIC);
112 if (ret < 0)
113 return ret;
114
115 for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
116 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL,
117 WL1271_CMD_TEMPL_DFLT_SIZE, i,
118 WL1271_RATE_AUTOMATIC);
119 if (ret < 0)
120 return ret;
121 }
122
123 return 0;
124 }
125
126 static int wl1271_ap_init_deauth_template(struct wl1271 *wl,
127 struct wl12xx_vif *wlvif)
128 {
129 struct wl12xx_disconn_template *tmpl;
130 int ret;
131 u32 rate;
132
133 tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
134 if (!tmpl) {
135 ret = -ENOMEM;
136 goto out;
137 }
138
139 tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
140 IEEE80211_STYPE_DEAUTH);
141
142 rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
143 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP,
144 tmpl, sizeof(*tmpl), 0, rate);
145
146 out:
147 kfree(tmpl);
148 return ret;
149 }
150
151 static int wl1271_ap_init_null_template(struct wl1271 *wl,
152 struct ieee80211_vif *vif)
153 {
154 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
155 struct ieee80211_hdr_3addr *nullfunc;
156 int ret;
157 u32 rate;
158
159 nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL);
160 if (!nullfunc) {
161 ret = -ENOMEM;
162 goto out;
163 }
164
165 nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
166 IEEE80211_STYPE_NULLFUNC |
167 IEEE80211_FCTL_FROMDS);
168
169 /* nullfunc->addr1 is filled by FW */
170
171 memcpy(nullfunc->addr2, vif->addr, ETH_ALEN);
172 memcpy(nullfunc->addr3, vif->addr, ETH_ALEN);
173
174 rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
175 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc,
176 sizeof(*nullfunc), 0, rate);
177
178 out:
179 kfree(nullfunc);
180 return ret;
181 }
182
183 static int wl1271_ap_init_qos_null_template(struct wl1271 *wl,
184 struct ieee80211_vif *vif)
185 {
186 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
187 struct ieee80211_qos_hdr *qosnull;
188 int ret;
189 u32 rate;
190
191 qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL);
192 if (!qosnull) {
193 ret = -ENOMEM;
194 goto out;
195 }
196
197 qosnull->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
198 IEEE80211_STYPE_QOS_NULLFUNC |
199 IEEE80211_FCTL_FROMDS);
200
201 /* qosnull->addr1 is filled by FW */
202
203 memcpy(qosnull->addr2, vif->addr, ETH_ALEN);
204 memcpy(qosnull->addr3, vif->addr, ETH_ALEN);
205
206 rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
207 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull,
208 sizeof(*qosnull), 0, rate);
209
210 out:
211 kfree(qosnull);
212 return ret;
213 }
214
215 static int wl12xx_init_rx_config(struct wl1271 *wl)
216 {
217 int ret;
218
219 ret = wl1271_acx_rx_msdu_life_time(wl);
220 if (ret < 0)
221 return ret;
222
223 return 0;
224 }
225
226 int wl1271_init_phy_config(struct wl1271 *wl)
227 {
228 int ret;
229
230 ret = wl1271_acx_pd_threshold(wl);
231 if (ret < 0)
232 return ret;
233
234 return 0;
235 }
236
237 static int wl12xx_init_phy_vif_config(struct wl1271 *wl,
238 struct wl12xx_vif *wlvif)
239 {
240 int ret;
241
242 ret = wl1271_acx_slot(wl, wlvif, DEFAULT_SLOT_TIME);
243 if (ret < 0)
244 return ret;
245
246 ret = wl1271_acx_service_period_timeout(wl, wlvif);
247 if (ret < 0)
248 return ret;
249
250 ret = wl1271_acx_rts_threshold(wl, wlvif, wl->hw->wiphy->rts_threshold);
251 if (ret < 0)
252 return ret;
253
254 return 0;
255 }
256
257 static int wl1271_init_sta_beacon_filter(struct wl1271 *wl,
258 struct wl12xx_vif *wlvif)
259 {
260 int ret;
261
262 ret = wl1271_acx_beacon_filter_table(wl, wlvif);
263 if (ret < 0)
264 return ret;
265
266 /* enable beacon filtering */
267 ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true);
268 if (ret < 0)
269 return ret;
270
271 return 0;
272 }
273
274 int wl1271_init_pta(struct wl1271 *wl)
275 {
276 int ret;
277
278 ret = wl12xx_acx_sg_cfg(wl);
279 if (ret < 0)
280 return ret;
281
282 ret = wl1271_acx_sg_enable(wl, wl->sg_enabled);
283 if (ret < 0)
284 return ret;
285
286 return 0;
287 }
288
289 int wl1271_init_energy_detection(struct wl1271 *wl)
290 {
291 int ret;
292
293 ret = wl1271_acx_cca_threshold(wl);
294 if (ret < 0)
295 return ret;
296
297 return 0;
298 }
299
300 static int wl1271_init_beacon_broadcast(struct wl1271 *wl,
301 struct wl12xx_vif *wlvif)
302 {
303 int ret;
304
305 ret = wl1271_acx_bcn_dtim_options(wl, wlvif);
306 if (ret < 0)
307 return ret;
308
309 return 0;
310 }
311
312 static int wl12xx_init_fwlog(struct wl1271 *wl)
313 {
314 int ret;
315
316 if (wl->quirks & WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED)
317 return 0;
318
319 ret = wl12xx_cmd_config_fwlog(wl);
320 if (ret < 0)
321 return ret;
322
323 return 0;
324 }
325
326 /* generic sta initialization (non vif-specific) */
327 static int wl1271_sta_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif)
328 {
329 int ret;
330
331 if (wl->chip.id != CHIP_ID_1283_PG20) {
332 ret = wl1271_cmd_ext_radio_parms(wl);
333 if (ret < 0)
334 return ret;
335 }
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 /* 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
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
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_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 */
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 */
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
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
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 else
665 ret = wl1271_cmd_general_parms(wl);
666 if (ret < 0)
667 return ret;
668
669 if (wl->chip.id == CHIP_ID_1283_PG20)
670 ret = wl128x_cmd_radio_parms(wl);
671 else
672 ret = wl1271_cmd_radio_parms(wl);
673 if (ret < 0)
674 return ret;
675
676 /* Chip-specific init */
677 ret = wl1271_chip_specific_init(wl);
678 if (ret < 0)
679 return ret;
680
681 /* Init templates */
682 ret = wl1271_init_templates_config(wl);
683 if (ret < 0)
684 return ret;
685
686 ret = wl12xx_acx_mem_cfg(wl);
687 if (ret < 0)
688 return ret;
689
690 /* Configure the FW logger */
691 ret = wl12xx_init_fwlog(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 /* PHY layer config */
711 ret = wl1271_init_phy_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 }