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