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
  23static char *reg_alpha2;
  24module_param(reg_alpha2, charp, 0);
  25
  26static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = {
  27        {
  28                .max = 2, .types = BIT(NL80211_IFTYPE_STATION) |
  29                                   BIT(NL80211_IFTYPE_P2P_GO) |
  30                                   BIT(NL80211_IFTYPE_P2P_CLIENT),
  31        },
  32        {
  33                .max = 1, .types = BIT(NL80211_IFTYPE_AP),
  34        },
  35};
  36
  37static const struct ieee80211_iface_combination mwifiex_iface_comb_ap_sta = {
  38        .limits = mwifiex_ap_sta_limits,
  39        .num_different_channels = 1,
  40        .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),
  41        .max_interfaces = MWIFIEX_MAX_BSS_NUM,
  42        .beacon_int_infra_match = true,
  43};
  44
  45/*
  46 * This function maps the nl802.11 channel type into driver channel type.
  47 *
  48 * The mapping is as follows -
  49 *      NL80211_CHAN_NO_HT     -> IEEE80211_HT_PARAM_CHA_SEC_NONE
  50 *      NL80211_CHAN_HT20      -> IEEE80211_HT_PARAM_CHA_SEC_NONE
  51 *      NL80211_CHAN_HT40PLUS  -> IEEE80211_HT_PARAM_CHA_SEC_ABOVE
  52 *      NL80211_CHAN_HT40MINUS -> IEEE80211_HT_PARAM_CHA_SEC_BELOW
  53 *      Others                 -> IEEE80211_HT_PARAM_CHA_SEC_NONE
  54 */
  55u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type)
  56{
  57        switch (chan_type) {
  58        case NL80211_CHAN_NO_HT:
  59        case NL80211_CHAN_HT20:
  60                return IEEE80211_HT_PARAM_CHA_SEC_NONE;
  61        case NL80211_CHAN_HT40PLUS:
  62                return IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
  63        case NL80211_CHAN_HT40MINUS:
  64                return IEEE80211_HT_PARAM_CHA_SEC_BELOW;
  65        default:
  66                return IEEE80211_HT_PARAM_CHA_SEC_NONE;
  67        }
  68}
  69
  70/*
  71 * This function checks whether WEP is set.
  72 */
  73static int
  74mwifiex_is_alg_wep(u32 cipher)
  75{
  76        switch (cipher) {
  77        case WLAN_CIPHER_SUITE_WEP40:
  78        case WLAN_CIPHER_SUITE_WEP104:
  79                return 1;
  80        default:
  81                break;
  82        }
  83
  84        return 0;
  85}
  86
  87/*
  88 * This function retrieves the private structure from kernel wiphy structure.
  89 */
  90static void *mwifiex_cfg80211_get_adapter(struct wiphy *wiphy)
  91{
  92        return (void *) (*(unsigned long *) wiphy_priv(wiphy));
  93}
  94
  95/*
  96 * CFG802.11 operation handler to delete a network key.
  97 */
  98static int
  99mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,
 100                         u8 key_index, bool pairwise, const u8 *mac_addr)
 101{
 102        struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
 103        const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 104        const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
 105
 106        if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index, peer_mac, 1)) {
 107                wiphy_err(wiphy, "deleting the crypto keys\n");
 108                return -EFAULT;
 109        }
 110
 111        wiphy_dbg(wiphy, "info: crypto keys deleted\n");
 112        return 0;
 113}
 114
 115/*
 116 * This function forms an skb for management frame.
 117 */
 118static int
 119mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len)
 120{
 121        u8 addr[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 122        u16 pkt_len;
 123        u32 tx_control = 0, pkt_type = PKT_TYPE_MGMT;
 124
 125        pkt_len = len + ETH_ALEN;
 126
 127        skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN +
 128                    MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
 129        memcpy(skb_push(skb, sizeof(pkt_len)), &pkt_len, sizeof(pkt_len));
 130
 131        memcpy(skb_push(skb, sizeof(tx_control)),
 132               &tx_control, sizeof(tx_control));
 133
 134        memcpy(skb_push(skb, sizeof(pkt_type)), &pkt_type, sizeof(pkt_type));
 135
 136        /* Add packet data and address4 */
 137        memcpy(skb_put(skb, sizeof(struct ieee80211_hdr_3addr)), buf,
 138               sizeof(struct ieee80211_hdr_3addr));
 139        memcpy(skb_put(skb, ETH_ALEN), addr, ETH_ALEN);
 140        memcpy(skb_put(skb, len - sizeof(struct ieee80211_hdr_3addr)),
 141               buf + sizeof(struct ieee80211_hdr_3addr),
 142               len - sizeof(struct ieee80211_hdr_3addr));
 143
 144        skb->priority = LOW_PRIO_TID;
 145        __net_timestamp(skb);
 146
 147        return 0;
 148}
 149
 150/*
 151 * CFG802.11 operation handler to transmit a management frame.
 152 */
 153static int
 154mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 155                         struct cfg80211_mgmt_tx_params *params, u64 *cookie)
 156{
 157        const u8 *buf = params->buf;
 158        size_t len = params->len;
 159        struct sk_buff *skb;
 160        u16 pkt_len;
 161        const struct ieee80211_mgmt *mgmt;
 162        struct mwifiex_txinfo *tx_info;
 163        struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
 164
 165        if (!buf || !len) {
 166                wiphy_err(wiphy, "invalid buffer and length\n");
 167                return -EFAULT;
 168        }
 169
 170        mgmt = (const struct ieee80211_mgmt *)buf;
 171        if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA &&
 172            ieee80211_is_probe_resp(mgmt->frame_control)) {
 173                /* Since we support offload probe resp, we need to skip probe
 174                 * resp in AP or GO mode */
 175                wiphy_dbg(wiphy,
 176                          "info: skip to send probe resp in AP or GO mode\n");
 177                return 0;
 178        }
 179
 180        pkt_len = len + ETH_ALEN;
 181        skb = dev_alloc_skb(MWIFIEX_MIN_DATA_HEADER_LEN +
 182                            MWIFIEX_MGMT_FRAME_HEADER_SIZE +
 183                            pkt_len + sizeof(pkt_len));
 184
 185        if (!skb) {
 186                wiphy_err(wiphy, "allocate skb failed for management frame\n");
 187                return -ENOMEM;
 188        }
 189
 190        tx_info = MWIFIEX_SKB_TXCB(skb);
 191        memset(tx_info, 0, sizeof(*tx_info));
 192        tx_info->bss_num = priv->bss_num;
 193        tx_info->bss_type = priv->bss_type;
 194        tx_info->pkt_len = pkt_len;
 195
 196        mwifiex_form_mgmt_frame(skb, buf, len);
 197        mwifiex_queue_tx_pkt(priv, skb);
 198
 199        *cookie = prandom_u32() | 1;
 200        cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, GFP_ATOMIC);
 201
 202        wiphy_dbg(wiphy, "info: management frame transmitted\n");
 203        return 0;
 204}
 205
 206/*
 207 * CFG802.11 operation handler to register a mgmt frame.
 208 */
 209static void
 210mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
 211                                     struct wireless_dev *wdev,
 212                                     u16 frame_type, bool reg)
 213{
 214        struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
 215        u32 mask;
 216
 217        if (reg)
 218                mask = priv->mgmt_frame_mask | BIT(frame_type >> 4);
 219        else
 220                mask = priv->mgmt_frame_mask & ~BIT(frame_type >> 4);
 221
 222        if (mask != priv->mgmt_frame_mask) {
 223                priv->mgmt_frame_mask = mask;
 224                mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
 225                                 HostCmd_ACT_GEN_SET, 0,
 226                                 &priv->mgmt_frame_mask, false);
 227                wiphy_dbg(wiphy, "info: mgmt frame registered\n");
 228        }
 229}
 230
 231/*
 232 * CFG802.11 operation handler to remain on channel.
 233 */
 234static int
 235mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
 236                                   struct wireless_dev *wdev,
 237                                   struct ieee80211_channel *chan,
 238                                   unsigned int duration, u64 *cookie)
 239{
 240        struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
 241        int ret;
 242
 243        if (!chan || !cookie) {
 244                wiphy_err(wiphy, "Invalid parameter for ROC\n");
 245                return -EINVAL;
 246        }
 247
 248        if (priv->roc_cfg.cookie) {
 249                wiphy_dbg(wiphy, "info: ongoing ROC, cookie = 0x%llx\n",
 250                          priv->roc_cfg.cookie);
 251                return -EBUSY;
 252        }
 253
 254        ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET, chan,
 255                                         duration);
 256
 257        if (!ret) {
 258                *cookie = prandom_u32() | 1;
 259                priv->roc_cfg.cookie = *cookie;
 260                priv->roc_cfg.chan = *chan;
 261
 262                cfg80211_ready_on_channel(wdev, *cookie, chan,
 263                                          duration, GFP_ATOMIC);
 264
 265                wiphy_dbg(wiphy, "info: ROC, cookie = 0x%llx\n", *cookie);
 266        }
 267
 268        return ret;
 269}
 270
 271/*
 272 * CFG802.11 operation handler to cancel remain on channel.
 273 */
 274static int
 275mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
 276                                          struct wireless_dev *wdev, u64 cookie)
 277{
 278        struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
 279        int ret;
 280
 281        if (cookie != priv->roc_cfg.cookie)
 282                return -ENOENT;
 283
 284        ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE,
 285                                         &priv->roc_cfg.chan, 0);
 286
 287        if (!ret) {
 288                cfg80211_remain_on_channel_expired(wdev, cookie,
 289                                                   &priv->roc_cfg.chan,
 290                                                   GFP_ATOMIC);
 291
 292                memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg));
 293
 294                wiphy_dbg(wiphy, "info: cancel ROC, cookie = 0x%llx\n", cookie);
 295        }
 296
 297        return ret;
 298}
 299
 300/*
 301 * CFG802.11 operation handler to set Tx power.
 302 */
 303static int
 304mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy,
 305                              struct wireless_dev *wdev,
 306                              enum nl80211_tx_power_setting type,
 307                              int mbm)
 308{
 309        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
 310        struct mwifiex_private *priv;
 311        struct mwifiex_power_cfg power_cfg;
 312        int dbm = MBM_TO_DBM(mbm);
 313
 314        if (type == NL80211_TX_POWER_FIXED) {
 315                power_cfg.is_power_auto = 0;
 316                power_cfg.power_level = dbm;
 317        } else {
 318                power_cfg.is_power_auto = 1;
 319        }
 320
 321        priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 322
 323        return mwifiex_set_tx_power(priv, &power_cfg);
 324}
 325
 326/*
 327 * CFG802.11 operation handler to set Power Save option.
 328 *
 329 * The timeout value, if provided, is currently ignored.
 330 */
 331static int
 332mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy,
 333                                struct net_device *dev,
 334                                bool enabled, int timeout)
 335{
 336        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 337        u32 ps_mode;
 338
 339        if (timeout)
 340                wiphy_dbg(wiphy,
 341                          "info: ignore timeout value for IEEE Power Save\n");
 342
 343        ps_mode = enabled;
 344
 345        return mwifiex_drv_set_power(priv, &ps_mode);
 346}
 347
 348/*
 349 * CFG802.11 operation handler to set the default network key.
 350 */
 351static int
 352mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
 353                                 u8 key_index, bool unicast,
 354                                 bool multicast)
 355{
 356        struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
 357
 358        /* Return if WEP key not configured */
 359        if (!priv->sec_info.wep_enabled)
 360                return 0;
 361
 362        if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) {
 363                priv->wep_key_curr_index = key_index;
 364        } else if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index,
 365                                      NULL, 0)) {
 366                wiphy_err(wiphy, "set default Tx key index\n");
 367                return -EFAULT;
 368        }
 369
 370        return 0;
 371}
 372
 373/*
 374 * CFG802.11 operation handler to add a network key.
 375 */
 376static int
 377mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
 378                         u8 key_index, bool pairwise, const u8 *mac_addr,
 379                         struct key_params *params)
 380{
 381        struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
 382        struct mwifiex_wep_key *wep_key;
 383        const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 384        const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
 385
 386        if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&
 387            (params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
 388             params->cipher == WLAN_CIPHER_SUITE_WEP104)) {
 389                if (params->key && params->key_len) {
 390                        wep_key = &priv->wep_key[key_index];
 391                        memset(wep_key, 0, sizeof(struct mwifiex_wep_key));
 392                        memcpy(wep_key->key_material, params->key,
 393                               params->key_len);
 394                        wep_key->key_index = key_index;
 395                        wep_key->key_length = params->key_len;
 396                        priv->sec_info.wep_enabled = 1;
 397                }
 398                return 0;
 399        }
 400
 401        if (mwifiex_set_encode(priv, params, params->key, params->key_len,
 402                               key_index, peer_mac, 0)) {
 403                wiphy_err(wiphy, "crypto keys added\n");
 404                return -EFAULT;
 405        }
 406
 407        return 0;
 408}
 409
 410/*
 411 * This function sends domain information to the firmware.
 412 *
 413 * The following information are passed to the firmware -
 414 *      - Country codes
 415 *      - Sub bands (first channel, number of channels, maximum Tx power)
 416 */
 417static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
 418{
 419        u8 no_of_triplet = 0;
 420        struct ieee80211_country_ie_triplet *t;
 421        u8 no_of_parsed_chan = 0;
 422        u8 first_chan = 0, next_chan = 0, max_pwr = 0;
 423        u8 i, flag = 0;
 424        enum ieee80211_band band;
 425        struct ieee80211_supported_band *sband;
 426        struct ieee80211_channel *ch;
 427        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
 428        struct mwifiex_private *priv;
 429        struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg;
 430
 431        /* Set country code */
 432        domain_info->country_code[0] = adapter->country_code[0];
 433        domain_info->country_code[1] = adapter->country_code[1];
 434        domain_info->country_code[2] = ' ';
 435
 436        band = mwifiex_band_to_radio_type(adapter->config_bands);
 437        if (!wiphy->bands[band]) {
 438                wiphy_err(wiphy, "11D: setting domain info in FW\n");
 439                return -1;
 440        }
 441
 442        sband = wiphy->bands[band];
 443
 444        for (i = 0; i < sband->n_channels ; i++) {
 445                ch = &sband->channels[i];
 446                if (ch->flags & IEEE80211_CHAN_DISABLED)
 447                        continue;
 448
 449                if (!flag) {
 450                        flag = 1;
 451                        first_chan = (u32) ch->hw_value;
 452                        next_chan = first_chan;
 453                        max_pwr = ch->max_power;
 454                        no_of_parsed_chan = 1;
 455                        continue;
 456                }
 457
 458                if (ch->hw_value == next_chan + 1 &&
 459                    ch->max_power == max_pwr) {
 460                        next_chan++;
 461                        no_of_parsed_chan++;
 462                } else {
 463                        t = &domain_info->triplet[no_of_triplet];
 464                        t->chans.first_channel = first_chan;
 465                        t->chans.num_channels = no_of_parsed_chan;
 466                        t->chans.max_power = max_pwr;
 467                        no_of_triplet++;
 468                        first_chan = (u32) ch->hw_value;
 469                        next_chan = first_chan;
 470                        max_pwr = ch->max_power;
 471                        no_of_parsed_chan = 1;
 472                }
 473        }
 474
 475        if (flag) {
 476                t = &domain_info->triplet[no_of_triplet];
 477                t->chans.first_channel = first_chan;
 478                t->chans.num_channels = no_of_parsed_chan;
 479                t->chans.max_power = max_pwr;
 480                no_of_triplet++;
 481        }
 482
 483        domain_info->no_of_triplet = no_of_triplet;
 484
 485        priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 486
 487        if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
 488                             HostCmd_ACT_GEN_SET, 0, NULL, false)) {
 489                wiphy_err(wiphy, "11D: setting domain info in FW\n");
 490                return -1;
 491        }
 492
 493        return 0;
 494}
 495
 496/*
 497 * CFG802.11 regulatory domain callback function.
 498 *
 499 * This function is called when the regulatory domain is changed due to the
 500 * following reasons -
 501 *      - Set by driver
 502 *      - Set by system core
 503 *      - Set by user
 504 *      - Set bt Country IE
 505 */
 506static void mwifiex_reg_notifier(struct wiphy *wiphy,
 507                                 struct regulatory_request *request)
 508{
 509        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
 510        struct mwifiex_private *priv = mwifiex_get_priv(adapter,
 511                                                        MWIFIEX_BSS_ROLE_ANY);
 512
 513        wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for %c%c\n",
 514                  request->alpha2[0], request->alpha2[1]);
 515
 516        switch (request->initiator) {
 517        case NL80211_REGDOM_SET_BY_DRIVER:
 518        case NL80211_REGDOM_SET_BY_CORE:
 519        case NL80211_REGDOM_SET_BY_USER:
 520        case NL80211_REGDOM_SET_BY_COUNTRY_IE:
 521                break;
 522        default:
 523                wiphy_err(wiphy, "unknown regdom initiator: %d\n",
 524                          request->initiator);
 525                return;
 526        }
 527
 528        /* Don't send world or same regdom info to firmware */
 529        if (strncmp(request->alpha2, "00", 2) &&
 530            strncmp(request->alpha2, adapter->country_code,
 531                    sizeof(request->alpha2))) {
 532                memcpy(adapter->country_code, request->alpha2,
 533                       sizeof(request->alpha2));
 534                mwifiex_send_domain_info_cmd_fw(wiphy);
 535                mwifiex_dnld_txpwr_table(priv);
 536        }
 537}
 538
 539/*
 540 * This function sets the fragmentation threshold.
 541 *
 542 * The fragmentation threshold value must lie between MWIFIEX_FRAG_MIN_VALUE
 543 * and MWIFIEX_FRAG_MAX_VALUE.
 544 */
 545static int
 546mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr)
 547{
 548        if (frag_thr < MWIFIEX_FRAG_MIN_VALUE ||
 549            frag_thr > MWIFIEX_FRAG_MAX_VALUE)
 550                frag_thr = MWIFIEX_FRAG_MAX_VALUE;
 551
 552        return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
 553                                HostCmd_ACT_GEN_SET, FRAG_THRESH_I,
 554                                &frag_thr, true);
 555}
 556
 557/*
 558 * This function sets the RTS threshold.
 559
 560 * The rts value must lie between MWIFIEX_RTS_MIN_VALUE
 561 * and MWIFIEX_RTS_MAX_VALUE.
 562 */
 563static int
 564mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr)
 565{
 566        if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE)
 567                rts_thr = MWIFIEX_RTS_MAX_VALUE;
 568
 569        return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
 570                                HostCmd_ACT_GEN_SET, RTS_THRESH_I,
 571                                &rts_thr, true);
 572}
 573
 574/*
 575 * CFG802.11 operation handler to set wiphy parameters.
 576 *
 577 * This function can be used to set the RTS threshold and the
 578 * Fragmentation threshold of the driver.
 579 */
 580static int
 581mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 582{
 583        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
 584        struct mwifiex_private *priv;
 585        struct mwifiex_uap_bss_param *bss_cfg;
 586        int ret, bss_started, i;
 587
 588        for (i = 0; i < adapter->priv_num; i++) {
 589                priv = adapter->priv[i];
 590
 591                switch (priv->bss_role) {
 592                case MWIFIEX_BSS_ROLE_UAP:
 593                        bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param),
 594                                          GFP_KERNEL);
 595                        if (!bss_cfg)
 596                                return -ENOMEM;
 597
 598                        mwifiex_set_sys_config_invalid_data(bss_cfg);
 599
 600                        if (changed & WIPHY_PARAM_RTS_THRESHOLD)
 601                                bss_cfg->rts_threshold = wiphy->rts_threshold;
 602                        if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
 603                                bss_cfg->frag_threshold = wiphy->frag_threshold;
 604                        if (changed & WIPHY_PARAM_RETRY_LONG)
 605                                bss_cfg->retry_limit = wiphy->retry_long;
 606
 607                        bss_started = priv->bss_started;
 608
 609                        ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
 610                                               HostCmd_ACT_GEN_SET, 0,
 611                                               NULL, true);
 612                        if (ret) {
 613                                wiphy_err(wiphy, "Failed to stop the BSS\n");
 614                                kfree(bss_cfg);
 615                                return ret;
 616                        }
 617
 618                        ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
 619                                               HostCmd_ACT_GEN_SET,
 620                                               UAP_BSS_PARAMS_I, bss_cfg,
 621                                               false);
 622
 623                        kfree(bss_cfg);
 624
 625                        if (ret) {
 626                                wiphy_err(wiphy, "Failed to set bss config\n");
 627                                return ret;
 628                        }
 629
 630                        if (!bss_started)
 631                                break;
 632
 633                        ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START,
 634                                               HostCmd_ACT_GEN_SET, 0,
 635                                               NULL, false);
 636                        if (ret) {
 637                                wiphy_err(wiphy, "Failed to start BSS\n");
 638                                return ret;
 639                        }
 640
 641                        break;
 642                case MWIFIEX_BSS_ROLE_STA:
 643                        if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
 644                                ret = mwifiex_set_rts(priv,
 645                                                      wiphy->rts_threshold);
 646                                if (ret)
 647                                        return ret;
 648                        }
 649                        if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
 650                                ret = mwifiex_set_frag(priv,
 651                                                       wiphy->frag_threshold);
 652                                if (ret)
 653                                        return ret;
 654                        }
 655                        break;
 656                }
 657        }
 658
 659        return 0;
 660}
 661
 662static int
 663mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv)
 664{
 665        u16 mode = P2P_MODE_DISABLE;
 666
 667        if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA)
 668                mwifiex_set_bss_role(priv, MWIFIEX_BSS_ROLE_STA);
 669
 670        if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
 671                             HostCmd_ACT_GEN_SET, 0, &mode, true))
 672                return -1;
 673
 674        return 0;
 675}
 676
 677/*
 678 * This function initializes the functionalities for P2P client.
 679 * The P2P client initialization sequence is:
 680 * disable -> device -> client
 681 */
 682static int
 683mwifiex_cfg80211_init_p2p_client(struct mwifiex_private *priv)
 684{
 685        u16 mode;
 686
 687        if (mwifiex_cfg80211_deinit_p2p(priv))
 688                return -1;
 689
 690        mode = P2P_MODE_DEVICE;
 691        if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
 692                             HostCmd_ACT_GEN_SET, 0, &mode, true))
 693                return -1;
 694
 695        mode = P2P_MODE_CLIENT;
 696        if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
 697                             HostCmd_ACT_GEN_SET, 0, &mode, true))
 698                return -1;
 699
 700        return 0;
 701}
 702
 703/*
 704 * This function initializes the functionalities for P2P GO.
 705 * The P2P GO initialization sequence is:
 706 * disable -> device -> GO
 707 */
 708static int
 709mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv)
 710{
 711        u16 mode;
 712
 713        if (mwifiex_cfg80211_deinit_p2p(priv))
 714                return -1;
 715
 716        mode = P2P_MODE_DEVICE;
 717        if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
 718                             HostCmd_ACT_GEN_SET, 0, &mode, true))
 719                return -1;
 720
 721        mode = P2P_MODE_GO;
 722        if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
 723                             HostCmd_ACT_GEN_SET, 0, &mode, true))
 724                return -1;
 725
 726        if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP)
 727                mwifiex_set_bss_role(priv, MWIFIEX_BSS_ROLE_UAP);
 728
 729        return 0;
 730}
 731
 732/*
 733 * CFG802.11 operation handler to change interface type.
 734 */
 735static int
 736mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
 737                                     struct net_device *dev,
 738                                     enum nl80211_iftype type, u32 *flags,
 739                                     struct vif_params *params)
 740{
 741        int ret;
 742        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 743
 744        switch (dev->ieee80211_ptr->iftype) {
 745        case NL80211_IFTYPE_ADHOC:
 746                switch (type) {
 747                case NL80211_IFTYPE_STATION:
 748                        break;
 749                case NL80211_IFTYPE_UNSPECIFIED:
 750                        wiphy_warn(wiphy, "%s: kept type as IBSS\n", dev->name);
 751                case NL80211_IFTYPE_ADHOC:      /* This shouldn't happen */
 752                        return 0;
 753                case NL80211_IFTYPE_AP:
 754                default:
 755                        wiphy_err(wiphy, "%s: changing to %d not supported\n",
 756                                  dev->name, type);
 757                        return -EOPNOTSUPP;
 758                }
 759                break;
 760        case NL80211_IFTYPE_STATION:
 761                switch (type) {
 762                case NL80211_IFTYPE_ADHOC:
 763                        break;
 764                case NL80211_IFTYPE_P2P_CLIENT:
 765                        if (mwifiex_cfg80211_init_p2p_client(priv))
 766                                return -EFAULT;
 767                        dev->ieee80211_ptr->iftype = type;
 768                        return 0;
 769                case NL80211_IFTYPE_P2P_GO:
 770                        if (mwifiex_cfg80211_init_p2p_go(priv))
 771                                return -EFAULT;
 772                        dev->ieee80211_ptr->iftype = type;
 773                        return 0;
 774                case NL80211_IFTYPE_UNSPECIFIED:
 775                        wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name);
 776                case NL80211_IFTYPE_STATION:    /* This shouldn't happen */
 777                        return 0;
 778                case NL80211_IFTYPE_AP:
 779                default:
 780                        wiphy_err(wiphy, "%s: changing to %d not supported\n",
 781                                  dev->name, type);
 782                        return -EOPNOTSUPP;
 783                }
 784                break;
 785        case NL80211_IFTYPE_AP:
 786                switch (type) {
 787                case NL80211_IFTYPE_UNSPECIFIED:
 788                        wiphy_warn(wiphy, "%s: kept type as AP\n", dev->name);
 789                case NL80211_IFTYPE_AP:         /* This shouldn't happen */
 790                        return 0;
 791                case NL80211_IFTYPE_ADHOC:
 792                case NL80211_IFTYPE_STATION:
 793                default:
 794                        wiphy_err(wiphy, "%s: changing to %d not supported\n",
 795                                  dev->name, type);
 796                        return -EOPNOTSUPP;
 797                }
 798                break;
 799        case NL80211_IFTYPE_P2P_CLIENT:
 800        case NL80211_IFTYPE_P2P_GO:
 801                switch (type) {
 802                case NL80211_IFTYPE_STATION:
 803                        if (mwifiex_cfg80211_deinit_p2p(priv))
 804                                return -EFAULT;
 805                        dev->ieee80211_ptr->iftype = type;
 806                        return 0;
 807                default:
 808                        return -EOPNOTSUPP;
 809                }
 810                break;
 811        default:
 812                wiphy_err(wiphy, "%s: unknown iftype: %d\n",
 813                          dev->name, dev->ieee80211_ptr->iftype);
 814                return -EOPNOTSUPP;
 815        }
 816
 817        dev->ieee80211_ptr->iftype = type;
 818        priv->bss_mode = type;
 819        mwifiex_deauthenticate(priv, NULL);
 820
 821        priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM;
 822
 823        ret = mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
 824                               HostCmd_ACT_GEN_SET, 0, NULL, true);
 825
 826        return ret;
 827}
 828
 829static void
 830mwifiex_parse_htinfo(struct mwifiex_private *priv, u8 tx_htinfo,
 831                     struct rate_info *rate)
 832{
 833        struct mwifiex_adapter *adapter = priv->adapter;
 834
 835        if (adapter->is_hw_11ac_capable) {
 836                /* bit[1-0]: 00=LG 01=HT 10=VHT */
 837                if (tx_htinfo & BIT(0)) {
 838                        /* HT */
 839                        rate->mcs = priv->tx_rate;
 840                        rate->flags |= RATE_INFO_FLAGS_MCS;
 841                }
 842                if (tx_htinfo & BIT(1)) {
 843                        /* VHT */
 844                        rate->mcs = priv->tx_rate & 0x0F;
 845                        rate->flags |= RATE_INFO_FLAGS_VHT_MCS;
 846                }
 847
 848                if (tx_htinfo & (BIT(1) | BIT(0))) {
 849                        /* HT or VHT */
 850                        switch (tx_htinfo & (BIT(3) | BIT(2))) {
 851                        case 0:
 852                                /* This will be 20MHz */
 853                                break;
 854                        case (BIT(2)):
 855                                rate->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
 856                                break;
 857                        case (BIT(3)):
 858                                rate->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
 859                                break;
 860                        case (BIT(3) | BIT(2)):
 861                                rate->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
 862                                break;
 863                        }
 864
 865                        if (tx_htinfo & BIT(4))
 866                                rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
 867
 868                        if ((priv->tx_rate >> 4) == 1)
 869                                rate->nss = 2;
 870                        else
 871                                rate->nss = 1;
 872                }
 873        } else {
 874                /*
 875                 * Bit 0 in tx_htinfo indicates that current Tx rate
 876                 * is 11n rate. Valid MCS index values for us are 0 to 15.
 877                 */
 878                if ((tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) {
 879                        rate->mcs = priv->tx_rate;
 880                        rate->flags |= RATE_INFO_FLAGS_MCS;
 881                        if (tx_htinfo & BIT(1))
 882                                rate->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
 883                        if (tx_htinfo & BIT(2))
 884                                rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
 885                }
 886        }
 887}
 888
 889/*
 890 * This function dumps the station information on a buffer.
 891 *
 892 * The following information are shown -
 893 *      - Total bytes transmitted
 894 *      - Total bytes received
 895 *      - Total packets transmitted
 896 *      - Total packets received
 897 *      - Signal quality level
 898 *      - Transmission rate
 899 */
 900static int
 901mwifiex_dump_station_info(struct mwifiex_private *priv,
 902                          struct station_info *sinfo)
 903{
 904        u32 rate;
 905
 906        sinfo->filled = STATION_INFO_RX_BYTES | STATION_INFO_TX_BYTES |
 907                        STATION_INFO_RX_PACKETS | STATION_INFO_TX_PACKETS |
 908                        STATION_INFO_TX_BITRATE |
 909                        STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG;
 910
 911        /* Get signal information from the firmware */
 912        if (mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
 913                             HostCmd_ACT_GEN_GET, 0, NULL, true)) {
 914                dev_err(priv->adapter->dev, "failed to get signal information\n");
 915                return -EFAULT;
 916        }
 917
 918        if (mwifiex_drv_get_data_rate(priv, &rate)) {
 919                dev_err(priv->adapter->dev, "getting data rate\n");
 920                return -EFAULT;
 921        }
 922
 923        /* Get DTIM period information from firmware */
 924        mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
 925                         HostCmd_ACT_GEN_GET, DTIM_PERIOD_I,
 926                         &priv->dtim_period, true);
 927
 928        mwifiex_parse_htinfo(priv, priv->tx_htinfo, &sinfo->txrate);
 929
 930        sinfo->signal_avg = priv->bcn_rssi_avg;
 931        sinfo->rx_bytes = priv->stats.rx_bytes;
 932        sinfo->tx_bytes = priv->stats.tx_bytes;
 933        sinfo->rx_packets = priv->stats.rx_packets;
 934        sinfo->tx_packets = priv->stats.tx_packets;
 935        sinfo->signal = priv->bcn_rssi_avg;
 936        /* bit rate is in 500 kb/s units. Convert it to 100kb/s units */
 937        sinfo->txrate.legacy = rate * 5;
 938
 939        if (priv->bss_mode == NL80211_IFTYPE_STATION) {
 940                sinfo->filled |= STATION_INFO_BSS_PARAM;
 941                sinfo->bss_param.flags = 0;
 942                if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap &
 943                                                WLAN_CAPABILITY_SHORT_PREAMBLE)
 944                        sinfo->bss_param.flags |=
 945                                        BSS_PARAM_FLAGS_SHORT_PREAMBLE;
 946                if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap &
 947                                                WLAN_CAPABILITY_SHORT_SLOT_TIME)
 948                        sinfo->bss_param.flags |=
 949                                        BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
 950                sinfo->bss_param.dtim_period = priv->dtim_period;
 951                sinfo->bss_param.beacon_interval =
 952                        priv->curr_bss_params.bss_descriptor.beacon_period;
 953        }
 954
 955        return 0;
 956}
 957
 958/*
 959 * CFG802.11 operation handler to get station information.
 960 *
 961 * This function only works in connected mode, and dumps the
 962 * requested station information, if available.
 963 */
 964static int
 965mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 966                             const u8 *mac, struct station_info *sinfo)
 967{
 968        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 969
 970        if (!priv->media_connected)
 971                return -ENOENT;
 972        if (memcmp(mac, priv->cfg_bssid, ETH_ALEN))
 973                return -ENOENT;
 974
 975        return mwifiex_dump_station_info(priv, sinfo);
 976}
 977
 978/*
 979 * CFG802.11 operation handler to dump station information.
 980 */
 981static int
 982mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
 983                              int idx, u8 *mac, struct station_info *sinfo)
 984{
 985        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 986
 987        if (!priv->media_connected || idx)
 988                return -ENOENT;
 989
 990        memcpy(mac, priv->cfg_bssid, ETH_ALEN);
 991
 992        return mwifiex_dump_station_info(priv, sinfo);
 993}
 994
 995/* Supported rates to be advertised to the cfg80211 */
 996static struct ieee80211_rate mwifiex_rates[] = {
 997        {.bitrate = 10, .hw_value = 2, },
 998        {.bitrate = 20, .hw_value = 4, },
 999        {.bitrate = 55, .hw_value = 11, },
1000        {.bitrate = 110, .hw_value = 22, },
1001        {.bitrate = 60, .hw_value = 12, },
1002        {.bitrate = 90, .hw_value = 18, },
1003        {.bitrate = 120, .hw_value = 24, },
1004        {.bitrate = 180, .hw_value = 36, },
1005        {.bitrate = 240, .hw_value = 48, },
1006        {.bitrate = 360, .hw_value = 72, },
1007        {.bitrate = 480, .hw_value = 96, },
1008        {.bitrate = 540, .hw_value = 108, },
1009};
1010
1011/* Channel definitions to be advertised to cfg80211 */
1012static struct ieee80211_channel mwifiex_channels_2ghz[] = {
1013        {.center_freq = 2412, .hw_value = 1, },
1014        {.center_freq = 2417, .hw_value = 2, },
1015        {.center_freq = 2422, .hw_value = 3, },
1016        {.center_freq = 2427, .hw_value = 4, },
1017        {.center_freq = 2432, .hw_value = 5, },
1018        {.center_freq = 2437, .hw_value = 6, },
1019        {.center_freq = 2442, .hw_value = 7, },
1020        {.center_freq = 2447, .hw_value = 8, },
1021        {.center_freq = 2452, .hw_value = 9, },
1022        {.center_freq = 2457, .hw_value = 10, },
1023        {.center_freq = 2462, .hw_value = 11, },
1024        {.center_freq = 2467, .hw_value = 12, },
1025        {.center_freq = 2472, .hw_value = 13, },
1026        {.center_freq = 2484, .hw_value = 14, },
1027};
1028
1029static struct ieee80211_supported_band mwifiex_band_2ghz = {
1030        .channels = mwifiex_channels_2ghz,
1031        .n_channels = ARRAY_SIZE(mwifiex_channels_2ghz),
1032        .bitrates = mwifiex_rates,
1033        .n_bitrates = ARRAY_SIZE(mwifiex_rates),
1034};
1035
1036static struct ieee80211_channel mwifiex_channels_5ghz[] = {
1037        {.center_freq = 5040, .hw_value = 8, },
1038        {.center_freq = 5060, .hw_value = 12, },
1039        {.center_freq = 5080, .hw_value = 16, },
1040        {.center_freq = 5170, .hw_value = 34, },
1041        {.center_freq = 5190, .hw_value = 38, },
1042        {.center_freq = 5210, .hw_value = 42, },
1043        {.center_freq = 5230, .hw_value = 46, },
1044        {.center_freq = 5180, .hw_value = 36, },
1045        {.center_freq = 5200, .hw_value = 40, },
1046        {.center_freq = 5220, .hw_value = 44, },
1047        {.center_freq = 5240, .hw_value = 48, },
1048        {.center_freq = 5260, .hw_value = 52, },
1049        {.center_freq = 5280, .hw_value = 56, },
1050        {.center_freq = 5300, .hw_value = 60, },
1051        {.center_freq = 5320, .hw_value = 64, },
1052        {.center_freq = 5500, .hw_value = 100, },
1053        {.center_freq = 5520, .hw_value = 104, },
1054        {.center_freq = 5540, .hw_value = 108, },
1055        {.center_freq = 5560, .hw_value = 112, },
1056        {.center_freq = 5580, .hw_value = 116, },
1057        {.center_freq = 5600, .hw_value = 120, },
1058        {.center_freq = 5620, .hw_value = 124, },
1059        {.center_freq = 5640, .hw_value = 128, },
1060        {.center_freq = 5660, .hw_value = 132, },
1061        {.center_freq = 5680, .hw_value = 136, },
1062        {.center_freq = 5700, .hw_value = 140, },
1063        {.center_freq = 5745, .hw_value = 149, },
1064        {.center_freq = 5765, .hw_value = 153, },
1065        {.center_freq = 5785, .hw_value = 157, },
1066        {.center_freq = 5805, .hw_value = 161, },
1067        {.center_freq = 5825, .hw_value = 165, },
1068};
1069
1070static struct ieee80211_supported_band mwifiex_band_5ghz = {
1071        .channels = mwifiex_channels_5ghz,
1072        .n_channels = ARRAY_SIZE(mwifiex_channels_5ghz),
1073        .bitrates = mwifiex_rates + 4,
1074        .n_bitrates = ARRAY_SIZE(mwifiex_rates) - 4,
1075};
1076
1077
1078/* Supported crypto cipher suits to be advertised to cfg80211 */
1079static const u32 mwifiex_cipher_suites[] = {
1080        WLAN_CIPHER_SUITE_WEP40,
1081        WLAN_CIPHER_SUITE_WEP104,
1082        WLAN_CIPHER_SUITE_TKIP,
1083        WLAN_CIPHER_SUITE_CCMP,
1084        WLAN_CIPHER_SUITE_AES_CMAC,
1085};
1086
1087/* Supported mgmt frame types to be advertised to cfg80211 */
1088static const struct ieee80211_txrx_stypes
1089mwifiex_mgmt_stypes[NUM_NL80211_IFTYPES] = {
1090        [NL80211_IFTYPE_STATION] = {
1091                .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1092                      BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
1093                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1094                      BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
1095        },
1096        [NL80211_IFTYPE_AP] = {
1097                .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1098                      BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
1099                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1100                      BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
1101        },
1102        [NL80211_IFTYPE_P2P_CLIENT] = {
1103                .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1104                      BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
1105                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1106                      BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
1107        },
1108        [NL80211_IFTYPE_P2P_GO] = {
1109                .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1110                      BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
1111                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1112                      BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
1113        },
1114};
1115
1116/*
1117 * CFG802.11 operation handler for setting bit rates.
1118 *
1119 * Function configures data rates to firmware using bitrate mask
1120 * provided by cfg80211.
1121 */
1122static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
1123                                struct net_device *dev,
1124                                const u8 *peer,
1125                                const struct cfg80211_bitrate_mask *mask)
1126{
1127        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1128        u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
1129        enum ieee80211_band band;
1130        struct mwifiex_adapter *adapter = priv->adapter;
1131
1132        if (!priv->media_connected) {
1133                dev_err(adapter->dev,
1134                        "Can not set Tx data rate in disconnected state\n");
1135                return -EINVAL;
1136        }
1137
1138        band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
1139
1140        memset(bitmap_rates, 0, sizeof(bitmap_rates));
1141
1142        /* Fill HR/DSSS rates. */
1143        if (band == IEEE80211_BAND_2GHZ)
1144                bitmap_rates[0] = mask->control[band].legacy & 0x000f;
1145
1146        /* Fill OFDM rates */
1147        if (band == IEEE80211_BAND_2GHZ)
1148                bitmap_rates[1] = (mask->control[band].legacy & 0x0ff0) >> 4;
1149        else
1150                bitmap_rates[1] = mask->control[band].legacy;
1151
1152        /* Fill HT MCS rates */
1153        bitmap_rates[2] = mask->control[band].ht_mcs[0];
1154        if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)
1155                bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8;
1156
1157       /* Fill VHT MCS rates */
1158        if (adapter->fw_api_ver == MWIFIEX_FW_V15) {
1159                bitmap_rates[10] = mask->control[band].vht_mcs[0];
1160                if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)
1161                        bitmap_rates[11] = mask->control[band].vht_mcs[1];
1162        }
1163
1164        return mwifiex_send_cmd(priv, HostCmd_CMD_TX_RATE_CFG,
1165                                HostCmd_ACT_GEN_SET, 0, bitmap_rates, true);
1166}
1167
1168/*
1169 * CFG802.11 operation handler for connection quality monitoring.
1170 *
1171 * This function subscribes/unsubscribes HIGH_RSSI and LOW_RSSI
1172 * events to FW.
1173 */
1174static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy,
1175                                                struct net_device *dev,
1176                                                s32 rssi_thold, u32 rssi_hyst)
1177{
1178        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1179        struct mwifiex_ds_misc_subsc_evt subsc_evt;
1180
1181        priv->cqm_rssi_thold = rssi_thold;
1182        priv->cqm_rssi_hyst = rssi_hyst;
1183
1184        memset(&subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt));
1185        subsc_evt.events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH;
1186
1187        /* Subscribe/unsubscribe low and high rssi events */
1188        if (rssi_thold && rssi_hyst) {
1189                subsc_evt.action = HostCmd_ACT_BITWISE_SET;
1190                subsc_evt.bcn_l_rssi_cfg.abs_value = abs(rssi_thold);
1191                subsc_evt.bcn_h_rssi_cfg.abs_value = abs(rssi_thold);
1192                subsc_evt.bcn_l_rssi_cfg.evt_freq = 1;
1193                subsc_evt.bcn_h_rssi_cfg.evt_freq = 1;
1194                return mwifiex_send_cmd(priv,
1195                                        HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
1196                                        0, 0, &subsc_evt, true);
1197        } else {
1198                subsc_evt.action = HostCmd_ACT_BITWISE_CLR;
1199                return mwifiex_send_cmd(priv,
1200                                        HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
1201                                        0, 0, &subsc_evt, true);
1202        }
1203
1204        return 0;
1205}
1206
1207/* cfg80211 operation handler for change_beacon.
1208 * Function retrieves and sets modified management IEs to FW.
1209 */
1210static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
1211                                          struct net_device *dev,
1212                                          struct cfg80211_beacon_data *data)
1213{
1214        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1215
1216        if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) {
1217                wiphy_err(wiphy, "%s: bss_type mismatched\n", __func__);
1218                return -EINVAL;
1219        }
1220
1221        if (!priv->bss_started) {
1222                wiphy_err(wiphy, "%s: bss not started\n", __func__);
1223                return -EINVAL;
1224        }
1225
1226        if (mwifiex_set_mgmt_ies(priv, data)) {
1227                wiphy_err(wiphy, "%s: setting mgmt ies failed\n", __func__);
1228                return -EFAULT;
1229        }
1230
1231        return 0;
1232}
1233
1234/* cfg80211 operation handler for del_station.
1235 * Function deauthenticates station which value is provided in mac parameter.
1236 * If mac is NULL/broadcast, all stations in associated station list are
1237 * deauthenticated. If bss is not started or there are no stations in
1238 * associated stations list, no action is taken.
1239 */
1240static int
1241mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
1242                             const u8 *mac)
1243{
1244        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1245        struct mwifiex_sta_node *sta_node;
1246        unsigned long flags;
1247
1248        if (list_empty(&priv->sta_list) || !priv->bss_started)
1249                return 0;
1250
1251        if (!mac || is_broadcast_ether_addr(mac)) {
1252                wiphy_dbg(wiphy, "%s: NULL/broadcast mac address\n", __func__);
1253                list_for_each_entry(sta_node, &priv->sta_list, list) {
1254                        if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH,
1255                                             HostCmd_ACT_GEN_SET, 0,
1256                                             sta_node->mac_addr, true))
1257                                return -1;
1258                        mwifiex_uap_del_sta_data(priv, sta_node);
1259                }
1260        } else {
1261                wiphy_dbg(wiphy, "%s: mac address %pM\n", __func__, mac);
1262                spin_lock_irqsave(&priv->sta_list_spinlock, flags);
1263                sta_node = mwifiex_get_sta_entry(priv, mac);
1264                spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
1265                if (sta_node) {
1266                        if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH,
1267                                             HostCmd_ACT_GEN_SET, 0,
1268                                             sta_node->mac_addr, true))
1269                                return -1;
1270                        mwifiex_uap_del_sta_data(priv, sta_node);
1271                }
1272        }
1273
1274        return 0;
1275}
1276
1277static int
1278mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
1279{
1280        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
1281        struct mwifiex_private *priv = mwifiex_get_priv(adapter,
1282                                                        MWIFIEX_BSS_ROLE_ANY);
1283        struct mwifiex_ds_ant_cfg ant_cfg;
1284
1285        if (!tx_ant || !rx_ant)
1286                return -EOPNOTSUPP;
1287
1288        if (adapter->hw_dev_mcs_support != HT_STREAM_2X2) {
1289                /* Not a MIMO chip. User should provide specific antenna number
1290                 * for Tx/Rx path or enable all antennas for diversity
1291                 */
1292                if (tx_ant != rx_ant)
1293                        return -EOPNOTSUPP;
1294
1295                if ((tx_ant & (tx_ant - 1)) &&
1296                    (tx_ant != BIT(adapter->number_of_antenna) - 1))
1297                        return -EOPNOTSUPP;
1298
1299                if ((tx_ant == BIT(adapter->number_of_antenna) - 1) &&
1300                    (priv->adapter->number_of_antenna > 1)) {
1301                        tx_ant = RF_ANTENNA_AUTO;
1302                        rx_ant = RF_ANTENNA_AUTO;
1303                }
1304        } else {
1305                struct ieee80211_sta_ht_cap *ht_info;
1306                int rx_mcs_supp;
1307                enum ieee80211_band band;
1308
1309                if ((tx_ant == 0x1 && rx_ant == 0x1)) {
1310                        adapter->user_dev_mcs_support = HT_STREAM_1X1;
1311                        if (adapter->is_hw_11ac_capable)
1312                                adapter->usr_dot_11ac_mcs_support =
1313                                                MWIFIEX_11AC_MCS_MAP_1X1;
1314                } else {
1315                        adapter->user_dev_mcs_support = HT_STREAM_2X2;
1316                        if (adapter->is_hw_11ac_capable)
1317                                adapter->usr_dot_11ac_mcs_support =
1318                                                MWIFIEX_11AC_MCS_MAP_2X2;
1319                }
1320
1321                for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
1322                        if (!adapter->wiphy->bands[band])
1323                                continue;
1324
1325                        ht_info = &adapter->wiphy->bands[band]->ht_cap;
1326                        rx_mcs_supp =
1327                                GET_RXMCSSUPP(adapter->user_dev_mcs_support);
1328                        memset(&ht_info->mcs, 0, adapter->number_of_antenna);
1329                        memset(&ht_info->mcs, 0xff, rx_mcs_supp);
1330                }
1331        }
1332
1333        ant_cfg.tx_ant = tx_ant;
1334        ant_cfg.rx_ant = rx_ant;
1335
1336        return mwifiex_send_cmd(priv, HostCmd_CMD_RF_ANTENNA,
1337                                HostCmd_ACT_GEN_SET, 0, &ant_cfg, true);
1338}
1339
1340/* cfg80211 operation handler for stop ap.
1341 * Function stops BSS running at uAP interface.
1342 */
1343static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
1344{
1345        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1346
1347        if (mwifiex_del_mgmt_ies(priv))
1348                wiphy_err(wiphy, "Failed to delete mgmt IEs!\n");
1349
1350        priv->ap_11n_enabled = 0;
1351
1352        if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
1353                             HostCmd_ACT_GEN_SET, 0, NULL, true)) {
1354                wiphy_err(wiphy, "Failed to stop the BSS\n");
1355                return -1;
1356        }
1357
1358        return 0;
1359}
1360
1361/* cfg80211 operation handler for start_ap.
1362 * Function sets beacon period, DTIM period, SSID and security into
1363 * AP config structure.
1364 * AP is configured with these settings and BSS is started.
1365 */
1366static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
1367                                     struct net_device *dev,
1368                                     struct cfg80211_ap_settings *params)
1369{
1370        struct mwifiex_uap_bss_param *bss_cfg;
1371        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1372        u8 config_bands = 0;
1373
1374        if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP)
1375                return -1;
1376        if (mwifiex_set_mgmt_ies(priv, &params->beacon))
1377                return -1;
1378
1379        bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL);
1380        if (!bss_cfg)
1381                return -ENOMEM;
1382
1383        mwifiex_set_sys_config_invalid_data(bss_cfg);
1384
1385        if (params->beacon_interval)
1386                bss_cfg->beacon_period = params->beacon_interval;
1387        if (params->dtim_period)
1388                bss_cfg->dtim_period = params->dtim_period;
1389
1390        if (params->ssid && params->ssid_len) {
1391                memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len);
1392                bss_cfg->ssid.ssid_len = params->ssid_len;
1393        }
1394
1395        switch (params->hidden_ssid) {
1396        case NL80211_HIDDEN_SSID_NOT_IN_USE:
1397                bss_cfg->bcast_ssid_ctl = 1;
1398                break;
1399        case NL80211_HIDDEN_SSID_ZERO_LEN:
1400                bss_cfg->bcast_ssid_ctl = 0;
1401                break;
1402        case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
1403                /* firmware doesn't support this type of hidden SSID */
1404        default:
1405                kfree(bss_cfg);
1406                return -EINVAL;
1407        }
1408
1409        bss_cfg->channel = ieee80211_frequency_to_channel(
1410                                params->chandef.chan->center_freq);
1411
1412        /* Set appropriate bands */
1413        if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) {
1414                bss_cfg->band_cfg = BAND_CONFIG_BG;
1415                config_bands = BAND_B | BAND_G;
1416
1417                if (params->chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
1418                        config_bands |= BAND_GN;
1419        } else {
1420                bss_cfg->band_cfg = BAND_CONFIG_A;
1421                config_bands = BAND_A;
1422
1423                if (params->chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
1424                        config_bands |= BAND_AN;
1425
1426                if (params->chandef.width > NL80211_CHAN_WIDTH_40)
1427                        config_bands |= BAND_AAC;
1428        }
1429
1430        if (!((config_bands | priv->adapter->fw_bands) &
1431              ~priv->adapter->fw_bands))
1432                priv->adapter->config_bands = config_bands;
1433
1434        mwifiex_set_uap_rates(bss_cfg, params);
1435        mwifiex_send_domain_info_cmd_fw(wiphy);
1436
1437        if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
1438                kfree(bss_cfg);
1439                wiphy_err(wiphy, "Failed to parse secuirty parameters!\n");
1440                return -1;
1441        }
1442
1443        mwifiex_set_ht_params(priv, bss_cfg, params);
1444
1445        if (priv->adapter->is_hw_11ac_capable) {
1446                mwifiex_set_vht_params(priv, bss_cfg, params);
1447                mwifiex_set_vht_width(priv, params->chandef.width,
1448                                      priv->ap_11ac_enabled);
1449        }
1450
1451        if (priv->ap_11ac_enabled)
1452                mwifiex_set_11ac_ba_params(priv);
1453        else
1454                mwifiex_set_ba_params(priv);
1455
1456        mwifiex_set_wmm_params(priv, bss_cfg, params);
1457
1458        if (params->inactivity_timeout > 0) {
1459                /* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */
1460                bss_cfg->sta_ao_timer = 10 * params->inactivity_timeout;
1461                bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout;
1462        }
1463
1464        if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
1465                             HostCmd_ACT_GEN_SET, 0, NULL, true)) {
1466                wiphy_err(wiphy, "Failed to stop the BSS\n");
1467                kfree(bss_cfg);
1468                return -1;
1469        }
1470
1471        if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
1472                             HostCmd_ACT_GEN_SET,
1473                             UAP_BSS_PARAMS_I, bss_cfg, false)) {
1474                wiphy_err(wiphy, "Failed to set the SSID\n");
1475                kfree(bss_cfg);
1476                return -1;
1477        }
1478
1479        kfree(bss_cfg);
1480
1481        if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START,
1482                             HostCmd_ACT_GEN_SET, 0, NULL, false)) {
1483                wiphy_err(wiphy, "Failed to start the BSS\n");
1484                return -1;
1485        }
1486
1487        if (priv->sec_info.wep_enabled)
1488                priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE;
1489        else
1490                priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
1491
1492        if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
1493                             HostCmd_ACT_GEN_SET, 0,
1494                             &priv->curr_pkt_filter, true))
1495                return -1;
1496
1497        return 0;
1498}
1499
1500/*
1501 * CFG802.11 operation handler for disconnection request.
1502 *
1503 * This function does not work when there is already a disconnection
1504 * procedure going on.
1505 */
1506static int
1507mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
1508                            u16 reason_code)
1509{
1510        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1511
1512        if (mwifiex_deauthenticate(priv, NULL))
1513                return -EFAULT;
1514
1515        wiphy_dbg(wiphy, "info: successfully disconnected from %pM:"
1516                " reason code %d\n", priv->cfg_bssid, reason_code);
1517
1518        memset(priv->cfg_bssid, 0, ETH_ALEN);
1519        priv->hs2_enabled = false;
1520
1521        return 0;
1522}
1523
1524/*
1525 * This function informs the CFG802.11 subsystem of a new IBSS.
1526 *
1527 * The following information are sent to the CFG802.11 subsystem
1528 * to register the new IBSS. If we do not register the new IBSS,
1529 * a kernel panic will result.
1530 *      - SSID
1531 *      - SSID length
1532 *      - BSSID
1533 *      - Channel
1534 */
1535static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
1536{
1537        struct ieee80211_channel *chan;
1538        struct mwifiex_bss_info bss_info;
1539        struct cfg80211_bss *bss;
1540        int ie_len;
1541        u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)];
1542        enum ieee80211_band band;
1543
1544        if (mwifiex_get_bss_info(priv, &bss_info))
1545                return -1;
1546
1547        ie_buf[0] = WLAN_EID_SSID;
1548        ie_buf[1] = bss_info.ssid.ssid_len;
1549
1550        memcpy(&ie_buf[sizeof(struct ieee_types_header)],
1551               &bss_info.ssid.ssid, bss_info.ssid.ssid_len);
1552        ie_len = ie_buf[1] + sizeof(struct ieee_types_header);
1553
1554        band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
1555        chan = __ieee80211_get_channel(priv->wdev->wiphy,
1556                        ieee80211_channel_to_frequency(bss_info.bss_chan,
1557                                                       band));
1558
1559        bss = cfg80211_inform_bss(priv->wdev->wiphy, chan,
1560                                  CFG80211_BSS_FTYPE_UNKNOWN,
1561                                  bss_info.bssid, 0, WLAN_CAPABILITY_IBSS,
1562                                  0, ie_buf, ie_len, 0, GFP_KERNEL);
1563        cfg80211_put_bss(priv->wdev->wiphy, bss);
1564        memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN);
1565
1566        return 0;
1567}
1568
1569/*
1570 * This function connects with a BSS.
1571 *
1572 * This function handles both Infra and Ad-Hoc modes. It also performs
1573 * validity checking on the provided parameters, disconnects from the
1574 * current BSS (if any), sets up the association/scan parameters,
1575 * including security settings, and performs specific SSID scan before
1576 * trying to connect.
1577 *
1578 * For Infra mode, the function returns failure if the specified SSID
1579 * is not found in scan table. However, for Ad-Hoc mode, it can create
1580 * the IBSS if it does not exist. On successful completion in either case,
1581 * the function notifies the CFG802.11 subsystem of the new BSS connection.
1582 */
1583static int
1584mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len,
1585                       const u8 *ssid, const u8 *bssid, int mode,
1586                       struct ieee80211_channel *channel,
1587                       struct cfg80211_connect_params *sme, bool privacy)
1588{
1589        struct cfg80211_ssid req_ssid;
1590        int ret, auth_type = 0;
1591        struct cfg80211_bss *bss = NULL;
1592        u8 is_scanning_required = 0;
1593
1594        memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));
1595
1596        req_ssid.ssid_len = ssid_len;
1597        if (ssid_len > IEEE80211_MAX_SSID_LEN) {
1598                dev_err(priv->adapter->dev, "invalid SSID - aborting\n");
1599                return -EINVAL;
1600        }
1601
1602        memcpy(req_ssid.ssid, ssid, ssid_len);
1603        if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) {
1604                dev_err(priv->adapter->dev, "invalid SSID - aborting\n");
1605                return -EINVAL;
1606        }
1607
1608        /* As this is new association, clear locally stored
1609         * keys and security related flags */
1610        priv->sec_info.wpa_enabled = false;
1611        priv->sec_info.wpa2_enabled = false;
1612        priv->wep_key_curr_index = 0;
1613        priv->sec_info.encryption_mode = 0;
1614        priv->sec_info.is_authtype_auto = 0;
1615        ret = mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1);
1616
1617        if (mode == NL80211_IFTYPE_ADHOC) {
1618                /* "privacy" is set only for ad-hoc mode */
1619                if (privacy) {
1620                        /*
1621                         * Keep WLAN_CIPHER_SUITE_WEP104 for now so that
1622                         * the firmware can find a matching network from the
1623                         * scan. The cfg80211 does not give us the encryption
1624                         * mode at this stage so just setting it to WEP here.
1625                         */
1626                        priv->sec_info.encryption_mode =
1627                                        WLAN_CIPHER_SUITE_WEP104;
1628                        priv->sec_info.authentication_mode =
1629                                        NL80211_AUTHTYPE_OPEN_SYSTEM;
1630                }
1631
1632                goto done;
1633        }
1634
1635        /* Now handle infra mode. "sme" is valid for infra mode only */
1636        if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
1637                auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
1638                priv->sec_info.is_authtype_auto = 1;
1639        } else {
1640                auth_type = sme->auth_type;
1641        }
1642
1643        if (sme->crypto.n_ciphers_pairwise) {
1644                priv->sec_info.encryption_mode =
1645                                                sme->crypto.ciphers_pairwise[0];
1646                priv->sec_info.authentication_mode = auth_type;
1647        }
1648
1649        if (sme->crypto.cipher_group) {
1650                priv->sec_info.encryption_mode = sme->crypto.cipher_group;
1651                priv->sec_info.authentication_mode = auth_type;
1652        }
1653        if (sme->ie)
1654                ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len);
1655
1656        if (sme->key) {
1657                if (mwifiex_is_alg_wep(priv->sec_info.encryption_mode)) {
1658                        dev_dbg(priv->adapter->dev,
1659                                "info: setting wep encryption"
1660                                " with key len %d\n", sme->key_len);
1661                        priv->wep_key_curr_index = sme->key_idx;
1662                        ret = mwifiex_set_encode(priv, NULL, sme->key,
1663                                                 sme->key_len, sme->key_idx,
1664                                                 NULL, 0);
1665                }
1666        }
1667done:
1668        /*
1669         * Scan entries are valid for some time (15 sec). So we can save one
1670         * active scan time if we just try cfg80211_get_bss first. If it fails
1671         * then request scan and cfg80211_get_bss() again for final output.
1672         */
1673        while (1) {
1674                if (is_scanning_required) {
1675                        /* Do specific SSID scanning */
1676                        if (mwifiex_request_scan(priv, &req_ssid)) {
1677                                dev_err(priv->adapter->dev, "scan error\n");
1678                                return -EFAULT;
1679                        }
1680                }
1681
1682                /* Find the BSS we want using available scan results */
1683                if (mode == NL80211_IFTYPE_ADHOC)
1684                        bss = cfg80211_get_bss(priv->wdev->wiphy, channel,
1685                                               bssid, ssid, ssid_len,
1686                                               WLAN_CAPABILITY_IBSS,
1687                                               WLAN_CAPABILITY_IBSS);
1688                else
1689                        bss = cfg80211_get_bss(priv->wdev->wiphy, channel,
1690                                               bssid, ssid, ssid_len,
1691                                               WLAN_CAPABILITY_ESS,
1692                                               WLAN_CAPABILITY_ESS);
1693
1694                if (!bss) {
1695                        if (is_scanning_required) {
1696                                dev_warn(priv->adapter->dev,
1697                                         "assoc: requested bss not found in scan results\n");
1698                                break;
1699                        }
1700                        is_scanning_required = 1;
1701                } else {
1702                        dev_dbg(priv->adapter->dev,
1703                                "info: trying to associate to '%s' bssid %pM\n",
1704                                (char *) req_ssid.ssid, bss->bssid);
1705                        memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);
1706                        break;
1707                }
1708        }
1709
1710        ret = mwifiex_bss_start(priv, bss, &req_ssid);
1711        if (ret)
1712                return ret;
1713
1714        if (mode == NL80211_IFTYPE_ADHOC) {
1715                /* Inform the BSS information to kernel, otherwise
1716                 * kernel will give a panic after successful assoc */
1717                if (mwifiex_cfg80211_inform_ibss_bss(priv))
1718                        return -EFAULT;
1719        }
1720
1721        return ret;
1722}
1723
1724/*
1725 * CFG802.11 operation handler for association request.
1726 *
1727 * This function does not work when the current mode is set to Ad-Hoc, or
1728 * when there is already an association procedure going on. The given BSS
1729 * information is used to associate.
1730 */
1731static int
1732mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
1733                         struct cfg80211_connect_params *sme)
1734{
1735        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1736        int ret;
1737
1738        if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) {
1739                wiphy_err(wiphy,
1740                          "%s: reject infra assoc request in non-STA role\n",
1741                          dev->name);
1742                return -EINVAL;
1743        }
1744
1745        if (priv->wdev && priv->wdev->current_bss) {
1746                wiphy_warn(wiphy, "%s: already connected\n", dev->name);
1747                return -EALREADY;
1748        }
1749
1750        wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n",
1751                  (char *) sme->ssid, sme->bssid);
1752
1753        ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid,
1754                                     priv->bss_mode, sme->channel, sme, 0);
1755        if (!ret) {
1756                cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0,
1757                                        NULL, 0, WLAN_STATUS_SUCCESS,
1758                                        GFP_KERNEL);
1759                dev_dbg(priv->adapter->dev,
1760                        "info: associated to bssid %pM successfully\n",
1761                        priv->cfg_bssid);
1762        } else {
1763                dev_dbg(priv->adapter->dev,
1764                        "info: association to bssid %pM failed\n",
1765                        priv->cfg_bssid);
1766                memset(priv->cfg_bssid, 0, ETH_ALEN);
1767
1768                if (ret > 0)
1769                        cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
1770                                                NULL, 0, NULL, 0, ret,
1771                                                GFP_KERNEL);
1772                else
1773                        cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
1774                                                NULL, 0, NULL, 0,
1775                                                WLAN_STATUS_UNSPECIFIED_FAILURE,
1776                                                GFP_KERNEL);
1777        }
1778
1779        return 0;
1780}
1781
1782/*
1783 * This function sets following parameters for ibss network.
1784 *  -  channel
1785 *  -  start band
1786 *  -  11n flag
1787 *  -  secondary channel offset
1788 */
1789static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
1790                                   struct cfg80211_ibss_params *params)
1791{
1792        struct wiphy *wiphy = priv->wdev->wiphy;
1793        struct mwifiex_adapter *adapter = priv->adapter;
1794        int index = 0, i;
1795        u8 config_bands = 0;
1796
1797        if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) {
1798                if (!params->basic_rates) {
1799                        config_bands = BAND_B | BAND_G;
1800                } else {
1801                        for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) {
1802                                /*
1803                                 * Rates below 6 Mbps in the table are CCK
1804                                 * rates; 802.11b and from 6 they are OFDM;
1805                                 * 802.11G
1806                                 */
1807                                if (mwifiex_rates[i].bitrate == 60) {
1808                                        index = 1 << i;
1809                                        break;
1810                                }
1811                        }
1812
1813                        if (params->basic_rates < index) {
1814                                config_bands = BAND_B;
1815                        } else {
1816                                config_bands = BAND_G;
1817                                if (params->basic_rates % index)
1818                                        config_bands |= BAND_B;
1819                        }
1820                }
1821
1822                if (cfg80211_get_chandef_type(&params->chandef) !=
1823                                                NL80211_CHAN_NO_HT)
1824                        config_bands |= BAND_G | BAND_GN;
1825        } else {
1826                if (cfg80211_get_chandef_type(&params->chandef) ==
1827                                                NL80211_CHAN_NO_HT)
1828                        config_bands = BAND_A;
1829                else
1830                        config_bands = BAND_AN | BAND_A;
1831        }
1832
1833        if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands)) {
1834                adapter->config_bands = config_bands;
1835                adapter->adhoc_start_band = config_bands;
1836
1837                if ((config_bands & BAND_GN) || (config_bands & BAND_AN))
1838                        adapter->adhoc_11n_enabled = true;
1839                else
1840                        adapter->adhoc_11n_enabled = false;
1841        }
1842
1843        adapter->sec_chan_offset =
1844                mwifiex_chan_type_to_sec_chan_offset(
1845                        cfg80211_get_chandef_type(&params->chandef));
1846        priv->adhoc_channel = ieee80211_frequency_to_channel(
1847                                params->chandef.chan->center_freq);
1848
1849        wiphy_dbg(wiphy, "info: set ibss band %d, chan %d, chan offset %d\n",
1850                  config_bands, priv->adhoc_channel, adapter->sec_chan_offset);
1851
1852        return 0;
1853}
1854
1855/*
1856 * CFG802.11 operation handler to join an IBSS.
1857 *
1858 * This function does not work in any mode other than Ad-Hoc, or if
1859 * a join operation is already in progress.
1860 */
1861static int
1862mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
1863                           struct cfg80211_ibss_params *params)
1864{
1865        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1866        int ret = 0;
1867
1868        if (priv->bss_mode != NL80211_IFTYPE_ADHOC) {
1869                wiphy_err(wiphy, "request to join ibss received "
1870                                "when station is not in ibss mode\n");
1871                goto done;
1872        }
1873
1874        wiphy_dbg(wiphy, "info: trying to join to %s and bssid %pM\n",
1875                  (char *) params->ssid, params->bssid);
1876
1877        mwifiex_set_ibss_params(priv, params);
1878
1879        ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid,
1880                                     params->bssid, priv->bss_mode,
1881                                     params->chandef.chan, NULL,
1882                                     params->privacy);
1883done:
1884        if (!ret) {
1885                cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
1886                                     params->chandef.chan, GFP_KERNEL);
1887                dev_dbg(priv->adapter->dev,
1888                        "info: joined/created adhoc network with bssid"
1889                        " %pM successfully\n", priv->cfg_bssid);
1890        } else {
1891                dev_dbg(priv->adapter->dev,
1892                        "info: failed creating/joining adhoc network\n");
1893        }
1894
1895        return ret;
1896}
1897
1898/*
1899 * CFG802.11 operation handler to leave an IBSS.
1900 *
1901 * This function does not work if a leave operation is
1902 * already in progress.
1903 */
1904static int
1905mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
1906{
1907        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1908
1909        wiphy_dbg(wiphy, "info: disconnecting from essid %pM\n",
1910                  priv->cfg_bssid);
1911        if (mwifiex_deauthenticate(priv, NULL))
1912                return -EFAULT;
1913
1914        memset(priv->cfg_bssid, 0, ETH_ALEN);
1915
1916        return 0;
1917}
1918
1919/*
1920 * CFG802.11 operation handler for scan request.
1921 *
1922 * This function issues a scan request to the firmware based upon
1923 * the user specified scan configuration. On successfull completion,
1924 * it also informs the results.
1925 */
1926static int
1927mwifiex_cfg80211_scan(struct wiphy *wiphy,
1928                      struct cfg80211_scan_request *request)
1929{
1930        struct net_device *dev = request->wdev->netdev;
1931        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1932        int i, offset, ret;
1933        struct ieee80211_channel *chan;
1934        struct ieee_types_header *ie;
1935        struct mwifiex_user_scan_cfg *user_scan_cfg;
1936
1937        wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name);
1938
1939        /* Block scan request if scan operation or scan cleanup when interface
1940         * is disabled is in process
1941         */
1942        if (priv->scan_request || priv->scan_aborting) {
1943                dev_err(priv->adapter->dev, "cmd: Scan already in process..\n");
1944                return -EBUSY;
1945        }
1946
1947        user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
1948        if (!user_scan_cfg)
1949                return -ENOMEM;
1950
1951        priv->scan_request = request;
1952
1953        user_scan_cfg->num_ssids = request->n_ssids;
1954        user_scan_cfg->ssid_list = request->ssids;
1955
1956        if (request->ie && request->ie_len) {
1957                offset = 0;
1958                for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {
1959                        if (priv->vs_ie[i].mask != MWIFIEX_VSIE_MASK_CLEAR)
1960                                continue;
1961                        priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_SCAN;
1962                        ie = (struct ieee_types_header *)(request->ie + offset);
1963                        memcpy(&priv->vs_ie[i].ie, ie, sizeof(*ie) + ie->len);
1964                        offset += sizeof(*ie) + ie->len;
1965
1966                        if (offset >= request->ie_len)
1967                                break;
1968                }
1969        }
1970
1971        for (i = 0; i < min_t(u32, request->n_channels,
1972                              MWIFIEX_USER_SCAN_CHAN_MAX); i++) {
1973                chan = request->channels[i];
1974                user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
1975                user_scan_cfg->chan_list[i].radio_type = chan->band;
1976
1977                if ((chan->flags & IEEE80211_CHAN_NO_IR) || !request->n_ssids)
1978                        user_scan_cfg->chan_list[i].scan_type =
1979                                                MWIFIEX_SCAN_TYPE_PASSIVE;
1980                else
1981                        user_scan_cfg->chan_list[i].scan_type =
1982                                                MWIFIEX_SCAN_TYPE_ACTIVE;
1983
1984                user_scan_cfg->chan_list[i].scan_time = 0;
1985        }
1986
1987        if (priv->adapter->scan_chan_gap_enabled &&
1988            mwifiex_is_any_intf_active(priv))
1989                user_scan_cfg->scan_chan_gap =
1990                                              priv->adapter->scan_chan_gap_time;
1991
1992        ret = mwifiex_scan_networks(priv, user_scan_cfg);
1993        kfree(user_scan_cfg);
1994        if (ret) {
1995                dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
1996                priv->scan_aborting = false;
1997                priv->scan_request = NULL;
1998                return ret;
1999        }
2000
2001        if (request->ie && request->ie_len) {
2002                for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {
2003                        if (priv->vs_ie[i].mask == MWIFIEX_VSIE_MASK_SCAN) {
2004                                priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_CLEAR;
2005                                memset(&priv->vs_ie[i].ie, 0,
2006                                       MWIFIEX_MAX_VSIE_LEN);
2007                        }
2008                }
2009        }
2010        return 0;
2011}
2012
2013static void mwifiex_setup_vht_caps(struct ieee80211_sta_vht_cap *vht_info,
2014                                   struct mwifiex_private *priv)
2015{
2016        struct mwifiex_adapter *adapter = priv->adapter;
2017
2018        vht_info->vht_supported = true;
2019
2020        vht_info->cap = adapter->hw_dot_11ac_dev_cap;
2021        /* Update MCS support for VHT */
2022        vht_info->vht_mcs.rx_mcs_map = cpu_to_le16(
2023                                adapter->hw_dot_11ac_mcs_support & 0xFFFF);
2024        vht_info->vht_mcs.rx_highest = 0;
2025        vht_info->vht_mcs.tx_mcs_map = cpu_to_le16(
2026                                adapter->hw_dot_11ac_mcs_support >> 16);
2027        vht_info->vht_mcs.tx_highest = 0;
2028}
2029
2030/*
2031 * This function sets up the CFG802.11 specific HT capability fields
2032 * with default values.
2033 *
2034 * The following default values are set -
2035 *      - HT Supported = True
2036 *      - Maximum AMPDU length factor = IEEE80211_HT_MAX_AMPDU_64K
2037 *      - Minimum AMPDU spacing = IEEE80211_HT_MPDU_DENSITY_NONE
2038 *      - HT Capabilities supported by firmware
2039 *      - MCS information, Rx mask = 0xff
2040 *      - MCD information, Tx parameters = IEEE80211_HT_MCS_TX_DEFINED (0x01)
2041 */
2042static void
2043mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info,
2044                      struct mwifiex_private *priv)
2045{
2046        int rx_mcs_supp;
2047        struct ieee80211_mcs_info mcs_set;
2048        u8 *mcs = (u8 *)&mcs_set;
2049        struct mwifiex_adapter *adapter = priv->adapter;
2050
2051        ht_info->ht_supported = true;
2052        ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
2053        ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
2054
2055        memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
2056
2057        /* Fill HT capability information */
2058        if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap))
2059                ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
2060        else
2061                ht_info->cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
2062
2063        if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap))
2064                ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
2065        else
2066                ht_info->cap &= ~IEEE80211_HT_CAP_SGI_20;
2067
2068        if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap))
2069                ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
2070        else
2071                ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40;
2072
2073        if (adapter->user_dev_mcs_support == HT_STREAM_2X2)
2074                ht_info->cap |= 3 << IEEE80211_HT_CAP_RX_STBC_SHIFT;
2075        else
2076                ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT;
2077
2078        if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap))
2079                ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
2080        else
2081                ht_info->cap &= ~IEEE80211_HT_CAP_TX_STBC;
2082
2083        if (ISSUPP_GREENFIELD(adapter->hw_dot_11n_dev_cap))
2084                ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
2085        else
2086                ht_info->cap &= ~IEEE80211_HT_CAP_GRN_FLD;
2087
2088        if (ISENABLED_40MHZ_INTOLERANT(adapter->hw_dot_11n_dev_cap))
2089                ht_info->cap |= IEEE80211_HT_CAP_40MHZ_INTOLERANT;
2090        else
2091                ht_info->cap &= ~IEEE80211_HT_CAP_40MHZ_INTOLERANT;
2092
2093        if (ISSUPP_RXLDPC(adapter->hw_dot_11n_dev_cap))
2094                ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
2095        else
2096                ht_info->cap &= ~IEEE80211_HT_CAP_LDPC_CODING;
2097
2098        ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU;
2099        ht_info->cap |= IEEE80211_HT_CAP_SM_PS;
2100
2101        rx_mcs_supp = GET_RXMCSSUPP(adapter->user_dev_mcs_support);
2102        /* Set MCS for 1x1/2x2 */
2103        memset(mcs, 0xff, rx_mcs_supp);
2104        /* Clear all the other values */
2105        memset(&mcs[rx_mcs_supp], 0,
2106               sizeof(struct ieee80211_mcs_info) - rx_mcs_supp);
2107        if (priv->bss_mode == NL80211_IFTYPE_STATION ||
2108            ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap))
2109                /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */
2110                SETHT_MCS32(mcs_set.rx_mask);
2111
2112        memcpy((u8 *) &ht_info->mcs, mcs, sizeof(struct ieee80211_mcs_info));
2113
2114        ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
2115}
2116
2117/*
2118 *  create a new virtual interface with the given name
2119 */
2120struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
2121                                              const char *name,
2122                                              enum nl80211_iftype type,
2123                                              u32 *flags,
2124                                              struct vif_params *params)
2125{
2126        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
2127        struct mwifiex_private *priv;
2128        struct net_device *dev;
2129        void *mdev_priv;
2130        struct wireless_dev *wdev;
2131
2132        if (!adapter)
2133                return ERR_PTR(-EFAULT);
2134
2135        switch (type) {
2136        case NL80211_IFTYPE_UNSPECIFIED:
2137        case NL80211_IFTYPE_STATION:
2138        case NL80211_IFTYPE_ADHOC:
2139                priv = adapter->priv[MWIFIEX_BSS_TYPE_STA];
2140                if (priv->bss_mode) {
2141                        wiphy_err(wiphy,
2142                                  "cannot create multiple sta/adhoc ifaces\n");
2143                        return ERR_PTR(-EINVAL);
2144                }
2145
2146                wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
2147                if (!wdev)
2148                        return ERR_PTR(-ENOMEM);
2149
2150                wdev->wiphy = wiphy;
2151                priv->wdev = wdev;
2152                wdev->iftype = NL80211_IFTYPE_STATION;
2153
2154                if (type == NL80211_IFTYPE_UNSPECIFIED)
2155                        priv->bss_mode = NL80211_IFTYPE_STATION;
2156                else
2157                        priv->bss_mode = type;
2158
2159                priv->bss_type = MWIFIEX_BSS_TYPE_STA;
2160                priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
2161                priv->bss_priority = 0;
2162                priv->bss_role = MWIFIEX_BSS_ROLE_STA;
2163                priv->bss_num = 0;
2164
2165                break;
2166        case NL80211_IFTYPE_AP:
2167                priv = adapter->priv[MWIFIEX_BSS_TYPE_UAP];
2168
2169                if (priv->bss_mode) {
2170                        wiphy_err(wiphy, "Can't create multiple AP interfaces");
2171                        return ERR_PTR(-EINVAL);
2172                }
2173
2174                wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
2175                if (!wdev)
2176                        return ERR_PTR(-ENOMEM);
2177
2178                priv->wdev = wdev;
2179                wdev->wiphy = wiphy;
2180                wdev->iftype = NL80211_IFTYPE_AP;
2181
2182                priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
2183                priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
2184                priv->bss_priority = 0;
2185                priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
2186                priv->bss_started = 0;
2187                priv->bss_num = 0;
2188                priv->bss_mode = type;
2189
2190                break;
2191        case NL80211_IFTYPE_P2P_CLIENT:
2192                priv = adapter->priv[MWIFIEX_BSS_TYPE_P2P];
2193
2194                if (priv->bss_mode) {
2195                        wiphy_err(wiphy, "Can't create multiple P2P ifaces");
2196                        return ERR_PTR(-EINVAL);
2197                }
2198
2199                wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
2200                if (!wdev)
2201                        return ERR_PTR(-ENOMEM);
2202
2203                priv->wdev = wdev;
2204                wdev->wiphy = wiphy;
2205
2206                /* At start-up, wpa_supplicant tries to change the interface
2207                 * to NL80211_IFTYPE_STATION if it is not managed mode.
2208                 */
2209                wdev->iftype = NL80211_IFTYPE_P2P_CLIENT;
2210                priv->bss_mode = NL80211_IFTYPE_P2P_CLIENT;
2211
2212                /* Setting bss_type to P2P tells firmware that this interface
2213                 * is receiving P2P peers found during find phase and doing
2214                 * action frame handshake.
2215                 */
2216                priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
2217
2218                priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
2219                priv->bss_priority = MWIFIEX_BSS_ROLE_STA;
2220                priv->bss_role = MWIFIEX_BSS_ROLE_STA;
2221                priv->bss_started = 0;
2222                priv->bss_num = 0;
2223
2224                if (mwifiex_cfg80211_init_p2p_client(priv)) {
2225                        wdev = ERR_PTR(-EFAULT);
2226                        goto done;
2227                }
2228
2229                break;
2230        default:
2231                wiphy_err(wiphy, "type not supported\n");
2232                return ERR_PTR(-EINVAL);
2233        }
2234
2235        dev = alloc_netdev_mqs(sizeof(struct mwifiex_private *), name,
2236                               NET_NAME_UNKNOWN, ether_setup,
2237                               IEEE80211_NUM_ACS, 1);
2238        if (!dev) {
2239                wiphy_err(wiphy, "no memory available for netdevice\n");
2240                priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
2241                wdev = ERR_PTR(-ENOMEM);
2242                goto done;
2243        }
2244
2245        mwifiex_init_priv_params(priv, dev);
2246        priv->netdev = dev;
2247
2248        mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv);
2249        if (adapter->is_hw_11ac_capable)
2250                mwifiex_setup_vht_caps(
2251                        &wiphy->bands[IEEE80211_BAND_2GHZ]->vht_cap, priv);
2252
2253        if (adapter->config_bands & BAND_A)
2254                mwifiex_setup_ht_caps(
2255                        &wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv);
2256
2257        if ((adapter->config_bands & BAND_A) && adapter->is_hw_11ac_capable)
2258                mwifiex_setup_vht_caps(
2259                        &wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap, priv);
2260
2261        dev_net_set(dev, wiphy_net(wiphy));
2262        dev->ieee80211_ptr = priv->wdev;
2263        dev->ieee80211_ptr->iftype = priv->bss_mode;
2264        memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN);
2265        SET_NETDEV_DEV(dev, wiphy_dev(wiphy));
2266
2267        dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
2268        dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT;
2269        dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN;
2270        dev->ethtool_ops = &mwifiex_ethtool_ops;
2271
2272        mdev_priv = netdev_priv(dev);
2273        *((unsigned long *) mdev_priv) = (unsigned long) priv;
2274
2275        SET_NETDEV_DEV(dev, adapter->dev);
2276
2277        /* Register network device */
2278        if (register_netdevice(dev)) {
2279                wiphy_err(wiphy, "cannot register virtual network device\n");
2280                free_netdev(dev);
2281                priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
2282                priv->netdev = NULL;
2283                wdev = ERR_PTR(-EFAULT);
2284                goto done;
2285        }
2286
2287        sema_init(&priv->async_sem, 1);
2288
2289        dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name);
2290
2291#ifdef CONFIG_DEBUG_FS
2292        mwifiex_dev_debugfs_init(priv);
2293#endif
2294
2295done:
2296        if (IS_ERR(wdev)) {
2297                kfree(priv->wdev);
2298                priv->wdev = NULL;
2299        }
2300
2301        return wdev;
2302}
2303EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
2304
2305/*
2306 * del_virtual_intf: remove the virtual interface determined by dev
2307 */
2308int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
2309{
2310        struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
2311
2312#ifdef CONFIG_DEBUG_FS
2313        mwifiex_dev_debugfs_remove(priv);
2314#endif
2315
2316        mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
2317
2318        if (netif_carrier_ok(priv->netdev))
2319                netif_carrier_off(priv->netdev);
2320
2321        if (wdev->netdev->reg_state == NETREG_REGISTERED)
2322                unregister_netdevice(wdev->netdev);
2323
2324        /* Clear the priv in adapter */
2325        priv->netdev->ieee80211_ptr = NULL;
2326        priv->netdev = NULL;
2327        kfree(wdev);
2328        priv->wdev = NULL;
2329
2330        priv->media_connected = false;
2331
2332        priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
2333
2334        return 0;
2335}
2336EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf);
2337
2338static bool
2339mwifiex_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_seq,
2340                             u8 max_byte_seq)
2341{
2342        int j, k, valid_byte_cnt = 0;
2343        bool dont_care_byte = false;
2344
2345        for (j = 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) {
2346                for (k = 0; k < 8; k++) {
2347                        if (pat->mask[j] & 1 << k) {
2348                                memcpy(byte_seq + valid_byte_cnt,
2349                                       &pat->pattern[j * 8 + k], 1);
2350                                valid_byte_cnt++;
2351                                if (dont_care_byte)
2352                                        return false;
2353                        } else {
2354                                if (valid_byte_cnt)
2355                                        dont_care_byte = true;
2356                        }
2357
2358                        if (valid_byte_cnt > max_byte_seq)
2359                                return false;
2360                }
2361        }
2362
2363        byte_seq[max_byte_seq] = valid_byte_cnt;
2364
2365        return true;
2366}
2367
2368#ifdef CONFIG_PM
2369static int mwifiex_cfg80211_suspend(struct wiphy *wiphy,
2370                                    struct cfg80211_wowlan *wowlan)
2371{
2372        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
2373        struct mwifiex_ds_mef_cfg mef_cfg;
2374        struct mwifiex_mef_entry *mef_entry;
2375        int i, filt_num = 0, ret;
2376        bool first_pat = true;
2377        u8 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ + 1];
2378        const u8 ipv4_mc_mac[] = {0x33, 0x33};
2379        const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};
2380        struct mwifiex_private *priv =
2381                        mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
2382
2383        if (!wowlan) {
2384                dev_warn(adapter->dev, "None of the WOWLAN triggers enabled\n");
2385                return 0;
2386        }
2387
2388        if (!priv->media_connected) {
2389                dev_warn(adapter->dev,
2390                         "Can not configure WOWLAN in disconnected state\n");
2391                return 0;
2392        }
2393
2394        mef_entry = kzalloc(sizeof(*mef_entry), GFP_KERNEL);
2395        if (!mef_entry)
2396                return -ENOMEM;
2397
2398        memset(&mef_cfg, 0, sizeof(mef_cfg));
2399        mef_cfg.num_entries = 1;
2400        mef_cfg.mef_entry = mef_entry;
2401        mef_entry->mode = MEF_MODE_HOST_SLEEP;
2402        mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST;
2403
2404        for (i = 0; i < wowlan->n_patterns; i++) {
2405                memset(byte_seq, 0, sizeof(byte_seq));
2406                if (!mwifiex_is_pattern_supported(&wowlan->patterns[i],
2407                                                  byte_seq,
2408                                                  MWIFIEX_MEF_MAX_BYTESEQ)) {
2409                        wiphy_err(wiphy, "Pattern not supported\n");
2410                        kfree(mef_entry);
2411                        return -EOPNOTSUPP;
2412                }
2413
2414                if (!wowlan->patterns[i].pkt_offset) {
2415                        if (!(byte_seq[0] & 0x01) &&
2416                            (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 1)) {
2417                                mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST;
2418                                continue;
2419                        } else if (is_broadcast_ether_addr(byte_seq)) {
2420                                mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST;
2421                                continue;
2422                        } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&
2423                                    (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 2)) ||
2424                                   (!memcmp(byte_seq, ipv6_mc_mac, 3) &&
2425                                    (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 3))) {
2426                                mef_cfg.criteria |= MWIFIEX_CRITERIA_MULTICAST;
2427                                continue;
2428                        }
2429                }
2430
2431                mef_entry->filter[filt_num].repeat = 1;
2432                mef_entry->filter[filt_num].offset =
2433                                                wowlan->patterns[i].pkt_offset;
2434                memcpy(mef_entry->filter[filt_num].byte_seq, byte_seq,
2435                       sizeof(byte_seq));
2436                mef_entry->filter[filt_num].filt_type = TYPE_EQ;
2437
2438                if (first_pat)
2439                        first_pat = false;
2440                else
2441                        mef_entry->filter[filt_num].filt_action = TYPE_AND;
2442
2443                filt_num++;
2444        }
2445
2446        if (wowlan->magic_pkt) {
2447                mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST;
2448                mef_entry->filter[filt_num].repeat = 16;
2449                memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,
2450                       ETH_ALEN);
2451                mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =
2452                                                                ETH_ALEN;
2453                mef_entry->filter[filt_num].offset = 28;
2454                mef_entry->filter[filt_num].filt_type = TYPE_EQ;
2455                if (filt_num)
2456                        mef_entry->filter[filt_num].filt_action = TYPE_OR;
2457
2458                filt_num++;
2459                mef_entry->filter[filt_num].repeat = 16;
2460                memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,
2461                       ETH_ALEN);
2462                mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =
2463                                                                ETH_ALEN;
2464                mef_entry->filter[filt_num].offset = 56;
2465                mef_entry->filter[filt_num].filt_type = TYPE_EQ;
2466                mef_entry->filter[filt_num].filt_action = TYPE_OR;
2467        }
2468
2469        if (!mef_cfg.criteria)
2470                mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST |
2471                                   MWIFIEX_CRITERIA_UNICAST |
2472                                   MWIFIEX_CRITERIA_MULTICAST;
2473
2474        ret = mwifiex_send_cmd(priv, HostCmd_CMD_MEF_CFG,
2475                               HostCmd_ACT_GEN_SET, 0, &mef_cfg, true);
2476
2477        kfree(mef_entry);
2478        return ret;
2479}
2480
2481static int mwifiex_cfg80211_resume(struct wiphy *wiphy)
2482{
2483        return 0;
2484}
2485
2486static void mwifiex_cfg80211_set_wakeup(struct wiphy *wiphy,
2487                                       bool enabled)
2488{
2489        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
2490
2491        device_set_wakeup_enable(adapter->dev, enabled);
2492}
2493#endif
2494
2495static int mwifiex_get_coalesce_pkt_type(u8 *byte_seq)
2496{
2497        const u8 ipv4_mc_mac[] = {0x33, 0x33};
2498        const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};
2499        const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff};
2500
2501        if ((byte_seq[0] & 0x01) &&
2502            (byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 1))
2503                return PACKET_TYPE_UNICAST;
2504        else if (!memcmp(byte_seq, bc_mac, 4))
2505                return PACKET_TYPE_BROADCAST;
2506        else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&
2507                  byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 2) ||
2508                 (!memcmp(byte_seq, ipv6_mc_mac, 3) &&
2509                  byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 3))
2510                return PACKET_TYPE_MULTICAST;
2511
2512        return 0;
2513}
2514
2515static int
2516mwifiex_fill_coalesce_rule_info(struct mwifiex_private *priv,
2517                                struct cfg80211_coalesce_rules *crule,
2518                                struct mwifiex_coalesce_rule *mrule)
2519{
2520        u8 byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ + 1];
2521        struct filt_field_param *param;
2522        int i;
2523
2524        mrule->max_coalescing_delay = crule->delay;
2525
2526        param = mrule->params;
2527
2528        for (i = 0; i < crule->n_patterns; i++) {
2529                memset(byte_seq, 0, sizeof(byte_seq));
2530                if (!mwifiex_is_pattern_supported(&crule->patterns[i],
2531                                                  byte_seq,
2532                                                MWIFIEX_COALESCE_MAX_BYTESEQ)) {
2533                        dev_err(priv->adapter->dev, "Pattern not supported\n");
2534                        return -EOPNOTSUPP;
2535                }
2536
2537                if (!crule->patterns[i].pkt_offset) {
2538                        u8 pkt_type;
2539
2540                        pkt_type = mwifiex_get_coalesce_pkt_type(byte_seq);
2541                        if (pkt_type && mrule->pkt_type) {
2542                                dev_err(priv->adapter->dev,
2543                                        "Multiple packet types not allowed\n");
2544                                return -EOPNOTSUPP;
2545                        } else if (pkt_type) {
2546                                mrule->pkt_type = pkt_type;
2547                                continue;
2548                        }
2549                }
2550
2551                if (crule->condition == NL80211_COALESCE_CONDITION_MATCH)
2552                        param->operation = RECV_FILTER_MATCH_TYPE_EQ;
2553                else
2554                        param->operation = RECV_FILTER_MATCH_TYPE_NE;
2555
2556                param->operand_len = byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ];
2557                memcpy(param->operand_byte_stream, byte_seq,
2558                       param->operand_len);
2559                param->offset = crule->patterns[i].pkt_offset;
2560                param++;
2561
2562                mrule->num_of_fields++;
2563        }
2564
2565        if (!mrule->pkt_type) {
2566                dev_err(priv->adapter->dev,
2567                        "Packet type can not be determined\n");
2568                return -EOPNOTSUPP;
2569        }
2570
2571        return 0;
2572}
2573
2574static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy,
2575                                         struct cfg80211_coalesce *coalesce)
2576{
2577        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
2578        int i, ret;
2579        struct mwifiex_ds_coalesce_cfg coalesce_cfg;
2580        struct mwifiex_private *priv =
2581                        mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
2582
2583        memset(&coalesce_cfg, 0, sizeof(coalesce_cfg));
2584        if (!coalesce) {
2585                dev_dbg(adapter->dev,
2586                        "Disable coalesce and reset all previous rules\n");
2587                return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG,
2588                                        HostCmd_ACT_GEN_SET, 0,
2589                                        &coalesce_cfg, true);
2590        }
2591
2592        coalesce_cfg.num_of_rules = coalesce->n_rules;
2593        for (i = 0; i < coalesce->n_rules; i++) {
2594                ret = mwifiex_fill_coalesce_rule_info(priv, &coalesce->rules[i],
2595                                                      &coalesce_cfg.rule[i]);
2596                if (ret) {
2597                        dev_err(priv->adapter->dev,
2598                                "Recheck the patterns provided for rule %d\n",
2599                                i + 1);
2600                        return ret;
2601                }
2602        }
2603
2604        return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG,
2605                                HostCmd_ACT_GEN_SET, 0, &coalesce_cfg, true);
2606}
2607
2608/* cfg80211 ops handler for tdls_mgmt.
2609 * Function prepares TDLS action frame packets and forwards them to FW
2610 */
2611static int
2612mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
2613                           const u8 *peer, u8 action_code, u8 dialog_token,
2614                           u16 status_code, u32 peer_capability,
2615                           bool initiator, const u8 *extra_ies,
2616                           size_t extra_ies_len)
2617{
2618        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
2619        int ret;
2620
2621        if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
2622                return -ENOTSUPP;
2623
2624        /* make sure we are in station mode and connected */
2625        if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
2626                return -ENOTSUPP;
2627
2628        switch (action_code) {
2629        case WLAN_TDLS_SETUP_REQUEST:
2630                dev_dbg(priv->adapter->dev,
2631                        "Send TDLS Setup Request to %pM status_code=%d\n", peer,
2632                         status_code);
2633                ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
2634                                                   dialog_token, status_code,
2635                                                   extra_ies, extra_ies_len);
2636                break;
2637        case WLAN_TDLS_SETUP_RESPONSE:
2638                dev_dbg(priv->adapter->dev,
2639                        "Send TDLS Setup Response to %pM status_code=%d\n",
2640                        peer, status_code);
2641                ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
2642                                                   dialog_token, status_code,
2643                                                   extra_ies, extra_ies_len);
2644                break;
2645        case WLAN_TDLS_SETUP_CONFIRM:
2646                dev_dbg(priv->adapter->dev,
2647                        "Send TDLS Confirm to %pM status_code=%d\n", peer,
2648                        status_code);
2649                ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
2650                                                   dialog_token, status_code,
2651                                                   extra_ies, extra_ies_len);
2652                break;
2653        case WLAN_TDLS_TEARDOWN:
2654                dev_dbg(priv->adapter->dev, "Send TDLS Tear down to %pM\n",
2655                        peer);
2656                ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
2657                                                   dialog_token, status_code,
2658                                                   extra_ies, extra_ies_len);
2659                break;
2660        case WLAN_TDLS_DISCOVERY_REQUEST:
2661                dev_dbg(priv->adapter->dev,
2662                        "Send TDLS Discovery Request to %pM\n", peer);
2663                ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
2664                                                   dialog_token, status_code,
2665                                                   extra_ies, extra_ies_len);
2666                break;
2667        case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
2668                dev_dbg(priv->adapter->dev,
2669                        "Send TDLS Discovery Response to %pM\n", peer);
2670                ret = mwifiex_send_tdls_action_frame(priv, peer, action_code,
2671                                                   dialog_token, status_code,
2672                                                   extra_ies, extra_ies_len);
2673                break;
2674        default:
2675                dev_warn(priv->adapter->dev,
2676                         "Unknown TDLS mgmt/action frame %pM\n", peer);
2677                ret = -EINVAL;
2678                break;
2679        }
2680
2681        return ret;
2682}
2683
2684static int
2685mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
2686                           const u8 *peer, enum nl80211_tdls_operation action)
2687{
2688        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
2689
2690        if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
2691            !(wiphy->flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
2692                return -ENOTSUPP;
2693
2694        /* make sure we are in station mode and connected */
2695        if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
2696                return -ENOTSUPP;
2697
2698        dev_dbg(priv->adapter->dev,
2699                "TDLS peer=%pM, oper=%d\n", peer, action);
2700
2701        switch (action) {
2702        case NL80211_TDLS_ENABLE_LINK:
2703                action = MWIFIEX_TDLS_ENABLE_LINK;
2704                break;
2705        case NL80211_TDLS_DISABLE_LINK:
2706                action = MWIFIEX_TDLS_DISABLE_LINK;
2707                break;
2708        case NL80211_TDLS_TEARDOWN:
2709                /* shouldn't happen!*/
2710                dev_warn(priv->adapter->dev,
2711                         "tdls_oper: teardown from driver not supported\n");
2712                return -EINVAL;
2713        case NL80211_TDLS_SETUP:
2714                /* shouldn't happen!*/
2715                dev_warn(priv->adapter->dev,
2716                         "tdls_oper: setup from driver not supported\n");
2717                return -EINVAL;
2718        case NL80211_TDLS_DISCOVERY_REQ:
2719                /* shouldn't happen!*/
2720                dev_warn(priv->adapter->dev,
2721                         "tdls_oper: discovery from driver not supported\n");
2722                return -EINVAL;
2723        default:
2724                dev_err(priv->adapter->dev,
2725                        "tdls_oper: operation not supported\n");
2726                return -ENOTSUPP;
2727        }
2728
2729        return mwifiex_tdls_oper(priv, peer, action);
2730}
2731
2732static int
2733mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev,
2734                             const u8 *mac, struct station_parameters *params)
2735{
2736        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
2737
2738        if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
2739                return -ENOTSUPP;
2740
2741        /* make sure we are in station mode and connected */
2742        if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected)
2743                return -ENOTSUPP;
2744
2745        return mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CREATE_LINK);
2746}
2747
2748static int
2749mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev,
2750                                const u8 *mac,
2751                                struct station_parameters *params)
2752{
2753        int ret;
2754        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
2755
2756        /* we support change_station handler only for TDLS peers*/
2757        if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
2758                return -ENOTSUPP;
2759
2760        /* make sure we are in station mode and connected */
2761        if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected)
2762                return -ENOTSUPP;
2763
2764        priv->sta_params = params;
2765
2766        ret = mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CONFIG_LINK);
2767        priv->sta_params = NULL;
2768
2769        return ret;
2770}
2771
2772/* station cfg80211 operations */
2773static struct cfg80211_ops mwifiex_cfg80211_ops = {
2774        .add_virtual_intf = mwifiex_add_virtual_intf,
2775        .del_virtual_intf = mwifiex_del_virtual_intf,
2776        .change_virtual_intf = mwifiex_cfg80211_change_virtual_intf,
2777        .scan = mwifiex_cfg80211_scan,
2778        .connect = mwifiex_cfg80211_connect,
2779        .disconnect = mwifiex_cfg80211_disconnect,
2780        .get_station = mwifiex_cfg80211_get_station,
2781        .dump_station = mwifiex_cfg80211_dump_station,
2782        .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params,
2783        .join_ibss = mwifiex_cfg80211_join_ibss,
2784        .leave_ibss = mwifiex_cfg80211_leave_ibss,
2785        .add_key = mwifiex_cfg80211_add_key,
2786        .del_key = mwifiex_cfg80211_del_key,
2787        .mgmt_tx = mwifiex_cfg80211_mgmt_tx,
2788        .mgmt_frame_register = mwifiex_cfg80211_mgmt_frame_register,
2789        .remain_on_channel = mwifiex_cfg80211_remain_on_channel,
2790        .cancel_remain_on_channel = mwifiex_cfg80211_cancel_remain_on_channel,
2791        .set_default_key = mwifiex_cfg80211_set_default_key,
2792        .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt,
2793        .set_tx_power = mwifiex_cfg80211_set_tx_power,
2794        .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask,
2795        .start_ap = mwifiex_cfg80211_start_ap,
2796        .stop_ap = mwifiex_cfg80211_stop_ap,
2797        .change_beacon = mwifiex_cfg80211_change_beacon,
2798        .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config,
2799        .set_antenna = mwifiex_cfg80211_set_antenna,
2800        .del_station = mwifiex_cfg80211_del_station,
2801#ifdef CONFIG_PM
2802        .suspend = mwifiex_cfg80211_suspend,
2803        .resume = mwifiex_cfg80211_resume,
2804        .set_wakeup = mwifiex_cfg80211_set_wakeup,
2805#endif
2806        .set_coalesce = mwifiex_cfg80211_set_coalesce,
2807        .tdls_mgmt = mwifiex_cfg80211_tdls_mgmt,
2808        .tdls_oper = mwifiex_cfg80211_tdls_oper,
2809        .add_station = mwifiex_cfg80211_add_station,
2810        .change_station = mwifiex_cfg80211_change_station,
2811};
2812
2813#ifdef CONFIG_PM
2814static const struct wiphy_wowlan_support mwifiex_wowlan_support = {
2815        .flags = WIPHY_WOWLAN_MAGIC_PKT,
2816        .n_patterns = MWIFIEX_MEF_MAX_FILTERS,
2817        .pattern_min_len = 1,
2818        .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN,
2819        .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,
2820};
2821#endif
2822
2823static bool mwifiex_is_valid_alpha2(const char *alpha2)
2824{
2825        if (!alpha2 || strlen(alpha2) != 2)
2826                return false;
2827
2828        if (isalpha(alpha2[0]) && isalpha(alpha2[1]))
2829                return true;
2830
2831        return false;
2832}
2833
2834static const struct wiphy_coalesce_support mwifiex_coalesce_support = {
2835        .n_rules = MWIFIEX_COALESCE_MAX_RULES,
2836        .max_delay = MWIFIEX_MAX_COALESCING_DELAY,
2837        .n_patterns = MWIFIEX_COALESCE_MAX_FILTERS,
2838        .pattern_min_len = 1,
2839        .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN,
2840        .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,
2841};
2842
2843/*
2844 * This function registers the device with CFG802.11 subsystem.
2845 *
2846 * The function creates the wireless device/wiphy, populates it with
2847 * default parameters and handler function pointers, and finally
2848 * registers the device.
2849 */
2850
2851int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
2852{
2853        int ret;
2854        void *wdev_priv;
2855        struct wiphy *wiphy;
2856        struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA];
2857        u8 *country_code;
2858        u32 thr, retry;
2859
2860        /* create a new wiphy for use with cfg80211 */
2861        wiphy = wiphy_new(&mwifiex_cfg80211_ops,
2862                          sizeof(struct mwifiex_adapter *));
2863        if (!wiphy) {
2864                dev_err(adapter->dev, "%s: creating new wiphy\n", __func__);
2865                return -ENOMEM;
2866        }
2867        wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;
2868        wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
2869        wiphy->mgmt_stypes = mwifiex_mgmt_stypes;
2870        wiphy->max_remain_on_channel_duration = 5000;
2871        wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
2872                                 BIT(NL80211_IFTYPE_ADHOC) |
2873                                 BIT(NL80211_IFTYPE_P2P_CLIENT) |
2874                                 BIT(NL80211_IFTYPE_P2P_GO) |
2875                                 BIT(NL80211_IFTYPE_AP);
2876
2877        wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz;
2878        if (adapter->config_bands & BAND_A)
2879                wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz;
2880        else
2881                wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
2882
2883        wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta;
2884        wiphy->n_iface_combinations = 1;
2885
2886        /* Initialize cipher suits */
2887        wiphy->cipher_suites = mwifiex_cipher_suites;
2888        wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);
2889
2890        memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN);
2891        wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
2892        wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
2893                        WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
2894                        WIPHY_FLAG_AP_UAPSD |
2895                        WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
2896
2897        if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))
2898                wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
2899                                WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
2900
2901#ifdef CONFIG_PM
2902        wiphy->wowlan = &mwifiex_wowlan_support;
2903#endif
2904
2905        wiphy->coalesce = &mwifiex_coalesce_support;
2906
2907        wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
2908                                    NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
2909                                    NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
2910
2911        wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;
2912        wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;
2913
2914        wiphy->features |= NL80211_FEATURE_HT_IBSS |
2915                           NL80211_FEATURE_INACTIVITY_TIMER |
2916                           NL80211_FEATURE_NEED_OBSS_SCAN;
2917
2918        /* Reserve space for mwifiex specific private data for BSS */
2919        wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
2920
2921        wiphy->reg_notifier = mwifiex_reg_notifier;
2922
2923        /* Set struct mwifiex_adapter pointer in wiphy_priv */
2924        wdev_priv = wiphy_priv(wiphy);
2925        *(unsigned long *)wdev_priv = (unsigned long)adapter;
2926
2927        set_wiphy_dev(wiphy, priv->adapter->dev);
2928
2929        ret = wiphy_register(wiphy);
2930        if (ret < 0) {
2931                dev_err(adapter->dev,
2932                        "%s: wiphy_register failed: %d\n", __func__, ret);
2933                wiphy_free(wiphy);
2934                return ret;
2935        }
2936
2937        if (reg_alpha2 && mwifiex_is_valid_alpha2(reg_alpha2)) {
2938                wiphy_info(wiphy, "driver hint alpha2: %2.2s\n", reg_alpha2);
2939                regulatory_hint(wiphy, reg_alpha2);
2940        } else {
2941                country_code = mwifiex_11d_code_2_region(adapter->region_code);
2942                if (country_code)
2943                        wiphy_info(wiphy, "ignoring F/W country code %2.2s\n",
2944                                   country_code);
2945        }
2946
2947        mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
2948                         HostCmd_ACT_GEN_GET, FRAG_THRESH_I, &thr, true);
2949        wiphy->frag_threshold = thr;
2950        mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
2951                         HostCmd_ACT_GEN_GET, RTS_THRESH_I, &thr, true);
2952        wiphy->rts_threshold = thr;
2953        mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
2954                         HostCmd_ACT_GEN_GET, SHORT_RETRY_LIM_I, &retry, true);
2955        wiphy->retry_short = (u8) retry;
2956        mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
2957                         HostCmd_ACT_GEN_GET, LONG_RETRY_LIM_I, &retry, true);
2958        wiphy->retry_long = (u8) retry;
2959
2960        adapter->wiphy = wiphy;
2961        return ret;
2962}
2963