linux/drivers/net/wireless/ath/wcn36xx/main.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
   3 *
   4 * Permission to use, copy, modify, and/or distribute this software for any
   5 * purpose with or without fee is hereby granted, provided that the above
   6 * copyright notice and this permission notice appear in all copies.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15 */
  16
  17#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  18
  19#include <linux/module.h>
  20#include <linux/firmware.h>
  21#include <linux/platform_device.h>
  22#include <linux/of_address.h>
  23#include <linux/of_device.h>
  24#include <linux/of_irq.h>
  25#include <linux/rpmsg.h>
  26#include <linux/soc/qcom/smem_state.h>
  27#include <linux/soc/qcom/wcnss_ctrl.h>
  28#include "wcn36xx.h"
  29#include "testmode.h"
  30
  31unsigned int wcn36xx_dbg_mask;
  32module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644);
  33MODULE_PARM_DESC(debug_mask, "Debugging mask");
  34
  35#define CHAN2G(_freq, _idx) { \
  36        .band = NL80211_BAND_2GHZ, \
  37        .center_freq = (_freq), \
  38        .hw_value = (_idx), \
  39        .max_power = 25, \
  40}
  41
  42#define CHAN5G(_freq, _idx, _phy_val) { \
  43        .band = NL80211_BAND_5GHZ, \
  44        .center_freq = (_freq), \
  45        .hw_value = (_phy_val) << HW_VALUE_PHY_SHIFT | HW_VALUE_CHANNEL(_idx), \
  46        .max_power = 25, \
  47}
  48
  49/* The wcn firmware expects channel values to matching
  50 * their mnemonic values. So use these for .hw_value. */
  51static struct ieee80211_channel wcn_2ghz_channels[] = {
  52        CHAN2G(2412, 1), /* Channel 1 */
  53        CHAN2G(2417, 2), /* Channel 2 */
  54        CHAN2G(2422, 3), /* Channel 3 */
  55        CHAN2G(2427, 4), /* Channel 4 */
  56        CHAN2G(2432, 5), /* Channel 5 */
  57        CHAN2G(2437, 6), /* Channel 6 */
  58        CHAN2G(2442, 7), /* Channel 7 */
  59        CHAN2G(2447, 8), /* Channel 8 */
  60        CHAN2G(2452, 9), /* Channel 9 */
  61        CHAN2G(2457, 10), /* Channel 10 */
  62        CHAN2G(2462, 11), /* Channel 11 */
  63        CHAN2G(2467, 12), /* Channel 12 */
  64        CHAN2G(2472, 13), /* Channel 13 */
  65        CHAN2G(2484, 14)  /* Channel 14 */
  66
  67};
  68
  69static struct ieee80211_channel wcn_5ghz_channels[] = {
  70        CHAN5G(5180, 36, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
  71        CHAN5G(5200, 40, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
  72        CHAN5G(5220, 44, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
  73        CHAN5G(5240, 48, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
  74        CHAN5G(5260, 52, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
  75        CHAN5G(5280, 56, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
  76        CHAN5G(5300, 60, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
  77        CHAN5G(5320, 64, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
  78        CHAN5G(5500, 100, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
  79        CHAN5G(5520, 104, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
  80        CHAN5G(5540, 108, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
  81        CHAN5G(5560, 112, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
  82        CHAN5G(5580, 116, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
  83        CHAN5G(5600, 120, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
  84        CHAN5G(5620, 124, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
  85        CHAN5G(5640, 128, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
  86        CHAN5G(5660, 132, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
  87        CHAN5G(5700, 140, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
  88        CHAN5G(5745, 149, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
  89        CHAN5G(5765, 153, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
  90        CHAN5G(5785, 157, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
  91        CHAN5G(5805, 161, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
  92        CHAN5G(5825, 165, 0)
  93};
  94
  95#define RATE(_bitrate, _hw_rate, _flags) { \
  96        .bitrate        = (_bitrate),                   \
  97        .flags          = (_flags),                     \
  98        .hw_value       = (_hw_rate),                   \
  99        .hw_value_short = (_hw_rate)  \
 100}
 101
 102static struct ieee80211_rate wcn_2ghz_rates[] = {
 103        RATE(10, HW_RATE_INDEX_1MBPS, 0),
 104        RATE(20, HW_RATE_INDEX_2MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
 105        RATE(55, HW_RATE_INDEX_5_5MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
 106        RATE(110, HW_RATE_INDEX_11MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
 107        RATE(60, HW_RATE_INDEX_6MBPS, 0),
 108        RATE(90, HW_RATE_INDEX_9MBPS, 0),
 109        RATE(120, HW_RATE_INDEX_12MBPS, 0),
 110        RATE(180, HW_RATE_INDEX_18MBPS, 0),
 111        RATE(240, HW_RATE_INDEX_24MBPS, 0),
 112        RATE(360, HW_RATE_INDEX_36MBPS, 0),
 113        RATE(480, HW_RATE_INDEX_48MBPS, 0),
 114        RATE(540, HW_RATE_INDEX_54MBPS, 0)
 115};
 116
 117static struct ieee80211_rate wcn_5ghz_rates[] = {
 118        RATE(60, HW_RATE_INDEX_6MBPS, 0),
 119        RATE(90, HW_RATE_INDEX_9MBPS, 0),
 120        RATE(120, HW_RATE_INDEX_12MBPS, 0),
 121        RATE(180, HW_RATE_INDEX_18MBPS, 0),
 122        RATE(240, HW_RATE_INDEX_24MBPS, 0),
 123        RATE(360, HW_RATE_INDEX_36MBPS, 0),
 124        RATE(480, HW_RATE_INDEX_48MBPS, 0),
 125        RATE(540, HW_RATE_INDEX_54MBPS, 0)
 126};
 127
 128static struct ieee80211_supported_band wcn_band_2ghz = {
 129        .channels       = wcn_2ghz_channels,
 130        .n_channels     = ARRAY_SIZE(wcn_2ghz_channels),
 131        .bitrates       = wcn_2ghz_rates,
 132        .n_bitrates     = ARRAY_SIZE(wcn_2ghz_rates),
 133        .ht_cap         = {
 134                .cap =  IEEE80211_HT_CAP_GRN_FLD |
 135                        IEEE80211_HT_CAP_SGI_20 |
 136                        IEEE80211_HT_CAP_DSSSCCK40 |
 137                        IEEE80211_HT_CAP_LSIG_TXOP_PROT,
 138                .ht_supported = true,
 139                .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
 140                .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
 141                .mcs = {
 142                        .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
 143                        .rx_highest = cpu_to_le16(72),
 144                        .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
 145                }
 146        }
 147};
 148
 149static struct ieee80211_supported_band wcn_band_5ghz = {
 150        .channels       = wcn_5ghz_channels,
 151        .n_channels     = ARRAY_SIZE(wcn_5ghz_channels),
 152        .bitrates       = wcn_5ghz_rates,
 153        .n_bitrates     = ARRAY_SIZE(wcn_5ghz_rates),
 154        .ht_cap         = {
 155                .cap =  IEEE80211_HT_CAP_GRN_FLD |
 156                        IEEE80211_HT_CAP_SGI_20 |
 157                        IEEE80211_HT_CAP_DSSSCCK40 |
 158                        IEEE80211_HT_CAP_LSIG_TXOP_PROT |
 159                        IEEE80211_HT_CAP_SGI_40 |
 160                        IEEE80211_HT_CAP_SUP_WIDTH_20_40,
 161                .ht_supported = true,
 162                .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
 163                .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
 164                .mcs = {
 165                        .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
 166                        .rx_highest = cpu_to_le16(150),
 167                        .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
 168                }
 169        }
 170};
 171
 172#ifdef CONFIG_PM
 173
 174static const struct wiphy_wowlan_support wowlan_support = {
 175        .flags = WIPHY_WOWLAN_ANY
 176};
 177
 178#endif
 179
 180static inline u8 get_sta_index(struct ieee80211_vif *vif,
 181                               struct wcn36xx_sta *sta_priv)
 182{
 183        return NL80211_IFTYPE_STATION == vif->type ?
 184               sta_priv->bss_sta_index :
 185               sta_priv->sta_index;
 186}
 187
 188static const char * const wcn36xx_caps_names[] = {
 189        "MCC",                          /* 0 */
 190        "P2P",                          /* 1 */
 191        "DOT11AC",                      /* 2 */
 192        "SLM_SESSIONIZATION",           /* 3 */
 193        "DOT11AC_OPMODE",               /* 4 */
 194        "SAP32STA",                     /* 5 */
 195        "TDLS",                         /* 6 */
 196        "P2P_GO_NOA_DECOUPLE_INIT_SCAN",/* 7 */
 197        "WLANACTIVE_OFFLOAD",           /* 8 */
 198        "BEACON_OFFLOAD",               /* 9 */
 199        "SCAN_OFFLOAD",                 /* 10 */
 200        "ROAM_OFFLOAD",                 /* 11 */
 201        "BCN_MISS_OFFLOAD",             /* 12 */
 202        "STA_POWERSAVE",                /* 13 */
 203        "STA_ADVANCED_PWRSAVE",         /* 14 */
 204        "AP_UAPSD",                     /* 15 */
 205        "AP_DFS",                       /* 16 */
 206        "BLOCKACK",                     /* 17 */
 207        "PHY_ERR",                      /* 18 */
 208        "BCN_FILTER",                   /* 19 */
 209        "RTT",                          /* 20 */
 210        "RATECTRL",                     /* 21 */
 211        "WOW",                          /* 22 */
 212        "WLAN_ROAM_SCAN_OFFLOAD",       /* 23 */
 213        "SPECULATIVE_PS_POLL",          /* 24 */
 214        "SCAN_SCH",                     /* 25 */
 215        "IBSS_HEARTBEAT_OFFLOAD",       /* 26 */
 216        "WLAN_SCAN_OFFLOAD",            /* 27 */
 217        "WLAN_PERIODIC_TX_PTRN",        /* 28 */
 218        "ADVANCE_TDLS",                 /* 29 */
 219        "BATCH_SCAN",                   /* 30 */
 220        "FW_IN_TX_PATH",                /* 31 */
 221        "EXTENDED_NSOFFLOAD_SLOT",      /* 32 */
 222        "CH_SWITCH_V1",                 /* 33 */
 223        "HT40_OBSS_SCAN",               /* 34 */
 224        "UPDATE_CHANNEL_LIST",          /* 35 */
 225        "WLAN_MCADDR_FLT",              /* 36 */
 226        "WLAN_CH144",                   /* 37 */
 227        "NAN",                          /* 38 */
 228        "TDLS_SCAN_COEXISTENCE",        /* 39 */
 229        "LINK_LAYER_STATS_MEAS",        /* 40 */
 230        "MU_MIMO",                      /* 41 */
 231        "EXTENDED_SCAN",                /* 42 */
 232        "DYNAMIC_WMM_PS",               /* 43 */
 233        "MAC_SPOOFED_SCAN",             /* 44 */
 234        "BMU_ERROR_GENERIC_RECOVERY",   /* 45 */
 235        "DISA",                         /* 46 */
 236        "FW_STATS",                     /* 47 */
 237        "WPS_PRBRSP_TMPL",              /* 48 */
 238        "BCN_IE_FLT_DELTA",             /* 49 */
 239        "TDLS_OFF_CHANNEL",             /* 51 */
 240        "RTT3",                         /* 52 */
 241        "MGMT_FRAME_LOGGING",           /* 53 */
 242        "ENHANCED_TXBD_COMPLETION",     /* 54 */
 243        "LOGGING_ENHANCEMENT",          /* 55 */
 244        "EXT_SCAN_ENHANCED",            /* 56 */
 245        "MEMORY_DUMP_SUPPORTED",        /* 57 */
 246        "PER_PKT_STATS_SUPPORTED",      /* 58 */
 247        "EXT_LL_STAT",                  /* 60 */
 248        "WIFI_CONFIG",                  /* 61 */
 249        "ANTENNA_DIVERSITY_SELECTION",  /* 62 */
 250};
 251
 252static const char *wcn36xx_get_cap_name(enum place_holder_in_cap_bitmap x)
 253{
 254        if (x >= ARRAY_SIZE(wcn36xx_caps_names))
 255                return "UNKNOWN";
 256        return wcn36xx_caps_names[x];
 257}
 258
 259static void wcn36xx_feat_caps_info(struct wcn36xx *wcn)
 260{
 261        int i;
 262
 263        for (i = 0; i < MAX_FEATURE_SUPPORTED; i++) {
 264                if (get_feat_caps(wcn->fw_feat_caps, i))
 265                        wcn36xx_dbg(WCN36XX_DBG_MAC, "FW Cap %s\n", wcn36xx_get_cap_name(i));
 266        }
 267}
 268
 269static int wcn36xx_start(struct ieee80211_hw *hw)
 270{
 271        struct wcn36xx *wcn = hw->priv;
 272        int ret;
 273
 274        wcn36xx_dbg(WCN36XX_DBG_MAC, "mac start\n");
 275
 276        /* SMD initialization */
 277        ret = wcn36xx_smd_open(wcn);
 278        if (ret) {
 279                wcn36xx_err("Failed to open smd channel: %d\n", ret);
 280                goto out_err;
 281        }
 282
 283        /* Allocate memory pools for Mgmt BD headers and Data BD headers */
 284        ret = wcn36xx_dxe_allocate_mem_pools(wcn);
 285        if (ret) {
 286                wcn36xx_err("Failed to alloc DXE mempool: %d\n", ret);
 287                goto out_smd_close;
 288        }
 289
 290        ret = wcn36xx_dxe_alloc_ctl_blks(wcn);
 291        if (ret) {
 292                wcn36xx_err("Failed to alloc DXE ctl blocks: %d\n", ret);
 293                goto out_free_dxe_pool;
 294        }
 295
 296        wcn->hal_buf = kmalloc(WCN36XX_HAL_BUF_SIZE, GFP_KERNEL);
 297        if (!wcn->hal_buf) {
 298                wcn36xx_err("Failed to allocate smd buf\n");
 299                ret = -ENOMEM;
 300                goto out_free_dxe_ctl;
 301        }
 302
 303        ret = wcn36xx_smd_load_nv(wcn);
 304        if (ret) {
 305                wcn36xx_err("Failed to push NV to chip\n");
 306                goto out_free_smd_buf;
 307        }
 308
 309        ret = wcn36xx_smd_start(wcn);
 310        if (ret) {
 311                wcn36xx_err("Failed to start chip\n");
 312                goto out_free_smd_buf;
 313        }
 314
 315        if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
 316                ret = wcn36xx_smd_feature_caps_exchange(wcn);
 317                if (ret)
 318                        wcn36xx_warn("Exchange feature caps failed\n");
 319                else
 320                        wcn36xx_feat_caps_info(wcn);
 321        }
 322
 323        /* DMA channel initialization */
 324        ret = wcn36xx_dxe_init(wcn);
 325        if (ret) {
 326                wcn36xx_err("DXE init failed\n");
 327                goto out_smd_stop;
 328        }
 329
 330        wcn36xx_debugfs_init(wcn);
 331
 332        INIT_LIST_HEAD(&wcn->vif_list);
 333        spin_lock_init(&wcn->dxe_lock);
 334
 335        return 0;
 336
 337out_smd_stop:
 338        wcn36xx_smd_stop(wcn);
 339out_free_smd_buf:
 340        kfree(wcn->hal_buf);
 341out_free_dxe_ctl:
 342        wcn36xx_dxe_free_ctl_blks(wcn);
 343out_free_dxe_pool:
 344        wcn36xx_dxe_free_mem_pools(wcn);
 345out_smd_close:
 346        wcn36xx_smd_close(wcn);
 347out_err:
 348        return ret;
 349}
 350
 351static void wcn36xx_stop(struct ieee80211_hw *hw)
 352{
 353        struct wcn36xx *wcn = hw->priv;
 354
 355        wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop\n");
 356
 357        mutex_lock(&wcn->scan_lock);
 358        if (wcn->scan_req) {
 359                struct cfg80211_scan_info scan_info = {
 360                        .aborted = true,
 361                };
 362
 363                ieee80211_scan_completed(wcn->hw, &scan_info);
 364        }
 365        wcn->scan_req = NULL;
 366        mutex_unlock(&wcn->scan_lock);
 367
 368        wcn36xx_debugfs_exit(wcn);
 369        wcn36xx_smd_stop(wcn);
 370        wcn36xx_dxe_deinit(wcn);
 371        wcn36xx_smd_close(wcn);
 372
 373        wcn36xx_dxe_free_mem_pools(wcn);
 374        wcn36xx_dxe_free_ctl_blks(wcn);
 375
 376        kfree(wcn->hal_buf);
 377}
 378
 379static void wcn36xx_change_ps(struct wcn36xx *wcn, bool enable)
 380{
 381        struct ieee80211_vif *vif = NULL;
 382        struct wcn36xx_vif *tmp;
 383
 384        list_for_each_entry(tmp, &wcn->vif_list, list) {
 385                vif = wcn36xx_priv_to_vif(tmp);
 386                if (enable && !wcn->sw_scan) {
 387                        if (vif->bss_conf.ps) /* ps allowed ? */
 388                                wcn36xx_pmc_enter_bmps_state(wcn, vif);
 389                } else {
 390                        wcn36xx_pmc_exit_bmps_state(wcn, vif);
 391                }
 392        }
 393}
 394
 395static void wcn36xx_change_opchannel(struct wcn36xx *wcn, int ch)
 396{
 397        struct ieee80211_vif *vif = NULL;
 398        struct wcn36xx_vif *tmp;
 399
 400        list_for_each_entry(tmp, &wcn->vif_list, list) {
 401                vif = wcn36xx_priv_to_vif(tmp);
 402                wcn36xx_smd_switch_channel(wcn, vif, ch);
 403        }
 404}
 405
 406static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
 407{
 408        struct wcn36xx *wcn = hw->priv;
 409
 410        wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed);
 411
 412        mutex_lock(&wcn->conf_mutex);
 413
 414        if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
 415                int ch = WCN36XX_HW_CHANNEL(wcn);
 416                wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n",
 417                            ch);
 418
 419                if (wcn->sw_scan_opchannel == ch) {
 420                        /* If channel is the initial operating channel, we may
 421                         * want to receive/transmit regular data packets, then
 422                         * simply stop the scan session and exit PS mode.
 423                         */
 424                        wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN,
 425                                                wcn->sw_scan_vif);
 426                } else if (wcn->sw_scan) {
 427                        /* A scan is ongoing, do not change the operating
 428                         * channel, but start a scan session on the channel.
 429                         */
 430                        wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN,
 431                                              wcn->sw_scan_vif);
 432                        wcn36xx_smd_start_scan(wcn, ch);
 433                } else {
 434                        wcn36xx_change_opchannel(wcn, ch);
 435                }
 436        }
 437
 438        if (changed & IEEE80211_CONF_CHANGE_PS)
 439                wcn36xx_change_ps(wcn, hw->conf.flags & IEEE80211_CONF_PS);
 440
 441        mutex_unlock(&wcn->conf_mutex);
 442
 443        return 0;
 444}
 445
 446static void wcn36xx_configure_filter(struct ieee80211_hw *hw,
 447                                     unsigned int changed,
 448                                     unsigned int *total, u64 multicast)
 449{
 450        struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp;
 451        struct wcn36xx *wcn = hw->priv;
 452        struct wcn36xx_vif *tmp;
 453        struct ieee80211_vif *vif = NULL;
 454
 455        wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n");
 456
 457        mutex_lock(&wcn->conf_mutex);
 458
 459        *total &= FIF_ALLMULTI;
 460
 461        fp = (void *)(unsigned long)multicast;
 462        list_for_each_entry(tmp, &wcn->vif_list, list) {
 463                vif = wcn36xx_priv_to_vif(tmp);
 464
 465                /* FW handles MC filtering only when connected as STA */
 466                if (*total & FIF_ALLMULTI)
 467                        wcn36xx_smd_set_mc_list(wcn, vif, NULL);
 468                else if (NL80211_IFTYPE_STATION == vif->type && tmp->sta_assoc)
 469                        wcn36xx_smd_set_mc_list(wcn, vif, fp);
 470        }
 471
 472        mutex_unlock(&wcn->conf_mutex);
 473        kfree(fp);
 474}
 475
 476static u64 wcn36xx_prepare_multicast(struct ieee80211_hw *hw,
 477                                     struct netdev_hw_addr_list *mc_list)
 478{
 479        struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp;
 480        struct netdev_hw_addr *ha;
 481
 482        wcn36xx_dbg(WCN36XX_DBG_MAC, "mac prepare multicast list\n");
 483        fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
 484        if (!fp) {
 485                wcn36xx_err("Out of memory setting filters.\n");
 486                return 0;
 487        }
 488
 489        fp->mc_addr_count = 0;
 490        /* update multicast filtering parameters */
 491        if (netdev_hw_addr_list_count(mc_list) <=
 492            WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS) {
 493                netdev_hw_addr_list_for_each(ha, mc_list) {
 494                        memcpy(fp->mc_addr[fp->mc_addr_count],
 495                                        ha->addr, ETH_ALEN);
 496                        fp->mc_addr_count++;
 497                }
 498        }
 499
 500        return (u64)(unsigned long)fp;
 501}
 502
 503static void wcn36xx_tx(struct ieee80211_hw *hw,
 504                       struct ieee80211_tx_control *control,
 505                       struct sk_buff *skb)
 506{
 507        struct wcn36xx *wcn = hw->priv;
 508        struct wcn36xx_sta *sta_priv = NULL;
 509
 510        if (control->sta)
 511                sta_priv = wcn36xx_sta_to_priv(control->sta);
 512
 513        if (wcn36xx_start_tx(wcn, sta_priv, skb))
 514                ieee80211_free_txskb(wcn->hw, skb);
 515}
 516
 517static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 518                           struct ieee80211_vif *vif,
 519                           struct ieee80211_sta *sta,
 520                           struct ieee80211_key_conf *key_conf)
 521{
 522        struct wcn36xx *wcn = hw->priv;
 523        struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
 524        struct wcn36xx_sta *sta_priv = sta ? wcn36xx_sta_to_priv(sta) : NULL;
 525        int ret = 0;
 526        u8 key[WLAN_MAX_KEY_LEN];
 527
 528        wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 set key\n");
 529        wcn36xx_dbg(WCN36XX_DBG_MAC, "Key: cmd=0x%x algo:0x%x, id:%d, len:%d flags 0x%x\n",
 530                    cmd, key_conf->cipher, key_conf->keyidx,
 531                    key_conf->keylen, key_conf->flags);
 532        wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "KEY: ",
 533                         key_conf->key,
 534                         key_conf->keylen);
 535
 536        mutex_lock(&wcn->conf_mutex);
 537
 538        switch (key_conf->cipher) {
 539        case WLAN_CIPHER_SUITE_WEP40:
 540                vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40;
 541                break;
 542        case WLAN_CIPHER_SUITE_WEP104:
 543                vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP104;
 544                break;
 545        case WLAN_CIPHER_SUITE_CCMP:
 546                vif_priv->encrypt_type = WCN36XX_HAL_ED_CCMP;
 547                break;
 548        case WLAN_CIPHER_SUITE_TKIP:
 549                vif_priv->encrypt_type = WCN36XX_HAL_ED_TKIP;
 550                break;
 551        default:
 552                wcn36xx_err("Unsupported key type 0x%x\n",
 553                              key_conf->cipher);
 554                ret = -EOPNOTSUPP;
 555                goto out;
 556        }
 557
 558        switch (cmd) {
 559        case SET_KEY:
 560                if (WCN36XX_HAL_ED_TKIP == vif_priv->encrypt_type) {
 561                        /*
 562                         * Supplicant is sending key in the wrong order:
 563                         * Temporal Key (16 b) - TX MIC (8 b) - RX MIC (8 b)
 564                         * but HW expects it to be in the order as described in
 565                         * IEEE 802.11 spec (see chapter 11.7) like this:
 566                         * Temporal Key (16 b) - RX MIC (8 b) - TX MIC (8 b)
 567                         */
 568                        memcpy(key, key_conf->key, 16);
 569                        memcpy(key + 16, key_conf->key + 24, 8);
 570                        memcpy(key + 24, key_conf->key + 16, 8);
 571                } else {
 572                        memcpy(key, key_conf->key, key_conf->keylen);
 573                }
 574
 575                if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) {
 576                        sta_priv->is_data_encrypted = true;
 577                        /* Reconfigure bss with encrypt_type */
 578                        if (NL80211_IFTYPE_STATION == vif->type)
 579                                wcn36xx_smd_config_bss(wcn,
 580                                                       vif,
 581                                                       sta,
 582                                                       sta->addr,
 583                                                       true);
 584
 585                        wcn36xx_smd_set_stakey(wcn,
 586                                vif_priv->encrypt_type,
 587                                key_conf->keyidx,
 588                                key_conf->keylen,
 589                                key,
 590                                get_sta_index(vif, sta_priv));
 591                } else {
 592                        wcn36xx_smd_set_bsskey(wcn,
 593                                vif_priv->encrypt_type,
 594                                vif_priv->bss_index,
 595                                key_conf->keyidx,
 596                                key_conf->keylen,
 597                                key);
 598
 599                        if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) ||
 600                            (WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) {
 601                                list_for_each_entry(sta_priv,
 602                                                    &vif_priv->sta_list, list) {
 603                                        sta_priv->is_data_encrypted = true;
 604                                        wcn36xx_smd_set_stakey(wcn,
 605                                                vif_priv->encrypt_type,
 606                                                key_conf->keyidx,
 607                                                key_conf->keylen,
 608                                                key,
 609                                                get_sta_index(vif, sta_priv));
 610                                }
 611                        }
 612                }
 613                /* FIXME: Only enable bmps support when encryption is enabled.
 614                 * For any reasons, when connected to open/no-security BSS,
 615                 * the wcn36xx controller in bmps mode does not forward
 616                 * 'wake-up' beacons despite AP sends DTIM with station AID.
 617                 * It could be due to a firmware issue or to the way driver
 618                 * configure the station.
 619                 */
 620                if (vif->type == NL80211_IFTYPE_STATION)
 621                        vif_priv->allow_bmps = true;
 622                break;
 623        case DISABLE_KEY:
 624                if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) {
 625                        if (vif_priv->bss_index != WCN36XX_HAL_BSS_INVALID_IDX)
 626                                wcn36xx_smd_remove_bsskey(wcn,
 627                                        vif_priv->encrypt_type,
 628                                        vif_priv->bss_index,
 629                                        key_conf->keyidx);
 630
 631                        vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE;
 632                } else {
 633                        sta_priv->is_data_encrypted = false;
 634                        /* do not remove key if disassociated */
 635                        if (sta_priv->aid)
 636                                wcn36xx_smd_remove_stakey(wcn,
 637                                        vif_priv->encrypt_type,
 638                                        key_conf->keyidx,
 639                                        get_sta_index(vif, sta_priv));
 640                }
 641                break;
 642        default:
 643                wcn36xx_err("Unsupported key cmd 0x%x\n", cmd);
 644                ret = -EOPNOTSUPP;
 645                goto out;
 646        }
 647
 648out:
 649        mutex_unlock(&wcn->conf_mutex);
 650
 651        return ret;
 652}
 653
 654static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
 655                           struct ieee80211_vif *vif,
 656                           struct ieee80211_scan_request *hw_req)
 657{
 658        struct wcn36xx *wcn = hw->priv;
 659        int i;
 660
 661        if (!get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) {
 662                /* fallback to mac80211 software scan */
 663                return 1;
 664        }
 665
 666        /* For unknown reason, the hardware offloaded scan only works with
 667         * 2.4Ghz channels, fallback to software scan in other cases.
 668         */
 669        for (i = 0; i < hw_req->req.n_channels; i++) {
 670                if (hw_req->req.channels[i]->band != NL80211_BAND_2GHZ)
 671                        return 1;
 672        }
 673
 674        mutex_lock(&wcn->scan_lock);
 675        if (wcn->scan_req) {
 676                mutex_unlock(&wcn->scan_lock);
 677                return -EBUSY;
 678        }
 679
 680        wcn->scan_aborted = false;
 681        wcn->scan_req = &hw_req->req;
 682
 683        mutex_unlock(&wcn->scan_lock);
 684
 685        return wcn36xx_smd_start_hw_scan(wcn, vif, &hw_req->req);
 686}
 687
 688static void wcn36xx_cancel_hw_scan(struct ieee80211_hw *hw,
 689                                   struct ieee80211_vif *vif)
 690{
 691        struct wcn36xx *wcn = hw->priv;
 692
 693        mutex_lock(&wcn->scan_lock);
 694        wcn->scan_aborted = true;
 695        mutex_unlock(&wcn->scan_lock);
 696
 697        if (get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) {
 698                /* ieee80211_scan_completed will be called on FW scan
 699                 * indication */
 700                wcn36xx_smd_stop_hw_scan(wcn);
 701        }
 702}
 703
 704static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw,
 705                                  struct ieee80211_vif *vif,
 706                                  const u8 *mac_addr)
 707{
 708        struct wcn36xx *wcn = hw->priv;
 709        struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
 710
 711        wcn->sw_scan = true;
 712        wcn->sw_scan_vif = vif;
 713        if (vif_priv->sta_assoc)
 714                wcn->sw_scan_opchannel = WCN36XX_HW_CHANNEL(wcn);
 715        else
 716                wcn->sw_scan_opchannel = 0;
 717}
 718
 719static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw,
 720                                     struct ieee80211_vif *vif)
 721{
 722        struct wcn36xx *wcn = hw->priv;
 723
 724        /* ensure that any scan session is finished */
 725        wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN, wcn->sw_scan_vif);
 726        wcn->sw_scan = false;
 727        wcn->sw_scan_opchannel = 0;
 728}
 729
 730static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
 731                                         enum nl80211_band band)
 732{
 733        int i, size;
 734        u16 *rates_table;
 735        struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
 736        u32 rates = sta->supp_rates[band];
 737
 738        memset(&sta_priv->supported_rates, 0,
 739                sizeof(sta_priv->supported_rates));
 740        sta_priv->supported_rates.op_rate_mode = STA_11n;
 741
 742        size = ARRAY_SIZE(sta_priv->supported_rates.dsss_rates);
 743        rates_table = sta_priv->supported_rates.dsss_rates;
 744        if (band == NL80211_BAND_2GHZ) {
 745                for (i = 0; i < size; i++) {
 746                        if (rates & 0x01) {
 747                                rates_table[i] = wcn_2ghz_rates[i].hw_value;
 748                                rates = rates >> 1;
 749                        }
 750                }
 751        }
 752
 753        size = ARRAY_SIZE(sta_priv->supported_rates.ofdm_rates);
 754        rates_table = sta_priv->supported_rates.ofdm_rates;
 755        for (i = 0; i < size; i++) {
 756                if (rates & 0x01) {
 757                        rates_table[i] = wcn_5ghz_rates[i].hw_value;
 758                        rates = rates >> 1;
 759                }
 760        }
 761
 762        if (sta->ht_cap.ht_supported) {
 763                BUILD_BUG_ON(sizeof(sta->ht_cap.mcs.rx_mask) >
 764                        sizeof(sta_priv->supported_rates.supported_mcs_set));
 765                memcpy(sta_priv->supported_rates.supported_mcs_set,
 766                       sta->ht_cap.mcs.rx_mask,
 767                       sizeof(sta->ht_cap.mcs.rx_mask));
 768        }
 769
 770        if (sta->vht_cap.vht_supported) {
 771                sta_priv->supported_rates.op_rate_mode = STA_11ac;
 772                sta_priv->supported_rates.vht_rx_mcs_map =
 773                                sta->vht_cap.vht_mcs.rx_mcs_map;
 774                sta_priv->supported_rates.vht_tx_mcs_map =
 775                                sta->vht_cap.vht_mcs.tx_mcs_map;
 776        }
 777}
 778
 779void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates)
 780{
 781        u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES] = {
 782                HW_RATE_INDEX_6MBPS,
 783                HW_RATE_INDEX_9MBPS,
 784                HW_RATE_INDEX_12MBPS,
 785                HW_RATE_INDEX_18MBPS,
 786                HW_RATE_INDEX_24MBPS,
 787                HW_RATE_INDEX_36MBPS,
 788                HW_RATE_INDEX_48MBPS,
 789                HW_RATE_INDEX_54MBPS
 790        };
 791        u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES] = {
 792                HW_RATE_INDEX_1MBPS,
 793                HW_RATE_INDEX_2MBPS,
 794                HW_RATE_INDEX_5_5MBPS,
 795                HW_RATE_INDEX_11MBPS
 796        };
 797
 798        rates->op_rate_mode = STA_11n;
 799        memcpy(rates->dsss_rates, dsss_rates,
 800                sizeof(*dsss_rates) * WCN36XX_HAL_NUM_DSSS_RATES);
 801        memcpy(rates->ofdm_rates, ofdm_rates,
 802                sizeof(*ofdm_rates) * WCN36XX_HAL_NUM_OFDM_RATES);
 803        rates->supported_mcs_set[0] = 0xFF;
 804}
 805
 806void wcn36xx_set_default_rates_v1(struct wcn36xx_hal_supported_rates_v1 *rates)
 807{
 808        rates->op_rate_mode = STA_11ac;
 809        rates->vht_rx_mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9;
 810        rates->vht_tx_mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9;
 811}
 812
 813static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
 814                                     struct ieee80211_vif *vif,
 815                                     struct ieee80211_bss_conf *bss_conf,
 816                                     u32 changed)
 817{
 818        struct wcn36xx *wcn = hw->priv;
 819        struct sk_buff *skb = NULL;
 820        u16 tim_off, tim_len;
 821        enum wcn36xx_hal_link_state link_state;
 822        struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
 823
 824        wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n",
 825                    vif, changed);
 826
 827        mutex_lock(&wcn->conf_mutex);
 828
 829        if (changed & BSS_CHANGED_BEACON_INFO) {
 830                wcn36xx_dbg(WCN36XX_DBG_MAC,
 831                            "mac bss changed dtim period %d\n",
 832                            bss_conf->dtim_period);
 833
 834                vif_priv->dtim_period = bss_conf->dtim_period;
 835        }
 836
 837        if (changed & BSS_CHANGED_BSSID) {
 838                wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n",
 839                            bss_conf->bssid);
 840
 841                if (!is_zero_ether_addr(bss_conf->bssid)) {
 842                        vif_priv->is_joining = true;
 843                        vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
 844                        wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, vif->addr,
 845                                                WCN36XX_HAL_LINK_PREASSOC_STATE);
 846                        wcn36xx_smd_join(wcn, bss_conf->bssid,
 847                                         vif->addr, WCN36XX_HW_CHANNEL(wcn));
 848                        wcn36xx_smd_config_bss(wcn, vif, NULL,
 849                                               bss_conf->bssid, false);
 850                } else {
 851                        vif_priv->is_joining = false;
 852                        wcn36xx_smd_delete_bss(wcn, vif);
 853                        wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, vif->addr,
 854                                                WCN36XX_HAL_LINK_IDLE_STATE);
 855                        vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE;
 856                }
 857        }
 858
 859        if (changed & BSS_CHANGED_SSID) {
 860                wcn36xx_dbg(WCN36XX_DBG_MAC,
 861                            "mac bss changed ssid\n");
 862                wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "ssid ",
 863                                 bss_conf->ssid, bss_conf->ssid_len);
 864
 865                vif_priv->ssid.length = bss_conf->ssid_len;
 866                memcpy(&vif_priv->ssid.ssid,
 867                       bss_conf->ssid,
 868                       bss_conf->ssid_len);
 869        }
 870
 871        if (changed & BSS_CHANGED_ASSOC) {
 872                vif_priv->is_joining = false;
 873                if (bss_conf->assoc) {
 874                        struct ieee80211_sta *sta;
 875                        struct wcn36xx_sta *sta_priv;
 876
 877                        wcn36xx_dbg(WCN36XX_DBG_MAC,
 878                                    "mac assoc bss %pM vif %pM AID=%d\n",
 879                                     bss_conf->bssid,
 880                                     vif->addr,
 881                                     bss_conf->aid);
 882
 883                        vif_priv->sta_assoc = true;
 884
 885                        /*
 886                         * Holding conf_mutex ensures mutal exclusion with
 887                         * wcn36xx_sta_remove() and as such ensures that sta
 888                         * won't be freed while we're operating on it. As such
 889                         * we do not need to hold the rcu_read_lock().
 890                         */
 891                        sta = ieee80211_find_sta(vif, bss_conf->bssid);
 892                        if (!sta) {
 893                                wcn36xx_err("sta %pM is not found\n",
 894                                              bss_conf->bssid);
 895                                goto out;
 896                        }
 897                        sta_priv = wcn36xx_sta_to_priv(sta);
 898
 899                        wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn));
 900
 901                        wcn36xx_smd_set_link_st(wcn, bss_conf->bssid,
 902                                vif->addr,
 903                                WCN36XX_HAL_LINK_POSTASSOC_STATE);
 904                        wcn36xx_smd_config_bss(wcn, vif, sta,
 905                                               bss_conf->bssid,
 906                                               true);
 907                        sta_priv->aid = bss_conf->aid;
 908                        /*
 909                         * config_sta must be called from  because this is the
 910                         * place where AID is available.
 911                         */
 912                        wcn36xx_smd_config_sta(wcn, vif, sta);
 913                        wcn36xx_enable_keep_alive_null_packet(wcn, vif);
 914                } else {
 915                        wcn36xx_dbg(WCN36XX_DBG_MAC,
 916                                    "disassociated bss %pM vif %pM AID=%d\n",
 917                                    bss_conf->bssid,
 918                                    vif->addr,
 919                                    bss_conf->aid);
 920                        vif_priv->sta_assoc = false;
 921                        vif_priv->allow_bmps = false;
 922                        wcn36xx_smd_set_link_st(wcn,
 923                                                bss_conf->bssid,
 924                                                vif->addr,
 925                                                WCN36XX_HAL_LINK_IDLE_STATE);
 926                }
 927        }
 928
 929        if (changed & BSS_CHANGED_AP_PROBE_RESP) {
 930                wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed ap probe resp\n");
 931                skb = ieee80211_proberesp_get(hw, vif);
 932                if (!skb) {
 933                        wcn36xx_err("failed to alloc probereq skb\n");
 934                        goto out;
 935                }
 936
 937                wcn36xx_smd_update_proberesp_tmpl(wcn, vif, skb);
 938                dev_kfree_skb(skb);
 939        }
 940
 941        if (changed & BSS_CHANGED_BEACON_ENABLED ||
 942            changed & BSS_CHANGED_BEACON) {
 943                wcn36xx_dbg(WCN36XX_DBG_MAC,
 944                            "mac bss changed beacon enabled %d\n",
 945                            bss_conf->enable_beacon);
 946
 947                if (bss_conf->enable_beacon) {
 948                        vif_priv->dtim_period = bss_conf->dtim_period;
 949                        vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
 950                        wcn36xx_smd_config_bss(wcn, vif, NULL,
 951                                               vif->addr, false);
 952                        skb = ieee80211_beacon_get_tim(hw, vif, &tim_off,
 953                                                       &tim_len);
 954                        if (!skb) {
 955                                wcn36xx_err("failed to alloc beacon skb\n");
 956                                goto out;
 957                        }
 958                        wcn36xx_smd_send_beacon(wcn, vif, skb, tim_off, 0);
 959                        dev_kfree_skb(skb);
 960
 961                        if (vif->type == NL80211_IFTYPE_ADHOC ||
 962                            vif->type == NL80211_IFTYPE_MESH_POINT)
 963                                link_state = WCN36XX_HAL_LINK_IBSS_STATE;
 964                        else
 965                                link_state = WCN36XX_HAL_LINK_AP_STATE;
 966
 967                        wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
 968                                                link_state);
 969                } else {
 970                        wcn36xx_smd_delete_bss(wcn, vif);
 971                        wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
 972                                                WCN36XX_HAL_LINK_IDLE_STATE);
 973                }
 974        }
 975out:
 976
 977        mutex_unlock(&wcn->conf_mutex);
 978}
 979
 980/* this is required when using IEEE80211_HW_HAS_RATE_CONTROL */
 981static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
 982{
 983        struct wcn36xx *wcn = hw->priv;
 984        wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value);
 985
 986        mutex_lock(&wcn->conf_mutex);
 987        wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_RTS_THRESHOLD, value);
 988        mutex_unlock(&wcn->conf_mutex);
 989
 990        return 0;
 991}
 992
 993static void wcn36xx_remove_interface(struct ieee80211_hw *hw,
 994                                     struct ieee80211_vif *vif)
 995{
 996        struct wcn36xx *wcn = hw->priv;
 997        struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
 998        wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif);
 999
1000        mutex_lock(&wcn->conf_mutex);
1001
1002        list_del(&vif_priv->list);
1003        wcn36xx_smd_delete_sta_self(wcn, vif->addr);
1004
1005        mutex_unlock(&wcn->conf_mutex);
1006}
1007
1008static int wcn36xx_add_interface(struct ieee80211_hw *hw,
1009                                 struct ieee80211_vif *vif)
1010{
1011        struct wcn36xx *wcn = hw->priv;
1012        struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1013
1014        wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n",
1015                    vif, vif->type);
1016
1017        if (!(NL80211_IFTYPE_STATION == vif->type ||
1018              NL80211_IFTYPE_AP == vif->type ||
1019              NL80211_IFTYPE_ADHOC == vif->type ||
1020              NL80211_IFTYPE_MESH_POINT == vif->type)) {
1021                wcn36xx_warn("Unsupported interface type requested: %d\n",
1022                             vif->type);
1023                return -EOPNOTSUPP;
1024        }
1025
1026        mutex_lock(&wcn->conf_mutex);
1027
1028        vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
1029        INIT_LIST_HEAD(&vif_priv->sta_list);
1030        list_add(&vif_priv->list, &wcn->vif_list);
1031        wcn36xx_smd_add_sta_self(wcn, vif);
1032
1033        mutex_unlock(&wcn->conf_mutex);
1034
1035        return 0;
1036}
1037
1038static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1039                           struct ieee80211_sta *sta)
1040{
1041        struct wcn36xx *wcn = hw->priv;
1042        struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1043        struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
1044        wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n",
1045                    vif, sta->addr);
1046
1047        mutex_lock(&wcn->conf_mutex);
1048
1049        spin_lock_init(&sta_priv->ampdu_lock);
1050        sta_priv->vif = vif_priv;
1051        list_add(&sta_priv->list, &vif_priv->sta_list);
1052
1053        /*
1054         * For STA mode HW will be configured on BSS_CHANGED_ASSOC because
1055         * at this stage AID is not available yet.
1056         */
1057        if (NL80211_IFTYPE_STATION != vif->type) {
1058                wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn));
1059                sta_priv->aid = sta->aid;
1060                wcn36xx_smd_config_sta(wcn, vif, sta);
1061        }
1062
1063        mutex_unlock(&wcn->conf_mutex);
1064
1065        return 0;
1066}
1067
1068static int wcn36xx_sta_remove(struct ieee80211_hw *hw,
1069                              struct ieee80211_vif *vif,
1070                              struct ieee80211_sta *sta)
1071{
1072        struct wcn36xx *wcn = hw->priv;
1073        struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
1074
1075        wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n",
1076                    vif, sta->addr, sta_priv->sta_index);
1077
1078        mutex_lock(&wcn->conf_mutex);
1079
1080        list_del(&sta_priv->list);
1081        wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index);
1082        sta_priv->vif = NULL;
1083
1084        mutex_unlock(&wcn->conf_mutex);
1085
1086        return 0;
1087}
1088
1089#ifdef CONFIG_PM
1090
1091static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow)
1092{
1093        struct wcn36xx *wcn = hw->priv;
1094
1095        wcn36xx_dbg(WCN36XX_DBG_MAC, "mac suspend\n");
1096
1097        flush_workqueue(wcn->hal_ind_wq);
1098        wcn36xx_smd_set_power_params(wcn, true);
1099        return 0;
1100}
1101
1102static int wcn36xx_resume(struct ieee80211_hw *hw)
1103{
1104        struct wcn36xx *wcn = hw->priv;
1105
1106        wcn36xx_dbg(WCN36XX_DBG_MAC, "mac resume\n");
1107
1108        flush_workqueue(wcn->hal_ind_wq);
1109        wcn36xx_smd_set_power_params(wcn, false);
1110        return 0;
1111}
1112
1113#endif
1114
1115static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
1116                    struct ieee80211_vif *vif,
1117                    struct ieee80211_ampdu_params *params)
1118{
1119        struct wcn36xx *wcn = hw->priv;
1120        struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(params->sta);
1121        struct ieee80211_sta *sta = params->sta;
1122        enum ieee80211_ampdu_mlme_action action = params->action;
1123        u16 tid = params->tid;
1124        u16 *ssn = &params->ssn;
1125        int ret = 0;
1126        u8 session;
1127
1128        wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
1129                    action, tid);
1130
1131        mutex_lock(&wcn->conf_mutex);
1132
1133        switch (action) {
1134        case IEEE80211_AMPDU_RX_START:
1135                sta_priv->tid = tid;
1136                session = wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0,
1137                                                     get_sta_index(vif, sta_priv));
1138                wcn36xx_smd_add_ba(wcn, session);
1139                wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv), tid,
1140                                       session);
1141                break;
1142        case IEEE80211_AMPDU_RX_STOP:
1143                wcn36xx_smd_del_ba(wcn, tid, 0, get_sta_index(vif, sta_priv));
1144                break;
1145        case IEEE80211_AMPDU_TX_START:
1146                spin_lock_bh(&sta_priv->ampdu_lock);
1147                sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START;
1148                spin_unlock_bh(&sta_priv->ampdu_lock);
1149
1150                ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
1151                break;
1152        case IEEE80211_AMPDU_TX_OPERATIONAL:
1153                spin_lock_bh(&sta_priv->ampdu_lock);
1154                sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_OPERATIONAL;
1155                spin_unlock_bh(&sta_priv->ampdu_lock);
1156
1157                wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1,
1158                        get_sta_index(vif, sta_priv));
1159                break;
1160        case IEEE80211_AMPDU_TX_STOP_FLUSH:
1161        case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
1162        case IEEE80211_AMPDU_TX_STOP_CONT:
1163                spin_lock_bh(&sta_priv->ampdu_lock);
1164                sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_NONE;
1165                spin_unlock_bh(&sta_priv->ampdu_lock);
1166
1167                wcn36xx_smd_del_ba(wcn, tid, 1, get_sta_index(vif, sta_priv));
1168                ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1169                break;
1170        default:
1171                wcn36xx_err("Unknown AMPDU action\n");
1172        }
1173
1174        mutex_unlock(&wcn->conf_mutex);
1175
1176        return ret;
1177}
1178
1179static const struct ieee80211_ops wcn36xx_ops = {
1180        .start                  = wcn36xx_start,
1181        .stop                   = wcn36xx_stop,
1182        .add_interface          = wcn36xx_add_interface,
1183        .remove_interface       = wcn36xx_remove_interface,
1184#ifdef CONFIG_PM
1185        .suspend                = wcn36xx_suspend,
1186        .resume                 = wcn36xx_resume,
1187#endif
1188        .config                 = wcn36xx_config,
1189        .prepare_multicast      = wcn36xx_prepare_multicast,
1190        .configure_filter       = wcn36xx_configure_filter,
1191        .tx                     = wcn36xx_tx,
1192        .set_key                = wcn36xx_set_key,
1193        .hw_scan                = wcn36xx_hw_scan,
1194        .cancel_hw_scan         = wcn36xx_cancel_hw_scan,
1195        .sw_scan_start          = wcn36xx_sw_scan_start,
1196        .sw_scan_complete       = wcn36xx_sw_scan_complete,
1197        .bss_info_changed       = wcn36xx_bss_info_changed,
1198        .set_rts_threshold      = wcn36xx_set_rts_threshold,
1199        .sta_add                = wcn36xx_sta_add,
1200        .sta_remove             = wcn36xx_sta_remove,
1201        .ampdu_action           = wcn36xx_ampdu_action,
1202
1203        CFG80211_TESTMODE_CMD(wcn36xx_tm_cmd)
1204};
1205
1206static void
1207wcn36xx_set_ieee80211_vht_caps(struct ieee80211_sta_vht_cap *vht_cap)
1208{
1209        vht_cap->vht_supported = true;
1210
1211        vht_cap->cap = (IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 |
1212                        IEEE80211_VHT_CAP_SHORT_GI_80 |
1213                        IEEE80211_VHT_CAP_RXSTBC_1 |
1214                        IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
1215                        IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
1216                        3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT |
1217                        7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1218
1219        vht_cap->vht_mcs.rx_mcs_map =
1220                cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 |
1221                            IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 |
1222                            IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 |
1223                            IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 |
1224                            IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 |
1225                            IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 |
1226                            IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 |
1227                            IEEE80211_VHT_MCS_NOT_SUPPORTED << 14);
1228
1229        vht_cap->vht_mcs.rx_highest = cpu_to_le16(433);
1230        vht_cap->vht_mcs.tx_highest = vht_cap->vht_mcs.rx_highest;
1231
1232        vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map;
1233}
1234
1235static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
1236{
1237        static const u32 cipher_suites[] = {
1238                WLAN_CIPHER_SUITE_WEP40,
1239                WLAN_CIPHER_SUITE_WEP104,
1240                WLAN_CIPHER_SUITE_TKIP,
1241                WLAN_CIPHER_SUITE_CCMP,
1242        };
1243
1244        ieee80211_hw_set(wcn->hw, TIMING_BEACON_ONLY);
1245        ieee80211_hw_set(wcn->hw, AMPDU_AGGREGATION);
1246        ieee80211_hw_set(wcn->hw, SUPPORTS_PS);
1247        ieee80211_hw_set(wcn->hw, SIGNAL_DBM);
1248        ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL);
1249        ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS);
1250        ieee80211_hw_set(wcn->hw, REPORTS_TX_ACK_STATUS);
1251        ieee80211_hw_set(wcn->hw, CONNECTION_MONITOR);
1252
1253        wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
1254                BIT(NL80211_IFTYPE_AP) |
1255                BIT(NL80211_IFTYPE_ADHOC) |
1256                BIT(NL80211_IFTYPE_MESH_POINT);
1257
1258        wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = &wcn_band_2ghz;
1259        if (wcn->rf_id != RF_IRIS_WCN3620)
1260                wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = &wcn_band_5ghz;
1261
1262        if (wcn->rf_id == RF_IRIS_WCN3680)
1263                wcn36xx_set_ieee80211_vht_caps(&wcn_band_5ghz.vht_cap);
1264
1265        wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS;
1266        wcn->hw->wiphy->max_scan_ie_len = WCN36XX_MAX_SCAN_IE_LEN;
1267
1268        wcn->hw->wiphy->cipher_suites = cipher_suites;
1269        wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
1270
1271#ifdef CONFIG_PM
1272        wcn->hw->wiphy->wowlan = &wowlan_support;
1273#endif
1274
1275        wcn->hw->max_listen_interval = 200;
1276
1277        wcn->hw->queues = 4;
1278
1279        SET_IEEE80211_DEV(wcn->hw, wcn->dev);
1280
1281        wcn->hw->sta_data_size = sizeof(struct wcn36xx_sta);
1282        wcn->hw->vif_data_size = sizeof(struct wcn36xx_vif);
1283
1284        wiphy_ext_feature_set(wcn->hw->wiphy,
1285                              NL80211_EXT_FEATURE_CQM_RSSI_LIST);
1286
1287        return 0;
1288}
1289
1290static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
1291                                          struct platform_device *pdev)
1292{
1293        struct device_node *mmio_node;
1294        struct device_node *iris_node;
1295        struct resource *res;
1296        int index;
1297        int ret;
1298
1299        /* Set TX IRQ */
1300        res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "tx");
1301        if (!res) {
1302                wcn36xx_err("failed to get tx_irq\n");
1303                return -ENOENT;
1304        }
1305        wcn->tx_irq = res->start;
1306
1307        /* Set RX IRQ */
1308        res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "rx");
1309        if (!res) {
1310                wcn36xx_err("failed to get rx_irq\n");
1311                return -ENOENT;
1312        }
1313        wcn->rx_irq = res->start;
1314
1315        /* Acquire SMSM tx enable handle */
1316        wcn->tx_enable_state = qcom_smem_state_get(&pdev->dev,
1317                        "tx-enable", &wcn->tx_enable_state_bit);
1318        if (IS_ERR(wcn->tx_enable_state)) {
1319                wcn36xx_err("failed to get tx-enable state\n");
1320                return PTR_ERR(wcn->tx_enable_state);
1321        }
1322
1323        /* Acquire SMSM tx rings empty handle */
1324        wcn->tx_rings_empty_state = qcom_smem_state_get(&pdev->dev,
1325                        "tx-rings-empty", &wcn->tx_rings_empty_state_bit);
1326        if (IS_ERR(wcn->tx_rings_empty_state)) {
1327                wcn36xx_err("failed to get tx-rings-empty state\n");
1328                return PTR_ERR(wcn->tx_rings_empty_state);
1329        }
1330
1331        mmio_node = of_parse_phandle(pdev->dev.parent->of_node, "qcom,mmio", 0);
1332        if (!mmio_node) {
1333                wcn36xx_err("failed to acquire qcom,mmio reference\n");
1334                return -EINVAL;
1335        }
1336
1337        wcn->is_pronto = !!of_device_is_compatible(mmio_node, "qcom,pronto");
1338
1339        /* Map the CCU memory */
1340        index = of_property_match_string(mmio_node, "reg-names", "ccu");
1341        wcn->ccu_base = of_iomap(mmio_node, index);
1342        if (!wcn->ccu_base) {
1343                wcn36xx_err("failed to map ccu memory\n");
1344                ret = -ENOMEM;
1345                goto put_mmio_node;
1346        }
1347
1348        /* Map the DXE memory */
1349        index = of_property_match_string(mmio_node, "reg-names", "dxe");
1350        wcn->dxe_base = of_iomap(mmio_node, index);
1351        if (!wcn->dxe_base) {
1352                wcn36xx_err("failed to map dxe memory\n");
1353                ret = -ENOMEM;
1354                goto unmap_ccu;
1355        }
1356
1357        /* External RF module */
1358        iris_node = of_get_child_by_name(mmio_node, "iris");
1359        if (iris_node) {
1360                if (of_device_is_compatible(iris_node, "qcom,wcn3620"))
1361                        wcn->rf_id = RF_IRIS_WCN3620;
1362                if (of_device_is_compatible(iris_node, "qcom,wcn3680"))
1363                        wcn->rf_id = RF_IRIS_WCN3680;
1364                of_node_put(iris_node);
1365        }
1366
1367        of_node_put(mmio_node);
1368        return 0;
1369
1370unmap_ccu:
1371        iounmap(wcn->ccu_base);
1372put_mmio_node:
1373        of_node_put(mmio_node);
1374        return ret;
1375}
1376
1377static int wcn36xx_probe(struct platform_device *pdev)
1378{
1379        struct ieee80211_hw *hw;
1380        struct wcn36xx *wcn;
1381        void *wcnss;
1382        int ret;
1383        const u8 *addr;
1384
1385        wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
1386
1387        wcnss = dev_get_drvdata(pdev->dev.parent);
1388
1389        hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops);
1390        if (!hw) {
1391                wcn36xx_err("failed to alloc hw\n");
1392                ret = -ENOMEM;
1393                goto out_err;
1394        }
1395        platform_set_drvdata(pdev, hw);
1396        wcn = hw->priv;
1397        wcn->hw = hw;
1398        wcn->dev = &pdev->dev;
1399        wcn->first_boot = true;
1400        mutex_init(&wcn->conf_mutex);
1401        mutex_init(&wcn->hal_mutex);
1402        mutex_init(&wcn->scan_lock);
1403
1404        ret = dma_set_mask_and_coherent(wcn->dev, DMA_BIT_MASK(32));
1405        if (ret < 0) {
1406                wcn36xx_err("failed to set DMA mask: %d\n", ret);
1407                goto out_wq;
1408        }
1409
1410        wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process, hw);
1411        if (IS_ERR(wcn->smd_channel)) {
1412                wcn36xx_err("failed to open WLAN_CTRL channel\n");
1413                ret = PTR_ERR(wcn->smd_channel);
1414                goto out_wq;
1415        }
1416
1417        addr = of_get_property(pdev->dev.of_node, "local-mac-address", &ret);
1418        if (addr && ret != ETH_ALEN) {
1419                wcn36xx_err("invalid local-mac-address\n");
1420                ret = -EINVAL;
1421                goto out_destroy_ept;
1422        } else if (addr) {
1423                wcn36xx_info("mac address: %pM\n", addr);
1424                SET_IEEE80211_PERM_ADDR(wcn->hw, addr);
1425        }
1426
1427        ret = wcn36xx_platform_get_resources(wcn, pdev);
1428        if (ret)
1429                goto out_destroy_ept;
1430
1431        wcn36xx_init_ieee80211(wcn);
1432        ret = ieee80211_register_hw(wcn->hw);
1433        if (ret)
1434                goto out_unmap;
1435
1436        return 0;
1437
1438out_unmap:
1439        iounmap(wcn->ccu_base);
1440        iounmap(wcn->dxe_base);
1441out_destroy_ept:
1442        rpmsg_destroy_ept(wcn->smd_channel);
1443out_wq:
1444        ieee80211_free_hw(hw);
1445out_err:
1446        return ret;
1447}
1448
1449static int wcn36xx_remove(struct platform_device *pdev)
1450{
1451        struct ieee80211_hw *hw = platform_get_drvdata(pdev);
1452        struct wcn36xx *wcn = hw->priv;
1453        wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n");
1454
1455        release_firmware(wcn->nv);
1456
1457        ieee80211_unregister_hw(hw);
1458
1459        qcom_smem_state_put(wcn->tx_enable_state);
1460        qcom_smem_state_put(wcn->tx_rings_empty_state);
1461
1462        rpmsg_destroy_ept(wcn->smd_channel);
1463
1464        iounmap(wcn->dxe_base);
1465        iounmap(wcn->ccu_base);
1466
1467        mutex_destroy(&wcn->hal_mutex);
1468        ieee80211_free_hw(hw);
1469
1470        return 0;
1471}
1472
1473static const struct of_device_id wcn36xx_of_match[] = {
1474        { .compatible = "qcom,wcnss-wlan" },
1475        {}
1476};
1477MODULE_DEVICE_TABLE(of, wcn36xx_of_match);
1478
1479static struct platform_driver wcn36xx_driver = {
1480        .probe      = wcn36xx_probe,
1481        .remove     = wcn36xx_remove,
1482        .driver         = {
1483                .name   = "wcn36xx",
1484                .of_match_table = wcn36xx_of_match,
1485        },
1486};
1487
1488module_platform_driver(wcn36xx_driver);
1489
1490MODULE_LICENSE("Dual BSD/GPL");
1491MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com");
1492MODULE_FIRMWARE(WLAN_NV_FILE);
1493