linux/drivers/net/wireless/mwifiex/cfg80211.c
<<
>>
Prefs
   1/*
   2 * Marvell Wireless LAN device driver: CFG80211
   3 *
   4 * Copyright (C) 2011-2014, Marvell International Ltd.
   5 *
   6 * This software file (the "File") is distributed by Marvell International
   7 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
   8 * (the "License").  You may use, redistribute and/or modify this File in
   9 * accordance with the terms and conditions of the License, a copy of which
  10 * is available by writing to the Free Software Foundation, Inc.,
  11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
  12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
  13 *
  14 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  15 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  16 * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
  17 * this warranty disclaimer.
  18 */
  19
  20#include "cfg80211.h"
  21#include "main.h"
  22#include "11n.h"
  23
  24static char *reg_alpha2;
  25module_param(reg_alpha2, charp, 0);
  26
  27static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = {
  28        {
  29                .max = 2, .types = BIT(NL80211_IFTYPE_STATION) |
  30                                   BIT(NL80211_IFTYPE_P2P_GO) |
  31                                   BIT(NL80211_IFTYPE_P2P_CLIENT),
  32        },
  33        {
  34                .max = 1, .types = BIT(NL80211_IFTYPE_AP),
  35        },
  36};
  37
  38static const struct ieee80211_iface_combination
  39mwifiex_iface_comb_ap_sta = {
  40        .limits = mwifiex_ap_sta_limits,
  41        .num_different_channels = 1,
  42        .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),
  43        .max_interfaces = MWIFIEX_MAX_BSS_NUM,
  44        .beacon_int_infra_match = true,
  45        .radar_detect_widths =  BIT(NL80211_CHAN_WIDTH_20_NOHT) |
  46                                BIT(NL80211_CHAN_WIDTH_20) |
  47                                BIT(NL80211_CHAN_WIDTH_40),
  48};
  49
  50static const struct ieee80211_iface_combination
  51mwifiex_iface_comb_ap_sta_vht = {
  52        .limits = mwifiex_ap_sta_limits,
  53        .num_different_channels = 1,
  54        .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),
  55        .max_interfaces = MWIFIEX_MAX_BSS_NUM,
  56        .beacon_int_infra_match = true,
  57        .radar_detect_widths =  BIT(NL80211_CHAN_WIDTH_20_NOHT) |
  58                                BIT(NL80211_CHAN_WIDTH_20) |
  59                                BIT(NL80211_CHAN_WIDTH_40) |
  60                                BIT(NL80211_CHAN_WIDTH_80),
  61};
  62
  63static const struct
  64ieee80211_iface_combination mwifiex_iface_comb_ap_sta_drcs = {
  65        .limits = mwifiex_ap_sta_limits,
  66        .num_different_channels = 2,
  67        .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),
  68        .max_interfaces = MWIFIEX_MAX_BSS_NUM,
  69        .beacon_int_infra_match = true,
  70};
  71
  72/*
  73 * This function maps the nl802.11 channel type into driver channel type.
  74 *
  75 * The mapping is as follows -
  76 *      NL80211_CHAN_NO_HT     -> IEEE80211_HT_PARAM_CHA_SEC_NONE
  77 *      NL80211_CHAN_HT20      -> IEEE80211_HT_PARAM_CHA_SEC_NONE
  78 *      NL80211_CHAN_HT40PLUS  -> IEEE80211_HT_PARAM_CHA_SEC_ABOVE
  79 *      NL80211_CHAN_HT40MINUS -> IEEE80211_HT_PARAM_CHA_SEC_BELOW
  80 *      Others                 -> IEEE80211_HT_PARAM_CHA_SEC_NONE
  81 */
  82u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type)
  83{
  84        switch (chan_type) {
  85        case NL80211_CHAN_NO_HT:
  86        case NL80211_CHAN_HT20:
  87                return IEEE80211_HT_PARAM_CHA_SEC_NONE;
  88        case NL80211_CHAN_HT40PLUS:
  89                return IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
  90        case NL80211_CHAN_HT40MINUS:
  91                return IEEE80211_HT_PARAM_CHA_SEC_BELOW;
  92        default:
  93                return IEEE80211_HT_PARAM_CHA_SEC_NONE;
  94        }
  95}
  96
  97/* This function maps IEEE HT secondary channel type to NL80211 channel type
  98 */
  99u8 mwifiex_sec_chan_offset_to_chan_type(u8 second_chan_offset)
 100{
 101        switch (second_chan_offset) {
 102        case IEEE80211_HT_PARAM_CHA_SEC_NONE:
 103                return NL80211_CHAN_HT20;
 104        case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
 105                return NL80211_CHAN_HT40PLUS;
 106        case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
 107                return NL80211_CHAN_HT40MINUS;
 108        default:
 109                return NL80211_CHAN_HT20;
 110        }
 111}
 112
 113/*
 114 * This function checks whether WEP is set.
 115 */
 116static int
 117mwifiex_is_alg_wep(u32 cipher)
 118{
 119        switch (cipher) {
 120        case WLAN_CIPHER_SUITE_WEP40:
 121        case WLAN_CIPHER_SUITE_WEP104:
 122                return 1;
 123        default:
 124                break;
 125        }
 126
 127        return 0;
 128}
 129
 130/*
 131 * This function retrieves the private structure from kernel wiphy structure.
 132 */
 133static void *mwifiex_cfg80211_get_adapter(struct wiphy *wiphy)
 134{
 135        return (void *) (*(unsigned long *) wiphy_priv(wiphy));
 136}
 137
 138/*
 139 * CFG802.11 operation handler to delete a network key.
 140 */
 141static int
 142mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,
 143                         u8 key_index, bool pairwise, const u8 *mac_addr)
 144{
 145        struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
 146        const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 147        const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
 148
 149        if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index, peer_mac, 1)) {
 150                mwifiex_dbg(priv->adapter, ERROR, "deleting the crypto keys\n");
 151                return -EFAULT;
 152        }
 153
 154        mwifiex_dbg(priv->adapter, INFO, "info: crypto keys deleted\n");
 155        return 0;
 156}
 157
 158/*
 159 * This function forms an skb for management frame.
 160 */
 161static int
 162mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len)
 163{
 164        u8 addr[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 165        u16 pkt_len;
 166        u32 tx_control = 0, pkt_type = PKT_TYPE_MGMT;
 167
 168        pkt_len = len + ETH_ALEN;
 169
 170        skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN +
 171                    MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
 172        memcpy(skb_push(skb, sizeof(pkt_len)), &pkt_len, sizeof(pkt_len));
 173
 174        memcpy(skb_push(skb, sizeof(tx_control)),
 175               &tx_control, sizeof(tx_control));
 176
 177        memcpy(skb_push(skb, sizeof(pkt_type)), &pkt_type, sizeof(pkt_type));
 178
 179        /* Add packet data and address4 */
 180        memcpy(skb_put(skb, sizeof(struct ieee80211_hdr_3addr)), buf,
 181               sizeof(struct ieee80211_hdr_3addr));
 182        memcpy(skb_put(skb, ETH_ALEN), addr, ETH_ALEN);
 183        memcpy(skb_put(skb, len - sizeof(struct ieee80211_hdr_3addr)),
 184               buf + sizeof(struct ieee80211_hdr_3addr),
 185               len - sizeof(struct ieee80211_hdr_3addr));
 186
 187        skb->priority = LOW_PRIO_TID;
 188        __net_timestamp(skb);
 189
 190        return 0;
 191}
 192
 193/*
 194 * CFG802.11 operation handler to transmit a management frame.
 195 */
 196static int
 197mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 198                         struct cfg80211_mgmt_tx_params *params, u64 *cookie)
 199{
 200        const u8 *buf = params->buf;
 201        size_t len = params->len;
 202        struct sk_buff *skb;
 203        u16 pkt_len;
 204        const struct ieee80211_mgmt *mgmt;
 205        struct mwifiex_txinfo *tx_info;
 206        struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
 207
 208        if (!buf || !len) {
 209                mwifiex_dbg(priv->adapter, ERROR, "invalid buffer and length\n");
 210                return -EFAULT;
 211        }
 212
 213        mgmt = (const struct ieee80211_mgmt *)buf;
 214        if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA &&
 215            ieee80211_is_probe_resp(mgmt->frame_control)) {
 216                /* Since we support offload probe resp, we need to skip probe
 217                 * resp in AP or GO mode */
 218                mwifiex_dbg(priv->adapter, INFO,
 219                            "info: skip to send probe resp in AP or GO mode\n");
 220                return 0;
 221        }
 222
 223        pkt_len = len + ETH_ALEN;
 224        skb = dev_alloc_skb(MWIFIEX_MIN_DATA_HEADER_LEN +
 225                            MWIFIEX_MGMT_FRAME_HEADER_SIZE +
 226                            pkt_len + sizeof(pkt_len));
 227
 228        if (!skb) {
 229                mwifiex_dbg(priv->adapter, ERROR,
 230                            "allocate skb failed for management frame\n");
 231                return -ENOMEM;
 232        }
 233
 234        tx_info = MWIFIEX_SKB_TXCB(skb);
 235        memset(tx_info, 0, sizeof(*tx_info));
 236        tx_info->bss_num = priv->bss_num;
 237        tx_info->bss_type = priv->bss_type;
 238        tx_info->pkt_len = pkt_len;
 239
 240        mwifiex_form_mgmt_frame(skb, buf, len);
 241        *cookie = prandom_u32() | 1;
 242
 243        if (ieee80211_is_action(mgmt->frame_control))
 244                skb = mwifiex_clone_skb_for_tx_status(priv,
 245                                                      skb,
 246                                MWIFIEX_BUF_FLAG_ACTION_TX_STATUS, cookie);
 247        else
 248                cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,
 249                                        GFP_ATOMIC);
 250
 251        mwifiex_queue_tx_pkt(priv, skb);
 252
 253        mwifiex_dbg(priv->adapter, INFO, "info: management frame transmitted\n");
 254        return 0;
 255}
 256
 257/*
 258 * CFG802.11 operation handler to register a mgmt frame.
 259 */
 260static void
 261mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
 262                                     struct wireless_dev *wdev,
 263                                     u16 frame_type, bool reg)
 264{
 265        struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
 266        u32 mask;
 267
 268        if (reg)
 269                mask = priv->mgmt_frame_mask | BIT(frame_type >> 4);
 270        else
 271                mask = priv->mgmt_frame_mask & ~BIT(frame_type >> 4);
 272
 273        if (mask != priv->mgmt_frame_mask) {
 274                priv->mgmt_frame_mask = mask;
 275                mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
 276                                 HostCmd_ACT_GEN_SET, 0,
 277                                 &priv->mgmt_frame_mask, false);
 278                mwifiex_dbg(priv->adapter, INFO, "info: mgmt frame registered\n");
 279        }
 280}
 281
 282/*
 283 * CFG802.11 operation handler to remain on channel.
 284 */
 285static int
 286mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
 287                                   struct wireless_dev *wdev,
 288                                   struct ieee80211_channel *chan,
 289                                   unsigned int duration, u64 *cookie)
 290{
 291        struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
 292        int ret;
 293
 294        if (!chan || !cookie) {
 295                mwifiex_dbg(priv->adapter, ERROR, "Invalid parameter for ROC\n");
 296                return -EINVAL;
 297        }
 298
 299        if (priv->roc_cfg.cookie) {
 300                mwifiex_dbg(priv->adapter, INFO,
 301                            "info: ongoing ROC, cookie = 0x%llx\n",
 302                            priv->roc_cfg.cookie);
 303                return -EBUSY;
 304        }
 305
 306        ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET, chan,
 307                                         duration);
 308
 309        if (!ret) {
 310                *cookie = prandom_u32() | 1;
 311                priv->roc_cfg.cookie = *cookie;
 312                priv->roc_cfg.chan = *chan;
 313
 314                cfg80211_ready_on_channel(wdev, *cookie, chan,
 315                                          duration, GFP_ATOMIC);
 316
 317                mwifiex_dbg(priv->adapter, INFO,
 318                            "info: ROC, cookie = 0x%llx\n", *cookie);
 319        }
 320
 321        return ret;
 322}
 323
 324/*
 325 * CFG802.11 operation handler to cancel remain on channel.
 326 */
 327static int
 328mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
 329                                          struct wireless_dev *wdev, u64 cookie)
 330{
 331        struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
 332        int ret;
 333
 334        if (cookie != priv->roc_cfg.cookie)
 335                return -ENOENT;
 336
 337        ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE,
 338                                         &priv->roc_cfg.chan, 0);
 339
 340        if (!ret) {
 341                cfg80211_remain_on_channel_expired(wdev, cookie,
 342                                                   &priv->roc_cfg.chan,
 343                                                   GFP_ATOMIC);
 344
 345                memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg));
 346
 347                mwifiex_dbg(priv->adapter, INFO,
 348                            "info: cancel ROC, cookie = 0x%llx\n", cookie);
 349        }
 350
 351        return ret;
 352}
 353
 354/*
 355 * CFG802.11 operation handler to set Tx power.
 356 */
 357static int
 358mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy,
 359                              struct wireless_dev *wdev,
 360                              enum nl80211_tx_power_setting type,
 361                              int mbm)
 362{
 363        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
 364        struct mwifiex_private *priv;
 365        struct mwifiex_power_cfg power_cfg;
 366        int dbm = MBM_TO_DBM(mbm);
 367
 368        if (type == NL80211_TX_POWER_FIXED) {
 369                power_cfg.is_power_auto = 0;
 370                power_cfg.power_level = dbm;
 371        } else {
 372                power_cfg.is_power_auto = 1;
 373        }
 374
 375        priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 376
 377        return mwifiex_set_tx_power(priv, &power_cfg);
 378}
 379
 380/*
 381 * CFG802.11 operation handler to set Power Save option.
 382 *
 383 * The timeout value, if provided, is currently ignored.
 384 */
 385static int
 386mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy,
 387                                struct net_device *dev,
 388                                bool enabled, int timeout)
 389{
 390        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 391        u32 ps_mode;
 392
 393        if (timeout)
 394                mwifiex_dbg(priv->adapter, INFO,
 395                            "info: ignore timeout value for IEEE Power Save\n");
 396
 397        ps_mode = enabled;
 398
 399        return mwifiex_drv_set_power(priv, &ps_mode);
 400}
 401
 402/*
 403 * CFG802.11 operation handler to set the default network key.
 404 */
 405static int
 406mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
 407                                 u8 key_index, bool unicast,
 408                                 bool multicast)
 409{
 410        struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
 411
 412        /* Return if WEP key not configured */
 413        if (!priv->sec_info.wep_enabled)
 414                return 0;
 415
 416        if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) {
 417                priv->wep_key_curr_index = key_index;
 418        } else if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index,
 419                                      NULL, 0)) {
 420                mwifiex_dbg(priv->adapter, ERROR, "set default Tx key index\n");
 421                return -EFAULT;
 422        }
 423
 424        return 0;
 425}
 426
 427/*
 428 * CFG802.11 operation handler to add a network key.
 429 */
 430static int
 431mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
 432                         u8 key_index, bool pairwise, const u8 *mac_addr,
 433                         struct key_params *params)
 434{
 435        struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
 436        struct mwifiex_wep_key *wep_key;
 437        const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 438        const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
 439
 440        if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&
 441            (params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
 442             params->cipher == WLAN_CIPHER_SUITE_WEP104)) {
 443                if (params->key && params->key_len) {
 444                        wep_key = &priv->wep_key[key_index];
 445                        memset(wep_key, 0, sizeof(struct mwifiex_wep_key));
 446                        memcpy(wep_key->key_material, params->key,
 447                               params->key_len);
 448                        wep_key->key_index = key_index;
 449                        wep_key->key_length = params->key_len;
 450                        priv->sec_info.wep_enabled = 1;
 451                }
 452                return 0;
 453        }
 454
 455        if (mwifiex_set_encode(priv, params, params->key, params->key_len,
 456                               key_index, peer_mac, 0)) {
 457                mwifiex_dbg(priv->adapter, ERROR, "crypto keys added\n");
 458                return -EFAULT;
 459        }
 460
 461        return 0;
 462}
 463
 464/*
 465 * This function sends domain information to the firmware.
 466 *
 467 * The following information are passed to the firmware -
 468 *      - Country codes
 469 *      - Sub bands (first channel, number of channels, maximum Tx power)
 470 */
 471int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
 472{
 473        u8 no_of_triplet = 0;
 474        struct ieee80211_country_ie_triplet *t;
 475        u8 no_of_parsed_chan = 0;
 476        u8 first_chan = 0, next_chan = 0, max_pwr = 0;
 477        u8 i, flag = 0;
 478        enum ieee80211_band band;
 479        struct ieee80211_supported_band *sband;
 480        struct ieee80211_channel *ch;
 481        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
 482        struct mwifiex_private *priv;
 483        struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg;
 484
 485        /* Set country code */
 486        domain_info->country_code[0] = adapter->country_code[0];
 487        domain_info->country_code[1] = adapter->country_code[1];
 488        domain_info->country_code[2] = ' ';
 489
 490        band = mwifiex_band_to_radio_type(adapter->config_bands);
 491        if (!wiphy->bands[band]) {
 492                mwifiex_dbg(adapter, ERROR,
 493                            "11D: setting domain info in FW\n");
 494                return -1;
 495        }
 496
 497        sband = wiphy->bands[band];
 498
 499        for (i = 0; i < sband->n_channels ; i++) {
 500                ch = &sband->channels[i];
 501                if (ch->flags & IEEE80211_CHAN_DISABLED)
 502                        continue;
 503
 504                if (!flag) {
 505                        flag = 1;
 506                        first_chan = (u32) ch->hw_value;
 507                        next_chan = first_chan;
 508                        max_pwr = ch->max_power;
 509                        no_of_parsed_chan = 1;
 510                        continue;
 511                }
 512
 513                if (ch->hw_value == next_chan + 1 &&
 514                    ch->max_power == max_pwr) {
 515                        next_chan++;
 516                        no_of_parsed_chan++;
 517                } else {
 518                        t = &domain_info->triplet[no_of_triplet];
 519                        t->chans.first_channel = first_chan;
 520                        t->chans.num_channels = no_of_parsed_chan;
 521                        t->chans.max_power = max_pwr;
 522                        no_of_triplet++;
 523                        first_chan = (u32) ch->hw_value;
 524                        next_chan = first_chan;
 525                        max_pwr = ch->max_power;
 526                        no_of_parsed_chan = 1;
 527                }
 528        }
 529
 530        if (flag) {
 531                t = &domain_info->triplet[no_of_triplet];
 532                t->chans.first_channel = first_chan;
 533                t->chans.num_channels = no_of_parsed_chan;
 534                t->chans.max_power = max_pwr;
 535                no_of_triplet++;
 536        }
 537
 538        domain_info->no_of_triplet = no_of_triplet;
 539
 540        priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 541
 542        if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
 543                             HostCmd_ACT_GEN_SET, 0, NULL, false)) {
 544                mwifiex_dbg(adapter, INFO,
 545                            "11D: setting domain info in FW\n");
 546                return -1;
 547        }
 548
 549        return 0;
 550}
 551
 552/*
 553 * CFG802.11 regulatory domain callback function.
 554 *
 555 * This function is called when the regulatory domain is changed due to the
 556 * following reasons -
 557 *      - Set by driver
 558 *      - Set by system core
 559 *      - Set by user
 560 *      - Set bt Country IE
 561 */
 562static void mwifiex_reg_notifier(struct wiphy *wiphy,
 563                                 struct regulatory_request *request)
 564{
 565        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
 566        struct mwifiex_private *priv = mwifiex_get_priv(adapter,
 567                                                        MWIFIEX_BSS_ROLE_ANY);
 568        mwifiex_dbg(adapter, INFO,
 569                    "info: cfg80211 regulatory domain callback for %c%c\n",
 570                    request->alpha2[0], request->alpha2[1]);
 571
 572        switch (request->initiator) {
 573        case NL80211_REGDOM_SET_BY_DRIVER:
 574        case NL80211_REGDOM_SET_BY_CORE:
 575        case NL80211_REGDOM_SET_BY_USER:
 576        case NL80211_REGDOM_SET_BY_COUNTRY_IE:
 577                break;
 578        default:
 579                mwifiex_dbg(adapter, ERROR,
 580                            "unknown regdom initiator: %d\n",
 581                            request->initiator);
 582                return;
 583        }
 584
 585        /* Don't send world or same regdom info to firmware */
 586        if (strncmp(request->alpha2, "00", 2) &&
 587            strncmp(request->alpha2, adapter->country_code,
 588                    sizeof(request->alpha2))) {
 589                memcpy(adapter->country_code, request->alpha2,
 590                       sizeof(request->alpha2));
 591                mwifiex_send_domain_info_cmd_fw(wiphy);
 592                mwifiex_dnld_txpwr_table(priv);
 593        }
 594}
 595
 596/*
 597 * This function sets the fragmentation threshold.
 598 *
 599 * The fragmentation threshold value must lie between MWIFIEX_FRAG_MIN_VALUE
 600 * and MWIFIEX_FRAG_MAX_VALUE.
 601 */
 602static int
 603mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr)
 604{
 605        if (frag_thr < MWIFIEX_FRAG_MIN_VALUE ||
 606            frag_thr > MWIFIEX_FRAG_MAX_VALUE)
 607                frag_thr = MWIFIEX_FRAG_MAX_VALUE;
 608
 609        return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
 610                                HostCmd_ACT_GEN_SET, FRAG_THRESH_I,
 611                                &frag_thr, true);
 612}
 613
 614/*
 615 * This function sets the RTS threshold.
 616
 617 * The rts value must lie between MWIFIEX_RTS_MIN_VALUE
 618 * and MWIFIEX_RTS_MAX_VALUE.
 619 */
 620static int
 621mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr)
 622{
 623        if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE)
 624                rts_thr = MWIFIEX_RTS_MAX_VALUE;
 625
 626        return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
 627                                HostCmd_ACT_GEN_SET, RTS_THRESH_I,
 628                                &rts_thr, true);
 629}
 630
 631/*
 632 * CFG802.11 operation handler to set wiphy parameters.
 633 *
 634 * This function can be used to set the RTS threshold and the
 635 * Fragmentation threshold of the driver.
 636 */
 637static int
 638mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 639{
 640        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
 641        struct mwifiex_private *priv;
 642        struct mwifiex_uap_bss_param *bss_cfg;
 643        int ret;
 644
 645        priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 646
 647        switch (priv->bss_role) {
 648        case MWIFIEX_BSS_ROLE_UAP:
 649                if (priv->bss_started) {
 650                        mwifiex_dbg(adapter, ERROR,
 651                                    "cannot change wiphy params when bss started");
 652                        return -EINVAL;
 653                }
 654
 655                bss_cfg = kzalloc(sizeof(*bss_cfg), GFP_KERNEL);
 656                if (!bss_cfg)
 657                        return -ENOMEM;
 658
 659                mwifiex_set_sys_config_invalid_data(bss_cfg);
 660
 661                if (changed & WIPHY_PARAM_RTS_THRESHOLD)
 662                        bss_cfg->rts_threshold = wiphy->rts_threshold;
 663                if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
 664                        bss_cfg->frag_threshold = wiphy->frag_threshold;
 665                if (changed & WIPHY_PARAM_RETRY_LONG)
 666                        bss_cfg->retry_limit = wiphy->retry_long;
 667
 668                ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
 669                                       HostCmd_ACT_GEN_SET,
 670                                       UAP_BSS_PARAMS_I, bss_cfg,
 671                                       false);
 672
 673                kfree(bss_cfg);
 674                if (ret) {
 675                        mwifiex_dbg(adapter, ERROR,
 676                                    "Failed to set wiphy phy params\n");
 677                        return ret;
 678                }
 679                break;
 680
 681                case MWIFIEX_BSS_ROLE_STA:
 682                if (priv->media_connected) {
 683                        mwifiex_dbg(adapter, ERROR,
 684                                    "cannot change wiphy params when connected");
 685                        return -EINVAL;
 686                }
 687                if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
 688                        ret = mwifiex_set_rts(priv,
 689                                              wiphy->rts_threshold);
 690                        if (ret)
 691                                return ret;
 692                }
 693                if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
 694                        ret = mwifiex_set_frag(priv,
 695                                               wiphy->frag_threshold);
 696                        if (ret)
 697                                return ret;
 698                }
 699                break;
 700        }
 701
 702        return 0;
 703}
 704
 705static int
 706mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv)
 707{
 708        u16 mode = P2P_MODE_DISABLE;
 709
 710        if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
 711                             HostCmd_ACT_GEN_SET, 0, &mode, true))
 712                return -1;
 713
 714        return 0;
 715}
 716
 717/*
 718 * This function initializes the functionalities for P2P client.
 719 * The P2P client initialization sequence is:
 720 * disable -> device -> client
 721 */
 722static int
 723mwifiex_cfg80211_init_p2p_client(struct mwifiex_private *priv)
 724{
 725        u16 mode;
 726
 727        if (mwifiex_cfg80211_deinit_p2p(priv))
 728                return -1;
 729
 730        mode = P2P_MODE_DEVICE;
 731        if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
 732                             HostCmd_ACT_GEN_SET, 0, &mode, true))
 733                return -1;
 734
 735        mode = P2P_MODE_CLIENT;
 736        if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
 737                             HostCmd_ACT_GEN_SET, 0, &mode, true))
 738                return -1;
 739
 740        return 0;
 741}
 742
 743/*
 744 * This function initializes the functionalities for P2P GO.
 745 * The P2P GO initialization sequence is:
 746 * disable -> device -> GO
 747 */
 748static int
 749mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv)
 750{
 751        u16 mode;
 752
 753        if (mwifiex_cfg80211_deinit_p2p(priv))
 754                return -1;
 755
 756        mode = P2P_MODE_DEVICE;
 757        if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
 758                             HostCmd_ACT_GEN_SET, 0, &mode, true))
 759                return -1;
 760
 761        mode = P2P_MODE_GO;
 762        if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
 763                             HostCmd_ACT_GEN_SET, 0, &mode, true))
 764                return -1;
 765
 766        return 0;
 767}
 768
 769static int mwifiex_deinit_priv_params(struct mwifiex_private *priv)
 770{
 771        struct mwifiex_adapter *adapter = priv->adapter;
 772        unsigned long flags;
 773
 774        priv->mgmt_frame_mask = 0;
 775        if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
 776                             HostCmd_ACT_GEN_SET, 0,
 777                             &priv->mgmt_frame_mask, false)) {
 778                mwifiex_dbg(adapter, ERROR,
 779                            "could not unregister mgmt frame rx\n");
 780                return -1;
 781        }
 782
 783        mwifiex_deauthenticate(priv, NULL);
 784
 785        spin_lock_irqsave(&adapter->main_proc_lock, flags);
 786        adapter->main_locked = true;
 787        if (adapter->mwifiex_processing) {
 788                spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
 789                flush_workqueue(adapter->workqueue);
 790        } else {
 791                spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
 792        }
 793
 794        spin_lock_irqsave(&adapter->rx_proc_lock, flags);
 795        adapter->rx_locked = true;
 796        if (adapter->rx_processing) {
 797                spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
 798                flush_workqueue(adapter->rx_workqueue);
 799        } else {
 800        spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
 801        }
 802
 803        mwifiex_free_priv(priv);
 804        priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
 805        priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
 806        priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM;
 807
 808        return 0;
 809}
 810
 811static int
 812mwifiex_init_new_priv_params(struct mwifiex_private *priv,
 813                             struct net_device *dev,
 814                             enum nl80211_iftype type)
 815{
 816        struct mwifiex_adapter *adapter = priv->adapter;
 817        unsigned long flags;
 818
 819        mwifiex_init_priv(priv);
 820
 821        priv->bss_mode = type;
 822        priv->wdev.iftype = type;
 823
 824        mwifiex_init_priv_params(priv, priv->netdev);
 825        priv->bss_started = 0;
 826
 827        switch (type) {
 828        case NL80211_IFTYPE_STATION:
 829        case NL80211_IFTYPE_ADHOC:
 830                priv->bss_role =  MWIFIEX_BSS_ROLE_STA;
 831                priv->bss_type = MWIFIEX_BSS_TYPE_STA;
 832                break;
 833        case NL80211_IFTYPE_P2P_CLIENT:
 834                priv->bss_role =  MWIFIEX_BSS_ROLE_STA;
 835                priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
 836                break;
 837        case NL80211_IFTYPE_P2P_GO:
 838                priv->bss_role =  MWIFIEX_BSS_ROLE_UAP;
 839                priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
 840                break;
 841        case NL80211_IFTYPE_AP:
 842                priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
 843                priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
 844                break;
 845        default:
 846                mwifiex_dbg(adapter, ERROR,
 847                            "%s: changing to %d not supported\n",
 848                            dev->name, type);
 849                return -EOPNOTSUPP;
 850        }
 851
 852        spin_lock_irqsave(&adapter->main_proc_lock, flags);
 853        adapter->main_locked = false;
 854        spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
 855
 856        spin_lock_irqsave(&adapter->rx_proc_lock, flags);
 857        adapter->rx_locked = false;
 858        spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
 859
 860        return 0;
 861}
 862
 863static int
 864mwifiex_change_vif_to_p2p(struct net_device *dev,
 865                          enum nl80211_iftype curr_iftype,
 866                          enum nl80211_iftype type, u32 *flags,
 867                          struct vif_params *params)
 868{
 869        struct mwifiex_private *priv;
 870        struct mwifiex_adapter *adapter;
 871
 872        priv = mwifiex_netdev_get_priv(dev);
 873
 874        if (!priv)
 875                return -1;
 876
 877        adapter = priv->adapter;
 878
 879        if (adapter->curr_iface_comb.p2p_intf ==
 880            adapter->iface_limit.p2p_intf) {
 881                mwifiex_dbg(adapter, ERROR,
 882                            "cannot create multiple P2P ifaces\n");
 883                return -1;
 884        }
 885
 886        mwifiex_dbg(adapter, INFO,
 887                    "%s: changing role to p2p\n", dev->name);
 888
 889        if (mwifiex_deinit_priv_params(priv))
 890                return -1;
 891        if (mwifiex_init_new_priv_params(priv, dev, type))
 892                return -1;
 893
 894        switch (type) {
 895        case NL80211_IFTYPE_P2P_CLIENT:
 896                if (mwifiex_cfg80211_init_p2p_client(priv))
 897                        return -EFAULT;
 898                break;
 899        case NL80211_IFTYPE_P2P_GO:
 900                if (mwifiex_cfg80211_init_p2p_go(priv))
 901                        return -EFAULT;
 902                break;
 903        default:
 904                mwifiex_dbg(adapter, ERROR,
 905                            "%s: changing to %d not supported\n",
 906                            dev->name, type);
 907                return -EOPNOTSUPP;
 908        }
 909
 910        if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
 911                             HostCmd_ACT_GEN_SET, 0, NULL, true))
 912                return -1;
 913
 914        if (mwifiex_sta_init_cmd(priv, false, false))
 915                return -1;
 916
 917        switch (curr_iftype) {
 918        case NL80211_IFTYPE_STATION:
 919        case NL80211_IFTYPE_ADHOC:
 920                adapter->curr_iface_comb.sta_intf--;
 921                break;
 922        case NL80211_IFTYPE_AP:
 923                adapter->curr_iface_comb.uap_intf--;
 924                break;
 925        default:
 926                break;
 927        }
 928
 929        adapter->curr_iface_comb.p2p_intf++;
 930        dev->ieee80211_ptr->iftype = type;
 931
 932        return 0;
 933}
 934
 935static int
 936mwifiex_change_vif_to_sta_adhoc(struct net_device *dev,
 937                                enum nl80211_iftype curr_iftype,
 938                                enum nl80211_iftype type, u32 *flags,
 939                                struct vif_params *params)
 940{
 941        struct mwifiex_private *priv;
 942        struct mwifiex_adapter *adapter;
 943
 944        priv = mwifiex_netdev_get_priv(dev);
 945
 946        if (!priv)
 947                return -1;
 948
 949        adapter = priv->adapter;
 950
 951        if ((curr_iftype != NL80211_IFTYPE_P2P_CLIENT &&
 952             curr_iftype != NL80211_IFTYPE_P2P_GO) &&
 953            (adapter->curr_iface_comb.sta_intf ==
 954             adapter->iface_limit.sta_intf)) {
 955                mwifiex_dbg(adapter, ERROR,
 956                            "cannot create multiple station/adhoc ifaces\n");
 957                return -1;
 958        }
 959
 960        if (type == NL80211_IFTYPE_STATION)
 961                mwifiex_dbg(adapter, INFO,
 962                            "%s: changing role to station\n", dev->name);
 963        else
 964                mwifiex_dbg(adapter, INFO,
 965                            "%s: changing role to adhoc\n", dev->name);
 966
 967        if (mwifiex_deinit_priv_params(priv))
 968                return -1;
 969        if (mwifiex_init_new_priv_params(priv, dev, type))
 970                return -1;
 971        if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
 972                             HostCmd_ACT_GEN_SET, 0, NULL, true))
 973                return -1;
 974        if (mwifiex_sta_init_cmd(priv, false, false))
 975                return -1;
 976
 977        switch (curr_iftype) {
 978        case NL80211_IFTYPE_P2P_CLIENT:
 979        case NL80211_IFTYPE_P2P_GO:
 980                adapter->curr_iface_comb.p2p_intf--;
 981                break;
 982        case NL80211_IFTYPE_AP:
 983                adapter->curr_iface_comb.uap_intf--;
 984                break;
 985        default:
 986                break;
 987        }
 988
 989        adapter->curr_iface_comb.sta_intf++;
 990        dev->ieee80211_ptr->iftype = type;
 991        return 0;
 992}
 993
 994static int
 995mwifiex_change_vif_to_ap(struct net_device *dev,
 996                         enum nl80211_iftype curr_iftype,
 997                         enum nl80211_iftype type, u32 *flags,
 998                         struct vif_params *params)
 999{
1000        struct mwifiex_private *priv;
1001        struct mwifiex_adapter *adapter;
1002
1003        priv = mwifiex_netdev_get_priv(dev);
1004
1005        if (!priv)
1006                return -1;
1007
1008        adapter = priv->adapter;
1009
1010        if (adapter->curr_iface_comb.uap_intf ==
1011            adapter->iface_limit.uap_intf) {
1012                mwifiex_dbg(adapter, ERROR,
1013                            "cannot create multiple AP ifaces\n");
1014                return -1;
1015        }
1016
1017        mwifiex_dbg(adapter, INFO,
1018                    "%s: changing role to AP\n", dev->name);
1019
1020        if (mwifiex_deinit_priv_params(priv))
1021                return -1;
1022        if (mwifiex_init_new_priv_params(priv, dev, type))
1023                return -1;
1024        if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
1025                             HostCmd_ACT_GEN_SET, 0, NULL, true))
1026                return -1;
1027        if (mwifiex_sta_init_cmd(priv, false, false))
1028                return -1;
1029
1030        switch (curr_iftype) {
1031        case NL80211_IFTYPE_P2P_CLIENT:
1032        case NL80211_IFTYPE_P2P_GO:
1033                adapter->curr_iface_comb.p2p_intf--;
1034                break;
1035        case NL80211_IFTYPE_STATION:
1036        case NL80211_IFTYPE_ADHOC:
1037                adapter->curr_iface_comb.sta_intf--;
1038                break;
1039        default:
1040                break;
1041        }
1042
1043        adapter->curr_iface_comb.uap_intf++;
1044        dev->ieee80211_ptr->iftype = type;
1045        return 0;
1046}
1047/*
1048 * CFG802.11 operation handler to change interface type.
1049 */
1050static int
1051mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
1052                                     struct net_device *dev,
1053                                     enum nl80211_iftype type, u32 *flags,
1054                                     struct vif_params *params)
1055{
1056        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1057        enum nl80211_iftype curr_iftype = dev->ieee80211_ptr->iftype;
1058
1059        switch (curr_iftype) {
1060        case NL80211_IFTYPE_ADHOC:
1061                switch (type) {
1062                case NL80211_IFTYPE_STATION:
1063                        priv->bss_mode = type;
1064                        priv->sec_info.authentication_mode =
1065                                                   NL80211_AUTHTYPE_OPEN_SYSTEM;
1066                        dev->ieee80211_ptr->iftype = type;
1067                        mwifiex_deauthenticate(priv, NULL);
1068                        return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
1069                                                HostCmd_ACT_GEN_SET, 0, NULL,
1070                                                true);
1071                case NL80211_IFTYPE_P2P_CLIENT:
1072                case NL80211_IFTYPE_P2P_GO:
1073                        return mwifiex_change_vif_to_p2p(dev, curr_iftype,
1074                                                         type, flags, params);
1075                case NL80211_IFTYPE_AP:
1076                        return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
1077                                                        flags, params);
1078                case NL80211_IFTYPE_UNSPECIFIED:
1079                        mwifiex_dbg(priv->adapter, INFO,
1080                                    "%s: kept type as IBSS\n", dev->name);
1081                case NL80211_IFTYPE_ADHOC:      /* This shouldn't happen */
1082                        return 0;
1083                default:
1084                        mwifiex_dbg(priv->adapter, ERROR,
1085                                    "%s: changing to %d not supported\n",
1086                                    dev->name, type);
1087                        return -EOPNOTSUPP;
1088                }
1089                break;
1090        case NL80211_IFTYPE_STATION:
1091                switch (type) {
1092                case NL80211_IFTYPE_ADHOC:
1093                        priv->bss_mode = type;
1094                        priv->sec_info.authentication_mode =
1095                                                   NL80211_AUTHTYPE_OPEN_SYSTEM;
1096                        dev->ieee80211_ptr->iftype = type;
1097                        mwifiex_deauthenticate(priv, NULL);
1098                        return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
1099                                                HostCmd_ACT_GEN_SET, 0, NULL,
1100                                                true);
1101                case NL80211_IFTYPE_P2P_CLIENT:
1102                case NL80211_IFTYPE_P2P_GO:
1103                        return mwifiex_change_vif_to_p2p(dev, curr_iftype,
1104                                                         type, flags, params);
1105                case NL80211_IFTYPE_AP:
1106                        return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
1107                                                        flags, params);
1108                case NL80211_IFTYPE_UNSPECIFIED:
1109                        mwifiex_dbg(priv->adapter, INFO,
1110                                    "%s: kept type as STA\n", dev->name);
1111                case NL80211_IFTYPE_STATION:    /* This shouldn't happen */
1112                        return 0;
1113                default:
1114                        mwifiex_dbg(priv->adapter, ERROR,
1115                                    "%s: changing to %d not supported\n",
1116                                    dev->name, type);
1117                        return -EOPNOTSUPP;
1118                }
1119                break;
1120        case NL80211_IFTYPE_AP:
1121                switch (type) {
1122                case NL80211_IFTYPE_ADHOC:
1123                case NL80211_IFTYPE_STATION:
1124                        return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,
1125                                                               type, flags,
1126                                                               params);
1127                        break;
1128                case NL80211_IFTYPE_P2P_CLIENT:
1129                case NL80211_IFTYPE_P2P_GO:
1130                        return mwifiex_change_vif_to_p2p(dev, curr_iftype,
1131                                                         type, flags, params);
1132                case NL80211_IFTYPE_UNSPECIFIED:
1133                        mwifiex_dbg(priv->adapter, INFO,
1134                                    "%s: kept type as AP\n", dev->name);
1135                case NL80211_IFTYPE_AP:         /* This shouldn't happen */
1136                        return 0;
1137                default:
1138                        mwifiex_dbg(priv->adapter, ERROR,
1139                                    "%s: changing to %d not supported\n",
1140                                    dev->name, type);
1141                        return -EOPNOTSUPP;
1142                }
1143                break;
1144        case NL80211_IFTYPE_P2P_CLIENT:
1145        case NL80211_IFTYPE_P2P_GO:
1146                switch (type) {
1147                case NL80211_IFTYPE_STATION:
1148                        if (mwifiex_cfg80211_deinit_p2p(priv))
1149                                return -EFAULT;
1150                        priv->adapter->curr_iface_comb.p2p_intf--;
1151                        priv->adapter->curr_iface_comb.sta_intf++;
1152                        dev->ieee80211_ptr->iftype = type;
1153                        break;
1154                case NL80211_IFTYPE_ADHOC:
1155                        if (mwifiex_cfg80211_deinit_p2p(priv))
1156                                return -EFAULT;
1157                        return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,
1158                                                               type, flags,
1159                                                               params);
1160                        break;
1161                case NL80211_IFTYPE_AP:
1162                        if (mwifiex_cfg80211_deinit_p2p(priv))
1163                                return -EFAULT;
1164                        return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
1165                                                        flags, params);
1166                case NL80211_IFTYPE_UNSPECIFIED:
1167                        mwifiex_dbg(priv->adapter, INFO,
1168                                    "%s: kept type as P2P\n", dev->name);
1169                case NL80211_IFTYPE_P2P_CLIENT:
1170                case NL80211_IFTYPE_P2P_GO:
1171                        return 0;
1172                default:
1173                        mwifiex_dbg(priv->adapter, ERROR,
1174                                    "%s: changing to %d not supported\n",
1175                                    dev->name, type);
1176                        return -EOPNOTSUPP;
1177                }
1178                break;
1179        default:
1180                mwifiex_dbg(priv->adapter, ERROR,
1181                            "%s: unknown iftype: %d\n",
1182                            dev->name, dev->ieee80211_ptr->iftype);
1183                return -EOPNOTSUPP;
1184        }
1185
1186
1187        return 0;
1188}
1189
1190static void
1191mwifiex_parse_htinfo(struct mwifiex_private *priv, u8 tx_htinfo,
1192                     struct rate_info *rate)
1193{
1194        struct mwifiex_adapter *adapter = priv->adapter;
1195
1196        if (adapter->is_hw_11ac_capable) {
1197                /* bit[1-0]: 00=LG 01=HT 10=VHT */
1198                if (tx_htinfo & BIT(0)) {
1199                        /* HT */
1200                        rate->mcs = priv->tx_rate;
1201                        rate->flags |= RATE_INFO_FLAGS_MCS;
1202                }
1203                if (tx_htinfo & BIT(1)) {
1204                        /* VHT */
1205                        rate->mcs = priv->tx_rate & 0x0F;
1206                        rate->flags |= RATE_INFO_FLAGS_VHT_MCS;
1207                }
1208
1209                if (tx_htinfo & (BIT(1) | BIT(0))) {
1210                        /* HT or VHT */
1211                        switch (tx_htinfo & (BIT(3) | BIT(2))) {
1212                        case 0:
1213                                rate->bw = RATE_INFO_BW_20;
1214                                break;
1215                        case (BIT(2)):
1216                                rate->bw = RATE_INFO_BW_40;
1217                                break;
1218                        case (BIT(3)):
1219                                rate->bw = RATE_INFO_BW_80;
1220                                break;
1221                        case (BIT(3) | BIT(2)):
1222                                rate->bw = RATE_INFO_BW_160;
1223                                break;
1224                        }
1225
1226                        if (tx_htinfo & BIT(4))
1227                                rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
1228
1229                        if ((priv->tx_rate >> 4) == 1)
1230                                rate->nss = 2;
1231                        else
1232                                rate->nss = 1;
1233                }
1234        } else {
1235                /*
1236                 * Bit 0 in tx_htinfo indicates that current Tx rate
1237                 * is 11n rate. Valid MCS index values for us are 0 to 15.
1238                 */
1239                if ((tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) {
1240                        rate->mcs = priv->tx_rate;
1241                        rate->flags |= RATE_INFO_FLAGS_MCS;
1242                        rate->bw = RATE_INFO_BW_20;
1243                        if (tx_htinfo & BIT(1))
1244                                rate->bw = RATE_INFO_BW_40;
1245                        if (tx_htinfo & BIT(2))
1246                                rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
1247                }
1248        }
1249}
1250
1251/*
1252 * This function dumps the station information on a buffer.
1253 *
1254 * The following information are shown -
1255 *      - Total bytes transmitted
1256 *      - Total bytes received
1257 *      - Total packets transmitted
1258 *      - Total packets received
1259 *      - Signal quality level
1260 *      - Transmission rate
1261 */
1262static int
1263mwifiex_dump_station_info(struct mwifiex_private *priv,
1264                          struct mwifiex_sta_node *node,
1265                          struct station_info *sinfo)
1266{
1267        u32 rate;
1268
1269        sinfo->filled = BIT(NL80211_STA_INFO_RX_BYTES) | BIT(NL80211_STA_INFO_TX_BYTES) |
1270                        BIT(NL80211_STA_INFO_RX_PACKETS) | BIT(NL80211_STA_INFO_TX_PACKETS) |
1271                        BIT(NL80211_STA_INFO_TX_BITRATE) |
1272                        BIT(NL80211_STA_INFO_SIGNAL) | BIT(NL80211_STA_INFO_SIGNAL_AVG);
1273
1274        if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
1275                if (!node)
1276                        return -ENOENT;
1277
1278                sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME) |
1279                                BIT(NL80211_STA_INFO_TX_FAILED);
1280                sinfo->inactive_time =
1281                        jiffies_to_msecs(jiffies - node->stats.last_rx);
1282
1283                sinfo->signal = node->stats.rssi;
1284                sinfo->signal_avg = node->stats.rssi;
1285                sinfo->rx_bytes = node->stats.rx_bytes;
1286                sinfo->tx_bytes = node->stats.tx_bytes;
1287                sinfo->rx_packets = node->stats.rx_packets;
1288                sinfo->tx_packets = node->stats.tx_packets;
1289                sinfo->tx_failed = node->stats.tx_failed;
1290
1291                mwifiex_parse_htinfo(priv, node->stats.last_tx_htinfo,
1292                                     &sinfo->txrate);
1293                sinfo->txrate.legacy = node->stats.last_tx_rate * 5;
1294
1295                return 0;
1296        }
1297
1298        /* Get signal information from the firmware */
1299        if (mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
1300                             HostCmd_ACT_GEN_GET, 0, NULL, true)) {
1301                mwifiex_dbg(priv->adapter, ERROR,
1302                            "failed to get signal information\n");
1303                return -EFAULT;
1304        }
1305
1306        if (mwifiex_drv_get_data_rate(priv, &rate)) {
1307                mwifiex_dbg(priv->adapter, ERROR,
1308                            "getting data rate error\n");
1309                return -EFAULT;
1310        }
1311
1312        /* Get DTIM period information from firmware */
1313        mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
1314                         HostCmd_ACT_GEN_GET, DTIM_PERIOD_I,
1315                         &priv->dtim_period, true);
1316
1317        mwifiex_parse_htinfo(priv, priv->tx_htinfo, &sinfo->txrate);
1318
1319        sinfo->signal_avg = priv->bcn_rssi_avg;
1320        sinfo->rx_bytes = priv->stats.rx_bytes;
1321        sinfo->tx_bytes = priv->stats.tx_bytes;
1322        sinfo->rx_packets = priv->stats.rx_packets;
1323        sinfo->tx_packets = priv->stats.tx_packets;
1324        sinfo->signal = priv->bcn_rssi_avg;
1325        /* bit rate is in 500 kb/s units. Convert it to 100kb/s units */
1326        sinfo->txrate.legacy = rate * 5;
1327
1328        if (priv->bss_mode == NL80211_IFTYPE_STATION) {
1329                sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
1330                sinfo->bss_param.flags = 0;
1331                if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap &
1332                                                WLAN_CAPABILITY_SHORT_PREAMBLE)
1333                        sinfo->bss_param.flags |=
1334                                        BSS_PARAM_FLAGS_SHORT_PREAMBLE;
1335                if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap &
1336                                                WLAN_CAPABILITY_SHORT_SLOT_TIME)
1337                        sinfo->bss_param.flags |=
1338                                        BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
1339                sinfo->bss_param.dtim_period = priv->dtim_period;
1340                sinfo->bss_param.beacon_interval =
1341                        priv->curr_bss_params.bss_descriptor.beacon_period;
1342        }
1343
1344        return 0;
1345}
1346
1347/*
1348 * CFG802.11 operation handler to get station information.
1349 *
1350 * This function only works in connected mode, and dumps the
1351 * requested station information, if available.
1352 */
1353static int
1354mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
1355                             const u8 *mac, struct station_info *sinfo)
1356{
1357        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1358
1359        if (!priv->media_connected)
1360                return -ENOENT;
1361        if (memcmp(mac, priv->cfg_bssid, ETH_ALEN))
1362                return -ENOENT;
1363
1364        return mwifiex_dump_station_info(priv, NULL, sinfo);
1365}
1366
1367/*
1368 * CFG802.11 operation handler to dump station information.
1369 */
1370static int
1371mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
1372                              int idx, u8 *mac, struct station_info *sinfo)
1373{
1374        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1375        static struct mwifiex_sta_node *node;
1376
1377        if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
1378            priv->media_connected && idx == 0) {
1379                ether_addr_copy(mac, priv->cfg_bssid);
1380                return mwifiex_dump_station_info(priv, NULL, sinfo);
1381        } else if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
1382                mwifiex_send_cmd(priv, HOST_CMD_APCMD_STA_LIST,
1383                                 HostCmd_ACT_GEN_GET, 0, NULL, true);
1384
1385                if (node && (&node->list == &priv->sta_list)) {
1386                        node = NULL;
1387                        return -ENOENT;
1388                }
1389
1390                node = list_prepare_entry(node, &priv->sta_list, list);
1391                list_for_each_entry_continue(node, &priv->sta_list, list) {
1392                        ether_addr_copy(mac, node->mac_addr);
1393                        return mwifiex_dump_station_info(priv, node, sinfo);
1394                }
1395        }
1396
1397        return -ENOENT;
1398}
1399
1400static int
1401mwifiex_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev,
1402                             int idx, struct survey_info *survey)
1403{
1404        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1405        struct mwifiex_chan_stats *pchan_stats = priv->adapter->chan_stats;
1406        enum ieee80211_band band;
1407
1408        mwifiex_dbg(priv->adapter, DUMP, "dump_survey idx=%d\n", idx);
1409
1410        memset(survey, 0, sizeof(struct survey_info));
1411
1412        if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
1413            priv->media_connected && idx == 0) {
1414                        u8 curr_bss_band = priv->curr_bss_params.band;
1415                        u32 chan = priv->curr_bss_params.bss_descriptor.channel;
1416
1417                        band = mwifiex_band_to_radio_type(curr_bss_band);
1418                        survey->channel = ieee80211_get_channel(wiphy,
1419                                ieee80211_channel_to_frequency(chan, band));
1420
1421                        if (priv->bcn_nf_last) {
1422                                survey->filled = SURVEY_INFO_NOISE_DBM;
1423                                survey->noise = priv->bcn_nf_last;
1424                        }
1425                        return 0;
1426        }
1427
1428        if (idx >= priv->adapter->num_in_chan_stats)
1429                return -ENOENT;
1430
1431        if (!pchan_stats[idx].cca_scan_dur)
1432                return 0;
1433
1434        band = pchan_stats[idx].bandcfg;
1435        survey->channel = ieee80211_get_channel(wiphy,
1436            ieee80211_channel_to_frequency(pchan_stats[idx].chan_num, band));
1437        survey->filled = SURVEY_INFO_NOISE_DBM |
1438                         SURVEY_INFO_TIME |
1439                         SURVEY_INFO_TIME_BUSY;
1440        survey->noise = pchan_stats[idx].noise;
1441        survey->time = pchan_stats[idx].cca_scan_dur;
1442        survey->time_busy = pchan_stats[idx].cca_busy_dur;
1443
1444        return 0;
1445}
1446
1447/* Supported rates to be advertised to the cfg80211 */
1448static struct ieee80211_rate mwifiex_rates[] = {
1449        {.bitrate = 10, .hw_value = 2, },
1450        {.bitrate = 20, .hw_value = 4, },
1451        {.bitrate = 55, .hw_value = 11, },
1452        {.bitrate = 110, .hw_value = 22, },
1453        {.bitrate = 60, .hw_value = 12, },
1454        {.bitrate = 90, .hw_value = 18, },
1455        {.bitrate = 120, .hw_value = 24, },
1456        {.bitrate = 180, .hw_value = 36, },
1457        {.bitrate = 240, .hw_value = 48, },
1458        {.bitrate = 360, .hw_value = 72, },
1459        {.bitrate = 480, .hw_value = 96, },
1460        {.bitrate = 540, .hw_value = 108, },
1461};
1462
1463/* Channel definitions to be advertised to cfg80211 */
1464static struct ieee80211_channel mwifiex_channels_2ghz[] = {
1465        {.center_freq = 2412, .hw_value = 1, },
1466        {.center_freq = 2417, .hw_value = 2, },
1467        {.center_freq = 2422, .hw_value = 3, },
1468        {.center_freq = 2427, .hw_value = 4, },
1469        {.center_freq = 2432, .hw_value = 5, },
1470        {.center_freq = 2437, .hw_value = 6, },
1471        {.center_freq = 2442, .hw_value = 7, },
1472        {.center_freq = 2447, .hw_value = 8, },
1473        {.center_freq = 2452, .hw_value = 9, },
1474        {.center_freq = 2457, .hw_value = 10, },
1475        {.center_freq = 2462, .hw_value = 11, },
1476        {.center_freq = 2467, .hw_value = 12, },
1477        {.center_freq = 2472, .hw_value = 13, },
1478        {.center_freq = 2484, .hw_value = 14, },
1479};
1480
1481static struct ieee80211_supported_band mwifiex_band_2ghz = {
1482        .channels = mwifiex_channels_2ghz,
1483        .n_channels = ARRAY_SIZE(mwifiex_channels_2ghz),
1484        .bitrates = mwifiex_rates,
1485        .n_bitrates = ARRAY_SIZE(mwifiex_rates),
1486};
1487
1488static struct ieee80211_channel mwifiex_channels_5ghz[] = {
1489        {.center_freq = 5040, .hw_value = 8, },
1490        {.center_freq = 5060, .hw_value = 12, },
1491        {.center_freq = 5080, .hw_value = 16, },
1492        {.center_freq = 5170, .hw_value = 34, },
1493        {.center_freq = 5190, .hw_value = 38, },
1494        {.center_freq = 5210, .hw_value = 42, },
1495        {.center_freq = 5230, .hw_value = 46, },
1496        {.center_freq = 5180, .hw_value = 36, },
1497        {.center_freq = 5200, .hw_value = 40, },
1498        {.center_freq = 5220, .hw_value = 44, },
1499        {.center_freq = 5240, .hw_value = 48, },
1500        {.center_freq = 5260, .hw_value = 52, },
1501        {.center_freq = 5280, .hw_value = 56, },
1502        {.center_freq = 5300, .hw_value = 60, },
1503        {.center_freq = 5320, .hw_value = 64, },
1504        {.center_freq = 5500, .hw_value = 100, },
1505        {.center_freq = 5520, .hw_value = 104, },
1506        {.center_freq = 5540, .hw_value = 108, },
1507        {.center_freq = 5560, .hw_value = 112, },
1508        {.center_freq = 5580, .hw_value = 116, },
1509        {.center_freq = 5600, .hw_value = 120, },
1510        {.center_freq = 5620, .hw_value = 124, },
1511        {.center_freq = 5640, .hw_value = 128, },
1512        {.center_freq = 5660, .hw_value = 132, },
1513        {.center_freq = 5680, .hw_value = 136, },
1514        {.center_freq = 5700, .hw_value = 140, },
1515        {.center_freq = 5745, .hw_value = 149, },
1516        {.center_freq = 5765, .hw_value = 153, },
1517        {.center_freq = 5785, .hw_value = 157, },
1518        {.center_freq = 5805, .hw_value = 161, },
1519        {.center_freq = 5825, .hw_value = 165, },
1520};
1521
1522static struct ieee80211_supported_band mwifiex_band_5ghz = {
1523        .channels = mwifiex_channels_5ghz,
1524        .n_channels = ARRAY_SIZE(mwifiex_channels_5ghz),
1525        .bitrates = mwifiex_rates + 4,
1526        .n_bitrates = ARRAY_SIZE(mwifiex_rates) - 4,
1527};
1528
1529
1530/* Supported crypto cipher suits to be advertised to cfg80211 */
1531static const u32 mwifiex_cipher_suites[] = {
1532        WLAN_CIPHER_SUITE_WEP40,
1533        WLAN_CIPHER_SUITE_WEP104,
1534        WLAN_CIPHER_SUITE_TKIP,
1535        WLAN_CIPHER_SUITE_CCMP,
1536        WLAN_CIPHER_SUITE_AES_CMAC,
1537};
1538
1539/* Supported mgmt frame types to be advertised to cfg80211 */
1540static const struct ieee80211_txrx_stypes
1541mwifiex_mgmt_stypes[NUM_NL80211_IFTYPES] = {
1542        [NL80211_IFTYPE_STATION] = {
1543                .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1544                      BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
1545                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1546                      BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
1547        },
1548        [NL80211_IFTYPE_AP] = {
1549                .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1550                      BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
1551                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1552                      BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
1553        },
1554        [NL80211_IFTYPE_P2P_CLIENT] = {
1555                .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1556                      BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
1557                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1558                      BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
1559        },
1560        [NL80211_IFTYPE_P2P_GO] = {
1561                .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1562                      BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
1563                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1564                      BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
1565        },
1566};
1567
1568/*
1569 * CFG802.11 operation handler for setting bit rates.
1570 *
1571 * Function configures data rates to firmware using bitrate mask
1572 * provided by cfg80211.
1573 */
1574static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
1575                                struct net_device *dev,
1576                                const u8 *peer,
1577                                const struct cfg80211_bitrate_mask *mask)
1578{
1579        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1580        u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
1581        enum ieee80211_band band;
1582        struct mwifiex_adapter *adapter = priv->adapter;
1583
1584        if (!priv->media_connected) {
1585                mwifiex_dbg(adapter, ERROR,
1586                            "Can not set Tx data rate in disconnected state\n");
1587                return -EINVAL;
1588        }
1589
1590        band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
1591
1592        memset(bitmap_rates, 0, sizeof(bitmap_rates));
1593
1594        /* Fill HR/DSSS rates. */
1595        if (band == IEEE80211_BAND_2GHZ)
1596                bitmap_rates[0] = mask->control[band].legacy & 0x000f;
1597
1598        /* Fill OFDM rates */
1599        if (band == IEEE80211_BAND_2GHZ)
1600                bitmap_rates[1] = (mask->control[band].legacy & 0x0ff0) >> 4;
1601        else
1602                bitmap_rates[1] = mask->control[band].legacy;
1603
1604        /* Fill HT MCS rates */
1605        bitmap_rates[2] = mask->control[band].ht_mcs[0];
1606        if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)
1607                bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8;
1608
1609       /* Fill VHT MCS rates */
1610        if (adapter->fw_api_ver == MWIFIEX_FW_V15) {
1611                bitmap_rates[10] = mask->control[band].vht_mcs[0];
1612                if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)
1613                        bitmap_rates[11] = mask->control[band].vht_mcs[1];
1614        }
1615
1616        return mwifiex_send_cmd(priv, HostCmd_CMD_TX_RATE_CFG,
1617                                HostCmd_ACT_GEN_SET, 0, bitmap_rates, true);
1618}
1619
1620/*
1621 * CFG802.11 operation handler for connection quality monitoring.
1622 *
1623 * This function subscribes/unsubscribes HIGH_RSSI and LOW_RSSI
1624 * events to FW.
1625 */
1626static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy,
1627                                                struct net_device *dev,
1628                                                s32 rssi_thold, u32 rssi_hyst)
1629{
1630        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1631        struct mwifiex_ds_misc_subsc_evt subsc_evt;
1632
1633        priv->cqm_rssi_thold = rssi_thold;
1634        priv->cqm_rssi_hyst = rssi_hyst;
1635
1636        memset(&subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt));
1637        subsc_evt.events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH;
1638
1639        /* Subscribe/unsubscribe low and high rssi events */
1640        if (rssi_thold && rssi_hyst) {
1641                subsc_evt.action = HostCmd_ACT_BITWISE_SET;
1642                subsc_evt.bcn_l_rssi_cfg.abs_value = abs(rssi_thold);
1643                subsc_evt.bcn_h_rssi_cfg.abs_value = abs(rssi_thold);
1644                subsc_evt.bcn_l_rssi_cfg.evt_freq = 1;
1645                subsc_evt.bcn_h_rssi_cfg.evt_freq = 1;
1646                return mwifiex_send_cmd(priv,
1647                                        HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
1648                                        0, 0, &subsc_evt, true);
1649        } else {
1650                subsc_evt.action = HostCmd_ACT_BITWISE_CLR;
1651                return mwifiex_send_cmd(priv,
1652                                        HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
1653                                        0, 0, &subsc_evt, true);
1654        }
1655
1656        return 0;
1657}
1658
1659/* cfg80211 operation handler for change_beacon.
1660 * Function retrieves and sets modified management IEs to FW.
1661 */
1662static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
1663                                          struct net_device *dev,
1664                                          struct cfg80211_beacon_data *data)
1665{
1666        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1667
1668        if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) {
1669                mwifiex_dbg(priv->adapter, ERROR,
1670                            "%s: bss_type mismatched\n", __func__);
1671                return -EINVAL;
1672        }
1673
1674        if (!priv->bss_started) {
1675                mwifiex_dbg(priv->adapter, ERROR,
1676                            "%s: bss not started\n", __func__);
1677                return -EINVAL;
1678        }
1679
1680        if (mwifiex_set_mgmt_ies(priv, data)) {
1681                mwifiex_dbg(priv->adapter, ERROR,
1682                            "%s: setting mgmt ies failed\n", __func__);
1683                return -EFAULT;
1684        }
1685
1686        return 0;
1687}
1688
1689/* cfg80211 operation handler for del_station.
1690 * Function deauthenticates station which value is provided in mac parameter.
1691 * If mac is NULL/broadcast, all stations in associated station list are
1692 * deauthenticated. If bss is not started or there are no stations in
1693 * associated stations list, no action is taken.
1694 */
1695static int
1696mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
1697                             struct station_del_parameters *params)
1698{
1699        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1700        struct mwifiex_sta_node *sta_node;
1701        u8 deauth_mac[ETH_ALEN];
1702        unsigned long flags;
1703
1704        if (list_empty(&priv->sta_list) || !priv->bss_started)
1705                return 0;
1706
1707        if (!params->mac || is_broadcast_ether_addr(params->mac))
1708                return 0;
1709
1710        mwifiex_dbg(priv->adapter, INFO, "%s: mac address %pM\n",
1711                    __func__, params->mac);
1712
1713        eth_zero_addr(deauth_mac);
1714
1715        spin_lock_irqsave(&priv->sta_list_spinlock, flags);
1716        sta_node = mwifiex_get_sta_entry(priv, params->mac);
1717        if (sta_node)
1718                ether_addr_copy(deauth_mac, params->mac);
1719        spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
1720
1721        if (is_valid_ether_addr(deauth_mac)) {
1722                if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH,
1723                                     HostCmd_ACT_GEN_SET, 0,
1724                                     deauth_mac, true))
1725                        return -1;
1726        }
1727
1728        return 0;
1729}
1730
1731static int
1732mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
1733{
1734        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
1735        struct mwifiex_private *priv = mwifiex_get_priv(adapter,
1736                                                        MWIFIEX_BSS_ROLE_ANY);
1737        struct mwifiex_ds_ant_cfg ant_cfg;
1738
1739        if (!tx_ant || !rx_ant)
1740                return -EOPNOTSUPP;
1741
1742        if (adapter->hw_dev_mcs_support != HT_STREAM_2X2) {
1743                /* Not a MIMO chip. User should provide specific antenna number
1744                 * for Tx/Rx path or enable all antennas for diversity
1745                 */
1746                if (tx_ant != rx_ant)
1747                        return -EOPNOTSUPP;
1748
1749                if ((tx_ant & (tx_ant - 1)) &&
1750                    (tx_ant != BIT(adapter->number_of_antenna) - 1))
1751                        return -EOPNOTSUPP;
1752
1753                if ((tx_ant == BIT(adapter->number_of_antenna) - 1) &&
1754                    (priv->adapter->number_of_antenna > 1)) {
1755                        tx_ant = RF_ANTENNA_AUTO;
1756                        rx_ant = RF_ANTENNA_AUTO;
1757                }
1758        } else {
1759                struct ieee80211_sta_ht_cap *ht_info;
1760                int rx_mcs_supp;
1761                enum ieee80211_band band;
1762
1763                if ((tx_ant == 0x1 && rx_ant == 0x1)) {
1764                        adapter->user_dev_mcs_support = HT_STREAM_1X1;
1765                        if (adapter->is_hw_11ac_capable)
1766                                adapter->usr_dot_11ac_mcs_support =
1767                                                MWIFIEX_11AC_MCS_MAP_1X1;
1768                } else {
1769                        adapter->user_dev_mcs_support = HT_STREAM_2X2;
1770                        if (adapter->is_hw_11ac_capable)
1771                                adapter->usr_dot_11ac_mcs_support =
1772                                                MWIFIEX_11AC_MCS_MAP_2X2;
1773                }
1774
1775                for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
1776                        if (!adapter->wiphy->bands[band])
1777                                continue;
1778
1779                        ht_info = &adapter->wiphy->bands[band]->ht_cap;
1780                        rx_mcs_supp =
1781                                GET_RXMCSSUPP(adapter->user_dev_mcs_support);
1782                        memset(&ht_info->mcs, 0, adapter->number_of_antenna);
1783                        memset(&ht_info->mcs, 0xff, rx_mcs_supp);
1784                }
1785        }
1786
1787        ant_cfg.tx_ant = tx_ant;
1788        ant_cfg.rx_ant = rx_ant;
1789
1790        return mwifiex_send_cmd(priv, HostCmd_CMD_RF_ANTENNA,
1791                                HostCmd_ACT_GEN_SET, 0, &ant_cfg, true);
1792}
1793
1794/* cfg80211 operation handler for stop ap.
1795 * Function stops BSS running at uAP interface.
1796 */
1797static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
1798{
1799        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1800
1801        mwifiex_abort_cac(priv);
1802
1803        if (mwifiex_del_mgmt_ies(priv))
1804                mwifiex_dbg(priv->adapter, ERROR,
1805                            "Failed to delete mgmt IEs!\n");
1806
1807        priv->ap_11n_enabled = 0;
1808        memset(&priv->bss_cfg, 0, sizeof(priv->bss_cfg));
1809
1810        if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
1811                             HostCmd_ACT_GEN_SET, 0, NULL, true)) {
1812                mwifiex_dbg(priv->adapter, ERROR,
1813                            "Failed to stop the BSS\n");
1814                return -1;
1815        }
1816
1817        if (mwifiex_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET,
1818                             HostCmd_ACT_GEN_SET, 0, NULL, true)) {
1819                mwifiex_dbg(priv->adapter, ERROR,
1820                            "Failed to reset BSS\n");
1821                return -1;
1822        }
1823
1824        if (netif_carrier_ok(priv->netdev))
1825                netif_carrier_off(priv->netdev);
1826        mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
1827
1828        return 0;
1829}
1830
1831/* cfg80211 operation handler for start_ap.
1832 * Function sets beacon period, DTIM period, SSID and security into
1833 * AP config structure.
1834 * AP is configured with these settings and BSS is started.
1835 */
1836static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
1837                                     struct net_device *dev,
1838                                     struct cfg80211_ap_settings *params)
1839{
1840        struct mwifiex_uap_bss_param *bss_cfg;
1841        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1842
1843        if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP)
1844                return -1;
1845
1846        bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL);
1847        if (!bss_cfg)
1848                return -ENOMEM;
1849
1850        mwifiex_set_sys_config_invalid_data(bss_cfg);
1851
1852        if (params->beacon_interval)
1853                bss_cfg->beacon_period = params->beacon_interval;
1854        if (params->dtim_period)
1855                bss_cfg->dtim_period = params->dtim_period;
1856
1857        if (params->ssid && params->ssid_len) {
1858                memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len);
1859                bss_cfg->ssid.ssid_len = params->ssid_len;
1860        }
1861        if (params->inactivity_timeout > 0) {
1862                /* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */
1863                bss_cfg->sta_ao_timer = 10 * params->inactivity_timeout;
1864                bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout;
1865        }
1866
1867        switch (params->hidden_ssid) {
1868        case NL80211_HIDDEN_SSID_NOT_IN_USE:
1869                bss_cfg->bcast_ssid_ctl = 1;
1870                break;
1871        case NL80211_HIDDEN_SSID_ZERO_LEN:
1872                bss_cfg->bcast_ssid_ctl = 0;
1873                break;
1874        case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
1875                /* firmware doesn't support this type of hidden SSID */
1876        default:
1877                kfree(bss_cfg);
1878                return -EINVAL;
1879        }
1880
1881        mwifiex_uap_set_channel(priv, bss_cfg, params->chandef);
1882        mwifiex_set_uap_rates(bss_cfg, params);
1883
1884        if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
1885                kfree(bss_cfg);
1886                mwifiex_dbg(priv->adapter, ERROR,
1887                            "Failed to parse secuirty parameters!\n");
1888                return -1;
1889        }
1890
1891        mwifiex_set_ht_params(priv, bss_cfg, params);
1892
1893        if (priv->adapter->is_hw_11ac_capable) {
1894                mwifiex_set_vht_params(priv, bss_cfg, params);
1895                mwifiex_set_vht_width(priv, params->chandef.width,
1896                                      priv->ap_11ac_enabled);
1897        }
1898
1899        if (priv->ap_11ac_enabled)
1900                mwifiex_set_11ac_ba_params(priv);
1901        else
1902                mwifiex_set_ba_params(priv);
1903
1904        mwifiex_set_wmm_params(priv, bss_cfg, params);
1905
1906        if (mwifiex_is_11h_active(priv))
1907                mwifiex_set_tpc_params(priv, bss_cfg, params);
1908
1909        if (mwifiex_is_11h_active(priv) &&
1910            !cfg80211_chandef_dfs_required(wiphy, &params->chandef,
1911                                           priv->bss_mode)) {
1912                mwifiex_dbg(priv->adapter, INFO,
1913                            "Disable 11h extensions in FW\n");
1914                if (mwifiex_11h_activate(priv, false)) {
1915                        mwifiex_dbg(priv->adapter, ERROR,
1916                                    "Failed to disable 11h extensions!!");
1917                        return -1;
1918                }
1919                priv->state_11h.is_11h_active = false;
1920        }
1921
1922        if (mwifiex_config_start_uap(priv, bss_cfg)) {
1923                mwifiex_dbg(priv->adapter, ERROR,
1924                            "Failed to start AP\n");
1925                kfree(bss_cfg);
1926                return -1;
1927        }
1928
1929        if (mwifiex_set_mgmt_ies(priv, &params->beacon))
1930                return -1;
1931
1932        if (!netif_carrier_ok(priv->netdev))
1933                netif_carrier_on(priv->netdev);
1934        mwifiex_wake_up_net_dev_queue(priv->netdev, priv->adapter);
1935
1936        memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg));
1937        kfree(bss_cfg);
1938        return 0;
1939}
1940
1941/*
1942 * CFG802.11 operation handler for disconnection request.
1943 *
1944 * This function does not work when there is already a disconnection
1945 * procedure going on.
1946 */
1947static int
1948mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
1949                            u16 reason_code)
1950{
1951        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1952
1953        if (mwifiex_deauthenticate(priv, NULL))
1954                return -EFAULT;
1955
1956        mwifiex_dbg(priv->adapter, MSG,
1957                    "info: successfully disconnected from %pM:\t"
1958                    "reason code %d\n", priv->cfg_bssid, reason_code);
1959
1960        eth_zero_addr(priv->cfg_bssid);
1961        priv->hs2_enabled = false;
1962
1963        return 0;
1964}
1965
1966/*
1967 * This function informs the CFG802.11 subsystem of a new IBSS.
1968 *
1969 * The following information are sent to the CFG802.11 subsystem
1970 * to register the new IBSS. If we do not register the new IBSS,
1971 * a kernel panic will result.
1972 *      - SSID
1973 *      - SSID length
1974 *      - BSSID
1975 *      - Channel
1976 */
1977static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
1978{
1979        struct ieee80211_channel *chan;
1980        struct mwifiex_bss_info bss_info;
1981        struct cfg80211_bss *bss;
1982        int ie_len;
1983        u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)];
1984        enum ieee80211_band band;
1985
1986        if (mwifiex_get_bss_info(priv, &bss_info))
1987                return -1;
1988
1989        ie_buf[0] = WLAN_EID_SSID;
1990        ie_buf[1] = bss_info.ssid.ssid_len;
1991
1992        memcpy(&ie_buf[sizeof(struct ieee_types_header)],
1993               &bss_info.ssid.ssid, bss_info.ssid.ssid_len);
1994        ie_len = ie_buf[1] + sizeof(struct ieee_types_header);
1995
1996        band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
1997        chan = __ieee80211_get_channel(priv->wdev.wiphy,
1998                        ieee80211_channel_to_frequency(bss_info.bss_chan,
1999                                                       band));
2000
2001        bss = cfg80211_inform_bss(priv->wdev.wiphy, chan,
2002                                  CFG80211_BSS_FTYPE_UNKNOWN,
2003                                  bss_info.bssid, 0, WLAN_CAPABILITY_IBSS,
2004                                  0, ie_buf, ie_len, 0, GFP_KERNEL);
2005        if (bss) {
2006                cfg80211_put_bss(priv->wdev.wiphy, bss);
2007                ether_addr_copy(priv->cfg_bssid, bss_info.bssid);
2008        }
2009
2010        return 0;
2011}
2012
2013/*
2014 * This function connects with a BSS.
2015 *
2016 * This function handles both Infra and Ad-Hoc modes. It also performs
2017 * validity checking on the provided parameters, disconnects from the
2018 * current BSS (if any), sets up the association/scan parameters,
2019 * including security settings, and performs specific SSID scan before
2020 * trying to connect.
2021 *
2022 * For Infra mode, the function returns failure if the specified SSID
2023 * is not found in scan table. However, for Ad-Hoc mode, it can create
2024 * the IBSS if it does not exist. On successful completion in either case,
2025 * the function notifies the CFG802.11 subsystem of the new BSS connection.
2026 */
2027static int
2028mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len,
2029                       const u8 *ssid, const u8 *bssid, int mode,
2030                       struct ieee80211_channel *channel,
2031                       struct cfg80211_connect_params *sme, bool privacy)
2032{
2033        struct cfg80211_ssid req_ssid;
2034        int ret, auth_type = 0;
2035        struct cfg80211_bss *bss = NULL;
2036        u8 is_scanning_required = 0;
2037
2038        memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));
2039
2040        req_ssid.ssid_len = ssid_len;
2041        if (ssid_len > IEEE80211_MAX_SSID_LEN) {
2042                mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n");
2043                return -EINVAL;
2044        }
2045
2046        memcpy(req_ssid.ssid, ssid, ssid_len);
2047        if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) {
2048                mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n");
2049                return -EINVAL;
2050        }
2051
2052        /* As this is new association, clear locally stored
2053         * keys and security related flags */
2054        priv->sec_info.wpa_enabled = false;
2055        priv->sec_info.wpa2_enabled = false;
2056        priv->wep_key_curr_index = 0;
2057        priv->sec_info.encryption_mode = 0;
2058        priv->sec_info.is_authtype_auto = 0;
2059        ret = mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1);
2060
2061        if (mode == NL80211_IFTYPE_ADHOC) {
2062                /* "privacy" is set only for ad-hoc mode */
2063                if (privacy) {
2064                        /*
2065                         * Keep WLAN_CIPHER_SUITE_WEP104 for now so that
2066                         * the firmware can find a matching network from the
2067                         * scan. The cfg80211 does not give us the encryption
2068                         * mode at this stage so just setting it to WEP here.
2069                         */
2070                        priv->sec_info.encryption_mode =
2071                                        WLAN_CIPHER_SUITE_WEP104;
2072                        priv->sec_info.authentication_mode =
2073                                        NL80211_AUTHTYPE_OPEN_SYSTEM;
2074                }
2075
2076                goto done;
2077        }
2078
2079        /* Now handle infra mode. "sme" is valid for infra mode only */
2080        if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
2081                auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
2082                priv->sec_info.is_authtype_auto = 1;
2083        } else {
2084                auth_type = sme->auth_type;
2085        }
2086
2087        if (sme->crypto.n_ciphers_pairwise) {
2088                priv->sec_info.encryption_mode =
2089                                                sme->crypto.ciphers_pairwise[0];
2090                priv->sec_info.authentication_mode = auth_type;
2091        }
2092
2093        if (sme->crypto.cipher_group) {
2094                priv->sec_info.encryption_mode = sme->crypto.cipher_group;
2095                priv->sec_info.authentication_mode = auth_type;
2096        }
2097        if (sme->ie)
2098                ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len);
2099
2100        if (sme->key) {
2101                if (mwifiex_is_alg_wep(priv->sec_info.encryption_mode)) {
2102                        mwifiex_dbg(priv->adapter, INFO,
2103                                    "info: setting wep encryption\t"
2104                                    "with key len %d\n", sme->key_len);
2105                        priv->wep_key_curr_index = sme->key_idx;
2106                        ret = mwifiex_set_encode(priv, NULL, sme->key,
2107                                                 sme->key_len, sme->key_idx,
2108                                                 NULL, 0);
2109                }
2110        }
2111done:
2112        /*
2113         * Scan entries are valid for some time (15 sec). So we can save one
2114         * active scan time if we just try cfg80211_get_bss first. If it fails
2115         * then request scan and cfg80211_get_bss() again for final output.
2116         */
2117        while (1) {
2118                if (is_scanning_required) {
2119                        /* Do specific SSID scanning */
2120                        if (mwifiex_request_scan(priv, &req_ssid)) {
2121                                mwifiex_dbg(priv->adapter, ERROR, "scan error\n");
2122                                return -EFAULT;
2123                        }
2124                }
2125
2126                /* Find the BSS we want using available scan results */
2127                if (mode == NL80211_IFTYPE_ADHOC)
2128                        bss = cfg80211_get_bss(priv->wdev.wiphy, channel,
2129                                               bssid, ssid, ssid_len,
2130                                               IEEE80211_BSS_TYPE_IBSS,
2131                                               IEEE80211_PRIVACY_ANY);
2132                else
2133                        bss = cfg80211_get_bss(priv->wdev.wiphy, channel,
2134                                               bssid, ssid, ssid_len,
2135                                               IEEE80211_BSS_TYPE_ESS,
2136                                               IEEE80211_PRIVACY_ANY);
2137
2138                if (!bss) {
2139                        if (is_scanning_required) {
2140                                mwifiex_dbg(priv->adapter, WARN,
2141                                            "assoc: requested bss not found in scan results\n");
2142                                break;
2143                        }
2144                        is_scanning_required = 1;
2145                } else {
2146                        mwifiex_dbg(priv->adapter, MSG,
2147                                    "info: trying to associate to '%s' bssid %pM\n",
2148                                    (char *)req_ssid.ssid, bss->bssid);
2149                        memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);
2150                        break;
2151                }
2152        }
2153
2154        ret = mwifiex_bss_start(priv, bss, &req_ssid);
2155        if (ret)
2156                return ret;
2157
2158        if (mode == NL80211_IFTYPE_ADHOC) {
2159                /* Inform the BSS information to kernel, otherwise
2160                 * kernel will give a panic after successful assoc */
2161                if (mwifiex_cfg80211_inform_ibss_bss(priv))
2162                        return -EFAULT;
2163        }
2164
2165        return ret;
2166}
2167
2168/*
2169 * CFG802.11 operation handler for association request.
2170 *
2171 * This function does not work when the current mode is set to Ad-Hoc, or
2172 * when there is already an association procedure going on. The given BSS
2173 * information is used to associate.
2174 */
2175static int
2176mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
2177                         struct cfg80211_connect_params *sme)
2178{
2179        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
2180        struct mwifiex_adapter *adapter = priv->adapter;
2181        int ret;
2182
2183        if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) {
2184                mwifiex_dbg(adapter, ERROR,
2185                            "%s: reject infra assoc request in non-STA role\n",
2186                            dev->name);
2187                return -EINVAL;
2188        }
2189
2190        if (priv->wdev.current_bss) {
2191                mwifiex_dbg(adapter, ERROR,
2192                            "%s: already connected\n", dev->name);
2193                return -EALREADY;
2194        }
2195
2196        if (adapter->surprise_removed || adapter->is_cmd_timedout) {
2197                mwifiex_dbg(adapter, ERROR,
2198                            "%s: Ignore connection.\t"
2199                            "Card removed or FW in bad state\n",
2200                            dev->name);
2201                return -EFAULT;
2202        }
2203
2204        mwifiex_dbg(adapter, INFO,
2205                    "info: Trying to associate to %s and bssid %pM\n",
2206                    (char *)sme->ssid, sme->bssid);
2207
2208        ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid,
2209                                     priv->bss_mode, sme->channel, sme, 0);
2210        if (!ret) {
2211                cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0,
2212                                        NULL, 0, WLAN_STATUS_SUCCESS,
2213                                        GFP_KERNEL);
2214                mwifiex_dbg(priv->adapter, MSG,
2215                            "info: associated to bssid %pM successfully\n",
2216                            priv->cfg_bssid);
2217                if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
2218                    priv->adapter->auto_tdls &&
2219                    priv->bss_type == MWIFIEX_BSS_TYPE_STA)
2220                        mwifiex_setup_auto_tdls_timer(priv);
2221        } else {
2222                mwifiex_dbg(priv->adapter, ERROR,
2223                            "info: association to bssid %pM failed\n",
2224                            priv->cfg_bssid);
2225                eth_zero_addr(priv->cfg_bssid);
2226
2227                if (ret > 0)
2228                        cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
2229                                                NULL, 0, NULL, 0, ret,
2230                                                GFP_KERNEL);
2231                else
2232                        cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
2233                                                NULL, 0, NULL, 0,
2234                                                WLAN_STATUS_UNSPECIFIED_FAILURE,
2235                                                GFP_KERNEL);
2236        }
2237
2238        return 0;
2239}
2240
2241/*
2242 * This function sets following parameters for ibss network.
2243 *  -  channel
2244 *  -  start band
2245 *  -  11n flag
2246 *  -  secondary channel offset
2247 */
2248static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
2249                                   struct cfg80211_ibss_params *params)
2250{
2251        struct mwifiex_adapter *adapter = priv->adapter;
2252        int index = 0, i;
2253        u8 config_bands = 0;
2254
2255        if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) {
2256                if (!params->basic_rates) {
2257                        config_bands = BAND_B | BAND_G;
2258                } else {
2259                        for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) {
2260                                /*
2261                                 * Rates below 6 Mbps in the table are CCK
2262                                 * rates; 802.11b and from 6 they are OFDM;
2263                                 * 802.11G
2264                                 */
2265                                if (mwifiex_rates[i].bitrate == 60) {
2266                                        index = 1 << i;
2267                                        break;
2268                                }
2269                        }
2270
2271                        if (params->basic_rates < index) {
2272                                config_bands = BAND_B;
2273                        } else {
2274                                config_bands = BAND_G;
2275                                if (params->basic_rates % index)
2276                                        config_bands |= BAND_B;
2277                        }
2278                }
2279
2280                if (cfg80211_get_chandef_type(&params->chandef) !=
2281                                                NL80211_CHAN_NO_HT)
2282                        config_bands |= BAND_G | BAND_GN;
2283        } else {
2284                if (cfg80211_get_chandef_type(&params->chandef) ==
2285                                                NL80211_CHAN_NO_HT)
2286                        config_bands = BAND_A;
2287                else
2288                        config_bands = BAND_AN | BAND_A;
2289        }
2290
2291        if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands)) {
2292                adapter->config_bands = config_bands;
2293                adapter->adhoc_start_band = config_bands;
2294
2295                if ((config_bands & BAND_GN) || (config_bands & BAND_AN))
2296                        adapter->adhoc_11n_enabled = true;
2297                else
2298                        adapter->adhoc_11n_enabled = false;
2299        }
2300
2301        adapter->sec_chan_offset =
2302                mwifiex_chan_type_to_sec_chan_offset(
2303                        cfg80211_get_chandef_type(&params->chandef));
2304        priv->adhoc_channel = ieee80211_frequency_to_channel(
2305                                params->chandef.chan->center_freq);
2306
2307        mwifiex_dbg(adapter, INFO,
2308                    "info: set ibss band %d, chan %d, chan offset %d\n",
2309                    config_bands, priv->adhoc_channel,
2310                    adapter->sec_chan_offset);
2311
2312        return 0;
2313}
2314
2315/*
2316 * CFG802.11 operation handler to join an IBSS.
2317 *
2318 * This function does not work in any mode other than Ad-Hoc, or if
2319 * a join operation is already in progress.
2320 */
2321static int
2322mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
2323                           struct cfg80211_ibss_params *params)
2324{
2325        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
2326        int ret = 0;
2327
2328        if (priv->bss_mode != NL80211_IFTYPE_ADHOC) {
2329                mwifiex_dbg(priv->adapter, ERROR,
2330                            "request to join ibss received\t"
2331                            "when station is not in ibss mode\n");
2332                goto done;
2333        }
2334
2335        mwifiex_dbg(priv->adapter, MSG,
2336                    "info: trying to join to %s and bssid %pM\n",
2337                    (char *)params->ssid, params->bssid);
2338
2339        mwifiex_set_ibss_params(priv, params);
2340
2341        ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid,
2342                                     params->bssid, priv->bss_mode,
2343                                     params->chandef.chan, NULL,
2344                                     params->privacy);
2345done:
2346        if (!ret) {
2347                cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
2348                                     params->chandef.chan, GFP_KERNEL);
2349                mwifiex_dbg(priv->adapter, MSG,
2350                            "info: joined/created adhoc network with bssid\t"
2351                            "%pM successfully\n", priv->cfg_bssid);
2352        } else {
2353                mwifiex_dbg(priv->adapter, ERROR,
2354                            "info: failed creating/joining adhoc network\n");
2355        }
2356
2357        return ret;
2358}
2359
2360/*
2361 * CFG802.11 operation handler to leave an IBSS.
2362 *
2363 * This function does not work if a leave operation is
2364 * already in progress.
2365 */
2366static int
2367mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
2368{
2369        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
2370
2371        mwifiex_dbg(priv->adapter, MSG, "info: disconnecting from essid %pM\n",
2372                    priv->cfg_bssid);
2373        if (mwifiex_deauthenticate(priv, NULL))
2374                return -EFAULT;
2375
2376        eth_zero_addr(priv->cfg_bssid);
2377
2378        return 0;
2379}
2380
2381/*
2382 * CFG802.11 operation handler for scan request.
2383 *
2384 * This function issues a scan request to the firmware based upon
2385 * the user specified scan configuration. On successful completion,
2386 * it also informs the results.
2387 */
2388static int
2389mwifiex_cfg80211_scan(struct wiphy *wiphy,
2390                      struct cfg80211_scan_request *request)
2391{
2392        struct net_device *dev = request->wdev->netdev;
2393        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
2394        int i, offset, ret;
2395        struct ieee80211_channel *chan;
2396        struct ieee_types_header *ie;
2397        struct mwifiex_user_scan_cfg *user_scan_cfg;
2398
2399        mwifiex_dbg(priv->adapter, CMD,
2400                    "info: received scan request on %s\n", dev->name);
2401
2402        /* Block scan request if scan operation or scan cleanup when interface
2403         * is disabled is in process
2404         */
2405        if (priv->scan_request || priv->scan_aborting) {
2406                mwifiex_dbg(priv->adapter, WARN,
2407                            "cmd: Scan already in process..\n");
2408                return -EBUSY;
2409        }
2410
2411        user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
2412        if (!user_scan_cfg)
2413                return -ENOMEM;
2414
2415        priv->scan_request = request;
2416
2417        user_scan_cfg->num_ssids = request->n_ssids;
2418        user_scan_cfg->ssid_list = request->ssids;
2419
2420        if (request->ie && request->ie_len) {
2421                offset = 0;
2422                for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {
2423                        if (priv->vs_ie[i].mask != MWIFIEX_VSIE_MASK_CLEAR)
2424                                continue;
2425                        priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_SCAN;
2426                        ie = (struct ieee_types_header *)(request->ie + offset);
2427                        memcpy(&priv->vs_ie[i].ie, ie, sizeof(*ie) + ie->len);
2428                        offset += sizeof(*ie) + ie->len;
2429
2430                        if (offset >= request->ie_len)
2431                                break;
2432                }
2433        }
2434
2435        for (i = 0; i < min_t(u32, request->n_channels,
2436                              MWIFIEX_USER_SCAN_CHAN_MAX); i++) {
2437                chan = request->channels[i];
2438                user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
2439                user_scan_cfg->chan_list[i].radio_type = chan->band;
2440
2441                if ((chan->flags & IEEE80211_CHAN_NO_IR) || !request->n_ssids)
2442                        user_scan_cfg->chan_list[i].scan_type =
2443                                                MWIFIEX_SCAN_TYPE_PASSIVE;
2444                else
2445                        user_scan_cfg->chan_list[i].scan_type =
2446                                                MWIFIEX_SCAN_TYPE_ACTIVE;
2447
2448                user_scan_cfg->chan_list[i].scan_time = 0;
2449        }
2450
2451        if (priv->adapter->scan_chan_gap_enabled &&
2452            mwifiex_is_any_intf_active(priv))
2453                user_scan_cfg->scan_chan_gap =
2454                                              priv->adapter->scan_chan_gap_time;
2455
2456        ret = mwifiex_scan_networks(priv, user_scan_cfg);
2457        kfree(user_scan_cfg);
2458        if (ret) {
2459                mwifiex_dbg(priv->adapter, ERROR,
2460                            "scan failed: %d\n", ret);
2461                priv->scan_aborting = false;
2462                priv->scan_request = NULL;
2463                return ret;
2464        }
2465
2466        if (request->ie && request->ie_len) {
2467                for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {
2468                        if (priv->vs_ie[i].mask == MWIFIEX_VSIE_MASK_SCAN) {
2469                                priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_CLEAR;
2470                                memset(&priv->vs_ie[i].ie, 0,
2471                                       MWIFIEX_MAX_VSIE_LEN);
2472                        }
2473                }
2474        }
2475        return 0;
2476}
2477
2478static void mwifiex_setup_vht_caps(struct ieee80211_sta_vht_cap *vht_info,
2479                                   struct mwifiex_private *priv)
2480{
2481        struct mwifiex_adapter *adapter = priv->adapter;
2482
2483        vht_info->vht_supported = true;
2484
2485        vht_info->cap = adapter->hw_dot_11ac_dev_cap;
2486        /* Update MCS support for VHT */
2487        vht_info->vht_mcs.rx_mcs_map = cpu_to_le16(
2488                                adapter->hw_dot_11ac_mcs_support & 0xFFFF);
2489        vht_info->vht_mcs.rx_highest = 0;
2490        vht_info->vht_mcs.tx_mcs_map = cpu_to_le16(
2491                                adapter->hw_dot_11ac_mcs_support >> 16);
2492        vht_info->vht_mcs.tx_highest = 0;
2493}
2494
2495/*
2496 * This function sets up the CFG802.11 specific HT capability fields
2497 * with default values.
2498 *
2499 * The following default values are set -
2500 *      - HT Supported = True
2501 *      - Maximum AMPDU length factor = IEEE80211_HT_MAX_AMPDU_64K
2502 *      - Minimum AMPDU spacing = IEEE80211_HT_MPDU_DENSITY_NONE
2503 *      - HT Capabilities supported by firmware
2504 *      - MCS information, Rx mask = 0xff
2505 *      - MCD information, Tx parameters = IEEE80211_HT_MCS_TX_DEFINED (0x01)
2506 */
2507static void
2508mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info,
2509                      struct mwifiex_private *priv)
2510{
2511        int rx_mcs_supp;
2512        struct ieee80211_mcs_info mcs_set;
2513        u8 *mcs = (u8 *)&mcs_set;
2514        struct mwifiex_adapter *adapter = priv->adapter;
2515
2516        ht_info->ht_supported = true;
2517        ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
2518        ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
2519
2520        memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
2521
2522        /* Fill HT capability information */
2523        if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap))
2524                ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
2525        else
2526                ht_info->cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
2527
2528        if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap))
2529                ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
2530        else
2531                ht_info->cap &= ~IEEE80211_HT_CAP_SGI_20;
2532
2533        if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap))
2534                ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
2535        else
2536                ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40;
2537
2538        if (adapter->user_dev_mcs_support == HT_STREAM_2X2)
2539                ht_info->cap |= 3 << IEEE80211_HT_CAP_RX_STBC_SHIFT;
2540        else
2541                ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT;
2542
2543        if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap))
2544                ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
2545        else
2546                ht_info->cap &= ~IEEE80211_HT_CAP_TX_STBC;
2547
2548        if (ISSUPP_GREENFIELD(adapter->hw_dot_11n_dev_cap))
2549                ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
2550        else
2551                ht_info->cap &= ~IEEE80211_HT_CAP_GRN_FLD;
2552
2553        if (ISENABLED_40MHZ_INTOLERANT(adapter->hw_dot_11n_dev_cap))
2554                ht_info->cap |= IEEE80211_HT_CAP_40MHZ_INTOLERANT;
2555        else
2556                ht_info->cap &= ~IEEE80211_HT_CAP_40MHZ_INTOLERANT;
2557
2558        if (ISSUPP_RXLDPC(adapter->hw_dot_11n_dev_cap))
2559                ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
2560        else
2561                ht_info->cap &= ~IEEE80211_HT_CAP_LDPC_CODING;
2562
2563        ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU;
2564        ht_info->cap |= IEEE80211_HT_CAP_SM_PS;
2565
2566        rx_mcs_supp = GET_RXMCSSUPP(adapter->user_dev_mcs_support);
2567        /* Set MCS for 1x1/2x2 */
2568        memset(mcs, 0xff, rx_mcs_supp);
2569        /* Clear all the other values */
2570        memset(&mcs[rx_mcs_supp], 0,
2571               sizeof(struct ieee80211_mcs_info) - rx_mcs_supp);
2572        if (priv->bss_mode == NL80211_IFTYPE_STATION ||
2573            ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap))
2574                /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */
2575                SETHT_MCS32(mcs_set.rx_mask);
2576
2577        memcpy((u8 *) &ht_info->mcs, mcs, sizeof(struct ieee80211_mcs_info));
2578
2579        ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
2580}
2581
2582/*
2583 *  create a new virtual interface with the given name and name assign type
2584 */
2585struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
2586                                              const char *name,
2587                                              unsigned char name_assign_type,
2588                                              enum nl80211_iftype type,
2589                                              u32 *flags,
2590                                              struct vif_params *params)
2591{
2592        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
2593        struct mwifiex_private *priv;
2594        struct net_device *dev;
2595        void *mdev_priv;
2596
2597        if (!adapter)
2598                return ERR_PTR(-EFAULT);
2599
2600        switch (type) {
2601        case NL80211_IFTYPE_UNSPECIFIED:
2602        case NL80211_IFTYPE_STATION:
2603        case NL80211_IFTYPE_ADHOC:
2604                if (adapter->curr_iface_comb.sta_intf ==
2605                    adapter->iface_limit.sta_intf) {
2606                        mwifiex_dbg(adapter, ERROR,
2607                                    "cannot create multiple sta/adhoc ifaces\n");
2608                        return ERR_PTR(-EINVAL);
2609                }
2610
2611                priv = mwifiex_get_unused_priv(adapter);
2612                if (!priv) {
2613                        mwifiex_dbg(adapter, ERROR,
2614                                    "could not get free private struct\n");
2615                        return ERR_PTR(-EFAULT);
2616                }
2617
2618                priv->wdev.wiphy = wiphy;
2619                priv->wdev.iftype = NL80211_IFTYPE_STATION;
2620
2621                if (type == NL80211_IFTYPE_UNSPECIFIED)
2622                        priv->bss_mode = NL80211_IFTYPE_STATION;
2623                else
2624                        priv->bss_mode = type;
2625
2626                priv->bss_type = MWIFIEX_BSS_TYPE_STA;
2627                priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
2628                priv->bss_priority = 0;
2629                priv->bss_role = MWIFIEX_BSS_ROLE_STA;
2630                priv->bss_num = adapter->curr_iface_comb.sta_intf;
2631
2632                break;
2633        case NL80211_IFTYPE_AP:
2634                if (adapter->curr_iface_comb.uap_intf ==
2635                    adapter->iface_limit.uap_intf) {
2636                        mwifiex_dbg(adapter, ERROR,
2637                                    "cannot create multiple AP ifaces\n");
2638                        return ERR_PTR(-EINVAL);
2639                }
2640
2641                priv = mwifiex_get_unused_priv(adapter);
2642                if (!priv) {
2643                        mwifiex_dbg(adapter, ERROR,
2644                                    "could not get free private struct\n");
2645                        return ERR_PTR(-EFAULT);
2646                }
2647
2648                priv->wdev.wiphy = wiphy;
2649                priv->wdev.iftype = NL80211_IFTYPE_AP;
2650
2651                priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
2652                priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
2653                priv->bss_priority = 0;
2654                priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
2655                priv->bss_started = 0;
2656                priv->bss_num = adapter->curr_iface_comb.uap_intf;
2657                priv->bss_mode = type;
2658
2659                break;
2660        case NL80211_IFTYPE_P2P_CLIENT:
2661                if (adapter->curr_iface_comb.p2p_intf ==
2662                    adapter->iface_limit.p2p_intf) {
2663                        mwifiex_dbg(adapter, ERROR,
2664                                    "cannot create multiple P2P ifaces\n");
2665                        return ERR_PTR(-EINVAL);
2666                }
2667
2668                priv = mwifiex_get_unused_priv(adapter);
2669                if (!priv) {
2670                        mwifiex_dbg(adapter, ERROR,
2671                                    "could not get free private struct\n");
2672                        return ERR_PTR(-EFAULT);
2673                }
2674
2675                priv->wdev.wiphy = wiphy;
2676                /* At start-up, wpa_supplicant tries to change the interface
2677                 * to NL80211_IFTYPE_STATION if it is not managed mode.
2678                 */
2679                priv->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
2680                priv->bss_mode = NL80211_IFTYPE_P2P_CLIENT;
2681
2682                /* Setting bss_type to P2P tells firmware that this interface
2683                 * is receiving P2P peers found during find phase and doing
2684                 * action frame handshake.
2685                 */
2686                priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
2687
2688                priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
2689                priv->bss_priority = MWIFIEX_BSS_ROLE_STA;
2690                priv->bss_role = MWIFIEX_BSS_ROLE_STA;
2691                priv->bss_started = 0;
2692                priv->bss_num = adapter->curr_iface_comb.p2p_intf;
2693
2694                if (mwifiex_cfg80211_init_p2p_client(priv)) {
2695                        memset(&priv->wdev, 0, sizeof(priv->wdev));
2696                        priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
2697                        return ERR_PTR(-EFAULT);
2698                }
2699
2700                break;
2701        default:
2702                mwifiex_dbg(adapter, ERROR, "type not supported\n");
2703                return ERR_PTR(-EINVAL);
2704        }
2705
2706        dev = alloc_netdev_mqs(sizeof(struct mwifiex_private *), name,
2707                               name_assign_type, ether_setup,
2708                               IEEE80211_NUM_ACS, 1);
2709        if (!dev) {
2710                mwifiex_dbg(adapter, ERROR,
2711                            "no memory available for netdevice\n");
2712                memset(&priv->wdev, 0, sizeof(priv->wdev));
2713                priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
2714                priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
2715                return ERR_PTR(-ENOMEM);
2716        }
2717
2718        mwifiex_init_priv_params(priv, dev);
2719        priv->netdev = dev;
2720
2721        mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv);
2722        if (adapter->is_hw_11ac_capable)
2723                mwifiex_setup_vht_caps(
2724                        &wiphy->bands[IEEE80211_BAND_2GHZ]->vht_cap, priv);
2725
2726        if (adapter->config_bands & BAND_A)
2727                mwifiex_setup_ht_caps(
2728                        &wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv);
2729
2730        if ((adapter->config_bands & BAND_A) && adapter->is_hw_11ac_capable)
2731                mwifiex_setup_vht_caps(
2732                        &wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap, priv);
2733
2734        dev_net_set(dev, wiphy_net(wiphy));
2735        dev->ieee80211_ptr = &priv->wdev;
2736        dev->ieee80211_ptr->iftype = priv->bss_mode;
2737        memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN);
2738        SET_NETDEV_DEV(dev, wiphy_dev(wiphy));
2739
2740        dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
2741        dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT;
2742        dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN;
2743        dev->ethtool_ops = &mwifiex_ethtool_ops;
2744
2745        mdev_priv = netdev_priv(dev);
2746        *((unsigned long *) mdev_priv) = (unsigned long) priv;
2747
2748        SET_NETDEV_DEV(dev, adapter->dev);
2749
2750        /* Register network device */
2751        if (register_netdevice(dev)) {
2752                mwifiex_dbg(adapter, ERROR,
2753                            "cannot register virtual network device\n");
2754                free_netdev(dev);
2755                priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
2756                priv->netdev = NULL;
2757                memset(&priv->wdev, 0, sizeof(priv->wdev));
2758                priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
2759                return ERR_PTR(-EFAULT);
2760        }
2761
2762        priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC%s",
2763                                                  WQ_HIGHPRI |
2764                                                  WQ_MEM_RECLAIM |
2765                                                  WQ_UNBOUND, 1, name);
2766        if (!priv->dfs_cac_workqueue) {
2767                mwifiex_dbg(adapter, ERROR,
2768                            "cannot register virtual network device\n");
2769                free_netdev(dev);
2770                priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
2771                priv->netdev = NULL;
2772                memset(&priv->wdev, 0, sizeof(priv->wdev));
2773                priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
2774                return ERR_PTR(-ENOMEM);
2775        }
2776
2777        INIT_DELAYED_WORK(&priv->dfs_cac_work, mwifiex_dfs_cac_work_queue);
2778
2779        priv->dfs_chan_sw_workqueue = alloc_workqueue("MWIFIEX_DFS_CHSW%s",
2780                                                      WQ_HIGHPRI | WQ_UNBOUND |
2781                                                      WQ_MEM_RECLAIM, 1, name);
2782        if (!priv->dfs_chan_sw_workqueue) {
2783                mwifiex_dbg(adapter, ERROR,
2784                            "cannot register virtual network device\n");
2785                free_netdev(dev);
2786                priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
2787                priv->netdev = NULL;
2788                memset(&priv->wdev, 0, sizeof(priv->wdev));
2789                priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
2790                return ERR_PTR(-ENOMEM);
2791        }
2792
2793        INIT_DELAYED_WORK(&priv->dfs_chan_sw_work,
2794                          mwifiex_dfs_chan_sw_work_queue);
2795
2796        sema_init(&priv->async_sem, 1);
2797
2798        mwifiex_dbg(adapter, INFO,
2799                    "info: %s: Marvell 802.11 Adapter\n", dev->name);
2800
2801#ifdef CONFIG_DEBUG_FS
2802        mwifiex_dev_debugfs_init(priv);
2803#endif
2804
2805        switch (type) {
2806        case NL80211_IFTYPE_UNSPECIFIED:
2807        case NL80211_IFTYPE_STATION:
2808        case NL80211_IFTYPE_ADHOC:
2809                adapter->curr_iface_comb.sta_intf++;
2810                break;
2811        case NL80211_IFTYPE_AP:
2812                adapter->curr_iface_comb.uap_intf++;
2813                break;
2814        case NL80211_IFTYPE_P2P_CLIENT:
2815                adapter->curr_iface_comb.p2p_intf++;
2816                break;
2817        default:
2818                mwifiex_dbg(adapter, ERROR, "type not supported\n");
2819                return ERR_PTR(-EINVAL);
2820        }
2821
2822        return &priv->wdev;
2823}
2824EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
2825
2826/*
2827 * del_virtual_intf: remove the virtual interface determined by dev
2828 */
2829int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
2830{
2831        struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
2832        struct mwifiex_adapter *adapter = priv->adapter;
2833        struct sk_buff *skb, *tmp;
2834
2835#ifdef CONFIG_DEBUG_FS
2836        mwifiex_dev_debugfs_remove(priv);
2837#endif
2838
2839        mwifiex_stop_net_dev_queue(priv->netdev, adapter);
2840
2841        skb_queue_walk_safe(&priv->bypass_txq, skb, tmp)
2842                mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
2843
2844        if (netif_carrier_ok(priv->netdev))
2845                netif_carrier_off(priv->netdev);
2846
2847        if (wdev->netdev->reg_state == NETREG_REGISTERED)
2848                unregister_netdevice(wdev->netdev);
2849
2850        if (priv->dfs_cac_workqueue) {
2851                flush_workqueue(priv->dfs_cac_workqueue);
2852                destroy_workqueue(priv->dfs_cac_workqueue);
2853                priv->dfs_cac_workqueue = NULL;
2854        }
2855
2856        if (priv->dfs_chan_sw_workqueue) {
2857                flush_workqueue(priv->dfs_chan_sw_workqueue);
2858                destroy_workqueue(priv->dfs_chan_sw_workqueue);
2859                priv->dfs_chan_sw_workqueue = NULL;
2860        }
2861        /* Clear the priv in adapter */
2862        priv->netdev->ieee80211_ptr = NULL;
2863        priv->netdev = NULL;
2864        priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
2865
2866        priv->media_connected = false;
2867
2868        switch (priv->bss_mode) {
2869        case NL80211_IFTYPE_UNSPECIFIED:
2870        case NL80211_IFTYPE_STATION:
2871        case NL80211_IFTYPE_ADHOC:
2872                adapter->curr_iface_comb.sta_intf--;
2873                break;
2874        case NL80211_IFTYPE_AP:
2875                adapter->curr_iface_comb.uap_intf--;
2876                break;
2877        case NL80211_IFTYPE_P2P_CLIENT:
2878        case NL80211_IFTYPE_P2P_GO:
2879                adapter->curr_iface_comb.p2p_intf--;
2880                break;
2881        default:
2882                mwifiex_dbg(adapter, ERROR,
2883                            "del_virtual_intf: type not supported\n");
2884                break;
2885        }
2886
2887        priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
2888
2889        if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA ||
2890            GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)
2891                kfree(priv->hist_data);
2892
2893        return 0;
2894}
2895EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf);
2896
2897static bool
2898mwifiex_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_seq,
2899                             u8 max_byte_seq)
2900{
2901        int j, k, valid_byte_cnt = 0;
2902        bool dont_care_byte = false;
2903
2904        for (j = 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) {
2905                for (k = 0; k < 8; k++) {
2906                        if (pat->mask[j] & 1 << k) {
2907                                memcpy(byte_seq + valid_byte_cnt,
2908                                       &pat->pattern[j * 8 + k], 1);
2909                                valid_byte_cnt++;
2910                                if (dont_care_byte)
2911                                        return false;
2912                        } else {
2913                                if (valid_byte_cnt)
2914                                        dont_care_byte = true;
2915                        }
2916
2917                        if (valid_byte_cnt > max_byte_seq)
2918                                return false;
2919                }
2920        }
2921
2922        byte_seq[max_byte_seq] = valid_byte_cnt;
2923
2924        return true;
2925}
2926
2927#ifdef CONFIG_PM
2928static void mwifiex_set_auto_arp_mef_entry(struct mwifiex_private *priv,
2929                                           struct mwifiex_mef_entry *mef_entry)
2930{
2931        int i, filt_num = 0, num_ipv4 = 0;
2932        struct in_device *in_dev;
2933        struct in_ifaddr *ifa;
2934        __be32 ips[MWIFIEX_MAX_SUPPORTED_IPADDR];
2935        struct mwifiex_adapter *adapter = priv->adapter;
2936
2937        mef_entry->mode = MEF_MODE_HOST_SLEEP;
2938        mef_entry->action = MEF_ACTION_AUTO_ARP;
2939
2940        /* Enable ARP offload feature */
2941        memset(ips, 0, sizeof(ips));
2942        for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) {
2943                if (adapter->priv[i]->netdev) {
2944                        in_dev = __in_dev_get_rtnl(adapter->priv[i]->netdev);
2945                        if (!in_dev)
2946                                continue;
2947                        ifa = in_dev->ifa_list;
2948                        if (!ifa || !ifa->ifa_local)
2949                                continue;
2950                        ips[i] = ifa->ifa_local;
2951                        num_ipv4++;
2952                }
2953        }
2954
2955        for (i = 0; i < num_ipv4; i++) {
2956                if (!ips[i])
2957                        continue;
2958                mef_entry->filter[filt_num].repeat = 1;
2959                memcpy(mef_entry->filter[filt_num].byte_seq,
2960                       (u8 *)&ips[i], sizeof(ips[i]));
2961                mef_entry->filter[filt_num].
2962                        byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =
2963                        sizeof(ips[i]);
2964                mef_entry->filter[filt_num].offset = 46;
2965                mef_entry->filter[filt_num].filt_type = TYPE_EQ;
2966                if (filt_num) {
2967                        mef_entry->filter[filt_num].filt_action =
2968                                TYPE_OR;
2969                }
2970                filt_num++;
2971        }
2972
2973        mef_entry->filter[filt_num].repeat = 1;
2974        mef_entry->filter[filt_num].byte_seq[0] = 0x08;
2975        mef_entry->filter[filt_num].byte_seq[1] = 0x06;
2976        mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] = 2;
2977        mef_entry->filter[filt_num].offset = 20;
2978        mef_entry->filter[filt_num].filt_type = TYPE_EQ;
2979        mef_entry->filter[filt_num].filt_action = TYPE_AND;
2980}
2981
2982static int mwifiex_set_wowlan_mef_entry(struct mwifiex_private *priv,
2983                                        struct mwifiex_ds_mef_cfg *mef_cfg,
2984                                        struct mwifiex_mef_entry *mef_entry,
2985                                        struct cfg80211_wowlan *wowlan)
2986{
2987        int i, filt_num = 0, ret = 0;
2988        bool first_pat = true;
2989        u8 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ + 1];
2990        const u8 ipv4_mc_mac[] = {0x33, 0x33};
2991        const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};
2992
2993        mef_entry->mode = MEF_MODE_HOST_SLEEP;
2994        mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST;
2995
2996        for (i = 0; i < wowlan->n_patterns; i++) {
2997                memset(byte_seq, 0, sizeof(byte_seq));
2998                if (!mwifiex_is_pattern_supported(&wowlan->patterns[i],
2999                                        byte_seq,
3000                                        MWIFIEX_MEF_MAX_BYTESEQ)) {
3001                        mwifiex_dbg(priv->adapter, ERROR,
3002                                    "Pattern not supported\n");
3003                        return -EOPNOTSUPP;
3004                }
3005
3006                if (!wowlan->patterns[i].pkt_offset) {
3007                        if (!(byte_seq[0] & 0x01) &&
3008                            (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 1)) {
3009                                mef_cfg->criteria |= MWIFIEX_CRITERIA_UNICAST;
3010                                continue;
3011                        } else if (is_broadcast_ether_addr(byte_seq)) {
3012                                mef_cfg->criteria |= MWIFIEX_CRITERIA_BROADCAST;
3013                                continue;
3014                        } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&
3015                                    (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 2)) ||
3016                                   (!memcmp(byte_seq, ipv6_mc_mac, 3) &&
3017                                    (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 3))) {
3018                                mef_cfg->criteria |= MWIFIEX_CRITERIA_MULTICAST;
3019                                continue;
3020                        }
3021                }
3022                mef_entry->filter[filt_num].repeat = 1;
3023                mef_entry->filter[filt_num].offset =
3024                        wowlan->patterns[i].pkt_offset;
3025                memcpy(mef_entry->filter[filt_num].byte_seq, byte_seq,
3026                                sizeof(byte_seq));
3027                mef_entry->filter[filt_num].filt_type = TYPE_EQ;
3028
3029                if (first_pat)
3030                        first_pat = false;
3031                else
3032                        mef_entry->filter[filt_num].filt_action = TYPE_AND;
3033
3034                filt_num++;
3035        }
3036
3037        if (wowlan->magic_pkt) {
3038                mef_cfg->criteria |= MWIFIEX_CRITERIA_UNICAST;
3039                mef_entry->filter[filt_num].repeat = 16;
3040                memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,
3041                                ETH_ALEN);
3042                mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =
3043                        ETH_ALEN;
3044                mef_entry->filter[filt_num].offset = 28;
3045                mef_entry->filter[filt_num].filt_type = TYPE_EQ;
3046                if (filt_num)
3047                        mef_entry->filter[filt_num].filt_action = TYPE_OR;
3048
3049                filt_num++;
3050                mef_entry->filter[filt_num].repeat = 16;
3051                memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,
3052                                ETH_ALEN);
3053                mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =
3054                        ETH_ALEN;
3055                mef_entry->filter[filt_num].offset = 56;
3056                mef_entry->filter[filt_num].filt_type = TYPE_EQ;
3057                mef_entry->filter[filt_num].filt_action = TYPE_OR;
3058        }
3059        return ret;
3060}
3061
3062static int mwifiex_set_mef_filter(struct mwifiex_private *priv,
3063                                  struct cfg80211_wowlan *wowlan)
3064{
3065        int ret = 0, num_entries = 1;
3066        struct mwifiex_ds_mef_cfg mef_cfg;
3067        struct mwifiex_mef_entry *mef_entry;
3068
3069        if (wowlan->n_patterns || wowlan->magic_pkt)
3070                num_entries++;
3071
3072        mef_entry = kcalloc(num_entries, sizeof(*mef_entry), GFP_KERNEL);
3073        if (!mef_entry)
3074                return -ENOMEM;
3075
3076        memset(&mef_cfg, 0, sizeof(mef_cfg));
3077        mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST |
3078                MWIFIEX_CRITERIA_UNICAST;
3079        mef_cfg.num_entries = num_entries;
3080        mef_cfg.mef_entry = mef_entry;
3081
3082        mwifiex_set_auto_arp_mef_entry(priv, &mef_entry[0]);
3083
3084        if (wowlan->n_patterns || wowlan->magic_pkt) {
3085                ret = mwifiex_set_wowlan_mef_entry(priv, &mef_cfg,
3086                                                   &mef_entry[1], wowlan);
3087                if (ret)
3088                        goto err;
3089        }
3090
3091        if (!mef_cfg.criteria)
3092                mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST |
3093                        MWIFIEX_CRITERIA_UNICAST |
3094                        MWIFIEX_CRITERIA_MULTICAST;
3095
3096        ret = mwifiex_send_cmd(priv, HostCmd_CMD_MEF_CFG,
3097                        HostCmd_ACT_GEN_SET, 0,
3098                        &mef_cfg, true);
3099
3100err:
3101        kfree(mef_entry);
3102        return ret;
3103}
3104
3105static int mwifiex_cfg80211_suspend(struct wiphy *wiphy,
3106                                    struct cfg80211_wowlan *wowlan)
3107{
3108        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
3109        struct mwifiex_ds_hs_cfg hs_cfg;
3110        int i, ret = 0;
3111        struct mwifiex_private *priv;
3112
3113        for (i = 0; i < adapter->priv_num; i++) {
3114                priv = adapter->priv[i];
3115                mwifiex_abort_cac(priv);
3116        }
3117
3118        mwifiex_cancel_all_pending_cmd(adapter);
3119
3120        if (!wowlan) {
3121                mwifiex_dbg(adapter, ERROR,
3122                            "None of the WOWLAN triggers enabled\n");
3123                return 0;
3124        }
3125
3126        priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
3127
3128        if (!priv->media_connected) {
3129                mwifiex_dbg(adapter, ERROR,
3130                            "Can not configure WOWLAN in disconnected state\n");
3131                return 0;
3132        }
3133
3134        ret = mwifiex_set_mef_filter(priv, wowlan);
3135        if (ret) {
3136                mwifiex_dbg(adapter, ERROR, "Failed to set MEF filter\n");
3137                return ret;
3138        }
3139
3140        if (wowlan->disconnect) {
3141                memset(&hs_cfg, 0, sizeof(hs_cfg));
3142                hs_cfg.is_invoke_hostcmd = false;
3143                hs_cfg.conditions = HS_CFG_COND_MAC_EVENT;
3144                hs_cfg.gpio = HS_CFG_GPIO_DEF;
3145                hs_cfg.gap = HS_CFG_GAP_DEF;
3146                ret = mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
3147                                            MWIFIEX_SYNC_CMD, &hs_cfg);
3148                if (ret) {
3149                        mwifiex_dbg(adapter, ERROR,
3150                                    "Failed to set HS params\n");
3151                        return ret;
3152                }
3153        }
3154
3155        return ret;
3156}
3157
3158static int mwifiex_cfg80211_resume(struct wiphy *wiphy)
3159{
3160        return 0;
3161}
3162
3163static void mwifiex_cfg80211_set_wakeup(struct wiphy *wiphy,
3164                                       bool enabled)
3165{
3166        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
3167
3168        device_set_wakeup_enable(adapter->dev, enabled);
3169}
3170#endif
3171
3172static int mwifiex_get_coalesce_pkt_type(u8 *byte_seq)
3173{
3174        const u8 ipv4_mc_mac[] = {0x33, 0x33};
3175        const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};
3176        const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff};
3177
3178        if ((byte_seq[0] & 0x01) &&
3179            (byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 1))
3180                return PACKET_TYPE_UNICAST;
3181        else if (!memcmp(byte_seq, bc_mac, 4))
3182                return PACKET_TYPE_BROADCAST;
3183        else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&
3184                  byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 2) ||
3185                 (!memcmp(byte_seq, ipv6_mc_mac, 3) &&
3186                  byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 3))
3187                return PACKET_TYPE_MULTICAST;
3188
3189        return 0;
3190}
3191
3192static int
3193mwifiex_fill_coalesce_rule_info(struct mwifiex_private *priv,
3194                                struct cfg80211_coalesce_rules *crule,
3195                                struct mwifiex_coalesce_rule *mrule)
3196{
3197        u8 byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ + 1];
3198        struct filt_field_param *param;
3199        int i;
3200
3201        mrule->max_coalescing_delay = crule->delay;
3202
3203        param = mrule->params;
3204
3205        for (i = 0; i < crule->n_patterns; i++) {
3206                memset(byte_seq, 0, sizeof(byte_seq));
3207                if (!mwifiex_is_pattern_supported(&crule->patterns[i],
3208                                                  byte_seq,
3209                                                MWIFIEX_COALESCE_MAX_BYTESEQ)) {
3210                        mwifiex_dbg(priv->adapter, ERROR,
3211                                    "Pattern not supported\n");
3212                        return -EOPNOTSUPP;
3213                }
3214
3215                if (!crule->patterns[i].pkt_offset) {
3216                        u8 pkt_type;
3217
3218                        pkt_type = mwifiex_get_coalesce_pkt_type(byte_seq);
3219                        if (pkt_type && mrule->pkt_type) {
3220                                mwifiex_dbg(priv->adapter, ERROR,
3221                                            "Multiple packet types not allowed\n");
3222                                return -EOPNOTSUPP;
3223                        } else if (pkt_type) {
3224                                mrule->pkt_type = pkt_type;
3225                                continue;
3226                        }
3227                }
3228
3229                if (crule->condition == NL80211_COALESCE_CONDITION_MATCH)
3230                        param->operation = RECV_FILTER_MATCH_TYPE_EQ;
3231                else
3232                        param->operation = RECV_FILTER_MATCH_TYPE_NE;
3233
3234                param->operand_len = byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ];
3235                memcpy(param->operand_byte_stream, byte_seq,
3236                       param->operand_len);
3237                param->offset = crule->patterns[i].pkt_offset;
3238                param++;
3239
3240                mrule->num_of_fields++;
3241        }
3242
3243        if (!mrule->pkt_type) {
3244                mwifiex_dbg(priv->adapter, ERROR,
3245                            "Packet type can not be determined\n");
3246                return -EOPNOTSUPP;
3247        }
3248
3249        return 0;
3250}
3251
3252static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy,
3253                                         struct cfg80211_coalesce *coalesce)
3254{
3255        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
3256        int i, ret;
3257        struct mwifiex_ds_coalesce_cfg coalesce_cfg;
3258        struct mwifiex_private *priv =
3259                        mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
3260
3261        memset(&coalesce_cfg, 0, sizeof(coalesce_cfg));
3262        if (!coalesce) {
3263                mwifiex_dbg(adapter, WARN,
3264                            "Disable coalesce and reset all previous rules\n");
3265                return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG,
3266                                        HostCmd_ACT_GEN_SET, 0,
3267                                        &coalesce_cfg, true);
3268        }
3269
3270        coalesce_cfg.num_of_rules = coalesce->n_rules;
3271        for (i = 0; i < coalesce->n_rules; i++) {
3272                ret = mwifiex_fill_coalesce_rule_info(priv, &coalesce->rules[i],
3273                                                      &coalesce_cfg.rule[i]);
3274                if (ret) {
3275                        mwifiex_dbg(adapter, ERROR,
3276                                    "Recheck the patterns provided for rule %d\n",
3277                                i + 1);
3278                        return ret;
3279                }
3280        }
3281
3282        return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG,
3283                                HostCmd_ACT_GEN_SET, 0, &coalesce_cfg, true);
3284}
3285
3286/* cfg80211 ops handler for tdls_mgmt.
3287 * Function prepares TDLS action frame packets and forwards them to FW
3288 */
3289static int
3290mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
3291                           const u8 *peer, u8 action_code, u8 dialog_token,
3292                           u16 status_code, u32 peer_capability,
3293                           bool initiator, const u8 *extra_ies,
3294                           size_t extra_ies_len)
3295{
3296        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
3297        int ret;
3298
3299        if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
3300                return -ENOTSUPP;
3301
3302        /* make sure we are in station mode and connected */
3303        if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
3304                return -ENOTSUPP;
3305
3306        switch (action_code) {
3307        case WLAN_TDLS_SETUP_REQUEST:
3308                mwifiex_dbg(priv->adapter, MSG,
3309                            "Send TDLS Setup Request to %pM status_code=%d\n",
3310                            peer, status_code);
3311                mwifiex_add_auto_tdls_peer(priv, peer);
3312                ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
3313                                                   dialog_token, status_code,
3314                                                   extra_ies, extra_ies_len);
3315                break;
3316        case WLAN_TDLS_SETUP_RESPONSE:
3317                mwifiex_add_auto_tdls_peer(priv, peer);
3318                mwifiex_dbg(priv->adapter, MSG,
3319                            "Send TDLS Setup Response to %pM status_code=%d\n",
3320                            peer, status_code);
3321                ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
3322                                                   dialog_token, status_code,
3323                                                   extra_ies, extra_ies_len);
3324                break;
3325        case WLAN_TDLS_SETUP_CONFIRM:
3326                mwifiex_dbg(priv->adapter, MSG,
3327                            "Send TDLS Confirm to %pM status_code=%d\n", peer,
3328                            status_code);
3329                ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
3330                                                   dialog_token, status_code,
3331                                                   extra_ies, extra_ies_len);
3332                break;
3333        case WLAN_TDLS_TEARDOWN:
3334                mwifiex_dbg(priv->adapter, MSG,
3335                            "Send TDLS Tear down to %pM\n", peer);
3336                ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
3337                                                   dialog_token, status_code,
3338                                                   extra_ies, extra_ies_len);
3339                break;
3340        case WLAN_TDLS_DISCOVERY_REQUEST:
3341                mwifiex_dbg(priv->adapter, MSG,
3342                            "Send TDLS Discovery Request to %pM\n", peer);
3343                ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
3344                                                   dialog_token, status_code,
3345                                                   extra_ies, extra_ies_len);
3346                break;
3347        case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
3348                mwifiex_dbg(priv->adapter, MSG,
3349                            "Send TDLS Discovery Response to %pM\n", peer);
3350                ret = mwifiex_send_tdls_action_frame(priv, peer, action_code,
3351                                                   dialog_token, status_code,
3352                                                   extra_ies, extra_ies_len);
3353                break;
3354        default:
3355                mwifiex_dbg(priv->adapter, ERROR,
3356                            "Unknown TDLS mgmt/action frame %pM\n", peer);
3357                ret = -EINVAL;
3358                break;
3359        }
3360
3361        return ret;
3362}
3363
3364static int
3365mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
3366                           const u8 *peer, enum nl80211_tdls_operation action)
3367{
3368        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
3369
3370        if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
3371            !(wiphy->flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
3372                return -ENOTSUPP;
3373
3374        /* make sure we are in station mode and connected */
3375        if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
3376                return -ENOTSUPP;
3377
3378        mwifiex_dbg(priv->adapter, MSG,
3379                    "TDLS peer=%pM, oper=%d\n", peer, action);
3380
3381        switch (action) {
3382        case NL80211_TDLS_ENABLE_LINK:
3383                action = MWIFIEX_TDLS_ENABLE_LINK;
3384                break;
3385        case NL80211_TDLS_DISABLE_LINK:
3386                action = MWIFIEX_TDLS_DISABLE_LINK;
3387                break;
3388        case NL80211_TDLS_TEARDOWN:
3389                /* shouldn't happen!*/
3390                mwifiex_dbg(priv->adapter, ERROR,
3391                            "tdls_oper: teardown from driver not supported\n");
3392                return -EINVAL;
3393        case NL80211_TDLS_SETUP:
3394                /* shouldn't happen!*/
3395                mwifiex_dbg(priv->adapter, ERROR,
3396                            "tdls_oper: setup from driver not supported\n");
3397                return -EINVAL;
3398        case NL80211_TDLS_DISCOVERY_REQ:
3399                /* shouldn't happen!*/
3400                mwifiex_dbg(priv->adapter, ERROR,
3401                            "tdls_oper: discovery from driver not supported\n");
3402                return -EINVAL;
3403        default:
3404                mwifiex_dbg(priv->adapter, ERROR,
3405                            "tdls_oper: operation not supported\n");
3406                return -ENOTSUPP;
3407        }
3408
3409        return mwifiex_tdls_oper(priv, peer, action);
3410}
3411
3412static int
3413mwifiex_cfg80211_tdls_chan_switch(struct wiphy *wiphy, struct net_device *dev,
3414                                  const u8 *addr, u8 oper_class,
3415                                  struct cfg80211_chan_def *chandef)
3416{
3417        struct mwifiex_sta_node *sta_ptr;
3418        unsigned long flags;
3419        u16 chan;
3420        u8 second_chan_offset, band;
3421        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
3422
3423        spin_lock_irqsave(&priv->sta_list_spinlock, flags);
3424        sta_ptr = mwifiex_get_sta_entry(priv, addr);
3425        spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
3426
3427        if (!sta_ptr) {
3428                wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",
3429                          __func__, addr);
3430                return -ENOENT;
3431        }
3432
3433        if (!(sta_ptr->tdls_cap.extcap.ext_capab[3] &
3434              WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH)) {
3435                wiphy_err(wiphy, "%pM do not support tdls cs\n", addr);
3436                return -ENOENT;
3437        }
3438
3439        if (sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||
3440            sta_ptr->tdls_status == TDLS_IN_OFF_CHAN) {
3441                wiphy_err(wiphy, "channel switch is running, abort request\n");
3442                return -EALREADY;
3443        }
3444
3445        chan = chandef->chan->hw_value;
3446        second_chan_offset = mwifiex_get_sec_chan_offset(chan);
3447        band = chandef->chan->band;
3448        mwifiex_start_tdls_cs(priv, addr, chan, second_chan_offset, band);
3449
3450        return 0;
3451}
3452
3453static void
3454mwifiex_cfg80211_tdls_cancel_chan_switch(struct wiphy *wiphy,
3455                                         struct net_device *dev,
3456                                         const u8 *addr)
3457{
3458        struct mwifiex_sta_node *sta_ptr;
3459        unsigned long flags;
3460        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
3461
3462        spin_lock_irqsave(&priv->sta_list_spinlock, flags);
3463        sta_ptr = mwifiex_get_sta_entry(priv, addr);
3464        spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
3465
3466        if (!sta_ptr) {
3467                wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",
3468                          __func__, addr);
3469        } else if (!(sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||
3470                     sta_ptr->tdls_status == TDLS_IN_BASE_CHAN ||
3471                     sta_ptr->tdls_status == TDLS_IN_OFF_CHAN)) {
3472                wiphy_err(wiphy, "tdls chan switch not initialize by %pM\n",
3473                          addr);
3474        } else
3475                mwifiex_stop_tdls_cs(priv, addr);
3476}
3477
3478static int
3479mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev,
3480                             const u8 *mac, struct station_parameters *params)
3481{
3482        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
3483
3484        if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
3485                return -ENOTSUPP;
3486
3487        /* make sure we are in station mode and connected */
3488        if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected)
3489                return -ENOTSUPP;
3490
3491        return mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CREATE_LINK);
3492}
3493
3494static int
3495mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
3496                                struct cfg80211_csa_settings *params)
3497{
3498        struct ieee_types_header *chsw_ie;
3499        struct ieee80211_channel_sw_ie *channel_sw;
3500        int chsw_msec;
3501        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
3502
3503        if (priv->adapter->scan_processing) {
3504                mwifiex_dbg(priv->adapter, ERROR,
3505                            "radar detection: scan in process...\n");
3506                return -EBUSY;
3507        }
3508
3509        if (priv->wdev.cac_started)
3510                return -EBUSY;
3511
3512        if (cfg80211_chandef_identical(&params->chandef,
3513                                       &priv->dfs_chandef))
3514                return -EINVAL;
3515
3516        chsw_ie = (void *)cfg80211_find_ie(WLAN_EID_CHANNEL_SWITCH,
3517                                           params->beacon_csa.tail,
3518                                           params->beacon_csa.tail_len);
3519        if (!chsw_ie) {
3520                mwifiex_dbg(priv->adapter, ERROR,
3521                            "Could not parse channel switch announcement IE\n");
3522                return -EINVAL;
3523        }
3524
3525        channel_sw = (void *)(chsw_ie + 1);
3526        if (channel_sw->mode) {
3527                if (netif_carrier_ok(priv->netdev))
3528                        netif_carrier_off(priv->netdev);
3529                mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
3530        }
3531
3532        if (mwifiex_del_mgmt_ies(priv))
3533                mwifiex_dbg(priv->adapter, ERROR,
3534                            "Failed to delete mgmt IEs!\n");
3535
3536        if (mwifiex_set_mgmt_ies(priv, &params->beacon_csa)) {
3537                mwifiex_dbg(priv->adapter, ERROR,
3538                            "%s: setting mgmt ies failed\n", __func__);
3539                return -EFAULT;
3540        }
3541
3542        memcpy(&priv->dfs_chandef, &params->chandef, sizeof(priv->dfs_chandef));
3543        memcpy(&priv->beacon_after, &params->beacon_after,
3544               sizeof(priv->beacon_after));
3545
3546        chsw_msec = max(channel_sw->count * priv->bss_cfg.beacon_period, 100);
3547        queue_delayed_work(priv->dfs_chan_sw_workqueue, &priv->dfs_chan_sw_work,
3548                           msecs_to_jiffies(chsw_msec));
3549        return 0;
3550}
3551
3552static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy,
3553                                        struct wireless_dev *wdev,
3554                                        struct cfg80211_chan_def *chandef)
3555{
3556        struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
3557        struct mwifiex_bssdescriptor *curr_bss;
3558        struct ieee80211_channel *chan;
3559        u8 second_chan_offset;
3560        enum nl80211_channel_type chan_type;
3561        enum ieee80211_band band;
3562        int freq;
3563        int ret = -ENODATA;
3564
3565        if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&
3566            cfg80211_chandef_valid(&priv->bss_chandef)) {
3567                *chandef = priv->bss_chandef;
3568                ret = 0;
3569        } else if (priv->media_connected) {
3570                curr_bss = &priv->curr_bss_params.bss_descriptor;
3571                band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
3572                freq = ieee80211_channel_to_frequency(curr_bss->channel, band);
3573                chan = ieee80211_get_channel(wiphy, freq);
3574
3575                if (curr_bss->bcn_ht_oper) {
3576                        second_chan_offset = curr_bss->bcn_ht_oper->ht_param &
3577                                        IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
3578                        chan_type = mwifiex_sec_chan_offset_to_chan_type
3579                                                        (second_chan_offset);
3580                        cfg80211_chandef_create(chandef, chan, chan_type);
3581                } else {
3582                        cfg80211_chandef_create(chandef, chan,
3583                                                NL80211_CHAN_NO_HT);
3584                }
3585                ret = 0;
3586        }
3587
3588        return ret;
3589}
3590
3591static int
3592mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy,
3593                                       struct net_device *dev,
3594                                       struct cfg80211_chan_def *chandef,
3595                                       u32 cac_time_ms)
3596{
3597        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
3598        struct mwifiex_radar_params radar_params;
3599
3600        if (priv->adapter->scan_processing) {
3601                mwifiex_dbg(priv->adapter, ERROR,
3602                            "radar detection: scan already in process...\n");
3603                return -EBUSY;
3604        }
3605
3606        if (!mwifiex_is_11h_active(priv)) {
3607                mwifiex_dbg(priv->adapter, INFO,
3608                            "Enable 11h extensions in FW\n");
3609                if (mwifiex_11h_activate(priv, true)) {
3610                        mwifiex_dbg(priv->adapter, ERROR,
3611                                    "Failed to activate 11h extensions!!");
3612                        return -1;
3613                }
3614                priv->state_11h.is_11h_active = true;
3615        }
3616
3617        memset(&radar_params, 0, sizeof(struct mwifiex_radar_params));
3618        radar_params.chandef = chandef;
3619        radar_params.cac_time_ms = cac_time_ms;
3620
3621        memcpy(&priv->dfs_chandef, chandef, sizeof(priv->dfs_chandef));
3622
3623        if (mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
3624                             HostCmd_ACT_GEN_SET, 0, &radar_params, true))
3625                return -1;
3626
3627        queue_delayed_work(priv->dfs_cac_workqueue, &priv->dfs_cac_work,
3628                           msecs_to_jiffies(cac_time_ms));
3629        return 0;
3630}
3631
3632static int
3633mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev,
3634                                const u8 *mac,
3635                                struct station_parameters *params)
3636{
3637        int ret;
3638        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
3639
3640        /* we support change_station handler only for TDLS peers*/
3641        if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
3642                return -ENOTSUPP;
3643
3644        /* make sure we are in station mode and connected */
3645        if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected)
3646                return -ENOTSUPP;
3647
3648        priv->sta_params = params;
3649
3650        ret = mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CONFIG_LINK);
3651        priv->sta_params = NULL;
3652
3653        return ret;
3654}
3655
3656/* station cfg80211 operations */
3657static struct cfg80211_ops mwifiex_cfg80211_ops = {
3658        .add_virtual_intf = mwifiex_add_virtual_intf,
3659        .del_virtual_intf = mwifiex_del_virtual_intf,
3660        .change_virtual_intf = mwifiex_cfg80211_change_virtual_intf,
3661        .scan = mwifiex_cfg80211_scan,
3662        .connect = mwifiex_cfg80211_connect,
3663        .disconnect = mwifiex_cfg80211_disconnect,
3664        .get_station = mwifiex_cfg80211_get_station,
3665        .dump_station = mwifiex_cfg80211_dump_station,
3666        .dump_survey = mwifiex_cfg80211_dump_survey,
3667        .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params,
3668        .join_ibss = mwifiex_cfg80211_join_ibss,
3669        .leave_ibss = mwifiex_cfg80211_leave_ibss,
3670        .add_key = mwifiex_cfg80211_add_key,
3671        .del_key = mwifiex_cfg80211_del_key,
3672        .mgmt_tx = mwifiex_cfg80211_mgmt_tx,
3673        .mgmt_frame_register = mwifiex_cfg80211_mgmt_frame_register,
3674        .remain_on_channel = mwifiex_cfg80211_remain_on_channel,
3675        .cancel_remain_on_channel = mwifiex_cfg80211_cancel_remain_on_channel,
3676        .set_default_key = mwifiex_cfg80211_set_default_key,
3677        .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt,
3678        .set_tx_power = mwifiex_cfg80211_set_tx_power,
3679        .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask,
3680        .start_ap = mwifiex_cfg80211_start_ap,
3681        .stop_ap = mwifiex_cfg80211_stop_ap,
3682        .change_beacon = mwifiex_cfg80211_change_beacon,
3683        .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config,
3684        .set_antenna = mwifiex_cfg80211_set_antenna,
3685        .del_station = mwifiex_cfg80211_del_station,
3686#ifdef CONFIG_PM
3687        .suspend = mwifiex_cfg80211_suspend,
3688        .resume = mwifiex_cfg80211_resume,
3689        .set_wakeup = mwifiex_cfg80211_set_wakeup,
3690#endif
3691        .set_coalesce = mwifiex_cfg80211_set_coalesce,
3692        .tdls_mgmt = mwifiex_cfg80211_tdls_mgmt,
3693        .tdls_oper = mwifiex_cfg80211_tdls_oper,
3694        .tdls_channel_switch = mwifiex_cfg80211_tdls_chan_switch,
3695        .tdls_cancel_channel_switch = mwifiex_cfg80211_tdls_cancel_chan_switch,
3696        .add_station = mwifiex_cfg80211_add_station,
3697        .change_station = mwifiex_cfg80211_change_station,
3698        .get_channel = mwifiex_cfg80211_get_channel,
3699        .start_radar_detection = mwifiex_cfg80211_start_radar_detection,
3700        .channel_switch = mwifiex_cfg80211_channel_switch,
3701};
3702
3703#ifdef CONFIG_PM
3704static const struct wiphy_wowlan_support mwifiex_wowlan_support = {
3705        .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
3706        .n_patterns = MWIFIEX_MEF_MAX_FILTERS,
3707        .pattern_min_len = 1,
3708        .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN,
3709        .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,
3710};
3711#endif
3712
3713static bool mwifiex_is_valid_alpha2(const char *alpha2)
3714{
3715        if (!alpha2 || strlen(alpha2) != 2)
3716                return false;
3717
3718        if (isalpha(alpha2[0]) && isalpha(alpha2[1]))
3719                return true;
3720
3721        return false;
3722}
3723
3724static const struct wiphy_coalesce_support mwifiex_coalesce_support = {
3725        .n_rules = MWIFIEX_COALESCE_MAX_RULES,
3726        .max_delay = MWIFIEX_MAX_COALESCING_DELAY,
3727        .n_patterns = MWIFIEX_COALESCE_MAX_FILTERS,
3728        .pattern_min_len = 1,
3729        .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN,
3730        .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,
3731};
3732
3733int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter)
3734{
3735        u32 n_channels_bg, n_channels_a = 0;
3736
3737        n_channels_bg = mwifiex_band_2ghz.n_channels;
3738
3739        if (adapter->config_bands & BAND_A)
3740                n_channels_a = mwifiex_band_5ghz.n_channels;
3741
3742        adapter->num_in_chan_stats = max_t(u32, n_channels_bg, n_channels_a);
3743        adapter->chan_stats = vmalloc(sizeof(*adapter->chan_stats) *
3744                                      adapter->num_in_chan_stats);
3745
3746        if (!adapter->chan_stats)
3747                return -ENOMEM;
3748
3749        return 0;
3750}
3751
3752/*
3753 * This function registers the device with CFG802.11 subsystem.
3754 *
3755 * The function creates the wireless device/wiphy, populates it with
3756 * default parameters and handler function pointers, and finally
3757 * registers the device.
3758 */
3759
3760int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
3761{
3762        int ret;
3763        void *wdev_priv;
3764        struct wiphy *wiphy;
3765        struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA];
3766        u8 *country_code;
3767        u32 thr, retry;
3768
3769        /* create a new wiphy for use with cfg80211 */
3770        wiphy = wiphy_new(&mwifiex_cfg80211_ops,
3771                          sizeof(struct mwifiex_adapter *));
3772        if (!wiphy) {
3773                mwifiex_dbg(adapter, ERROR,
3774                            "%s: creating new wiphy\n", __func__);
3775                return -ENOMEM;
3776        }
3777        wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;
3778        wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
3779        wiphy->mgmt_stypes = mwifiex_mgmt_stypes;
3780        wiphy->max_remain_on_channel_duration = 5000;
3781        wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
3782                                 BIT(NL80211_IFTYPE_ADHOC) |
3783                                 BIT(NL80211_IFTYPE_P2P_CLIENT) |
3784                                 BIT(NL80211_IFTYPE_P2P_GO) |
3785                                 BIT(NL80211_IFTYPE_AP);
3786
3787        wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz;
3788        if (adapter->config_bands & BAND_A)
3789                wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz;
3790        else
3791                wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
3792
3793        if (adapter->drcs_enabled && ISSUPP_DRCS_ENABLED(adapter->fw_cap_info))
3794                wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_drcs;
3795        else if (adapter->is_hw_11ac_capable)
3796                wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_vht;
3797        else
3798                wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta;
3799        wiphy->n_iface_combinations = 1;
3800
3801        /* Initialize cipher suits */
3802        wiphy->cipher_suites = mwifiex_cipher_suites;
3803        wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);
3804
3805        ether_addr_copy(wiphy->perm_addr, adapter->perm_addr);
3806        wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
3807        wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
3808                        WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
3809                        WIPHY_FLAG_AP_UAPSD |
3810                        WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
3811                        WIPHY_FLAG_HAS_CHANNEL_SWITCH |
3812                        WIPHY_FLAG_PS_ON_BY_DEFAULT;
3813
3814        if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))
3815                wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
3816                                WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
3817
3818#ifdef CONFIG_PM
3819        wiphy->wowlan = &mwifiex_wowlan_support;
3820#endif
3821
3822        wiphy->coalesce = &mwifiex_coalesce_support;
3823
3824        wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
3825                                    NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
3826                                    NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
3827
3828        wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;
3829        wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;
3830
3831        wiphy->features |= NL80211_FEATURE_HT_IBSS |
3832                           NL80211_FEATURE_INACTIVITY_TIMER |
3833                           NL80211_FEATURE_NEED_OBSS_SCAN;
3834
3835        if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))
3836                wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
3837
3838        if (adapter->fw_api_ver == MWIFIEX_FW_V15)
3839                wiphy->features |= NL80211_FEATURE_SK_TX_STATUS;
3840
3841        /* Reserve space for mwifiex specific private data for BSS */
3842        wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
3843
3844        wiphy->reg_notifier = mwifiex_reg_notifier;
3845
3846        /* Set struct mwifiex_adapter pointer in wiphy_priv */
3847        wdev_priv = wiphy_priv(wiphy);
3848        *(unsigned long *)wdev_priv = (unsigned long)adapter;
3849
3850        set_wiphy_dev(wiphy, priv->adapter->dev);
3851
3852        ret = wiphy_register(wiphy);
3853        if (ret < 0) {
3854                mwifiex_dbg(adapter, ERROR,
3855                            "%s: wiphy_register failed: %d\n", __func__, ret);
3856                wiphy_free(wiphy);
3857                return ret;
3858        }
3859
3860        if (reg_alpha2 && mwifiex_is_valid_alpha2(reg_alpha2)) {
3861                mwifiex_dbg(adapter, INFO,
3862                            "driver hint alpha2: %2.2s\n", reg_alpha2);
3863                regulatory_hint(wiphy, reg_alpha2);
3864        } else {
3865                country_code = mwifiex_11d_code_2_region(adapter->region_code);
3866                if (country_code)
3867                        mwifiex_dbg(adapter, WARN,
3868                                    "ignoring F/W country code %2.2s\n",
3869                                    country_code);
3870        }
3871
3872        mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
3873                         HostCmd_ACT_GEN_GET, FRAG_THRESH_I, &thr, true);
3874        wiphy->frag_threshold = thr;
3875        mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
3876                         HostCmd_ACT_GEN_GET, RTS_THRESH_I, &thr, true);
3877        wiphy->rts_threshold = thr;
3878        mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
3879                         HostCmd_ACT_GEN_GET, SHORT_RETRY_LIM_I, &retry, true);
3880        wiphy->retry_short = (u8) retry;
3881        mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
3882                         HostCmd_ACT_GEN_GET, LONG_RETRY_LIM_I, &retry, true);
3883        wiphy->retry_long = (u8) retry;
3884
3885        adapter->wiphy = wiphy;
3886        return ret;
3887}
3888