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