root/drivers/net/wireless/ti/wlcore/init.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wl1271_init_templates_config
  2. wl1271_ap_init_deauth_template
  3. wl1271_ap_init_null_template
  4. wl1271_ap_init_qos_null_template
  5. wl12xx_init_rx_config
  6. wl12xx_init_phy_vif_config
  7. wl1271_init_sta_beacon_filter
  8. wl1271_init_pta
  9. wl1271_init_energy_detection
  10. wl1271_init_beacon_broadcast
  11. wl12xx_init_fwlog
  12. wl1271_sta_hw_init
  13. wl1271_sta_hw_init_post_mem
  14. wl1271_ap_hw_init
  15. wl1271_ap_init_templates
  16. wl1271_ap_hw_init_post_mem
  17. wl1271_init_ap_rates
  18. wl1271_set_ba_policies
  19. wl12xx_init_sta_role
  20. wl12xx_init_ap_role
  21. wl1271_init_vif_specific
  22. wl1271_hw_init

   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 
  23 int 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 
 144 static 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 
 165 out:
 166         kfree(tmpl);
 167         return ret;
 168 }
 169 
 170 static 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 
 198 out:
 199         kfree(nullfunc);
 200         return ret;
 201 }
 202 
 203 static 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 
 231 out:
 232         kfree(qosnull);
 233         return ret;
 234 }
 235 
 236 static 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 
 247 static 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 
 267 static 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 
 284 int 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 
 299 int 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 
 310 static 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 
 322 static 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) */
 337 int 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 
 358 static 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) */
 373 static 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 
 389 int 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 
 417 static 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 
 423 int 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 
 482 static 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 */
 502 static 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 */
 534 static 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 
 555 int 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 
 659 int 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 }

/* [<][>][^][v][top][bottom][index][help] */