linux/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of version 2 of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12 * more details.
  13 *
  14 ******************************************************************************/
  15#define  _IOCTL_CFG80211_C_
  16
  17#include <osdep_service.h>
  18#include <drv_types.h>
  19#include <xmit_osdep.h>
  20
  21#include "ioctl_cfg80211.h"
  22
  23#define RTW_MAX_MGMT_TX_CNT 8
  24
  25#define RTW_MAX_REMAIN_ON_CHANNEL_DURATION 65535        /* ms */
  26#define RTW_MAX_NUM_PMKIDS 4
  27
  28static const u32 rtw_cipher_suites[] = {
  29        WLAN_CIPHER_SUITE_WEP40,
  30        WLAN_CIPHER_SUITE_WEP104,
  31        WLAN_CIPHER_SUITE_TKIP,
  32        WLAN_CIPHER_SUITE_CCMP,
  33};
  34
  35#define RATETAB_ENT(_rate, _rateid, _flags) {                   \
  36        .bitrate        = (_rate),                              \
  37        .hw_value       = (_rateid),                            \
  38        .flags          = (_flags),                             \
  39}
  40
  41#define CHAN2G(_channel, _freq, _flags) {                       \
  42        .band                   = IEEE80211_BAND_2GHZ,          \
  43        .center_freq            = (_freq),                      \
  44        .hw_value               = (_channel),                   \
  45        .flags                  = (_flags),                     \
  46        .max_antenna_gain       = 0,                            \
  47        .max_power              = 30,                           \
  48}
  49
  50#define CHAN5G(_channel, _flags) {                              \
  51        .band                   = IEEE80211_BAND_5GHZ,          \
  52        .center_freq            = 5000 + (5 * (_channel)),      \
  53        .hw_value               = (_channel),                   \
  54        .flags                  = (_flags),                     \
  55        .max_antenna_gain       = 0,                            \
  56        .max_power              = 30,                           \
  57}
  58
  59static struct ieee80211_rate rtw_rates[] = {
  60        RATETAB_ENT(10, 0x1, 0),
  61        RATETAB_ENT(20, 0x2, 0),
  62        RATETAB_ENT(55, 0x4, 0),
  63        RATETAB_ENT(110, 0x8, 0),
  64        RATETAB_ENT(60, 0x10, 0),
  65        RATETAB_ENT(90, 0x20, 0),
  66        RATETAB_ENT(120, 0x40, 0),
  67        RATETAB_ENT(180, 0x80, 0),
  68        RATETAB_ENT(240, 0x100, 0),
  69        RATETAB_ENT(360, 0x200, 0),
  70        RATETAB_ENT(480, 0x400, 0),
  71        RATETAB_ENT(540, 0x800, 0),
  72};
  73
  74#define rtw_a_rates             (rtw_rates + 4)
  75#define RTW_A_RATES_NUM 8
  76#define rtw_g_rates             (rtw_rates + 0)
  77#define RTW_G_RATES_NUM 12
  78
  79#define RTW_2G_CHANNELS_NUM 14
  80#define RTW_5G_CHANNELS_NUM 37
  81
  82static struct ieee80211_channel rtw_2ghz_channels[] = {
  83        CHAN2G(1, 2412, 0),
  84        CHAN2G(2, 2417, 0),
  85        CHAN2G(3, 2422, 0),
  86        CHAN2G(4, 2427, 0),
  87        CHAN2G(5, 2432, 0),
  88        CHAN2G(6, 2437, 0),
  89        CHAN2G(7, 2442, 0),
  90        CHAN2G(8, 2447, 0),
  91        CHAN2G(9, 2452, 0),
  92        CHAN2G(10, 2457, 0),
  93        CHAN2G(11, 2462, 0),
  94        CHAN2G(12, 2467, 0),
  95        CHAN2G(13, 2472, 0),
  96        CHAN2G(14, 2484, 0),
  97};
  98
  99static struct ieee80211_channel rtw_5ghz_a_channels[] = {
 100        CHAN5G(34, 0), CHAN5G(36, 0),
 101        CHAN5G(38, 0), CHAN5G(40, 0),
 102        CHAN5G(42, 0), CHAN5G(44, 0),
 103        CHAN5G(46, 0), CHAN5G(48, 0),
 104        CHAN5G(52, 0), CHAN5G(56, 0),
 105        CHAN5G(60, 0), CHAN5G(64, 0),
 106        CHAN5G(100, 0), CHAN5G(104, 0),
 107        CHAN5G(108, 0), CHAN5G(112, 0),
 108        CHAN5G(116, 0), CHAN5G(120, 0),
 109        CHAN5G(124, 0), CHAN5G(128, 0),
 110        CHAN5G(132, 0), CHAN5G(136, 0),
 111        CHAN5G(140, 0), CHAN5G(149, 0),
 112        CHAN5G(153, 0), CHAN5G(157, 0),
 113        CHAN5G(161, 0), CHAN5G(165, 0),
 114        CHAN5G(184, 0), CHAN5G(188, 0),
 115        CHAN5G(192, 0), CHAN5G(196, 0),
 116        CHAN5G(200, 0), CHAN5G(204, 0),
 117        CHAN5G(208, 0), CHAN5G(212, 0),
 118        CHAN5G(216, 0),
 119};
 120
 121static void rtw_2g_channels_init(struct ieee80211_channel *channels)
 122{
 123        memcpy((void *)channels, (void *)rtw_2ghz_channels,
 124               sizeof(struct ieee80211_channel) * RTW_2G_CHANNELS_NUM);
 125}
 126
 127static void rtw_5g_channels_init(struct ieee80211_channel *channels)
 128{
 129        memcpy((void *)channels, (void *)rtw_5ghz_a_channels,
 130               sizeof(struct ieee80211_channel) * RTW_5G_CHANNELS_NUM);
 131}
 132
 133static void rtw_2g_rates_init(struct ieee80211_rate *rates)
 134{
 135        memcpy(rates, rtw_g_rates,
 136               sizeof(struct ieee80211_rate) * RTW_G_RATES_NUM);
 137}
 138
 139static void rtw_5g_rates_init(struct ieee80211_rate *rates)
 140{
 141        memcpy(rates, rtw_a_rates,
 142               sizeof(struct ieee80211_rate) * RTW_A_RATES_NUM);
 143}
 144
 145static struct ieee80211_supported_band *
 146rtw_spt_band_alloc(enum ieee80211_band band)
 147{
 148        struct ieee80211_supported_band *spt_band = NULL;
 149        int n_channels, n_bitrates;
 150
 151        if (band == IEEE80211_BAND_2GHZ) {
 152                n_channels = RTW_2G_CHANNELS_NUM;
 153                n_bitrates = RTW_G_RATES_NUM;
 154        } else if (band == IEEE80211_BAND_5GHZ) {
 155                n_channels = RTW_5G_CHANNELS_NUM;
 156                n_bitrates = RTW_A_RATES_NUM;
 157        } else {
 158                goto exit;
 159        }
 160        spt_band = kzalloc(sizeof(struct ieee80211_supported_band) +
 161                           sizeof(struct ieee80211_channel) * n_channels +
 162                           sizeof(struct ieee80211_rate) * n_bitrates,
 163                           GFP_KERNEL);
 164        if (!spt_band)
 165                goto exit;
 166
 167        spt_band->channels =
 168                (struct ieee80211_channel *)(((u8 *) spt_band) +
 169                                             sizeof(struct
 170                                                    ieee80211_supported_band));
 171        spt_band->bitrates =
 172                (struct ieee80211_rate *)(((u8 *) spt_band->channels) +
 173                                          sizeof(struct ieee80211_channel) *
 174                                          n_channels);
 175        spt_band->band = band;
 176        spt_band->n_channels = n_channels;
 177        spt_band->n_bitrates = n_bitrates;
 178
 179        if (band == IEEE80211_BAND_2GHZ) {
 180                rtw_2g_channels_init(spt_band->channels);
 181                rtw_2g_rates_init(spt_band->bitrates);
 182        } else if (band == IEEE80211_BAND_5GHZ) {
 183                rtw_5g_channels_init(spt_band->channels);
 184                rtw_5g_rates_init(spt_band->bitrates);
 185        }
 186
 187        /* spt_band.ht_cap */
 188
 189exit:
 190        return spt_band;
 191}
 192
 193static const struct ieee80211_txrx_stypes
 194rtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
 195        [NL80211_IFTYPE_ADHOC] = {
 196                .tx = 0xffff,
 197                .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
 198        },
 199        [NL80211_IFTYPE_STATION] = {
 200                .tx = 0xffff,
 201                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
 202                      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
 203        },
 204        [NL80211_IFTYPE_AP] = {
 205                .tx = 0xffff,
 206                .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
 207                      BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
 208                      BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
 209                      BIT(IEEE80211_STYPE_DISASSOC >> 4) |
 210                      BIT(IEEE80211_STYPE_AUTH >> 4) |
 211                      BIT(IEEE80211_STYPE_DEAUTH >> 4) |
 212                      BIT(IEEE80211_STYPE_ACTION >> 4)
 213        },
 214        [NL80211_IFTYPE_AP_VLAN] = {
 215                /* copy AP */
 216                .tx = 0xffff,
 217                .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
 218                      BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
 219                      BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
 220                      BIT(IEEE80211_STYPE_DISASSOC >> 4) |
 221                      BIT(IEEE80211_STYPE_AUTH >> 4) |
 222                      BIT(IEEE80211_STYPE_DEAUTH >> 4) |
 223                      BIT(IEEE80211_STYPE_ACTION >> 4)
 224        },
 225        [NL80211_IFTYPE_P2P_CLIENT] = {
 226                .tx = 0xffff,
 227                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
 228                      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
 229        },
 230        [NL80211_IFTYPE_P2P_GO] = {
 231                .tx = 0xffff,
 232                .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
 233                      BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
 234                      BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
 235                      BIT(IEEE80211_STYPE_DISASSOC >> 4) |
 236                      BIT(IEEE80211_STYPE_AUTH >> 4) |
 237                      BIT(IEEE80211_STYPE_DEAUTH >> 4) |
 238                      BIT(IEEE80211_STYPE_ACTION >> 4)
 239        },
 240};
 241
 242static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter,
 243                                   struct wlan_network *pnetwork)
 244{
 245        int ret = 0;
 246        struct ieee80211_channel *notify_channel;
 247        struct cfg80211_bss *bss;
 248        u16 channel;
 249        u32 freq;
 250        u8 *notify_ie;
 251        size_t notify_ielen;
 252        s32 notify_signal;
 253        struct wireless_dev *wdev = padapter->rtw_wdev;
 254        struct wiphy *wiphy = wdev->wiphy;
 255        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 256
 257        channel = pnetwork->network.DSConfig;
 258        if (channel <= RTW_CH_MAX_2G_CHANNEL)
 259                freq = ieee80211_channel_to_frequency(channel,
 260                                                      IEEE80211_BAND_2GHZ);
 261        else
 262                freq = ieee80211_channel_to_frequency(channel,
 263                                                      IEEE80211_BAND_5GHZ);
 264
 265        notify_channel = ieee80211_get_channel(wiphy, freq);
 266
 267        notify_ie = pnetwork->network.IEs;
 268        notify_ielen = pnetwork->network.IELength;
 269
 270        /* We've set wiphy's signal_type as CFG80211_SIGNAL_TYPE_MBM:
 271         *  signal strength in mBm (100*dBm)
 272         */
 273        if (check_fwstate(pmlmepriv, _FW_LINKED) &&
 274            is_same_network23a(&pmlmepriv->cur_network.network,
 275                            &pnetwork->network)) {
 276                notify_signal = 100 * translate_percentage_to_dbm(padapter->recvpriv.signal_strength);  /* dbm */
 277        } else {
 278                notify_signal = 100 * translate_percentage_to_dbm(
 279                        pnetwork->network.SignalStrength);      /* dbm */
 280        }
 281
 282        bss = cfg80211_inform_bss(wiphy, notify_channel,
 283                                  CFG80211_BSS_FTYPE_UNKNOWN,
 284                                  pnetwork->network.MacAddress,
 285                                  pnetwork->network.tsf,
 286                                  pnetwork->network.capability,
 287                                  pnetwork->network.beacon_interval,
 288                                  notify_ie, notify_ielen,
 289                                  notify_signal, GFP_ATOMIC);
 290
 291        if (unlikely(!bss)) {
 292                DBG_8723A("rtw_cfg80211_inform_bss error\n");
 293                return -EINVAL;
 294        }
 295
 296        cfg80211_put_bss(wiphy, bss);
 297
 298        return ret;
 299}
 300
 301void rtw_cfg80211_indicate_connect(struct rtw_adapter *padapter)
 302{
 303        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 304        struct wlan_network *cur_network = &pmlmepriv->cur_network;
 305        struct wireless_dev *pwdev = padapter->rtw_wdev;
 306
 307        DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
 308
 309        if (pwdev->iftype != NL80211_IFTYPE_STATION &&
 310            pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
 311                return;
 312
 313        if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
 314                return;
 315
 316        if (padapter->mlmepriv.to_roaming > 0) {
 317                struct wiphy *wiphy = pwdev->wiphy;
 318                struct ieee80211_channel *notify_channel;
 319                u32 freq;
 320                u16 channel = cur_network->network.DSConfig;
 321
 322                if (channel <= RTW_CH_MAX_2G_CHANNEL)
 323                        freq =
 324                            ieee80211_channel_to_frequency(channel,
 325                                                           IEEE80211_BAND_2GHZ);
 326                else
 327                        freq =
 328                            ieee80211_channel_to_frequency(channel,
 329                                                           IEEE80211_BAND_5GHZ);
 330
 331                notify_channel = ieee80211_get_channel(wiphy, freq);
 332
 333                DBG_8723A("%s call cfg80211_roamed\n", __func__);
 334                cfg80211_roamed(padapter->pnetdev, notify_channel,
 335                                cur_network->network.MacAddress,
 336                                pmlmepriv->assoc_req +
 337                                sizeof(struct ieee80211_hdr_3addr) + 2,
 338                                pmlmepriv->assoc_req_len -
 339                                sizeof(struct ieee80211_hdr_3addr) - 2,
 340                                pmlmepriv->assoc_rsp +
 341                                sizeof(struct ieee80211_hdr_3addr) + 6,
 342                                pmlmepriv->assoc_rsp_len -
 343                                sizeof(struct ieee80211_hdr_3addr) - 6,
 344                                GFP_ATOMIC);
 345        } else {
 346                cfg80211_connect_result(padapter->pnetdev,
 347                                        cur_network->network.MacAddress,
 348                                        pmlmepriv->assoc_req +
 349                                        sizeof(struct ieee80211_hdr_3addr) + 2,
 350                                        pmlmepriv->assoc_req_len -
 351                                        sizeof(struct ieee80211_hdr_3addr) - 2,
 352                                        pmlmepriv->assoc_rsp +
 353                                        sizeof(struct ieee80211_hdr_3addr) + 6,
 354                                        pmlmepriv->assoc_rsp_len -
 355                                        sizeof(struct ieee80211_hdr_3addr) - 6,
 356                                        WLAN_STATUS_SUCCESS, GFP_ATOMIC);
 357        }
 358}
 359
 360void rtw_cfg80211_indicate_disconnect(struct rtw_adapter *padapter)
 361{
 362        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 363        struct wireless_dev *pwdev = padapter->rtw_wdev;
 364
 365        DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
 366
 367        if (pwdev->iftype != NL80211_IFTYPE_STATION &&
 368            pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
 369                return;
 370
 371        if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
 372                return;
 373
 374        if (!padapter->mlmepriv.not_indic_disco) {
 375                if (check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING)) {
 376                        cfg80211_connect_result(padapter->pnetdev, NULL, NULL,
 377                                                0, NULL, 0,
 378                                                WLAN_STATUS_UNSPECIFIED_FAILURE,
 379                                                GFP_ATOMIC);
 380                } else {
 381                        cfg80211_disconnected(padapter->pnetdev, 0, NULL,
 382                                              0, false, GFP_ATOMIC);
 383                }
 384        }
 385}
 386
 387#ifdef CONFIG_8723AU_AP_MODE
 388static int set_pairwise_key(struct rtw_adapter *padapter, struct sta_info *psta)
 389{
 390        struct cmd_obj *ph2c;
 391        struct set_stakey_parm *psetstakey_para;
 392        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 393        int res = _SUCCESS;
 394
 395        ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 396        if (ph2c == NULL) {
 397                res = _FAIL;
 398                goto exit;
 399        }
 400
 401        psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
 402        if (psetstakey_para == NULL) {
 403                kfree(ph2c);
 404                res = _FAIL;
 405                goto exit;
 406        }
 407
 408        init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
 409
 410        psetstakey_para->algorithm = psta->dot118021XPrivacy;
 411
 412        ether_addr_copy(psetstakey_para->addr, psta->hwaddr);
 413
 414        memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
 415
 416        res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
 417
 418exit:
 419        return res;
 420}
 421
 422static int set_group_key(struct rtw_adapter *padapter, struct key_params *parms,
 423                         u32 alg, u8 keyid)
 424{
 425        struct cmd_obj *pcmd;
 426        struct setkey_parm *psetkeyparm;
 427        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 428        int res = _SUCCESS;
 429
 430        DBG_8723A("%s\n", __func__);
 431
 432        if (keyid >= 4) {
 433                res = _FAIL;
 434                goto exit;
 435        }
 436
 437        pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
 438        if (!pcmd) {
 439                res = _FAIL;
 440                goto exit;
 441        }
 442        psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
 443        if (!psetkeyparm) {
 444                kfree(pcmd);
 445                res = _FAIL;
 446                goto exit;
 447        }
 448
 449        psetkeyparm->keyid = keyid;
 450        if (is_wep_enc(alg))
 451                padapter->mlmepriv.key_mask |= BIT(psetkeyparm->keyid);
 452
 453        psetkeyparm->algorithm = alg;
 454
 455        psetkeyparm->set_tx = 1;
 456
 457        memcpy(&psetkeyparm->key, parms->key, parms->key_len);
 458
 459        pcmd->cmdcode = _SetKey_CMD_;
 460        pcmd->parmbuf = (u8 *) psetkeyparm;
 461        pcmd->cmdsz = (sizeof(struct setkey_parm));
 462        pcmd->rsp = NULL;
 463        pcmd->rspsz = 0;
 464
 465        res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
 466
 467exit:
 468        return res;
 469}
 470
 471static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, u8 key_index,
 472                                          int set_tx, const u8 *sta_addr,
 473                                          struct key_params *keyparms)
 474{
 475        int key_len;
 476        struct sta_info *psta = NULL, *pbcmc_sta = NULL;
 477        struct rtw_adapter *padapter = netdev_priv(dev);
 478        struct security_priv *psecuritypriv = &padapter->securitypriv;
 479        struct sta_priv *pstapriv = &padapter->stapriv;
 480
 481        DBG_8723A("%s\n", __func__);
 482
 483        if (!is_broadcast_ether_addr(sta_addr)) {
 484                psta = rtw_get_stainfo23a(pstapriv, sta_addr);
 485                if (!psta) {
 486                        /* ret = -EINVAL; */
 487                        DBG_8723A("rtw_set_encryption(), sta has already "
 488                                  "been removed or never been added\n");
 489                        goto exit;
 490                }
 491        }
 492
 493        key_len = keyparms->key_len;
 494
 495        if (!psta && (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
 496                      keyparms->cipher == WLAN_CIPHER_SUITE_WEP104)) {
 497                DBG_8723A("r871x_set_encryption, crypt.alg = WEP\n");
 498
 499                DBG_8723A("r871x_set_encryption, wep_key_idx =%d, len =%d\n",
 500                          key_index, key_len);
 501
 502                if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
 503                        /* wep default key has not been set, so use
 504                           this key index as default key. */
 505
 506                        psecuritypriv->ndisencryptstatus =
 507                                Ndis802_11Encryption1Enabled;
 508                        psecuritypriv->dot11PrivacyAlgrthm = keyparms->cipher;
 509                        psecuritypriv->dot118021XGrpPrivacy = keyparms->cipher;
 510
 511                        psecuritypriv->dot11PrivacyKeyIndex = key_index;
 512                }
 513
 514                memcpy(&psecuritypriv->wep_key[key_index].key,
 515                       keyparms->key, key_len);
 516
 517                psecuritypriv->wep_key[key_index].keylen = key_len;
 518
 519                set_group_key(padapter, keyparms, keyparms->cipher, key_index);
 520
 521                goto exit;
 522        }
 523
 524        if (!psta) {    /*  group key */
 525                if (set_tx == 0) {      /* group key */
 526                        if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
 527                            keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) {
 528                                DBG_8723A("%s, set group_key, WEP\n", __func__);
 529
 530                                memcpy(psecuritypriv->
 531                                       dot118021XGrpKey[key_index].skey,
 532                                       keyparms->key, key_len);
 533
 534                                psecuritypriv->dot118021XGrpPrivacy =
 535                                        keyparms->cipher;
 536                        } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) {
 537                                DBG_8723A("%s, set group_key, TKIP\n",
 538                                          __func__);
 539
 540                                psecuritypriv->dot118021XGrpPrivacy =
 541                                        WLAN_CIPHER_SUITE_TKIP;
 542
 543                                memcpy(psecuritypriv->
 544                                       dot118021XGrpKey[key_index].skey,
 545                                       keyparms->key,
 546                                       (key_len > 16 ? 16 : key_len));
 547
 548                                /* set mic key */
 549                                memcpy(psecuritypriv->
 550                                       dot118021XGrptxmickey[key_index].skey,
 551                                       &keyparms->key[16], 8);
 552                                memcpy(psecuritypriv->
 553                                       dot118021XGrprxmickey[key_index].skey,
 554                                       &keyparms->key[24], 8);
 555
 556                                psecuritypriv->busetkipkey = 1;
 557
 558                        } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) {
 559                                        DBG_8723A("%s, set group_key, CCMP\n",
 560                                          __func__);
 561
 562                                psecuritypriv->dot118021XGrpPrivacy =
 563                                        WLAN_CIPHER_SUITE_CCMP;
 564
 565                                memcpy(psecuritypriv->
 566                                       dot118021XGrpKey[key_index].skey,
 567                                       keyparms->key,
 568                                       (key_len > 16 ? 16 : key_len));
 569                        } else {
 570                                DBG_8723A("%s, set group_key, none\n",
 571                                          __func__);
 572
 573                                psecuritypriv->dot118021XGrpPrivacy = 0;
 574                        }
 575
 576                        psecuritypriv->dot118021XGrpKeyid = key_index;
 577
 578                        psecuritypriv->binstallGrpkey = 1;
 579
 580                        psecuritypriv->dot11PrivacyAlgrthm =
 581                                psecuritypriv->dot118021XGrpPrivacy;
 582
 583                        set_group_key(padapter, keyparms,
 584                                      psecuritypriv->dot118021XGrpPrivacy,
 585                                      key_index);
 586
 587                        pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
 588                        if (pbcmc_sta) {
 589                                pbcmc_sta->ieee8021x_blocked = false;
 590                                /* rx will use bmc_sta's dot118021XPrivacy */
 591                                pbcmc_sta->dot118021XPrivacy =
 592                                        psecuritypriv->dot118021XGrpPrivacy;
 593
 594                        }
 595
 596                }
 597
 598                goto exit;
 599        }
 600
 601        if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) {
 602                /*  psk/802_1x */
 603                if (set_tx == 1) {
 604                        /* pairwise key */
 605                        memcpy(psta->dot118021x_UncstKey.skey,
 606                               keyparms->key, (key_len > 16 ? 16 : key_len));
 607
 608                        if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
 609                            keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) {
 610                                DBG_8723A("%s, set pairwise key, WEP\n",
 611                                          __func__);
 612
 613                                psecuritypriv->dot118021XGrpPrivacy =
 614                                        keyparms->cipher;
 615                        } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) {
 616                                DBG_8723A("%s, set pairwise key, TKIP\n",
 617                                          __func__);
 618
 619                                psta->dot118021XPrivacy =
 620                                        WLAN_CIPHER_SUITE_TKIP;
 621
 622                                /* set mic key */
 623                                memcpy(psta->dot11tkiptxmickey.skey,
 624                                       &keyparms->key[16], 8);
 625                                memcpy(psta->dot11tkiprxmickey.skey,
 626                                       &keyparms->key[24], 8);
 627
 628                                psecuritypriv->busetkipkey = 1;
 629
 630                        } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) {
 631                                DBG_8723A("%s, set pairwise key, CCMP\n",
 632                                          __func__);
 633
 634                                psta->dot118021XPrivacy =
 635                                        WLAN_CIPHER_SUITE_CCMP;
 636                        } else {
 637                                DBG_8723A("%s, set pairwise key, none\n",
 638                                          __func__);
 639
 640                                psta->dot118021XPrivacy = 0;
 641                        }
 642
 643                        set_pairwise_key(padapter, psta);
 644
 645                        psta->ieee8021x_blocked = false;
 646
 647                        psta->bpairwise_key_installed = true;
 648                } else {        /* group key??? */
 649                        if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
 650                            keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) {
 651                                memcpy(psecuritypriv->
 652                                       dot118021XGrpKey[key_index].skey,
 653                                       keyparms->key, key_len);
 654
 655                                psecuritypriv->dot118021XGrpPrivacy =
 656                                        keyparms->cipher;
 657                        } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) {
 658                                psecuritypriv->dot118021XGrpPrivacy =
 659                                        WLAN_CIPHER_SUITE_TKIP;
 660
 661                                memcpy(psecuritypriv->
 662                                       dot118021XGrpKey[key_index].skey,
 663                                       keyparms->key,
 664                                       (key_len > 16 ? 16 : key_len));
 665
 666                                /* set mic key */
 667                                memcpy(psecuritypriv->
 668                                       dot118021XGrptxmickey[key_index].skey,
 669                                       &keyparms->key[16], 8);
 670                                memcpy(psecuritypriv->
 671                                       dot118021XGrprxmickey[key_index].skey,
 672                                       &keyparms->key[24], 8);
 673
 674                                psecuritypriv->busetkipkey = 1;
 675                        } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) {
 676                                psecuritypriv->dot118021XGrpPrivacy =
 677                                        WLAN_CIPHER_SUITE_CCMP;
 678
 679                                memcpy(psecuritypriv->
 680                                       dot118021XGrpKey[key_index].skey,
 681                                       keyparms->key,
 682                                       (key_len > 16 ? 16 : key_len));
 683                        } else {
 684                                psecuritypriv->dot118021XGrpPrivacy = 0;
 685                        }
 686
 687                        psecuritypriv->dot118021XGrpKeyid = key_index;
 688
 689                        psecuritypriv->binstallGrpkey = 1;
 690
 691                        psecuritypriv->dot11PrivacyAlgrthm =
 692                                psecuritypriv->dot118021XGrpPrivacy;
 693
 694                        set_group_key(padapter, keyparms,
 695                                      psecuritypriv->dot118021XGrpPrivacy,
 696                                      key_index);
 697
 698                        pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
 699                        if (pbcmc_sta) {
 700                                /* rx will use bmc_sta's
 701                                   dot118021XPrivacy */
 702                                pbcmc_sta->ieee8021x_blocked = false;
 703                                pbcmc_sta->dot118021XPrivacy =
 704                                        psecuritypriv->dot118021XGrpPrivacy;
 705                        }
 706                }
 707        }
 708
 709exit:
 710
 711        return 0;
 712}
 713#endif
 714
 715static int rtw_cfg80211_set_encryption(struct net_device *dev, u8 key_index,
 716                                       int set_tx, const u8 *sta_addr,
 717                                       struct key_params *keyparms)
 718{
 719        int ret = 0;
 720        int key_len;
 721        struct rtw_adapter *padapter = netdev_priv(dev);
 722        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 723        struct security_priv *psecuritypriv = &padapter->securitypriv;
 724
 725        DBG_8723A("%s\n", __func__);
 726
 727        key_len = keyparms->key_len;
 728
 729        if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
 730            keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) {
 731                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
 732                         "wpa_set_encryption, crypt.alg = WEP\n");
 733                DBG_8723A("wpa_set_encryption, crypt.alg = WEP\n");
 734
 735                if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
 736                        /* wep default key has not been set, so use this
 737                           key index as default key. */
 738
 739                        psecuritypriv->ndisencryptstatus =
 740                                Ndis802_11Encryption1Enabled;
 741                        psecuritypriv->dot11PrivacyAlgrthm = keyparms->cipher;
 742                        psecuritypriv->dot118021XGrpPrivacy = keyparms->cipher;
 743
 744                        psecuritypriv->dot11PrivacyKeyIndex = key_index;
 745                }
 746
 747                memcpy(&psecuritypriv->wep_key[key_index].key,
 748                       keyparms->key, key_len);
 749
 750                psecuritypriv->wep_key[key_index].keylen = key_len;
 751
 752                rtw_set_key23a(padapter, psecuritypriv, key_index, 0);
 753
 754                goto exit;
 755        }
 756
 757        if (padapter->securitypriv.dot11AuthAlgrthm ==
 758            dot11AuthAlgrthm_8021X) {   /*  802_1x */
 759                struct sta_info *psta, *pbcmc_sta;
 760                struct sta_priv *pstapriv = &padapter->stapriv;
 761
 762                if (check_fwstate(pmlmepriv,
 763                                  WIFI_STATION_STATE | WIFI_MP_STATE)) {
 764                        /* sta mode */
 765                        psta = rtw_get_stainfo23a(pstapriv, get_bssid(pmlmepriv));
 766                        if (psta == NULL) {
 767                                DBG_8723A("%s, : Obtain Sta_info fail\n",
 768                                          __func__);
 769                        } else {
 770                                /* Jeff: don't disable ieee8021x_blocked
 771                                   while clearing key */
 772                                if (keyparms->cipher != IW_AUTH_CIPHER_NONE &&
 773                                    keyparms->cipher != 0)
 774                                        psta->ieee8021x_blocked = false;
 775
 776                                if ((padapter->securitypriv.ndisencryptstatus ==
 777                                     Ndis802_11Encryption2Enabled) ||
 778                                    (padapter->securitypriv.ndisencryptstatus ==
 779                                     Ndis802_11Encryption3Enabled)) {
 780                                        psta->dot118021XPrivacy =
 781                                                padapter->securitypriv.
 782                                                dot11PrivacyAlgrthm;
 783                                }
 784
 785                                if (set_tx == 1) {
 786                                        /* pairwise key */
 787                                        DBG_8723A("%s, : set_tx == 1\n",
 788                                                  __func__);
 789
 790                                        memcpy(psta->dot118021x_UncstKey.skey,
 791                                               keyparms->key,
 792                                               (key_len > 16 ? 16 : key_len));
 793
 794                                        if (keyparms->cipher ==
 795                                            WLAN_CIPHER_SUITE_TKIP) {
 796                                                memcpy(psta->dot11tkiptxmickey.
 797                                                       skey,
 798                                                       &keyparms->key[16], 8);
 799                                                memcpy(psta->dot11tkiprxmickey.
 800                                                       skey,
 801                                                       &keyparms->key[24], 8);
 802
 803                                                padapter->securitypriv.
 804                                                        busetkipkey = 0;
 805                                        }
 806                                        DBG_8723A(" ~~~~set sta key:unicastkey\n");
 807
 808                                        rtw_setstakey_cmd23a(padapter,
 809                                                          (unsigned char *)psta,
 810                                                          true);
 811                                } else {        /* group key */
 812                                        memcpy(padapter->securitypriv.
 813                                               dot118021XGrpKey[key_index].skey,
 814                                               keyparms->key,
 815                                               (key_len > 16 ? 16 : key_len));
 816                                        memcpy(padapter->securitypriv.
 817                                               dot118021XGrptxmickey[key_index].
 818                                               skey, &keyparms->key[16], 8);
 819                                        memcpy(padapter->securitypriv.
 820                                               dot118021XGrprxmickey[key_index].
 821                                               skey, &keyparms->key[24], 8);
 822                                        padapter->securitypriv.binstallGrpkey =
 823                                                1;
 824                                        DBG_8723A
 825                                            (" ~~~~set sta key:groupkey\n");
 826
 827                                        padapter->securitypriv.
 828                                            dot118021XGrpKeyid = key_index;
 829
 830                                        rtw_set_key23a(padapter,
 831                                                    &padapter->securitypriv,
 832                                                    key_index, 1);
 833                                }
 834                        }
 835
 836                        pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
 837                        if (pbcmc_sta) {
 838                                /* Jeff: don't disable ieee8021x_blocked
 839                                   while clearing key */
 840                                if (keyparms->cipher != IW_AUTH_CIPHER_NONE &&
 841                                    keyparms->cipher != 0)
 842                                        pbcmc_sta->ieee8021x_blocked = false;
 843
 844                                if ((padapter->securitypriv.ndisencryptstatus ==
 845                                     Ndis802_11Encryption2Enabled) ||
 846                                    (padapter->securitypriv.ndisencryptstatus ==
 847                                     Ndis802_11Encryption3Enabled)) {
 848                                        pbcmc_sta->dot118021XPrivacy =
 849                                            padapter->securitypriv.
 850                                            dot11PrivacyAlgrthm;
 851                                }
 852                        }
 853                }
 854        }
 855
 856exit:
 857
 858        DBG_8723A("%s, ret =%d\n", __func__, ret);
 859
 860
 861
 862        return ret;
 863}
 864
 865static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev,
 866                                u8 key_index, bool pairwise,
 867                                const u8 *mac_addr, struct key_params *params)
 868{
 869        int set_tx, ret = 0;
 870        struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
 871        struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
 872        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 873        u8 sta_addr[ETH_ALEN];
 874
 875        DBG_8723A("%s(%s): adding key for %pM\n", __func__, ndev->name,
 876                  mac_addr);
 877        DBG_8723A("cipher = 0x%x\n", params->cipher);
 878        DBG_8723A("key_len = 0x%x\n", params->key_len);
 879        DBG_8723A("seq_len = 0x%x\n", params->seq_len);
 880        DBG_8723A("key_index =%d\n", key_index);
 881        DBG_8723A("pairwise =%d\n", pairwise);
 882
 883        switch (params->cipher) {
 884        case IW_AUTH_CIPHER_NONE:
 885        case WLAN_CIPHER_SUITE_WEP40:
 886                if (params->key_len != WLAN_KEY_LEN_WEP40) {
 887                        ret = -EINVAL;
 888                        goto exit;
 889                }
 890        case WLAN_CIPHER_SUITE_WEP104:
 891                if (params->key_len != WLAN_KEY_LEN_WEP104) {
 892                        ret = -EINVAL;
 893                        goto exit;
 894                }
 895        case WLAN_CIPHER_SUITE_TKIP:
 896        case WLAN_CIPHER_SUITE_CCMP:
 897                break;
 898        default:
 899                ret = -ENOTSUPP;
 900                goto exit;
 901        }
 902
 903        if (key_index >= WEP_KEYS || params->key_len < 0) {
 904                ret = -EINVAL;
 905                goto exit;
 906        }
 907
 908        eth_broadcast_addr(sta_addr);
 909
 910        if (!mac_addr || is_broadcast_ether_addr(mac_addr))
 911                set_tx = 0;     /* for wpa/wpa2 group key */
 912        else
 913                set_tx = 1;     /* for wpa/wpa2 pairwise key */
 914
 915        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
 916                ret = rtw_cfg80211_set_encryption(ndev, key_index, set_tx,
 917                                                  sta_addr, params);
 918        } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
 919#ifdef CONFIG_8723AU_AP_MODE
 920                if (mac_addr)
 921                        ether_addr_copy(sta_addr, mac_addr);
 922
 923                ret = rtw_cfg80211_ap_set_encryption(ndev, key_index, set_tx,
 924                                                     sta_addr, params);
 925#endif
 926        } else {
 927                DBG_8723A("error! fw_state = 0x%x, iftype =%d\n",
 928                          pmlmepriv->fw_state, rtw_wdev->iftype);
 929
 930        }
 931
 932exit:
 933        return ret;
 934}
 935
 936static int
 937cfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev,
 938                     u8 key_index, bool pairwise, const u8 *mac_addr,
 939                     void *cookie,
 940                     void (*callback) (void *cookie, struct key_params *))
 941{
 942        DBG_8723A("%s(%s)\n", __func__, ndev->name);
 943        return 0;
 944}
 945
 946static int cfg80211_rtw_del_key(struct wiphy *wiphy, struct net_device *ndev,
 947                                u8 key_index, bool pairwise,
 948                                const u8 *mac_addr)
 949{
 950        struct rtw_adapter *padapter = netdev_priv(ndev);
 951        struct security_priv *psecuritypriv = &padapter->securitypriv;
 952
 953        DBG_8723A("%s(%s): key_index =%d\n", __func__, ndev->name, key_index);
 954
 955        if (key_index == psecuritypriv->dot11PrivacyKeyIndex) {
 956                /* clear the flag of wep default key set. */
 957                psecuritypriv->bWepDefaultKeyIdxSet = 0;
 958        }
 959
 960        return 0;
 961}
 962
 963static int cfg80211_rtw_set_default_key(struct wiphy *wiphy,
 964                                        struct net_device *ndev, u8 key_index,
 965                                        bool unicast, bool multicast)
 966{
 967        struct rtw_adapter *padapter = netdev_priv(ndev);
 968        struct security_priv *psecuritypriv = &padapter->securitypriv;
 969
 970        DBG_8723A("%s(%s): key_index =%d, unicast =%d, multicast =%d.\n",
 971                  __func__, ndev->name, key_index, unicast, multicast);
 972
 973        if (key_index < NUM_WEP_KEYS &&
 974            (psecuritypriv->dot11PrivacyAlgrthm == WLAN_CIPHER_SUITE_WEP40 ||
 975             psecuritypriv->dot11PrivacyAlgrthm == WLAN_CIPHER_SUITE_WEP104)) {
 976                /* set wep default key */
 977                psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
 978
 979                psecuritypriv->dot11PrivacyKeyIndex = key_index;
 980
 981                psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
 982                psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40;
 983                if (psecuritypriv->wep_key[key_index].keylen == 13) {
 984                        psecuritypriv->dot11PrivacyAlgrthm =
 985                                WLAN_CIPHER_SUITE_WEP104;
 986                        psecuritypriv->dot118021XGrpPrivacy =
 987                                WLAN_CIPHER_SUITE_WEP104;
 988                }
 989
 990                /* set the flag to represent that wep default key
 991                   has been set */
 992                psecuritypriv->bWepDefaultKeyIdxSet = 1;
 993        }
 994
 995        return 0;
 996}
 997
 998static u16 rtw_get_cur_max_rate(struct rtw_adapter *adapter)
 999{
1000        int i = 0;
1001        const u8 *p;
1002        u16 rate = 0, max_rate = 0;
1003        struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
1004        struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1005        struct registry_priv *pregistrypriv = &adapter->registrypriv;
1006        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1007        struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
1008        struct ieee80211_ht_cap *pht_capie;
1009        u8 rf_type = 0;
1010        u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0;
1011        u16 mcs_rate = 0;
1012
1013        p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
1014                             pcur_bss->IEs, pcur_bss->IELength);
1015        if (p && p[1] > 0) {
1016                pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1017
1018                memcpy(&mcs_rate, &pht_capie->mcs, 2);
1019
1020                /* bw_40MHz = (pht_capie->cap_info&
1021                   IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1:0; */
1022                /* cur_bwmod is updated by beacon, pmlmeinfo is
1023                   updated by association response */
1024                bw_40MHz = (pmlmeext->cur_bwmode &&
1025                            (pmlmeinfo->HT_info.ht_param &
1026                             IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) ? 1:0;
1027
1028                /* short_GI = (pht_capie->cap_info & (IEEE80211_HT_CAP
1029                   _SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; */
1030                short_GI_20 = (pmlmeinfo->ht_cap.cap_info &
1031                               cpu_to_le16(IEEE80211_HT_CAP_SGI_20)) ? 1:0;
1032                short_GI_40 = (pmlmeinfo->ht_cap.cap_info &
1033                               cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) ? 1:0;
1034
1035                rf_type = rtl8723a_get_rf_type(adapter);
1036                max_rate = rtw_mcs_rate23a(rf_type, bw_40MHz &
1037                                           pregistrypriv->cbw40_enable,
1038                                           short_GI_20, short_GI_40,
1039                                           &pmlmeinfo->ht_cap.mcs);
1040        } else {
1041                while (pcur_bss->SupportedRates[i] != 0 &&
1042                       pcur_bss->SupportedRates[i] != 0xFF) {
1043                        rate = pcur_bss->SupportedRates[i] & 0x7F;
1044                        if (rate > max_rate)
1045                                max_rate = rate;
1046                        i++;
1047                }
1048
1049                max_rate = max_rate * 10 / 2;
1050        }
1051
1052        return max_rate;
1053}
1054
1055static int cfg80211_rtw_get_station(struct wiphy *wiphy,
1056                                    struct net_device *ndev,
1057                                    const u8 *mac, struct station_info *sinfo)
1058{
1059        int ret = 0;
1060        struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1061        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1062        struct sta_info *psta = NULL;
1063        struct sta_priv *pstapriv = &padapter->stapriv;
1064
1065        sinfo->filled = 0;
1066
1067        if (!mac) {
1068                DBG_8723A("%s(%s): mac ==%p\n", __func__, ndev->name, mac);
1069                ret = -ENOENT;
1070                goto exit;
1071        }
1072
1073        psta = rtw_get_stainfo23a(pstapriv, mac);
1074        if (psta == NULL) {
1075                DBG_8723A("%s, sta_info is null\n", __func__);
1076                ret = -ENOENT;
1077                goto exit;
1078        }
1079        DBG_8723A("%s(%s): mac=%pM\n", __func__, ndev->name, mac);
1080
1081        /* for infra./P2PClient mode */
1082        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
1083            check_fwstate(pmlmepriv, _FW_LINKED)) {
1084                struct wlan_network *cur_network = &pmlmepriv->cur_network;
1085
1086                if (!ether_addr_equal(mac, cur_network->network.MacAddress)) {
1087                        DBG_8723A("%s, mismatch bssid=%pM\n",
1088                                  __func__, cur_network->network.MacAddress);
1089                        ret = -ENOENT;
1090                        goto exit;
1091                }
1092
1093                sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
1094                sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv.
1095                                                            signal_strength);
1096
1097                sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
1098                sinfo->txrate.legacy = rtw_get_cur_max_rate(padapter);
1099
1100                sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS);
1101                sinfo->rx_packets = sta_rx_data_pkts(psta);
1102
1103                sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS);
1104                sinfo->tx_packets = psta->sta_stats.tx_pkts;
1105        }
1106
1107        /* for Ad-Hoc/AP mode */
1108        if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
1109             check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1110             check_fwstate(pmlmepriv, WIFI_AP_STATE)) &&
1111            check_fwstate(pmlmepriv, _FW_LINKED)
1112            ) {
1113                /* TODO: should acquire station info... */
1114        }
1115
1116exit:
1117        return ret;
1118}
1119
1120static int cfg80211_infrastructure_mode(struct rtw_adapter *padapter,
1121                                 enum nl80211_iftype ifmode)
1122{
1123        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1124        struct wlan_network *cur_network = &pmlmepriv->cur_network;
1125        enum nl80211_iftype old_mode;
1126
1127        old_mode = cur_network->network.ifmode;
1128
1129        RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_,
1130                 "+%s: old =%d new =%d fw_state = 0x%08x\n", __func__,
1131                 old_mode, ifmode, get_fwstate(pmlmepriv));
1132
1133        if (old_mode != ifmode) {
1134                spin_lock_bh(&pmlmepriv->lock);
1135
1136                RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1137                         "change mode!\n");
1138
1139                if (old_mode == NL80211_IFTYPE_AP ||
1140                    old_mode == NL80211_IFTYPE_P2P_GO) {
1141                        /* change to other mode from Ndis802_11APMode */
1142                        cur_network->join_res = -1;
1143
1144#ifdef CONFIG_8723AU_AP_MODE
1145                        stop_ap_mode23a(padapter);
1146#endif
1147                }
1148
1149                if (check_fwstate(pmlmepriv, _FW_LINKED) ||
1150                    old_mode == NL80211_IFTYPE_ADHOC)
1151                        rtw_disassoc_cmd23a(padapter, 0, true);
1152
1153                if (check_fwstate(pmlmepriv, _FW_LINKED) ||
1154                    check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
1155                        rtw_free_assoc_resources23a(padapter, 1);
1156
1157                if (old_mode == NL80211_IFTYPE_STATION ||
1158                    old_mode == NL80211_IFTYPE_P2P_CLIENT ||
1159                    old_mode == NL80211_IFTYPE_ADHOC) {
1160                        if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1161                                /* will clr Linked_state; before this function,
1162                                   we must have chked whether issue
1163                                   dis-assoc_cmd or not */
1164                                rtw_indicate_disconnect23a(padapter);
1165                        }
1166               }
1167
1168                cur_network->network.ifmode = ifmode;
1169
1170                _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
1171
1172                switch (ifmode) {
1173                case NL80211_IFTYPE_ADHOC:
1174                        set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
1175                        break;
1176
1177                case NL80211_IFTYPE_P2P_CLIENT:
1178                case NL80211_IFTYPE_STATION:
1179                        set_fwstate(pmlmepriv, WIFI_STATION_STATE);
1180                        break;
1181
1182                case NL80211_IFTYPE_P2P_GO:
1183                case NL80211_IFTYPE_AP:
1184                        set_fwstate(pmlmepriv, WIFI_AP_STATE);
1185#ifdef CONFIG_8723AU_AP_MODE
1186                        start_ap_mode23a(padapter);
1187                        /* rtw_indicate_connect23a(padapter); */
1188#endif
1189                        break;
1190
1191                default:
1192                        break;
1193                }
1194
1195                /* SecClearAllKeys(adapter); */
1196
1197                spin_unlock_bh(&pmlmepriv->lock);
1198        }
1199
1200        return _SUCCESS;
1201}
1202
1203static int cfg80211_rtw_change_iface(struct wiphy *wiphy,
1204                                     struct net_device *ndev,
1205                                     enum nl80211_iftype type, u32 *flags,
1206                                     struct vif_params *params)
1207{
1208        enum nl80211_iftype old_type;
1209        struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1210        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1211        struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
1212        int ret = 0;
1213
1214        DBG_8723A("%s(%s): call netdev_open23a\n", __func__, ndev->name);
1215
1216        old_type = rtw_wdev->iftype;
1217        DBG_8723A("%s(%s): old_iftype =%d, new_iftype =%d\n",
1218                  __func__, ndev->name, old_type, type);
1219
1220        if (old_type != type) {
1221                pmlmeext->action_public_rxseq = 0xffff;
1222                pmlmeext->action_public_dialog_token = 0xff;
1223        }
1224
1225        switch (type) {
1226        case NL80211_IFTYPE_ADHOC:
1227        case NL80211_IFTYPE_P2P_CLIENT:
1228        case NL80211_IFTYPE_STATION:
1229        case NL80211_IFTYPE_P2P_GO:
1230        case NL80211_IFTYPE_AP:
1231        case NL80211_IFTYPE_UNSPECIFIED:
1232                break;
1233        default:
1234                return -EOPNOTSUPP;
1235        }
1236
1237        rtw_wdev->iftype = type;
1238
1239        if (cfg80211_infrastructure_mode(padapter, type) != _SUCCESS) {
1240                rtw_wdev->iftype = old_type;
1241                ret = -EPERM;
1242                goto exit;
1243        }
1244
1245        rtw_setopmode_cmd23a(padapter, type);
1246
1247exit:
1248        return ret;
1249}
1250
1251void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv,
1252                                     bool aborted)
1253{
1254        spin_lock_bh(&pwdev_priv->scan_req_lock);
1255        if (pwdev_priv->scan_request != NULL) {
1256                DBG_8723A("%s with scan req\n", __func__);
1257
1258                if (pwdev_priv->scan_request->wiphy !=
1259                    pwdev_priv->rtw_wdev->wiphy)
1260                        DBG_8723A("error wiphy compare\n");
1261                else
1262                        cfg80211_scan_done(pwdev_priv->scan_request, aborted);
1263
1264                pwdev_priv->scan_request = NULL;
1265        } else {
1266                DBG_8723A("%s without scan req\n", __func__);
1267        }
1268        spin_unlock_bh(&pwdev_priv->scan_req_lock);
1269}
1270
1271void rtw_cfg80211_surveydone_event_callback(struct rtw_adapter *padapter)
1272{
1273        struct list_head *plist, *phead, *ptmp;
1274        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1275        struct rtw_queue *queue = &pmlmepriv->scanned_queue;
1276        struct wlan_network *pnetwork;
1277
1278        spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1279
1280        phead = get_list_head(queue);
1281
1282        list_for_each_safe(plist, ptmp, phead) {
1283                pnetwork = container_of(plist, struct wlan_network, list);
1284
1285                /* report network only if the current channel set
1286                   contains the channel to which this network belongs */
1287                if (rtw_ch_set_search_ch23a
1288                    (padapter->mlmeextpriv.channel_set,
1289                     pnetwork->network.DSConfig) >= 0)
1290                        rtw_cfg80211_inform_bss(padapter, pnetwork);
1291        }
1292
1293        spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1294
1295        /* call this after other things have been done */
1296        rtw_cfg80211_indicate_scan_done(wdev_to_priv(padapter->rtw_wdev),
1297                                        false);
1298}
1299
1300static int rtw_cfg80211_set_probe_req_wpsp2pie(struct rtw_adapter *padapter,
1301                                               char *buf, int len)
1302{
1303        int ret = 0;
1304        const u8 *wps_ie;
1305        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1306
1307        DBG_8723A("%s, ielen =%d\n", __func__, len);
1308
1309        if (len > 0) {
1310                wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1311                                                 WLAN_OUI_TYPE_MICROSOFT_WPS,
1312                                                 buf, len);
1313                if (wps_ie) {
1314                        DBG_8723A("probe_req_wps_ielen =%d\n", wps_ie[1]);
1315
1316                        if (pmlmepriv->wps_probe_req_ie) {
1317                                pmlmepriv->wps_probe_req_ie_len = 0;
1318                                kfree(pmlmepriv->wps_probe_req_ie);
1319                                pmlmepriv->wps_probe_req_ie = NULL;
1320                        }
1321
1322                        pmlmepriv->wps_probe_req_ie = kmemdup(wps_ie, wps_ie[1],
1323                                                              GFP_KERNEL);
1324                        if (pmlmepriv->wps_probe_req_ie == NULL) {
1325                                DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
1326                                          __func__, __LINE__);
1327                                return -EINVAL;
1328                        }
1329                        pmlmepriv->wps_probe_req_ie_len = wps_ie[1];
1330                }
1331        }
1332
1333        return ret;
1334}
1335
1336static int cfg80211_rtw_scan(struct wiphy *wiphy,
1337                             struct cfg80211_scan_request *request)
1338{
1339        int i;
1340        u8 _status = false;
1341        int ret = 0;
1342        struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1343        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1344        struct cfg80211_ssid ssid[RTW_SSID_SCAN_AMOUNT];
1345        struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];
1346        struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
1347        struct cfg80211_ssid *ssids = request->ssids;
1348        bool need_indicate_scan_done = false;
1349
1350        DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name);
1351
1352        spin_lock_bh(&pwdev_priv->scan_req_lock);
1353        pwdev_priv->scan_request = request;
1354        spin_unlock_bh(&pwdev_priv->scan_req_lock);
1355
1356        if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1357                DBG_8723A("%s under WIFI_AP_STATE\n", __func__);
1358                /* need_indicate_scan_done = true; */
1359                /* goto check_need_indicate_scan_done; */
1360        }
1361
1362        if (rtw_pwr_wakeup(padapter) == _FAIL) {
1363                need_indicate_scan_done = true;
1364                goto check_need_indicate_scan_done;
1365        }
1366
1367        if (request->ie && request->ie_len > 0) {
1368                rtw_cfg80211_set_probe_req_wpsp2pie(padapter,
1369                                                    (u8 *) request->ie,
1370                                                    request->ie_len);
1371        }
1372
1373        if (pmlmepriv->LinkDetectInfo.bBusyTraffic == true) {
1374                DBG_8723A("%s, bBusyTraffic == true\n", __func__);
1375                need_indicate_scan_done = true;
1376                goto check_need_indicate_scan_done;
1377        }
1378        if (rtw_is_scan_deny(padapter)) {
1379                DBG_8723A("%s(%s): scan deny\n", __func__,
1380                          padapter->pnetdev->name);
1381                need_indicate_scan_done = true;
1382                goto check_need_indicate_scan_done;
1383        }
1384
1385        if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ==
1386            true) {
1387                DBG_8723A("%s, fwstate = 0x%x\n", __func__, pmlmepriv->fw_state);
1388                need_indicate_scan_done = true;
1389                goto check_need_indicate_scan_done;
1390        }
1391
1392        memset(ssid, 0, sizeof(struct cfg80211_ssid) * RTW_SSID_SCAN_AMOUNT);
1393        /* parsing request ssids, n_ssids */
1394        for (i = 0; i < request->n_ssids && i < RTW_SSID_SCAN_AMOUNT; i++) {
1395                DBG_8723A("ssid =%s, len =%d\n", ssids[i].ssid,
1396                          ssids[i].ssid_len);
1397                memcpy(ssid[i].ssid, ssids[i].ssid, ssids[i].ssid_len);
1398                ssid[i].ssid_len = ssids[i].ssid_len;
1399        }
1400
1401        /* parsing channels, n_channels */
1402        memset(ch, 0,
1403               sizeof(struct rtw_ieee80211_channel) * RTW_CHANNEL_SCAN_AMOUNT);
1404
1405        if (request->n_channels == 1) {
1406                for (i = 0; i < request->n_channels &&
1407                     i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
1408                        DBG_8723A("%s:(%s):" CHAN_FMT "\n",
1409                                  __func__, padapter->pnetdev->name,
1410                                  CHAN_ARG(request->channels[i]));
1411                        ch[i].hw_value = request->channels[i]->hw_value;
1412                        ch[i].flags = request->channels[i]->flags;
1413                }
1414        }
1415
1416        spin_lock_bh(&pmlmepriv->lock);
1417        if (request->n_channels == 1) {
1418                memcpy(&ch[1], &ch[0], sizeof(struct rtw_ieee80211_channel));
1419                memcpy(&ch[2], &ch[0], sizeof(struct rtw_ieee80211_channel));
1420                _status = rtw_sitesurvey_cmd23a(padapter, ssid,
1421                                             RTW_SSID_SCAN_AMOUNT, ch, 3);
1422        } else {
1423                _status = rtw_sitesurvey_cmd23a(padapter, ssid,
1424                                             RTW_SSID_SCAN_AMOUNT, NULL, 0);
1425        }
1426        spin_unlock_bh(&pmlmepriv->lock);
1427
1428        if (_status == false)
1429                ret = -1;
1430
1431check_need_indicate_scan_done:
1432        if (need_indicate_scan_done)
1433                rtw_cfg80211_surveydone_event_callback(padapter);
1434        return ret;
1435}
1436
1437static int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1438{
1439        DBG_8723A("%s\n", __func__);
1440        return 0;
1441}
1442
1443static int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
1444                                  struct cfg80211_ibss_params *params)
1445{
1446        DBG_8723A("%s(%s)\n", __func__, ndev->name);
1447        return 0;
1448}
1449
1450static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
1451{
1452        DBG_8723A("%s(%s)\n", __func__, ndev->name);
1453        return 0;
1454}
1455
1456static int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv,
1457                                        u32 wpa_version)
1458{
1459        DBG_8723A("%s, wpa_version =%d\n", __func__, wpa_version);
1460
1461        if (!wpa_version) {
1462                psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
1463                return 0;
1464        }
1465
1466        if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))
1467                psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK;
1468
1469/*
1470        if (wpa_version & NL80211_WPA_VERSION_2)
1471        {
1472                psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK;
1473        }
1474*/
1475
1476        return 0;
1477}
1478
1479static int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv,
1480                                      enum nl80211_auth_type sme_auth_type)
1481{
1482        DBG_8723A("%s, nl80211_auth_type =%d\n", __func__, sme_auth_type);
1483
1484        switch (sme_auth_type) {
1485        case NL80211_AUTHTYPE_AUTOMATIC:
1486                psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
1487
1488                break;
1489        case NL80211_AUTHTYPE_OPEN_SYSTEM:
1490                psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1491
1492                if (psecuritypriv->ndisauthtype > Ndis802_11AuthModeWPA)
1493                        psecuritypriv->dot11AuthAlgrthm =
1494                                dot11AuthAlgrthm_8021X;
1495                break;
1496        case NL80211_AUTHTYPE_SHARED_KEY:
1497                psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1498
1499                psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
1500                break;
1501        default:
1502                psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1503                /* return -ENOTSUPP; */
1504        }
1505
1506        return 0;
1507}
1508
1509static int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv,
1510                                   u32 cipher, bool ucast)
1511{
1512        u32 ndisencryptstatus = Ndis802_11EncryptionDisabled;
1513
1514        u32 *profile_cipher = ucast ? &psecuritypriv->dot11PrivacyAlgrthm :
1515            &psecuritypriv->dot118021XGrpPrivacy;
1516
1517        DBG_8723A("%s, ucast =%d, cipher = 0x%x\n", __func__, ucast, cipher);
1518
1519        if (!cipher) {
1520                *profile_cipher = 0;
1521                psecuritypriv->ndisencryptstatus = ndisencryptstatus;
1522                return 0;
1523        }
1524
1525        switch (cipher) {
1526        case IW_AUTH_CIPHER_NONE:
1527                *profile_cipher = 0;
1528                ndisencryptstatus = Ndis802_11EncryptionDisabled;
1529                break;
1530        case WLAN_CIPHER_SUITE_WEP40:
1531                *profile_cipher = WLAN_CIPHER_SUITE_WEP40;
1532                ndisencryptstatus = Ndis802_11Encryption1Enabled;
1533                break;
1534        case WLAN_CIPHER_SUITE_WEP104:
1535                *profile_cipher = WLAN_CIPHER_SUITE_WEP104;
1536                ndisencryptstatus = Ndis802_11Encryption1Enabled;
1537                break;
1538        case WLAN_CIPHER_SUITE_TKIP:
1539                *profile_cipher = WLAN_CIPHER_SUITE_TKIP;
1540                ndisencryptstatus = Ndis802_11Encryption2Enabled;
1541                break;
1542        case WLAN_CIPHER_SUITE_CCMP:
1543                *profile_cipher = WLAN_CIPHER_SUITE_CCMP;
1544                ndisencryptstatus = Ndis802_11Encryption3Enabled;
1545                break;
1546        default:
1547                DBG_8723A("Unsupported cipher: 0x%x\n", cipher);
1548                return -ENOTSUPP;
1549        }
1550
1551        if (ucast)
1552                psecuritypriv->ndisencryptstatus = ndisencryptstatus;
1553
1554        return 0;
1555}
1556
1557static int rtw_cfg80211_set_key_mgt(struct security_priv *psecuritypriv,
1558                                    u32 key_mgt)
1559{
1560        DBG_8723A("%s, key_mgt = 0x%x\n", __func__, key_mgt);
1561
1562        if (key_mgt == WLAN_AKM_SUITE_8021X)
1563                psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1564        else if (key_mgt == WLAN_AKM_SUITE_PSK)
1565                psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1566        else
1567                DBG_8723A("Invalid key mgt: 0x%x\n", key_mgt);
1568
1569        return 0;
1570}
1571
1572static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie,
1573                                   size_t ielen)
1574{
1575        const u8 *wps_ie;
1576        int group_cipher = 0, pairwise_cipher = 0;
1577        int ret = 0;
1578        const u8 *pwpa, *pwpa2;
1579        int i;
1580
1581        if (!pie || !ielen) {
1582                /* Treat this as normal case, but need to clear
1583                   WIFI_UNDER_WPS */
1584                _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1585                goto exit;
1586        }
1587        if (ielen > MAX_WPA_IE_LEN + MAX_WPS_IE_LEN + MAX_P2P_IE_LEN) {
1588                ret = -EINVAL;
1589                goto exit;
1590        }
1591
1592        /* dump */
1593        DBG_8723A("set wpa_ie(length:%zu):\n", ielen);
1594        for (i = 0; i < ielen; i = i + 8)
1595                DBG_8723A("0x%.2x 0x%.2x 0x%.2x 0x%.2x "
1596                          "0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
1597                          pie[i], pie[i + 1], pie[i + 2], pie[i + 3],
1598                          pie[i + 4], pie[i + 5], pie[i + 6], pie[i + 7]);
1599        if (ielen < RSN_HEADER_LEN) {
1600                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
1601                         "Ie len too short %d\n", (int)ielen);
1602                ret = -1;
1603                goto exit;
1604        }
1605
1606        pwpa = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1607                                       WLAN_OUI_TYPE_MICROSOFT_WPA,
1608                                       pie, ielen);
1609        if (pwpa && pwpa[1] > 0) {
1610                if (rtw_parse_wpa_ie23a(pwpa, pwpa[1] + 2, &group_cipher,
1611                                        &pairwise_cipher, NULL) == _SUCCESS) {
1612                        padapter->securitypriv.dot11AuthAlgrthm =
1613                                dot11AuthAlgrthm_8021X;
1614                        padapter->securitypriv.ndisauthtype =
1615                                Ndis802_11AuthModeWPAPSK;
1616                        memcpy(padapter->securitypriv.supplicant_ie, pwpa,
1617                               pwpa[1] + 2);
1618
1619                        DBG_8723A("got wpa_ie, wpa_ielen:%u\n", pwpa[1]);
1620                }
1621        }
1622
1623        pwpa2 = cfg80211_find_ie(WLAN_EID_RSN, pie, ielen);
1624        if (pwpa2 && pwpa2[1] > 0) {
1625                if (rtw_parse_wpa2_ie23a (pwpa2, pwpa2[1] + 2, &group_cipher,
1626                                          &pairwise_cipher, NULL) == _SUCCESS) {
1627                        padapter->securitypriv.dot11AuthAlgrthm =
1628                                dot11AuthAlgrthm_8021X;
1629                        padapter->securitypriv.ndisauthtype =
1630                                Ndis802_11AuthModeWPA2PSK;
1631                        memcpy(padapter->securitypriv.supplicant_ie, pwpa2,
1632                               pwpa2[1] + 2);
1633
1634                        DBG_8723A("got wpa2_ie, wpa2_ielen:%u\n", pwpa2[1]);
1635                }
1636        }
1637
1638        if (group_cipher == 0) {
1639                group_cipher = WPA_CIPHER_NONE;
1640        }
1641        if (pairwise_cipher == 0) {
1642                pairwise_cipher = WPA_CIPHER_NONE;
1643        }
1644
1645        switch (group_cipher) {
1646        case WPA_CIPHER_NONE:
1647                padapter->securitypriv.dot118021XGrpPrivacy = 0;
1648                padapter->securitypriv.ndisencryptstatus =
1649                        Ndis802_11EncryptionDisabled;
1650                break;
1651        case WPA_CIPHER_WEP40:
1652                padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40;
1653                padapter->securitypriv.ndisencryptstatus =
1654                        Ndis802_11Encryption1Enabled;
1655                break;
1656        case WPA_CIPHER_TKIP:
1657                padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_TKIP;
1658                padapter->securitypriv.ndisencryptstatus =
1659                        Ndis802_11Encryption2Enabled;
1660                break;
1661        case WPA_CIPHER_CCMP:
1662                padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_CCMP;
1663                padapter->securitypriv.ndisencryptstatus =
1664                        Ndis802_11Encryption3Enabled;
1665                break;
1666        case WPA_CIPHER_WEP104:
1667                padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP104;
1668                padapter->securitypriv.ndisencryptstatus =
1669                        Ndis802_11Encryption1Enabled;
1670                break;
1671        }
1672
1673        switch (pairwise_cipher) {
1674        case WPA_CIPHER_NONE:
1675                padapter->securitypriv.dot11PrivacyAlgrthm = 0;
1676                padapter->securitypriv.ndisencryptstatus =
1677                        Ndis802_11EncryptionDisabled;
1678                break;
1679        case WPA_CIPHER_WEP40:
1680                padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
1681                padapter->securitypriv.ndisencryptstatus =
1682                        Ndis802_11Encryption1Enabled;
1683                break;
1684        case WPA_CIPHER_TKIP:
1685                padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_TKIP;
1686                padapter->securitypriv.ndisencryptstatus =
1687                        Ndis802_11Encryption2Enabled;
1688                break;
1689        case WPA_CIPHER_CCMP:
1690                padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_CCMP;
1691                padapter->securitypriv.ndisencryptstatus =
1692                        Ndis802_11Encryption3Enabled;
1693                break;
1694        case WPA_CIPHER_WEP104:
1695                padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104;
1696                padapter->securitypriv.ndisencryptstatus =
1697                        Ndis802_11Encryption1Enabled;
1698                break;
1699        }
1700
1701        wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1702                                         WLAN_OUI_TYPE_MICROSOFT_WPS,
1703                                         pie, ielen);
1704        if (wps_ie && wps_ie[1] > 0) {
1705                DBG_8723A("got wps_ie, wps_ielen:%u\n", wps_ie[1]);
1706                padapter->securitypriv.wps_ie_len = wps_ie[1];
1707                memcpy(padapter->securitypriv.wps_ie, wps_ie,
1708                       padapter->securitypriv.wps_ie_len);
1709                set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
1710        } else {
1711                _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1712        }
1713
1714        /* TKIP and AES disallow multicast packets until installing group key */
1715        if (padapter->securitypriv.dot11PrivacyAlgrthm ==
1716            WLAN_CIPHER_SUITE_TKIP ||
1717            padapter->securitypriv.dot11PrivacyAlgrthm ==
1718            WLAN_CIPHER_SUITE_CCMP)
1719                /* WPS open need to enable multicast */
1720                /* check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true)*/
1721                rtl8723a_off_rcr_am(padapter);
1722
1723        RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1724                 "rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->securitypriv.ndisencryptstatus =%d padapter->securitypriv.ndisauthtype =%d\n",
1725                 pairwise_cipher,
1726                 padapter->securitypriv.ndisencryptstatus,
1727                 padapter->securitypriv.ndisauthtype);
1728
1729exit:
1730        if (ret)
1731                _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1732        return ret;
1733}
1734
1735static int rtw_cfg80211_add_wep(struct rtw_adapter *padapter,
1736                                struct rtw_wep_key *wep, u8 keyid)
1737{
1738        int res;
1739        struct security_priv *psecuritypriv = &padapter->securitypriv;
1740
1741        if (keyid >= NUM_WEP_KEYS) {
1742                RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
1743                         "%s:keyid>4 =>fail\n", __func__);
1744                res = _FAIL;
1745                goto exit;
1746        }
1747
1748        switch (wep->keylen) {
1749        case WLAN_KEY_LEN_WEP40:
1750                psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
1751                RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1752                         "%s:wep->KeyLength = 5\n", __func__);
1753                break;
1754        case WLAN_KEY_LEN_WEP104:
1755                psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104;
1756                RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1757                         "%s:wep->KeyLength = 13\n", __func__);
1758                break;
1759        default:
1760                psecuritypriv->dot11PrivacyAlgrthm = 0;
1761                RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1762                         "%s:wep->KeyLength!= 5 or 13\n", __func__);
1763                res = _FAIL;
1764                goto exit;
1765        }
1766
1767        RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1768                 "%s:before memcpy, wep->KeyLength = 0x%x keyid =%x\n",
1769                 __func__, wep->keylen, keyid);
1770
1771        memcpy(&psecuritypriv->wep_key[keyid], wep, sizeof(struct rtw_wep_key));
1772
1773        psecuritypriv->dot11PrivacyKeyIndex = keyid;
1774
1775        RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1776                 "%s:security key material : %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
1777                 __func__,
1778                 psecuritypriv->wep_key[keyid].key[0],
1779                 psecuritypriv->wep_key[keyid].key[1],
1780                 psecuritypriv->wep_key[keyid].key[2],
1781                 psecuritypriv->wep_key[keyid].key[3],
1782                 psecuritypriv->wep_key[keyid].key[4],
1783                 psecuritypriv->wep_key[keyid].key[5],
1784                 psecuritypriv->wep_key[keyid].key[6],
1785                 psecuritypriv->wep_key[keyid].key[7],
1786                 psecuritypriv->wep_key[keyid].key[8],
1787                 psecuritypriv->wep_key[keyid].key[9],
1788                 psecuritypriv->wep_key[keyid].key[10],
1789                 psecuritypriv->wep_key[keyid].key[11],
1790                 psecuritypriv->wep_key[keyid].key[12]);
1791
1792        res = rtw_set_key23a(padapter, psecuritypriv, keyid, 1);
1793
1794exit:
1795
1796        return res;
1797}
1798
1799static int rtw_set_ssid(struct rtw_adapter *padapter,
1800                        struct wlan_network *newnetwork)
1801{
1802        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1803        struct wlan_network *pnetwork = &pmlmepriv->cur_network;
1804        int status = _SUCCESS;
1805        u32 cur_time = 0;
1806
1807        DBG_8723A_LEVEL(_drv_always_, "set ssid [%s] fw_state = 0x%08x\n",
1808                        newnetwork->network.Ssid.ssid, get_fwstate(pmlmepriv));
1809
1810        if (padapter->hw_init_completed == false) {
1811                RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
1812                         "set_ssid: hw_init_completed == false =>exit!!!\n");
1813                status = _FAIL;
1814                goto exit;
1815        }
1816
1817        spin_lock_bh(&pmlmepriv->lock);
1818
1819        DBG_8723A("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
1820        if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1821                goto handle_tkip_countermeasure;
1822
1823        if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1824                RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1825                         "set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n");
1826
1827                if (pmlmepriv->assoc_ssid.ssid_len ==
1828                    newnetwork->network.Ssid.ssid_len &&
1829                    !memcmp(&pmlmepriv->assoc_ssid.ssid,
1830                            newnetwork->network.Ssid.ssid,
1831                            newnetwork->network.Ssid.ssid_len)) {
1832                        if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
1833                                RT_TRACE(_module_rtl871x_ioctl_set_c_,
1834                                         _drv_err_,
1835                                         "New SSID is same SSID, fw_state = 0x%08x\n",
1836                                         get_fwstate(pmlmepriv));
1837
1838                                if (rtw_is_same_ibss23a(padapter, pnetwork)) {
1839                                        /*
1840                                         * it means driver is in
1841                                         * WIFI_ADHOC_MASTER_STATE, we needn't
1842                                         * create bss again.
1843                                         */
1844                                        goto release_mlme_lock;
1845                                }
1846
1847                                /*
1848                                 * if in WIFI_ADHOC_MASTER_STATE |
1849                                 * WIFI_ADHOC_STATE, create bss or
1850                                 * rejoin again
1851                                 */
1852                                rtw_disassoc_cmd23a(padapter, 0, true);
1853
1854                                if (check_fwstate(pmlmepriv, _FW_LINKED))
1855                                        rtw_indicate_disconnect23a(padapter);
1856
1857                                rtw_free_assoc_resources23a(padapter, 1);
1858
1859                                if (check_fwstate(pmlmepriv,
1860                                                  WIFI_ADHOC_MASTER_STATE)) {
1861                                        _clr_fwstate_(pmlmepriv,
1862                                                      WIFI_ADHOC_MASTER_STATE);
1863                                        set_fwstate(pmlmepriv,
1864                                                    WIFI_ADHOC_STATE);
1865                                }
1866                        } else {
1867                                rtw_lps_ctrl_wk_cmd23a(padapter,
1868                                                       LPS_CTRL_JOINBSS, 1);
1869                        }
1870                } else {
1871                        RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1872                                 "Set SSID not the same ssid\n");
1873                        RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1874                                 "set_ssid =[%s] len = 0x%x\n",
1875                                 newnetwork->network.Ssid.ssid,
1876                                 newnetwork->network.Ssid.ssid_len);
1877                        RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
1878                                 "assoc_ssid =[%s] len = 0x%x\n",
1879                                 pmlmepriv->assoc_ssid.ssid,
1880                                 pmlmepriv->assoc_ssid.ssid_len);
1881
1882                        rtw_disassoc_cmd23a(padapter, 0, true);
1883
1884                        if (check_fwstate(pmlmepriv, _FW_LINKED))
1885                                rtw_indicate_disconnect23a(padapter);
1886
1887                        rtw_free_assoc_resources23a(padapter, 1);
1888
1889                        if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1890                                _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
1891                                set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
1892                        }
1893                }
1894        }
1895
1896handle_tkip_countermeasure:
1897
1898        if (padapter->securitypriv.btkip_countermeasure == true) {
1899                cur_time = jiffies;
1900
1901                if ((cur_time -
1902                     padapter->securitypriv.btkip_countermeasure_time) >
1903                    60 * HZ) {
1904                        padapter->securitypriv.btkip_countermeasure = false;
1905                        padapter->securitypriv.btkip_countermeasure_time = 0;
1906                } else {
1907                        status = _FAIL;
1908                        goto release_mlme_lock;
1909                }
1910        }
1911
1912        memcpy(&pmlmepriv->assoc_ssid, &newnetwork->network.Ssid,
1913               sizeof(struct cfg80211_ssid));
1914
1915        pmlmepriv->assoc_by_bssid = false;
1916
1917        pmlmepriv->to_join = true;
1918
1919        if (!check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
1920                pmlmepriv->cur_network.join_res = -2;
1921
1922                status = rtw_do_join_network(padapter, newnetwork);
1923                if (status == _SUCCESS) {
1924                        pmlmepriv->to_join = false;
1925                } else {
1926                        if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1927                                /* switch to ADHOC_MASTER */
1928                                status = rtw_do_join_adhoc(padapter);
1929                                if (status != _SUCCESS)
1930                                        goto release_mlme_lock;
1931                        } else {
1932                                /* can't associate ; reset under-linking */
1933                                _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1934                                status = _FAIL;
1935                                pmlmepriv->to_join = false;
1936                        }
1937                }
1938        }
1939release_mlme_lock:
1940        spin_unlock_bh(&pmlmepriv->lock);
1941
1942exit:
1943        RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
1944                 "-%s: status =%d\n", __func__, status);
1945
1946        return status;
1947}
1948
1949static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
1950                                struct cfg80211_connect_params *sme)
1951{
1952        int ret = 0;
1953        struct list_head *phead, *plist, *ptmp;
1954        struct wlan_network *pnetwork = NULL;
1955        /* u8 matched_by_bssid = false; */
1956        /* u8 matched_by_ssid = false; */
1957        u8 matched = false;
1958        struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1959        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1960        struct security_priv *psecuritypriv = &padapter->securitypriv;
1961        struct rtw_queue *queue = &pmlmepriv->scanned_queue;
1962
1963        DBG_8723A("=>" "%s(%s)\n", __func__, ndev->name);
1964        DBG_8723A("privacy =%d, key =%p, key_len =%d, key_idx =%d\n",
1965                  sme->privacy, sme->key, sme->key_len, sme->key_idx);
1966
1967        if (_FAIL == rtw_pwr_wakeup(padapter)) {
1968                ret = -EPERM;
1969                goto exit;
1970        }
1971
1972        if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1973                ret = -EPERM;
1974                goto exit;
1975        }
1976
1977        if (!sme->ssid || !sme->ssid_len ||
1978            sme->ssid_len > IEEE80211_MAX_SSID_LEN) {
1979                ret = -EINVAL;
1980                goto exit;
1981        }
1982
1983        DBG_8723A("ssid =%s, len =%zu\n", sme->ssid, sme->ssid_len);
1984
1985        if (sme->bssid)
1986                DBG_8723A("bssid=%pM\n", sme->bssid);
1987
1988        if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
1989                ret = -EBUSY;
1990                DBG_8723A("%s, fw_state = 0x%x, goto exit\n", __func__,
1991                          pmlmepriv->fw_state);
1992                goto exit;
1993        }
1994        if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
1995                rtw_scan_abort23a(padapter);
1996        }
1997
1998        spin_lock_bh(&queue->lock);
1999
2000        phead = get_list_head(queue);
2001
2002        list_for_each_safe(plist, ptmp, phead) {
2003                pnetwork = container_of(plist, struct wlan_network, list);
2004
2005                if (sme->bssid) {
2006                        if (!ether_addr_equal(pnetwork->network.MacAddress,
2007                                              sme->bssid))
2008                                continue;
2009                }
2010
2011                if (sme->ssid && sme->ssid_len) {
2012                        if (pnetwork->network.Ssid.ssid_len != sme->ssid_len ||
2013                            memcmp(pnetwork->network.Ssid.ssid, sme->ssid,
2014                                   sme->ssid_len))
2015                                continue;
2016                }
2017
2018                if (sme->bssid) {
2019                        if (ether_addr_equal(pnetwork->network.MacAddress,
2020                                             sme->bssid)) {
2021                                DBG_8723A("matched by bssid\n");
2022
2023                                matched = true;
2024                                break;
2025                        }
2026                } else if (sme->ssid && sme->ssid_len) {
2027                        if (!memcmp(pnetwork->network.Ssid.ssid,
2028                                    sme->ssid, sme->ssid_len) &&
2029                            pnetwork->network.Ssid.ssid_len == sme->ssid_len) {
2030                                DBG_8723A("matched by ssid\n");
2031
2032                                matched = true;
2033                                break;
2034                        }
2035                }
2036        }
2037
2038        spin_unlock_bh(&queue->lock);
2039
2040        if (!matched || !pnetwork) {
2041                ret = -ENOENT;
2042                DBG_8723A("connect, matched == false, goto exit\n");
2043                goto exit;
2044        }
2045
2046        if (cfg80211_infrastructure_mode(
2047                    padapter, pnetwork->network.ifmode) != _SUCCESS) {
2048                ret = -EPERM;
2049                goto exit;
2050        }
2051
2052        psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
2053        psecuritypriv->dot11PrivacyAlgrthm = 0;
2054        psecuritypriv->dot118021XGrpPrivacy = 0;
2055        psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
2056        psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
2057
2058        ret = rtw_cfg80211_set_wpa_version(psecuritypriv,
2059                                           sme->crypto.wpa_versions);
2060        if (ret < 0)
2061                goto exit;
2062
2063        ret = rtw_cfg80211_set_auth_type(psecuritypriv, sme->auth_type);
2064
2065        if (ret < 0)
2066                goto exit;
2067
2068        DBG_8723A("%s, ie_len =%zu\n", __func__, sme->ie_len);
2069
2070        ret = rtw_cfg80211_set_wpa_ie(padapter, sme->ie, sme->ie_len);
2071        if (ret < 0)
2072                goto exit;
2073
2074        if (sme->crypto.n_ciphers_pairwise) {
2075                ret = rtw_cfg80211_set_cipher(psecuritypriv,
2076                                              sme->crypto.ciphers_pairwise[0],
2077                                              true);
2078                if (ret < 0)
2079                        goto exit;
2080        }
2081
2082        /* For WEP Shared auth */
2083        if ((psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Shared ||
2084             psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Auto) &&
2085            sme->key) {
2086                struct rtw_wep_key wep_key;
2087                u8 wep_key_idx, wep_key_len;
2088                DBG_8723A("%s(): Shared/Auto WEP\n", __func__);
2089
2090                wep_key_idx = sme->key_idx;
2091                wep_key_len = sme->key_len;
2092
2093                if (wep_key_idx > WEP_KEYS || !wep_key_len ||
2094                    wep_key_len > WLAN_KEY_LEN_WEP104) {
2095                        ret = -EINVAL;
2096                        goto exit;
2097                }
2098
2099                wep_key_len = wep_key_len <= 5 ? 5 : 13;
2100
2101                memset(&wep_key, 0, sizeof(struct rtw_wep_key));
2102
2103                wep_key.keylen = wep_key_len;
2104
2105                if (wep_key_len == 13) {
2106                        padapter->securitypriv.dot11PrivacyAlgrthm =
2107                                WLAN_CIPHER_SUITE_WEP104;
2108                        padapter->securitypriv.dot118021XGrpPrivacy =
2109                                WLAN_CIPHER_SUITE_WEP104;
2110                } else {
2111                        padapter->securitypriv.dot11PrivacyAlgrthm =
2112                                WLAN_CIPHER_SUITE_WEP40;
2113                        padapter->securitypriv.dot118021XGrpPrivacy =
2114                                WLAN_CIPHER_SUITE_WEP40;
2115                }
2116
2117                memcpy(wep_key.key, (void *)sme->key, wep_key.keylen);
2118
2119                if (rtw_cfg80211_add_wep(padapter, &wep_key, wep_key_idx) !=
2120                    _SUCCESS)
2121                        ret = -EOPNOTSUPP;
2122
2123                if (ret < 0)
2124                        goto exit;
2125        }
2126
2127        ret = rtw_cfg80211_set_cipher(psecuritypriv,
2128                                      sme->crypto.cipher_group, false);
2129        if (ret < 0)
2130                goto exit;
2131
2132        if (sme->crypto.n_akm_suites) {
2133                ret = rtw_cfg80211_set_key_mgt(psecuritypriv,
2134                                               sme->crypto.akm_suites[0]);
2135                if (ret < 0)
2136                        goto exit;
2137        }
2138
2139        if (psecuritypriv->ndisauthtype > 3)
2140                psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
2141
2142        if (rtw_set_auth23a(padapter, psecuritypriv) != _SUCCESS) {
2143                ret = -EBUSY;
2144                goto exit;
2145        }
2146
2147        /* rtw_set_802_11_encryption_mode(padapter,
2148           padapter->securitypriv.ndisencryptstatus); */
2149
2150        if (rtw_set_ssid(padapter, pnetwork) != _SUCCESS) {
2151                ret = -EBUSY;
2152                goto exit;
2153        }
2154
2155        DBG_8723A("set ssid:dot11AuthAlgrthm =%d, dot11PrivacyAlgrthm =%d, "
2156                  "dot118021XGrpPrivacy =%d\n", psecuritypriv->dot11AuthAlgrthm,
2157                  psecuritypriv->dot11PrivacyAlgrthm,
2158                  psecuritypriv->dot118021XGrpPrivacy);
2159
2160exit:
2161
2162        DBG_8723A("<=%s, ret %d\n", __func__, ret);
2163
2164        return ret;
2165}
2166
2167static int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev,
2168                                   u16 reason_code)
2169{
2170        struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2171
2172        DBG_8723A("%s(%s)\n", __func__, ndev->name);
2173
2174        rtw_set_roaming(padapter, 0);
2175
2176        if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
2177                rtw_scan_abort23a(padapter);
2178                LeaveAllPowerSaveMode23a(padapter);
2179                rtw_disassoc_cmd23a(padapter, 500, false);
2180
2181                DBG_8723A("%s...call rtw_indicate_disconnect23a\n", __func__);
2182
2183                padapter->mlmepriv.not_indic_disco = true;
2184                rtw_indicate_disconnect23a(padapter);
2185                padapter->mlmepriv.not_indic_disco = false;
2186
2187                rtw_free_assoc_resources23a(padapter, 1);
2188        }
2189
2190        return 0;
2191}
2192
2193static int cfg80211_rtw_set_txpower(struct wiphy *wiphy,
2194                                    struct wireless_dev *wdev,
2195                                    enum nl80211_tx_power_setting type, int mbm)
2196{
2197        DBG_8723A("%s\n", __func__);
2198        return 0;
2199}
2200
2201static int cfg80211_rtw_get_txpower(struct wiphy *wiphy,
2202                                    struct wireless_dev *wdev, int *dbm)
2203{
2204        DBG_8723A("%s\n", __func__);
2205        *dbm = (12);
2206        return 0;
2207}
2208
2209inline bool rtw_cfg80211_pwr_mgmt(struct rtw_adapter *adapter)
2210{
2211        struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(adapter->rtw_wdev);
2212        return rtw_wdev_priv->power_mgmt;
2213}
2214
2215static int cfg80211_rtw_set_power_mgmt(struct wiphy *wiphy,
2216                                       struct net_device *ndev,
2217                                       bool enabled, int timeout)
2218{
2219        struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2220        struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(padapter->rtw_wdev);
2221
2222        DBG_8723A("%s(%s): enabled:%u, timeout:%d\n",
2223                  __func__, ndev->name, enabled, timeout);
2224
2225        rtw_wdev_priv->power_mgmt = enabled;
2226
2227        if (!enabled)
2228                LPS_Leave23a(padapter);
2229
2230        return 0;
2231}
2232
2233static int cfg80211_rtw_set_pmksa(struct wiphy *wiphy,
2234                                  struct net_device *netdev,
2235                                  struct cfg80211_pmksa *pmksa)
2236{
2237        u8 index, blInserted = false;
2238        struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2239        struct security_priv *psecuritypriv = &padapter->securitypriv;
2240
2241        DBG_8723A("%s(%s)\n", __func__, netdev->name);
2242
2243        if (is_zero_ether_addr(pmksa->bssid))
2244                return -EINVAL;
2245
2246        blInserted = false;
2247
2248        /* overwrite PMKID */
2249        for (index = 0; index < NUM_PMKID_CACHE; index++) {
2250                if (ether_addr_equal(psecuritypriv->PMKIDList[index].Bssid,
2251                                     pmksa->bssid)) {
2252                        /* BSSID is matched, the same AP => rewrite with
2253                           new PMKID. */
2254                        DBG_8723A("%s(%s):  BSSID exists in the PMKList.\n",
2255                                  __func__, netdev->name);
2256
2257                        memcpy(psecuritypriv->PMKIDList[index].PMKID,
2258                               pmksa->pmkid, WLAN_PMKID_LEN);
2259                        psecuritypriv->PMKIDList[index].bUsed = true;
2260                        psecuritypriv->PMKIDIndex = index + 1;
2261                        blInserted = true;
2262                        break;
2263                }
2264        }
2265
2266        if (!blInserted) {
2267                /*  Find a new entry */
2268                DBG_8723A("%s(%s): Use new entry index = %d for this PMKID\n",
2269                          __func__, netdev->name, psecuritypriv->PMKIDIndex);
2270
2271                ether_addr_copy(
2272                        psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
2273                        Bssid, pmksa->bssid);
2274                memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
2275                       PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2276
2277                psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed =
2278                        true;
2279                psecuritypriv->PMKIDIndex++;
2280                if (psecuritypriv->PMKIDIndex == 16) {
2281                        psecuritypriv->PMKIDIndex = 0;
2282                }
2283        }
2284
2285        return 0;
2286}
2287
2288static int cfg80211_rtw_del_pmksa(struct wiphy *wiphy,
2289                                  struct net_device *netdev,
2290                                  struct cfg80211_pmksa *pmksa)
2291{
2292        u8 index, bMatched = false;
2293        struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2294        struct security_priv *psecuritypriv = &padapter->securitypriv;
2295
2296        DBG_8723A("%s(%s)\n", __func__, netdev->name);
2297
2298        for (index = 0; index < NUM_PMKID_CACHE; index++) {
2299                if (ether_addr_equal(psecuritypriv->PMKIDList[index].Bssid,
2300                                     pmksa->bssid)) {
2301                        /* BSSID is matched, the same AP => Remove this PMKID
2302                           information and reset it. */
2303                        eth_zero_addr(psecuritypriv->PMKIDList[index].Bssid);
2304                        memset(psecuritypriv->PMKIDList[index].PMKID, 0x00,
2305                               WLAN_PMKID_LEN);
2306                        psecuritypriv->PMKIDList[index].bUsed = false;
2307                        bMatched = true;
2308                        break;
2309                }
2310        }
2311
2312        if (false == bMatched) {
2313                DBG_8723A("%s(%s): do not have matched BSSID\n", __func__,
2314                          netdev->name);
2315                return -EINVAL;
2316        }
2317
2318        return 0;
2319}
2320
2321static int cfg80211_rtw_flush_pmksa(struct wiphy *wiphy,
2322                                    struct net_device *netdev)
2323{
2324        struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2325        struct security_priv *psecuritypriv = &padapter->securitypriv;
2326
2327        DBG_8723A("%s(%s)\n", __func__, netdev->name);
2328
2329        memset(&psecuritypriv->PMKIDList[0], 0x00,
2330               sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
2331        psecuritypriv->PMKIDIndex = 0;
2332
2333        return 0;
2334}
2335
2336#ifdef CONFIG_8723AU_AP_MODE
2337void rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter,
2338                                     u8 *pmgmt_frame, uint frame_len)
2339{
2340        s32 freq;
2341        int channel;
2342        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2343        struct net_device *ndev = padapter->pnetdev;
2344
2345        DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name);
2346
2347#if defined(RTW_USE_CFG80211_STA_EVENT)
2348        {
2349                struct station_info sinfo;
2350                u8 ie_offset;
2351
2352                if (ieee80211_is_assoc_req(hdr->frame_control))
2353                        ie_offset = offsetof(struct ieee80211_mgmt,
2354                                             u.assoc_req.variable);
2355                else            /*  WIFI_REASSOCREQ */
2356                        ie_offset = offsetof(struct ieee80211_mgmt,
2357                                             u.reassoc_req.variable);
2358
2359                sinfo.filled = 0;
2360                sinfo.assoc_req_ies = pmgmt_frame + ie_offset;
2361                sinfo.assoc_req_ies_len = frame_len - ie_offset;
2362                cfg80211_new_sta(ndev, hdr->addr2, &sinfo, GFP_ATOMIC);
2363        }
2364#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
2365        channel = pmlmeext->cur_channel;
2366        if (channel <= RTW_CH_MAX_2G_CHANNEL)
2367                freq = ieee80211_channel_to_frequency(channel,
2368                                                      IEEE80211_BAND_2GHZ);
2369        else
2370                freq = ieee80211_channel_to_frequency(channel,
2371                                                      IEEE80211_BAND_5GHZ);
2372
2373        cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pmgmt_frame, frame_len,
2374                         0);
2375#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
2376}
2377
2378void rtw_cfg80211_indicate_sta_disassoc(struct rtw_adapter *padapter,
2379                                        unsigned char *da,
2380                                        unsigned short reason)
2381{
2382        s32 freq;
2383        int channel;
2384        uint frame_len;
2385        struct ieee80211_mgmt mgmt;
2386        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2387        struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2388        struct net_device *ndev = padapter->pnetdev;
2389
2390        DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name);
2391
2392        memset(&mgmt, 0, sizeof(struct ieee80211_mgmt));
2393
2394#if defined(RTW_USE_CFG80211_STA_EVENT)
2395        cfg80211_del_sta(ndev, da, GFP_ATOMIC);
2396#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
2397        channel = pmlmeext->cur_channel;
2398        if (channel <= RTW_CH_MAX_2G_CHANNEL)
2399                freq = ieee80211_channel_to_frequency(channel,
2400                                                      IEEE80211_BAND_2GHZ);
2401        else
2402                freq = ieee80211_channel_to_frequency(channel,
2403                                                      IEEE80211_BAND_5GHZ);
2404
2405        mgmt.frame_control =
2406                cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
2407
2408        ether_addr_copy(mgmt.da, myid(&padapter->eeprompriv));
2409        ether_addr_copy(mgmt.sa, da);
2410        ether_addr_copy(mgmt.bssid, get_my_bssid23a(&pmlmeinfo->network));
2411
2412        mgmt.seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2413        pmlmeext->mgnt_seq++;
2414
2415        mgmt.u.disassoc.reason_code = cpu_to_le16(reason);
2416
2417        frame_len = sizeof(struct ieee80211_hdr_3addr) + 2;
2418
2419        cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, (u8 *)&mgmt, frame_len,
2420                         0);
2421#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
2422}
2423
2424static int rtw_cfg80211_monitor_if_open(struct net_device *ndev)
2425{
2426        DBG_8723A("%s\n", __func__);
2427
2428        return 0;
2429}
2430
2431static int rtw_cfg80211_monitor_if_close(struct net_device *ndev)
2432{
2433        DBG_8723A("%s\n", __func__);
2434
2435        return 0;
2436}
2437
2438static int rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb,
2439                                              struct net_device *ndev)
2440{
2441        int ret = 0;
2442        int rtap_len;
2443        int qos_len = 0;
2444        int dot11_hdr_len = 24;
2445        int snap_len = 6;
2446        unsigned char *pdata;
2447        unsigned char src_mac_addr[6];
2448        unsigned char dst_mac_addr[6];
2449        struct ieee80211_hdr *dot11_hdr;
2450        struct ieee80211_radiotap_header *rtap_hdr;
2451        struct rtw_adapter *padapter = netdev_priv(ndev);
2452
2453        DBG_8723A("%s(%s)\n", __func__, ndev->name);
2454
2455        if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
2456                goto fail;
2457
2458        rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;
2459        if (unlikely(rtap_hdr->it_version))
2460                goto fail;
2461
2462        rtap_len = ieee80211_get_radiotap_len(skb->data);
2463        if (unlikely(skb->len < rtap_len))
2464                goto fail;
2465
2466        if (rtap_len != 14) {
2467                DBG_8723A("radiotap len (should be 14): %d\n", rtap_len);
2468                goto fail;
2469        }
2470
2471        /* Skip the ratio tap header */
2472        skb_pull(skb, rtap_len);
2473
2474        dot11_hdr = (struct ieee80211_hdr *)skb->data;
2475        /* Check if the QoS bit is set */
2476        if (ieee80211_is_data(dot11_hdr->frame_control)) {
2477                /* Check if this ia a Wireless Distribution System (WDS) frame
2478                 * which has 4 MAC addresses
2479                 */
2480                if (ieee80211_is_data_qos(dot11_hdr->frame_control))
2481                        qos_len = IEEE80211_QOS_CTL_LEN;
2482                if (ieee80211_has_a4(dot11_hdr->frame_control))
2483                        dot11_hdr_len += 6;
2484
2485                memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
2486                memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
2487
2488                /*
2489                 * Skip the 802.11 header, QoS (if any) and SNAP,
2490                 * but leave spaces for two MAC addresses
2491                 */
2492                skb_pull(skb, dot11_hdr_len + qos_len + snap_len -
2493                         ETH_ALEN * 2);
2494                pdata = (unsigned char *)skb->data;
2495                ether_addr_copy(pdata, dst_mac_addr);
2496                ether_addr_copy(pdata + ETH_ALEN, src_mac_addr);
2497
2498                DBG_8723A("should be eapol packet\n");
2499
2500                /* Use the real net device to transmit the packet */
2501                ret = rtw_xmit23a_entry23a(skb, padapter->pnetdev);
2502
2503                return ret;
2504
2505        } else if (ieee80211_is_action(dot11_hdr->frame_control)) {
2506                struct ieee80211_mgmt *mgmt;
2507                /* only for action frames */
2508                struct xmit_frame *pmgntframe;
2509                struct pkt_attrib *pattrib;
2510                unsigned char *pframe;
2511                /* u8 category, action, OUI_Subtype, dialogToken = 0; */
2512                /* unsigned char        *frame_body; */
2513                struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2514                struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2515                u32 len = skb->len;
2516                u8 category, action;
2517
2518                mgmt = (struct ieee80211_mgmt *)dot11_hdr;
2519
2520                DBG_8723A("RTW_Tx:da=%pM via %s(%s)\n",
2521                          mgmt->da, __func__, ndev->name);
2522                category = mgmt->u.action.category;
2523                action = mgmt->u.action.u.wme_action.action_code;
2524                DBG_8723A("RTW_Tx:category(%u), action(%u)\n",
2525                          category, action);
2526
2527                /* starting alloc mgmt frame to dump it */
2528                pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2529                if (pmgntframe == NULL)
2530                        goto fail;
2531
2532                /* update attribute */
2533                pattrib = &pmgntframe->attrib;
2534                update_mgntframe_attrib23a(padapter, pattrib);
2535                pattrib->retry_ctrl = false;
2536
2537                memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2538
2539                pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2540
2541                memcpy(pframe, skb->data, len);
2542                pattrib->pktlen = len;
2543
2544                /* update seq number */
2545                pmlmeext->mgnt_seq = le16_to_cpu(dot11_hdr->seq_ctrl) >> 4;
2546                pattrib->seqnum = pmlmeext->mgnt_seq;
2547                pmlmeext->mgnt_seq++;
2548
2549                pattrib->last_txcmdsz = pattrib->pktlen;
2550
2551                dump_mgntframe23a(padapter, pmgntframe);
2552        }
2553
2554fail:
2555
2556        dev_kfree_skb(skb);
2557
2558        return 0;
2559}
2560
2561static int
2562rtw_cfg80211_monitor_if_set_mac_address(struct net_device *ndev, void *addr)
2563{
2564        DBG_8723A("%s\n", __func__);
2565
2566        return 0;
2567}
2568
2569static const struct net_device_ops rtw_cfg80211_monitor_if_ops = {
2570        .ndo_open = rtw_cfg80211_monitor_if_open,
2571        .ndo_stop = rtw_cfg80211_monitor_if_close,
2572        .ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry,
2573        .ndo_set_mac_address = rtw_cfg80211_monitor_if_set_mac_address,
2574};
2575
2576static int rtw_cfg80211_add_monitor_if(struct rtw_adapter *padapter, char *name,
2577                                       unsigned char name_assign_type,
2578                                       struct net_device **ndev)
2579{
2580        int ret = 0;
2581        struct net_device *mon_ndev = NULL;
2582        struct wireless_dev *mon_wdev = NULL;
2583        struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
2584
2585        if (!name) {
2586                DBG_8723A("%s(%s): without specific name\n",
2587                          __func__, padapter->pnetdev->name);
2588                ret = -EINVAL;
2589                goto out;
2590        }
2591
2592        if (pwdev_priv->pmon_ndev) {
2593                DBG_8723A("%s(%s): monitor interface exist: %s\n", __func__,
2594                          padapter->pnetdev->name, pwdev_priv->pmon_ndev->name);
2595                ret = -EBUSY;
2596                goto out;
2597        }
2598
2599        mon_ndev = alloc_etherdev(sizeof(struct rtw_adapter));
2600        if (!mon_ndev) {
2601                DBG_8723A("%s(%s): allocate ndev fail\n", __func__,
2602                          padapter->pnetdev->name);
2603                ret = -ENOMEM;
2604                goto out;
2605        }
2606
2607        mon_ndev->type = ARPHRD_IEEE80211_RADIOTAP;
2608        strncpy(mon_ndev->name, name, IFNAMSIZ);
2609        mon_ndev->name[IFNAMSIZ - 1] = 0;
2610        mon_ndev->name_assign_type = name_assign_type;
2611        mon_ndev->destructor = rtw_ndev_destructor;
2612
2613        mon_ndev->netdev_ops = &rtw_cfg80211_monitor_if_ops;
2614
2615        /*  wdev */
2616        mon_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
2617        if (!mon_wdev) {
2618                DBG_8723A("%s(%s): allocate mon_wdev fail\n", __func__,
2619                          padapter->pnetdev->name);
2620                ret = -ENOMEM;
2621                goto out;
2622        }
2623
2624        mon_wdev->wiphy = padapter->rtw_wdev->wiphy;
2625        mon_wdev->netdev = mon_ndev;
2626        mon_wdev->iftype = NL80211_IFTYPE_MONITOR;
2627        mon_ndev->ieee80211_ptr = mon_wdev;
2628
2629        ret = register_netdevice(mon_ndev);
2630        if (ret) {
2631                goto out;
2632        }
2633
2634        *ndev = pwdev_priv->pmon_ndev = mon_ndev;
2635        memcpy(pwdev_priv->ifname_mon, name, IFNAMSIZ + 1);
2636
2637out:
2638        if (ret) {
2639                kfree(mon_wdev);
2640                mon_wdev = NULL;
2641        }
2642
2643        if (ret && mon_ndev) {
2644                free_netdev(mon_ndev);
2645                *ndev = mon_ndev = NULL;
2646        }
2647
2648        return ret;
2649}
2650
2651static struct wireless_dev *
2652cfg80211_rtw_add_virtual_intf(struct wiphy *wiphy, const char *name,
2653                              unsigned char name_assign_type,
2654                              enum nl80211_iftype type, u32 *flags,
2655                              struct vif_params *params)
2656{
2657        int ret = 0;
2658        struct net_device *ndev = NULL;
2659        struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2660
2661        DBG_8723A("%s(%s): wiphy:%s, name:%s, type:%d\n", __func__,
2662                  padapter->pnetdev->name, wiphy_name(wiphy), name, type);
2663
2664        switch (type) {
2665        case NL80211_IFTYPE_ADHOC:
2666        case NL80211_IFTYPE_AP_VLAN:
2667        case NL80211_IFTYPE_WDS:
2668        case NL80211_IFTYPE_MESH_POINT:
2669                ret = -ENODEV;
2670                break;
2671        case NL80211_IFTYPE_MONITOR:
2672                ret =
2673                    rtw_cfg80211_add_monitor_if(padapter, (char *)name,
2674                                                name_assign_type, &ndev);
2675                break;
2676
2677        case NL80211_IFTYPE_P2P_CLIENT:
2678        case NL80211_IFTYPE_STATION:
2679                ret = -ENODEV;
2680                break;
2681
2682        case NL80211_IFTYPE_P2P_GO:
2683        case NL80211_IFTYPE_AP:
2684                ret = -ENODEV;
2685                break;
2686        default:
2687                ret = -ENODEV;
2688                DBG_8723A("Unsupported interface type\n");
2689                break;
2690        }
2691
2692        DBG_8723A("%s(%s): ndev:%p, ret:%d\n", __func__,
2693                  padapter->pnetdev->name,
2694                  ndev, ret);
2695
2696        return ndev ? ndev->ieee80211_ptr : ERR_PTR(ret);
2697}
2698
2699static int cfg80211_rtw_del_virtual_intf(struct wiphy *wiphy,
2700                                         struct wireless_dev *wdev)
2701{
2702        struct rtw_wdev_priv *pwdev_priv =
2703            (struct rtw_wdev_priv *)wiphy_priv(wiphy);
2704        struct net_device *ndev;
2705        ndev = wdev ? wdev->netdev : NULL;
2706
2707        if (!ndev)
2708                goto exit;
2709
2710        unregister_netdevice(ndev);
2711
2712        if (ndev == pwdev_priv->pmon_ndev) {
2713                pwdev_priv->pmon_ndev = NULL;
2714                pwdev_priv->ifname_mon[0] = '\0';
2715                DBG_8723A("%s(%s): remove monitor interface\n",
2716                          __func__, ndev->name);
2717        }
2718
2719exit:
2720        return 0;
2721}
2722
2723static int rtw_add_beacon(struct rtw_adapter *adapter, const u8 *head,
2724                          size_t head_len, const u8 *tail, size_t tail_len)
2725{
2726        int ret = 0;
2727        u8 *pbuf;
2728        uint len, ielen, wps_ielen = 0;
2729        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2730        struct wlan_bssid_ex *bss = &pmlmepriv->cur_network.network;
2731        const struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)head;
2732        struct ieee80211_mgmt *tmpmgmt;
2733        /* struct sta_priv *pstapriv = &padapter->stapriv; */
2734
2735        DBG_8723A("%s beacon_head_len =%zu, beacon_tail_len =%zu\n",
2736                  __func__, head_len, tail_len);
2737
2738        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2739                return -EINVAL;
2740
2741        if (head_len < offsetof(struct ieee80211_mgmt, u.beacon.variable))
2742                return -EINVAL;
2743
2744        pbuf = kzalloc(head_len + tail_len, GFP_KERNEL);
2745        if (!pbuf)
2746                return -ENOMEM;
2747        tmpmgmt = (struct ieee80211_mgmt *)pbuf;
2748
2749        bss->beacon_interval = get_unaligned_le16(&mgmt->u.beacon.beacon_int);
2750        bss->capability = get_unaligned_le16(&mgmt->u.beacon.capab_info);
2751        bss->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp);
2752
2753        /*  24 = beacon header len. */
2754        memcpy(pbuf, (void *)head, head_len);
2755        memcpy(pbuf + head_len, (void *)tail, tail_len);
2756
2757        len = head_len + tail_len;
2758        ielen = len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
2759        /* check wps ie if inclued */
2760        if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
2761                                    WLAN_OUI_TYPE_MICROSOFT_WPS,
2762                                    tmpmgmt->u.beacon.variable, ielen))
2763                DBG_8723A("add bcn, wps_ielen =%d\n", wps_ielen);
2764
2765        /* pbss_network->IEs will not include p2p_ie, wfd ie */
2766        rtw_ies_remove_ie23a(tmpmgmt->u.beacon.variable, &ielen, 0,
2767                             WLAN_EID_VENDOR_SPECIFIC, P2P_OUI23A, 4);
2768        rtw_ies_remove_ie23a(tmpmgmt->u.beacon.variable, &ielen, 0,
2769                             WLAN_EID_VENDOR_SPECIFIC, WFD_OUI23A, 4);
2770
2771        len = ielen + offsetof(struct ieee80211_mgmt, u.beacon.variable);
2772        if (rtw_check_beacon_data23a(adapter, tmpmgmt, len) == _SUCCESS) {
2773                ret = 0;
2774        } else {
2775                ret = -EINVAL;
2776        }
2777
2778        kfree(pbuf);
2779
2780        return ret;
2781}
2782
2783static int cfg80211_rtw_start_ap(struct wiphy *wiphy, struct net_device *ndev,
2784                                 struct cfg80211_ap_settings *settings)
2785{
2786        int ret = 0;
2787        struct rtw_adapter *adapter = wiphy_to_adapter(wiphy);
2788
2789        DBG_8723A("%s(%s): hidden_ssid:%d, auth_type:%d\n",
2790                  __func__, ndev->name, settings->hidden_ssid,
2791                  settings->auth_type);
2792
2793        ret = rtw_add_beacon(adapter, settings->beacon.head,
2794                             settings->beacon.head_len, settings->beacon.tail,
2795                             settings->beacon.tail_len);
2796
2797        adapter->mlmeextpriv.mlmext_info.hidden_ssid_mode =
2798                settings->hidden_ssid;
2799
2800        if (settings->ssid && settings->ssid_len) {
2801                struct wlan_bssid_ex *pbss_network =
2802                        &adapter->mlmepriv.cur_network.network;
2803                struct wlan_bssid_ex *pbss_network_ext =
2804                        &adapter->mlmeextpriv.mlmext_info.network;
2805
2806                memcpy(pbss_network->Ssid.ssid, (void *)settings->ssid,
2807                       settings->ssid_len);
2808                pbss_network->Ssid.ssid_len = settings->ssid_len;
2809                memcpy(pbss_network_ext->Ssid.ssid, (void *)settings->ssid,
2810                       settings->ssid_len);
2811                pbss_network_ext->Ssid.ssid_len = settings->ssid_len;
2812        }
2813
2814        return ret;
2815}
2816
2817static int cfg80211_rtw_change_beacon(struct wiphy *wiphy,
2818                                      struct net_device *ndev,
2819                                      struct cfg80211_beacon_data *info)
2820{
2821        int ret = 0;
2822        struct rtw_adapter *adapter = wiphy_to_adapter(wiphy);
2823
2824        DBG_8723A("%s(%s)\n", __func__, ndev->name);
2825
2826        ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail,
2827                             info->tail_len);
2828
2829        return ret;
2830}
2831
2832static int cfg80211_rtw_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
2833{
2834        DBG_8723A("%s(%s)\n", __func__, ndev->name);
2835        return 0;
2836}
2837
2838static int cfg80211_rtw_add_station(struct wiphy *wiphy,
2839                                    struct net_device *ndev, const u8 *mac,
2840                                    struct station_parameters *params)
2841{
2842        DBG_8723A("%s(%s)\n", __func__, ndev->name);
2843
2844        return 0;
2845}
2846
2847static int cfg80211_rtw_del_station(struct wiphy *wiphy,
2848                                    struct net_device *ndev,
2849                                    struct station_del_parameters *params)
2850{
2851        const u8 *mac = params->mac;
2852        int ret = 0;
2853        struct list_head *phead, *plist, *ptmp;
2854        u8 updated = 0;
2855        struct sta_info *psta;
2856        struct rtw_adapter *padapter = netdev_priv(ndev);
2857        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2858        struct sta_priv *pstapriv = &padapter->stapriv;
2859
2860        DBG_8723A("+%s(%s)\n", __func__, ndev->name);
2861
2862        if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true) {
2863                DBG_8723A("%s, fw_state != FW_LINKED|WIFI_AP_STATE\n",
2864                          __func__);
2865                return -EINVAL;
2866        }
2867
2868        if (!mac) {
2869                DBG_8723A("flush all sta, and cam_entry\n");
2870
2871                flush_all_cam_entry23a(padapter);       /* clear CAM */
2872
2873                ret = rtw_sta_flush23a(padapter);
2874
2875                return ret;
2876        }
2877
2878        DBG_8723A("free sta macaddr=%pM\n", mac);
2879
2880        if (is_broadcast_ether_addr(mac))
2881                return -EINVAL;
2882
2883        spin_lock_bh(&pstapriv->asoc_list_lock);
2884
2885        phead = &pstapriv->asoc_list;
2886
2887        /* check asoc_queue */
2888        list_for_each_safe(plist, ptmp, phead) {
2889                psta = container_of(plist, struct sta_info, asoc_list);
2890
2891                if (ether_addr_equal(mac, psta->hwaddr)) {
2892                        if (psta->dot8021xalg == 1 &&
2893                            psta->bpairwise_key_installed == false) {
2894                                DBG_8723A("%s, sta's dot8021xalg = 1 and "
2895                                          "key_installed = false\n", __func__);
2896                        } else {
2897                                DBG_8723A("free psta =%p, aid =%d\n", psta,
2898                                          psta->aid);
2899
2900                                list_del_init(&psta->asoc_list);
2901                                pstapriv->asoc_list_cnt--;
2902
2903                                /* spin_unlock_bh(&pstapriv->asoc_list_lock); */
2904                                updated =
2905                                    ap_free_sta23a(padapter, psta, true,
2906                                                WLAN_REASON_DEAUTH_LEAVING);
2907                                /* spin_lock_bh(&pstapriv->asoc_list_lock); */
2908
2909                                psta = NULL;
2910
2911                                break;
2912                        }
2913                }
2914        }
2915
2916        spin_unlock_bh(&pstapriv->asoc_list_lock);
2917
2918        associated_clients_update23a(padapter, updated);
2919
2920        DBG_8723A("-%s(%s)\n", __func__, ndev->name);
2921
2922        return ret;
2923}
2924
2925static int cfg80211_rtw_change_station(struct wiphy *wiphy,
2926                                       struct net_device *ndev, const u8 *mac,
2927                                       struct station_parameters *params)
2928{
2929        DBG_8723A("%s(%s)\n", __func__, ndev->name);
2930        return 0;
2931}
2932
2933static int cfg80211_rtw_dump_station(struct wiphy *wiphy,
2934                                     struct net_device *ndev, int idx, u8 *mac,
2935                                     struct station_info *sinfo)
2936{
2937        DBG_8723A("%s(%s)\n", __func__, ndev->name);
2938
2939        /* TODO: dump scanned queue */
2940
2941        return -ENOENT;
2942}
2943
2944static int cfg80211_rtw_change_bss(struct wiphy *wiphy, struct net_device *ndev,
2945                                   struct bss_parameters *params)
2946{
2947        DBG_8723A("%s(%s)\n", __func__, ndev->name);
2948        return 0;
2949}
2950#endif /* CONFIG_8723AU_AP_MODE */
2951
2952static int _cfg80211_rtw_mgmt_tx(struct rtw_adapter *padapter, u8 tx_ch,
2953                                 const u8 *buf, size_t len)
2954{
2955        struct xmit_frame *pmgntframe;
2956        struct pkt_attrib *pattrib;
2957        unsigned char *pframe;
2958        int ret = _FAIL;
2959        struct ieee80211_hdr *pwlanhdr;
2960        struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2961        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2962
2963        if (_FAIL == rtw_pwr_wakeup(padapter)) {
2964                ret = -EFAULT;
2965                goto exit;
2966        }
2967
2968        rtw_set_scan_deny(padapter, 1000);
2969
2970        rtw_scan_abort23a(padapter);
2971
2972        if (tx_ch != rtw_get_oper_ch23a(padapter)) {
2973                if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED))
2974                        pmlmeext->cur_channel = tx_ch;
2975                set_channel_bwmode23a(padapter, tx_ch,
2976                                   HAL_PRIME_CHNL_OFFSET_DONT_CARE,
2977                                   HT_CHANNEL_WIDTH_20);
2978        }
2979
2980        /* starting alloc mgmt frame to dump it */
2981        pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2982        if (!pmgntframe) {
2983                /* ret = -ENOMEM; */
2984                ret = _FAIL;
2985                goto exit;
2986        }
2987
2988        /* update attribute */
2989        pattrib = &pmgntframe->attrib;
2990        update_mgntframe_attrib23a(padapter, pattrib);
2991        pattrib->retry_ctrl = false;
2992
2993        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2994
2995        pframe = (u8 *) (pmgntframe->buf_addr) + TXDESC_OFFSET;
2996
2997        memcpy(pframe, (void *)buf, len);
2998        pattrib->pktlen = len;
2999
3000        pwlanhdr = (struct ieee80211_hdr *)pframe;
3001        /* update seq number */
3002        pmlmeext->mgnt_seq = le16_to_cpu(pwlanhdr->seq_ctrl) >> 4;
3003        pattrib->seqnum = pmlmeext->mgnt_seq;
3004        pmlmeext->mgnt_seq++;
3005
3006        pattrib->last_txcmdsz = pattrib->pktlen;
3007
3008        ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3009
3010        if (ret  != _SUCCESS)
3011                DBG_8723A("%s, ack == false\n", __func__);
3012        else
3013                DBG_8723A("%s, ack == true\n", __func__);
3014
3015exit:
3016
3017        DBG_8723A("%s, ret =%d\n", __func__, ret);
3018
3019        return ret;
3020}
3021
3022static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
3023                                struct cfg80211_mgmt_tx_params *params,
3024                                u64 *cookie)
3025{
3026        struct rtw_adapter *padapter =
3027                (struct rtw_adapter *)wiphy_to_adapter(wiphy);
3028        int ret = 0;
3029        int tx_ret;
3030        u32 dump_limit = RTW_MAX_MGMT_TX_CNT;
3031        u32 dump_cnt = 0;
3032        bool ack = true;
3033        u8 category, action;
3034        unsigned long start = jiffies;
3035        size_t len = params->len;
3036        struct ieee80211_channel *chan = params->chan;
3037        const u8 *buf = params->buf;
3038        struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *)buf;
3039        u8 tx_ch = (u8) ieee80211_frequency_to_channel(chan->center_freq);
3040
3041        if (!ieee80211_is_action(hdr->frame_control))
3042                return -EINVAL;
3043
3044        /* cookie generation */
3045        *cookie = (unsigned long)buf;
3046
3047        DBG_8723A("%s(%s): len =%zu, ch =%d\n", __func__,
3048                  padapter->pnetdev->name, len, tx_ch);
3049
3050        /* indicate ack before issue frame to avoid racing with rsp frame */
3051        cfg80211_mgmt_tx_status(padapter->rtw_wdev, *cookie, buf, len, ack,
3052                                GFP_KERNEL);
3053
3054        DBG_8723A("RTW_Tx:tx_ch =%d, da =%pM\n", tx_ch, hdr->da);
3055        category = hdr->u.action.category;
3056        action = hdr->u.action.u.wme_action.action_code;
3057        DBG_8723A("RTW_Tx:category(%u), action(%u)\n", category, action);
3058
3059        do {
3060                dump_cnt++;
3061                tx_ret = _cfg80211_rtw_mgmt_tx(padapter, tx_ch, buf, len);
3062        } while (dump_cnt < dump_limit && tx_ret != _SUCCESS);
3063
3064        if (tx_ret != _SUCCESS || dump_cnt > 1) {
3065                DBG_8723A("%s(%s): %s (%d/%d) in %d ms\n",
3066                          __func__, padapter->pnetdev->name,
3067                          tx_ret == _SUCCESS ? "OK" : "FAIL", dump_cnt,
3068                          dump_limit, jiffies_to_msecs(jiffies - start));
3069        }
3070
3071        return ret;
3072}
3073
3074static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy,
3075                                             struct wireless_dev *wdev,
3076                                             u16 frame_type, bool reg)
3077{
3078        if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
3079                return;
3080
3081        return;
3082}
3083
3084static struct cfg80211_ops rtw_cfg80211_ops = {
3085        .change_virtual_intf = cfg80211_rtw_change_iface,
3086        .add_key = cfg80211_rtw_add_key,
3087        .get_key = cfg80211_rtw_get_key,
3088        .del_key = cfg80211_rtw_del_key,
3089        .set_default_key = cfg80211_rtw_set_default_key,
3090        .get_station = cfg80211_rtw_get_station,
3091        .scan = cfg80211_rtw_scan,
3092        .set_wiphy_params = cfg80211_rtw_set_wiphy_params,
3093        .connect = cfg80211_rtw_connect,
3094        .disconnect = cfg80211_rtw_disconnect,
3095        .join_ibss = cfg80211_rtw_join_ibss,
3096        .leave_ibss = cfg80211_rtw_leave_ibss,
3097        .set_tx_power = cfg80211_rtw_set_txpower,
3098        .get_tx_power = cfg80211_rtw_get_txpower,
3099        .set_power_mgmt = cfg80211_rtw_set_power_mgmt,
3100        .set_pmksa = cfg80211_rtw_set_pmksa,
3101        .del_pmksa = cfg80211_rtw_del_pmksa,
3102        .flush_pmksa = cfg80211_rtw_flush_pmksa,
3103
3104#ifdef CONFIG_8723AU_AP_MODE
3105        .add_virtual_intf = cfg80211_rtw_add_virtual_intf,
3106        .del_virtual_intf = cfg80211_rtw_del_virtual_intf,
3107
3108        .start_ap = cfg80211_rtw_start_ap,
3109        .change_beacon = cfg80211_rtw_change_beacon,
3110        .stop_ap = cfg80211_rtw_stop_ap,
3111
3112        .add_station = cfg80211_rtw_add_station,
3113        .del_station = cfg80211_rtw_del_station,
3114        .change_station = cfg80211_rtw_change_station,
3115        .dump_station = cfg80211_rtw_dump_station,
3116        .change_bss = cfg80211_rtw_change_bss,
3117#endif /* CONFIG_8723AU_AP_MODE */
3118
3119        .mgmt_tx = cfg80211_rtw_mgmt_tx,
3120        .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register,
3121};
3122
3123static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap,
3124                                       enum ieee80211_band band, u8 rf_type)
3125{
3126
3127#define MAX_BIT_RATE_40MHZ_MCS15        300     /* Mbps */
3128#define MAX_BIT_RATE_40MHZ_MCS7         150     /* Mbps */
3129
3130        ht_cap->ht_supported = true;
3131
3132        ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
3133            IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 |
3134            IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU;
3135
3136        /*
3137         *Maximum length of AMPDU that the STA can receive.
3138         *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
3139         */
3140        ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
3141
3142        /*Minimum MPDU start spacing , */
3143        ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
3144
3145        ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
3146
3147        /*
3148         *hw->wiphy->bands[IEEE80211_BAND_2GHZ]
3149         *base on ant_num
3150         *rx_mask: RX mask
3151         *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7
3152         *if rx_ant = 2 rx_mask[1]= 0xff;==>MCS8-MCS15
3153         *if rx_ant >= 3 rx_mask[2]= 0xff;
3154         *if BW_40 rx_mask[4]= 0x01;
3155         *highest supported RX rate
3156         */
3157        if (rf_type == RF_1T1R) {
3158                ht_cap->mcs.rx_mask[0] = 0xFF;
3159                ht_cap->mcs.rx_mask[1] = 0x00;
3160                ht_cap->mcs.rx_mask[4] = 0x01;
3161
3162                ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7);
3163        } else if ((rf_type == RF_1T2R) || (rf_type == RF_2T2R)) {
3164                ht_cap->mcs.rx_mask[0] = 0xFF;
3165                ht_cap->mcs.rx_mask[1] = 0xFF;
3166                ht_cap->mcs.rx_mask[4] = 0x01;
3167
3168                ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15);
3169        } else {
3170                DBG_8723A("%s, error rf_type =%d\n", __func__, rf_type);
3171        }
3172
3173}
3174
3175void rtw_cfg80211_init_wiphy(struct rtw_adapter *padapter)
3176{
3177        u8 rf_type;
3178        struct ieee80211_supported_band *bands;
3179        struct wireless_dev *pwdev = padapter->rtw_wdev;
3180        struct wiphy *wiphy = pwdev->wiphy;
3181
3182        rf_type = rtl8723a_get_rf_type(padapter);
3183
3184        DBG_8723A("%s:rf_type =%d\n", __func__, rf_type);
3185
3186        /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */
3187        {
3188                bands = wiphy->bands[IEEE80211_BAND_2GHZ];
3189                if (bands)
3190                        rtw_cfg80211_init_ht_capab(&bands->ht_cap,
3191                                                   IEEE80211_BAND_2GHZ,
3192                                                   rf_type);
3193        }
3194
3195        /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */
3196        {
3197                bands = wiphy->bands[IEEE80211_BAND_5GHZ];
3198                if (bands)
3199                        rtw_cfg80211_init_ht_capab(&bands->ht_cap,
3200                                                   IEEE80211_BAND_5GHZ,
3201                                                   rf_type);
3202        }
3203}
3204
3205static void rtw_cfg80211_preinit_wiphy(struct rtw_adapter *padapter,
3206                                       struct wiphy *wiphy)
3207{
3208        wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
3209
3210        wiphy->max_scan_ssids = RTW_SSID_SCAN_AMOUNT;
3211        wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
3212        wiphy->max_num_pmkids = RTW_MAX_NUM_PMKIDS;
3213
3214        wiphy->max_remain_on_channel_duration =
3215            RTW_MAX_REMAIN_ON_CHANNEL_DURATION;
3216
3217        wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
3218            BIT(NL80211_IFTYPE_ADHOC) |
3219#ifdef CONFIG_8723AU_AP_MODE
3220            BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR) |
3221#endif
3222            0;
3223
3224#ifdef CONFIG_8723AU_AP_MODE
3225        wiphy->mgmt_stypes = rtw_cfg80211_default_mgmt_stypes;
3226#endif /* CONFIG_8723AU_AP_MODE */
3227
3228        wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
3229
3230        /*
3231           wiphy->iface_combinations = &rtw_combinations;
3232           wiphy->n_iface_combinations = 1;
3233         */
3234
3235        wiphy->cipher_suites = rtw_cipher_suites;
3236        wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites);
3237
3238        /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */
3239        wiphy->bands[IEEE80211_BAND_2GHZ] =
3240            rtw_spt_band_alloc(IEEE80211_BAND_2GHZ);
3241        /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */
3242        wiphy->bands[IEEE80211_BAND_5GHZ] =
3243            rtw_spt_band_alloc(IEEE80211_BAND_5GHZ);
3244
3245        wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
3246        wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAVE_AP_SME;
3247
3248        if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)
3249                wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
3250        else
3251                wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
3252}
3253
3254int rtw_wdev_alloc(struct rtw_adapter *padapter, struct device *dev)
3255{
3256        int ret = 0;
3257        struct wiphy *wiphy;
3258        struct wireless_dev *wdev;
3259        struct rtw_wdev_priv *pwdev_priv;
3260        struct net_device *pnetdev = padapter->pnetdev;
3261
3262        DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
3263
3264        /* wiphy */
3265        wiphy = wiphy_new(&rtw_cfg80211_ops, sizeof(struct rtw_wdev_priv));
3266        if (!wiphy) {
3267                DBG_8723A("Couldn't allocate wiphy device\n");
3268                ret = -ENOMEM;
3269                goto exit;
3270        }
3271
3272        /*  wdev */
3273        wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
3274        if (!wdev) {
3275                DBG_8723A("Couldn't allocate wireless device\n");
3276                ret = -ENOMEM;
3277                goto free_wiphy;
3278        }
3279
3280        set_wiphy_dev(wiphy, dev);
3281        rtw_cfg80211_preinit_wiphy(padapter, wiphy);
3282
3283        ret = wiphy_register(wiphy);
3284        if (ret < 0) {
3285                DBG_8723A("Couldn't register wiphy device\n");
3286                goto free_wdev;
3287        }
3288
3289        wdev->wiphy = wiphy;
3290        wdev->netdev = pnetdev;
3291        /* wdev->iftype = NL80211_IFTYPE_STATION; */
3292        /*  for rtw_setopmode_cmd23a() in cfg80211_rtw_change_iface() */
3293        wdev->iftype = NL80211_IFTYPE_MONITOR;
3294        padapter->rtw_wdev = wdev;
3295        pnetdev->ieee80211_ptr = wdev;
3296
3297        /* init pwdev_priv */
3298        pwdev_priv = wdev_to_priv(wdev);
3299        pwdev_priv->rtw_wdev = wdev;
3300        pwdev_priv->pmon_ndev = NULL;
3301        pwdev_priv->ifname_mon[0] = '\0';
3302        pwdev_priv->padapter = padapter;
3303        pwdev_priv->scan_request = NULL;
3304        spin_lock_init(&pwdev_priv->scan_req_lock);
3305
3306        pwdev_priv->p2p_enabled = false;
3307
3308        if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)
3309                pwdev_priv->power_mgmt = true;
3310        else
3311                pwdev_priv->power_mgmt = false;
3312
3313        return ret;
3314free_wdev:
3315        kfree(wdev);
3316free_wiphy:
3317        wiphy_free(wiphy);
3318exit:
3319        return ret;
3320}
3321
3322void rtw_wdev_free(struct wireless_dev *wdev)
3323{
3324        DBG_8723A("%s(wdev =%p)\n", __func__, wdev);
3325
3326        if (!wdev)
3327                return;
3328
3329        kfree(wdev->wiphy->bands[IEEE80211_BAND_2GHZ]);
3330        kfree(wdev->wiphy->bands[IEEE80211_BAND_5GHZ]);
3331
3332        wiphy_free(wdev->wiphy);
3333
3334        kfree(wdev);
3335}
3336
3337void rtw_wdev_unregister(struct wireless_dev *wdev)
3338{
3339        struct rtw_wdev_priv *pwdev_priv;
3340
3341        DBG_8723A("%s(wdev =%p)\n", __func__, wdev);
3342
3343        if (!wdev)
3344                return;
3345
3346        pwdev_priv = wdev_to_priv(wdev);
3347
3348        rtw_cfg80211_indicate_scan_done(pwdev_priv, true);
3349
3350        if (pwdev_priv->pmon_ndev) {
3351                DBG_8723A("%s, unregister monitor interface\n", __func__);
3352                unregister_netdev(pwdev_priv->pmon_ndev);
3353        }
3354
3355        wiphy_unregister(wdev->wiphy);
3356}
3357