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