linux/drivers/staging/rtl8188eu/core/rtw_mlme.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/******************************************************************************
   3 *
   4 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
   5 *
   6 ******************************************************************************/
   7#define _RTW_MLME_C_
   8
   9#include <linux/ieee80211.h>
  10
  11#include <osdep_service.h>
  12#include <drv_types.h>
  13#include <recv_osdep.h>
  14#include <xmit_osdep.h>
  15#include <hal_intf.h>
  16#include <mlme_osdep.h>
  17#include <sta_info.h>
  18#include <wifi.h>
  19#include <wlan_bssdef.h>
  20#include <rtw_ioctl_set.h>
  21#include <linux/vmalloc.h>
  22#include <linux/etherdevice.h>
  23
  24extern const u8 MCS_rate_1R[16];
  25
  26int rtw_init_mlme_priv(struct adapter *padapter)
  27{
  28        int i;
  29        u8 *pbuf;
  30        struct wlan_network *pnetwork;
  31        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  32        int res = _SUCCESS;
  33
  34        /*  We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */
  35
  36        pmlmepriv->pscanned = NULL;
  37        pmlmepriv->fw_state = 0;
  38        pmlmepriv->cur_network.network.InfrastructureMode = Ndis802_11AutoUnknown;
  39        pmlmepriv->scan_mode = SCAN_ACTIVE;/*  1: active, 0: passive. Maybe someday we should rename this variable to "active_mode" (Jeff) */
  40
  41        spin_lock_init(&pmlmepriv->lock);
  42        _rtw_init_queue(&pmlmepriv->free_bss_pool);
  43        _rtw_init_queue(&pmlmepriv->scanned_queue);
  44
  45        memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
  46
  47        pbuf = vzalloc(array_size(MAX_BSS_CNT, sizeof(struct wlan_network)));
  48
  49        if (!pbuf) {
  50                res = _FAIL;
  51                goto exit;
  52        }
  53        pmlmepriv->free_bss_buf = pbuf;
  54
  55        pnetwork = (struct wlan_network *)pbuf;
  56
  57        for (i = 0; i < MAX_BSS_CNT; i++) {
  58                INIT_LIST_HEAD(&pnetwork->list);
  59
  60                list_add_tail(&pnetwork->list, &pmlmepriv->free_bss_pool.queue);
  61
  62                pnetwork++;
  63        }
  64
  65        /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
  66
  67        rtw_clear_scan_deny(padapter);
  68
  69        rtw_init_mlme_timer(padapter);
  70
  71exit:
  72        return res;
  73}
  74
  75#if defined(CONFIG_88EU_AP_MODE)
  76static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen)
  77{
  78        kfree(*ppie);
  79        *plen = 0;
  80        *ppie = NULL;
  81}
  82
  83void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
  84{
  85        rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
  86        rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
  87        rtw_free_mlme_ie_data(&pmlmepriv->wps_beacon_ie, &pmlmepriv->wps_beacon_ie_len);
  88        rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie, &pmlmepriv->wps_probe_req_ie_len);
  89        rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_resp_ie, &pmlmepriv->wps_probe_resp_ie_len);
  90        rtw_free_mlme_ie_data(&pmlmepriv->wps_assoc_resp_ie, &pmlmepriv->wps_assoc_resp_ie_len);
  91}
  92#else
  93void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
  94{
  95}
  96#endif
  97
  98void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv)
  99{
 100        if (pmlmepriv) {
 101                rtw_free_mlme_priv_ie_data(pmlmepriv);
 102                vfree(pmlmepriv->free_bss_buf);
 103        }
 104}
 105
 106struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv)
 107                                        /* _queue *free_queue) */
 108{
 109        struct wlan_network *pnetwork;
 110        struct __queue *free_queue = &pmlmepriv->free_bss_pool;
 111
 112        spin_lock_bh(&free_queue->lock);
 113        pnetwork = list_first_entry_or_null(&free_queue->queue,
 114                                            struct wlan_network, list);
 115        if (!pnetwork)
 116                goto exit;
 117
 118        list_del_init(&pnetwork->list);
 119
 120        pnetwork->network_type = 0;
 121        pnetwork->fixed = false;
 122        pnetwork->last_scanned = jiffies;
 123        pnetwork->aid = 0;
 124        pnetwork->join_res = 0;
 125
 126exit:
 127        spin_unlock_bh(&free_queue->lock);
 128
 129        return pnetwork;
 130}
 131
 132static void _rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 isfreeall)
 133{
 134        unsigned long curr_time;
 135        u32 delta_time;
 136        u32 lifetime = SCANQUEUE_LIFETIME;
 137        struct __queue *free_queue = &pmlmepriv->free_bss_pool;
 138
 139        if (!pnetwork)
 140                return;
 141
 142        if (pnetwork->fixed)
 143                return;
 144        curr_time = jiffies;
 145        if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
 146            (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
 147                lifetime = 1;
 148        if (!isfreeall) {
 149                delta_time = (curr_time - pnetwork->last_scanned) / HZ;
 150                if (delta_time < lifetime)/*  unit:sec */
 151                        return;
 152        }
 153        spin_lock_bh(&free_queue->lock);
 154        list_del_init(&pnetwork->list);
 155        list_add_tail(&pnetwork->list, &free_queue->queue);
 156        spin_unlock_bh(&free_queue->lock);
 157}
 158
 159static void rtw_free_network_nolock(struct mlme_priv *pmlmepriv,
 160                                    struct wlan_network *pnetwork)
 161{
 162        struct __queue *free_queue = &pmlmepriv->free_bss_pool;
 163
 164        if (!pnetwork)
 165                return;
 166        if (pnetwork->fixed)
 167                return;
 168        list_del_init(&pnetwork->list);
 169        list_add_tail(&pnetwork->list, get_list_head(free_queue));
 170}
 171
 172/*
 173 * return the wlan_network with the matching addr
 174 *
 175 * Shall be called under atomic context... to avoid possible racing condition...
 176 */
 177struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr)
 178{
 179        struct list_head *phead, *plist;
 180        struct wlan_network *pnetwork = NULL;
 181
 182        if (is_zero_ether_addr(addr)) {
 183                pnetwork = NULL;
 184                goto exit;
 185        }
 186        phead = get_list_head(scanned_queue);
 187        list_for_each(plist, phead) {
 188                pnetwork = list_entry(plist, struct wlan_network, list);
 189                if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN))
 190                        break;
 191        }
 192        if (plist == phead)
 193                pnetwork = NULL;
 194exit:
 195        return pnetwork;
 196}
 197
 198void rtw_free_network_queue(struct adapter *padapter, u8 isfreeall)
 199{
 200        struct list_head *phead;
 201        struct wlan_network *pnetwork, *temp;
 202        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 203        struct __queue *scanned_queue = &pmlmepriv->scanned_queue;
 204
 205        spin_lock_bh(&scanned_queue->lock);
 206
 207        phead = get_list_head(scanned_queue);
 208        list_for_each_entry_safe(pnetwork, temp, phead, list)
 209                _rtw_free_network(pmlmepriv, pnetwork, isfreeall);
 210
 211        spin_unlock_bh(&scanned_queue->lock);
 212}
 213
 214int rtw_if_up(struct adapter *padapter)
 215{
 216        int res;
 217
 218        if (padapter->bDriverStopped || padapter->bSurpriseRemoved ||
 219            !check_fwstate(&padapter->mlmepriv, _FW_LINKED))
 220                res = false;
 221        else
 222                res =  true;
 223        return res;
 224}
 225
 226void rtw_generate_random_ibss(u8 *pibss)
 227{
 228        unsigned long curtime = jiffies;
 229
 230        pibss[0] = 0x02;  /* in ad-hoc mode bit1 must set to 1 */
 231        pibss[1] = 0x11;
 232        pibss[2] = 0x87;
 233        pibss[3] = (u8)(curtime & 0xff);/* p[0]; */
 234        pibss[4] = (u8)((curtime >> 8) & 0xff);/* p[1]; */
 235        pibss[5] = (u8)((curtime >> 16) & 0xff);/* p[2]; */
 236}
 237
 238u8 *rtw_get_capability_from_ie(u8 *ie)
 239{
 240        return ie + 8 + 2;
 241}
 242
 243u16 rtw_get_capability(struct wlan_bssid_ex *bss)
 244{
 245        __le16 val;
 246
 247        memcpy((u8 *)&val, rtw_get_capability_from_ie(bss->ies), 2);
 248
 249        return le16_to_cpu(val);
 250}
 251
 252u8 *rtw_get_beacon_interval_from_ie(u8 *ie)
 253{
 254        return ie + 8;
 255}
 256
 257int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork)
 258{
 259        int ret = true;
 260        struct security_priv *psecuritypriv = &adapter->securitypriv;
 261
 262        if ((psecuritypriv->dot11PrivacyAlgrthm != _NO_PRIVACY_) &&
 263            (pnetwork->network.Privacy == 0))
 264                ret = false;
 265        else if ((psecuritypriv->dot11PrivacyAlgrthm == _NO_PRIVACY_) &&
 266                 (pnetwork->network.Privacy == 1))
 267                ret = false;
 268        else
 269                ret = true;
 270        return ret;
 271}
 272
 273static int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b)
 274{
 275        return (a->ssid.ssid_length == b->ssid.ssid_length) &&
 276               !memcmp(a->ssid.ssid, b->ssid.ssid, a->ssid.ssid_length);
 277}
 278
 279int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst)
 280{
 281        u16 s_cap, d_cap;
 282        __le16 le_scap, le_dcap;
 283
 284        memcpy((u8 *)&le_scap, rtw_get_capability_from_ie(src->ies), 2);
 285        memcpy((u8 *)&le_dcap, rtw_get_capability_from_ie(dst->ies), 2);
 286
 287        s_cap = le16_to_cpu(le_scap);
 288        d_cap = le16_to_cpu(le_dcap);
 289
 290        return ((src->ssid.ssid_length == dst->ssid.ssid_length) &&
 291                (!memcmp(src->MacAddress, dst->MacAddress, ETH_ALEN)) &&
 292                (!memcmp(src->ssid.ssid, dst->ssid.ssid, src->ssid.ssid_length)) &&
 293                ((s_cap & WLAN_CAPABILITY_IBSS) ==
 294                (d_cap & WLAN_CAPABILITY_IBSS)) &&
 295                ((s_cap & WLAN_CAPABILITY_ESS) ==
 296                (d_cap & WLAN_CAPABILITY_ESS)));
 297}
 298
 299struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue)
 300{
 301        struct list_head *plist, *phead;
 302        struct wlan_network *pwlan = NULL;
 303        struct wlan_network *oldest = NULL;
 304
 305        phead = get_list_head(scanned_queue);
 306
 307        for (plist = phead->next; plist != phead; plist = plist->next) {
 308                pwlan = container_of(plist, struct wlan_network, list);
 309
 310                if (!pwlan->fixed) {
 311                        if (!oldest || time_after(oldest->last_scanned, pwlan->last_scanned))
 312                                oldest = pwlan;
 313                }
 314        }
 315        return oldest;
 316}
 317
 318void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
 319                    struct adapter *padapter, bool update_ie)
 320{
 321        long rssi_ori = dst->Rssi;
 322        u8 sq_smp = src->PhyInfo.SignalQuality;
 323        u8 ss_final;
 324        u8 sq_final;
 325        long rssi_final;
 326
 327        rtw_hal_antdiv_rssi_compared(padapter, dst, src); /* this will update src.Rssi, need consider again */
 328
 329        /* The rule below is 1/5 for sample value, 4/5 for history value */
 330        if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) &&
 331            is_same_network(&padapter->mlmepriv.cur_network.network, src)) {
 332                /* Take the recvpriv's value for the connected AP*/
 333                ss_final = padapter->recvpriv.signal_strength;
 334                sq_final = padapter->recvpriv.signal_qual;
 335                /* the rssi value here is undecorated, and will be used for antenna diversity */
 336                if (sq_smp != 101) /* from the right channel */
 337                        rssi_final = (src->Rssi + dst->Rssi * 4) / 5;
 338                else
 339                        rssi_final = rssi_ori;
 340        } else {
 341                if (sq_smp != 101) { /* from the right channel */
 342                        ss_final = ((u32)(src->PhyInfo.SignalStrength) + (u32)(dst->PhyInfo.SignalStrength) * 4) / 5;
 343                        sq_final = ((u32)(src->PhyInfo.SignalQuality) + (u32)(dst->PhyInfo.SignalQuality) * 4) / 5;
 344                        rssi_final = (src->Rssi + dst->Rssi * 4) / 5;
 345                } else {
 346                        /* bss info not receiving from the right channel, use the original RX signal infos */
 347                        ss_final = dst->PhyInfo.SignalStrength;
 348                        sq_final = dst->PhyInfo.SignalQuality;
 349                        rssi_final = dst->Rssi;
 350                }
 351        }
 352        if (update_ie)
 353                memcpy((u8 *)dst, (u8 *)src, get_wlan_bssid_ex_sz(src));
 354        dst->PhyInfo.SignalStrength = ss_final;
 355        dst->PhyInfo.SignalQuality = sq_final;
 356        dst->Rssi = rssi_final;
 357}
 358
 359static void update_current_network(struct adapter *adapter, struct wlan_bssid_ex *pnetwork)
 360{
 361        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 362
 363        if (check_fwstate(pmlmepriv, _FW_LINKED) &&
 364            is_same_network(&pmlmepriv->cur_network.network, pnetwork)) {
 365                update_network(&pmlmepriv->cur_network.network, pnetwork, adapter, true);
 366                rtw_update_protection(adapter, (pmlmepriv->cur_network.network.ies) + sizeof(struct ndis_802_11_fixed_ie),
 367                                      pmlmepriv->cur_network.network.ie_length);
 368        }
 369}
 370
 371/*
 372 * Caller must hold pmlmepriv->lock first.
 373 */
 374void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *target)
 375{
 376        struct list_head *plist, *phead;
 377        u32 bssid_ex_sz;
 378        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 379        struct __queue *queue = &pmlmepriv->scanned_queue;
 380        struct wlan_network *pnetwork = NULL;
 381        struct wlan_network *oldest = NULL;
 382
 383        spin_lock_bh(&queue->lock);
 384        phead = get_list_head(queue);
 385        list_for_each(plist, phead) {
 386                pnetwork = list_entry(plist, struct wlan_network, list);
 387
 388                if (is_same_network(&pnetwork->network, target))
 389                        break;
 390                if ((oldest == ((struct wlan_network *)0)) ||
 391                    time_after(oldest->last_scanned, pnetwork->last_scanned))
 392                        oldest = pnetwork;
 393        }
 394        /* If we didn't find a match, then get a new network slot to initialize
 395         * with this beacon's information
 396         */
 397        if (phead == plist) {
 398                if (list_empty(&pmlmepriv->free_bss_pool.queue)) {
 399                        /* If there are no more slots, expire the oldest */
 400                        pnetwork = oldest;
 401
 402                        rtw_hal_get_def_var(adapter, HAL_DEF_CURRENT_ANTENNA,
 403                                            &target->PhyInfo.Optimum_antenna);
 404                        memcpy(&pnetwork->network, target,
 405                               get_wlan_bssid_ex_sz(target));
 406                        /*  variable initialize */
 407                        pnetwork->fixed = false;
 408                        pnetwork->last_scanned = jiffies;
 409
 410                        pnetwork->network_type = 0;
 411                        pnetwork->aid = 0;
 412                        pnetwork->join_res = 0;
 413
 414                        /* bss info not receiving from the right channel */
 415                        if (pnetwork->network.PhyInfo.SignalQuality == 101)
 416                                pnetwork->network.PhyInfo.SignalQuality = 0;
 417                } else {
 418                        /* Otherwise just pull from the free list */
 419
 420                        pnetwork = rtw_alloc_network(pmlmepriv); /*  will update scan_time */
 421
 422                        if (!pnetwork)
 423                                goto exit;
 424
 425                        bssid_ex_sz = get_wlan_bssid_ex_sz(target);
 426                        target->Length = bssid_ex_sz;
 427                        rtw_hal_get_def_var(adapter, HAL_DEF_CURRENT_ANTENNA,
 428                                            &target->PhyInfo.Optimum_antenna);
 429                        memcpy(&pnetwork->network, target, bssid_ex_sz);
 430
 431                        pnetwork->last_scanned = jiffies;
 432
 433                        /* bss info not receiving from the right channel */
 434                        if (pnetwork->network.PhyInfo.SignalQuality == 101)
 435                                pnetwork->network.PhyInfo.SignalQuality = 0;
 436                        list_add_tail(&pnetwork->list, &queue->queue);
 437                }
 438        } else {
 439                /* we have an entry and we are going to update it. But this
 440                 * entry may be already expired. In this case we do the same
 441                 * as we found a new net and call the new_net handler
 442                 */
 443                bool update_ie = true;
 444
 445                pnetwork->last_scanned = jiffies;
 446
 447                /* target.Reserved[0]== 1, means that scanned network is a bcn frame. */
 448                if ((pnetwork->network.ie_length > target->ie_length) && (target->Reserved[0] == 1))
 449                        update_ie = false;
 450
 451                update_network(&pnetwork->network, target, adapter, update_ie);
 452        }
 453
 454exit:
 455        spin_unlock_bh(&queue->lock);
 456}
 457
 458static void rtw_add_network(struct adapter *adapter,
 459                            struct wlan_bssid_ex *pnetwork)
 460{
 461        update_current_network(adapter, pnetwork);
 462        rtw_update_scanned_network(adapter, pnetwork);
 463}
 464
 465/*
 466 * select the desired network based on the capability of the (i)bss.
 467 * check items: (1) security
 468 *                      (2) network_type
 469 *                      (3) WMM
 470 *                      (4) HT
 471 *                      (5) others
 472 */
 473static int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *pnetwork)
 474{
 475        struct security_priv *psecuritypriv = &adapter->securitypriv;
 476        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 477        u32 desired_encmode;
 478        u32 privacy;
 479
 480        /* u8 wps_ie[512]; */
 481        uint wps_ielen;
 482
 483        int bselected = true;
 484
 485        desired_encmode = psecuritypriv->ndisencryptstatus;
 486        privacy = pnetwork->network.Privacy;
 487
 488        if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
 489                if (rtw_get_wps_ie(pnetwork->network.ies + _FIXED_IE_LENGTH_, pnetwork->network.ie_length - _FIXED_IE_LENGTH_, NULL, &wps_ielen))
 490                        return true;
 491                else
 492                        return false;
 493        }
 494        if (adapter->registrypriv.wifi_spec == 1) { /* for  correct flow of 8021X  to do.... */
 495                if ((desired_encmode == Ndis802_11EncryptionDisabled) && (privacy != 0))
 496                        bselected = false;
 497        }
 498
 499        if ((desired_encmode != Ndis802_11EncryptionDisabled) && (privacy == 0))
 500                bselected = false;
 501
 502        if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
 503                if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
 504                        bselected = false;
 505        }
 506
 507        return bselected;
 508}
 509
 510void rtw_survey_event_callback(struct adapter   *adapter, u8 *pbuf)
 511{
 512        u32 len;
 513        struct wlan_bssid_ex *pnetwork;
 514        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 515
 516        pnetwork = (struct wlan_bssid_ex *)pbuf;
 517
 518        len = get_wlan_bssid_ex_sz(pnetwork);
 519        if (len > (sizeof(struct wlan_bssid_ex)))
 520                return;
 521        spin_lock_bh(&pmlmepriv->lock);
 522
 523        /*  update IBSS_network 's timestamp */
 524        if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
 525                if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, pnetwork->MacAddress, ETH_ALEN)) {
 526                        struct wlan_network *ibss_wlan = NULL;
 527
 528                        memcpy(pmlmepriv->cur_network.network.ies, pnetwork->ies, 8);
 529                        spin_lock_bh(&pmlmepriv->scanned_queue.lock);
 530                        ibss_wlan = rtw_find_network(&pmlmepriv->scanned_queue,  pnetwork->MacAddress);
 531                        if (ibss_wlan) {
 532                                memcpy(ibss_wlan->network.ies, pnetwork->ies, 8);
 533                                spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 534                                goto exit;
 535                        }
 536                        spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 537                }
 538        }
 539
 540        /*  lock pmlmepriv->lock when you accessing network_q */
 541        if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
 542                if (pnetwork->ssid.ssid[0] == 0)
 543                        pnetwork->ssid.ssid_length = 0;
 544                rtw_add_network(adapter, pnetwork);
 545        }
 546
 547exit:
 548        spin_unlock_bh(&pmlmepriv->lock);
 549}
 550
 551void rtw_surveydone_event_callback(struct adapter       *adapter, u8 *pbuf)
 552{
 553        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 554
 555        spin_lock_bh(&pmlmepriv->lock);
 556
 557        if (pmlmepriv->wps_probe_req_ie) {
 558                pmlmepriv->wps_probe_req_ie_len = 0;
 559                kfree(pmlmepriv->wps_probe_req_ie);
 560                pmlmepriv->wps_probe_req_ie = NULL;
 561        }
 562
 563        if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
 564                del_timer_sync(&pmlmepriv->scan_to_timer);
 565                _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
 566        }
 567
 568        rtw_set_signal_stat_timer(&adapter->recvpriv);
 569
 570        if (pmlmepriv->to_join) {
 571                if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
 572                        if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
 573                                set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
 574
 575                                if (rtw_select_and_join_from_scanned_queue(pmlmepriv) == _SUCCESS) {
 576                                        mod_timer(&pmlmepriv->assoc_timer,
 577                                                  jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
 578                                } else {
 579                                        struct wlan_bssid_ex *pdev_network = &adapter->registrypriv.dev_network;
 580                                        u8 *pibss = adapter->registrypriv.dev_network.MacAddress;
 581
 582                                        _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
 583
 584                                        memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
 585
 586                                        rtw_update_registrypriv_dev_network(adapter);
 587                                        rtw_generate_random_ibss(pibss);
 588
 589                                        pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
 590
 591                                        rtw_createbss_cmd(adapter);
 592                                        pmlmepriv->to_join = false;
 593                                }
 594                        }
 595                } else {
 596                        int s_ret;
 597
 598                        set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
 599                        pmlmepriv->to_join = false;
 600                        s_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
 601                        if (s_ret == _SUCCESS) {
 602                                mod_timer(&pmlmepriv->assoc_timer,
 603                                          jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
 604                        } else if (s_ret == 2) { /* there is no need to wait for join */
 605                                _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
 606                                rtw_indicate_connect(adapter);
 607                        } else {
 608                                if (pmlmepriv->to_roaming != 0) {
 609                                        if (--pmlmepriv->to_roaming == 0 ||
 610                                            rtw_sitesurvey_cmd(adapter, &pmlmepriv->assoc_ssid, 1, NULL, 0) != _SUCCESS) {
 611                                                pmlmepriv->to_roaming = 0;
 612                                                rtw_free_assoc_resources(adapter);
 613                                                rtw_indicate_disconnect(adapter);
 614                                        } else {
 615                                                pmlmepriv->to_join = true;
 616                                        }
 617                                }
 618                                _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
 619                        }
 620                }
 621        }
 622
 623        indicate_wx_scan_complete_event(adapter);
 624
 625        spin_unlock_bh(&pmlmepriv->lock);
 626
 627        rtw_os_xmit_schedule(adapter);
 628}
 629
 630void rtw_dummy_event_callback(struct adapter *adapter, u8 *pbuf)
 631{
 632}
 633
 634void rtw_fwdbg_event_callback(struct adapter *adapter, u8 *pbuf)
 635{
 636}
 637
 638static void free_scanqueue(struct       mlme_priv *pmlmepriv)
 639{
 640        struct __queue *free_queue = &pmlmepriv->free_bss_pool;
 641        struct __queue *scan_queue = &pmlmepriv->scanned_queue;
 642        struct list_head *plist, *phead, *ptemp;
 643
 644        spin_lock_bh(&scan_queue->lock);
 645        spin_lock_bh(&free_queue->lock);
 646
 647        phead = get_list_head(scan_queue);
 648        plist = phead->next;
 649
 650        while (plist != phead) {
 651                ptemp = plist->next;
 652                list_del_init(plist);
 653                list_add_tail(plist, &free_queue->queue);
 654                plist = ptemp;
 655        }
 656
 657        spin_unlock_bh(&free_queue->lock);
 658        spin_unlock_bh(&scan_queue->lock);
 659}
 660
 661/*
 662 * rtw_free_assoc_resources: the caller has to lock pmlmepriv->lock
 663 */
 664void rtw_free_assoc_resources(struct adapter *adapter)
 665{
 666        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 667
 668        spin_lock_bh(&pmlmepriv->scanned_queue.lock);
 669        rtw_free_assoc_resources_locked(adapter);
 670        spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 671}
 672
 673/*
 674 * rtw_free_assoc_resources_locked: the caller has to lock pmlmepriv->lock
 675 */
 676void rtw_free_assoc_resources_locked(struct adapter *adapter)
 677{
 678        struct wlan_network *pwlan = NULL;
 679        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 680        struct sta_priv *pstapriv = &adapter->stapriv;
 681        struct wlan_network *tgt_network = &pmlmepriv->cur_network;
 682
 683        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) {
 684                struct sta_info *psta;
 685
 686                psta = rtw_get_stainfo(&adapter->stapriv, tgt_network->network.MacAddress);
 687
 688                spin_lock_bh(&pstapriv->sta_hash_lock);
 689                rtw_free_stainfo(adapter,  psta);
 690                spin_unlock_bh(&pstapriv->sta_hash_lock);
 691        }
 692
 693        if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE)) {
 694                struct sta_info *psta;
 695
 696                rtw_free_all_stainfo(adapter);
 697
 698                psta = rtw_get_bcmc_stainfo(adapter);
 699                spin_lock_bh(&pstapriv->sta_hash_lock);
 700                rtw_free_stainfo(adapter, psta);
 701                spin_unlock_bh(&pstapriv->sta_hash_lock);
 702
 703                rtw_init_bcmc_stainfo(adapter);
 704        }
 705
 706        pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
 707        if (pwlan)
 708                pwlan->fixed = false;
 709
 710        if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && (adapter->stapriv.asoc_sta_count == 1)))
 711                rtw_free_network_nolock(pmlmepriv, pwlan);
 712
 713        pmlmepriv->key_mask = 0;
 714}
 715
 716/*
 717 * rtw_indicate_connect: the caller has to lock pmlmepriv->lock
 718 */
 719void rtw_indicate_connect(struct adapter *padapter)
 720{
 721        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 722
 723        pmlmepriv->to_join = false;
 724
 725        if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
 726                set_fwstate(pmlmepriv, _FW_LINKED);
 727
 728                led_control_8188eu(padapter, LED_CTL_LINK);
 729
 730                rtw_os_indicate_connect(padapter);
 731        }
 732
 733        pmlmepriv->to_roaming = 0;
 734
 735        rtw_set_scan_deny(padapter, 3000);
 736}
 737
 738/*
 739 * rtw_indicate_disconnect: the caller has to lock pmlmepriv->lock
 740 */
 741void rtw_indicate_disconnect(struct adapter *padapter)
 742{
 743        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 744
 745        _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING | WIFI_UNDER_WPS);
 746
 747        if (pmlmepriv->to_roaming > 0)
 748                _clr_fwstate_(pmlmepriv, _FW_LINKED);
 749
 750        if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) ||
 751            (pmlmepriv->to_roaming <= 0)) {
 752                rtw_os_indicate_disconnect(padapter);
 753
 754                _clr_fwstate_(pmlmepriv, _FW_LINKED);
 755                led_control_8188eu(padapter, LED_CTL_NO_LINK);
 756                rtw_clear_scan_deny(padapter);
 757        }
 758
 759        rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 1);
 760}
 761
 762inline void rtw_indicate_scan_done(struct adapter *padapter, bool aborted)
 763{
 764        indicate_wx_scan_complete_event(padapter);
 765}
 766
 767static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, struct wlan_network *pnetwork)
 768{
 769        int i;
 770        struct sta_info *bmc_sta, *psta = NULL;
 771        struct recv_reorder_ctrl *preorder_ctrl;
 772        struct sta_priv *pstapriv = &padapter->stapriv;
 773
 774        psta = rtw_get_stainfo(pstapriv, pnetwork->network.MacAddress);
 775        if (!psta)
 776                psta = rtw_alloc_stainfo(pstapriv, pnetwork->network.MacAddress);
 777
 778        if (psta) { /* update ptarget_sta */
 779                psta->aid  = pnetwork->join_res;
 780                psta->mac_id = 0;
 781                /* sta mode */
 782                rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
 783                /* security related */
 784                if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
 785                        padapter->securitypriv.binstallGrpkey = false;
 786                        padapter->securitypriv.busetkipkey = false;
 787                        padapter->securitypriv.bgrpkey_handshake = false;
 788                        psta->ieee8021x_blocked = true;
 789                        psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
 790                        memset((u8 *)&psta->dot118021x_UncstKey, 0, sizeof(union Keytype));
 791                        memset((u8 *)&psta->dot11tkiprxmickey, 0, sizeof(union Keytype));
 792                        memset((u8 *)&psta->dot11tkiptxmickey, 0, sizeof(union Keytype));
 793                        memset((u8 *)&psta->dot11txpn, 0, sizeof(union pn48));
 794                        memset((u8 *)&psta->dot11rxpn, 0, sizeof(union pn48));
 795                }
 796                /*
 797                 * Commented by Albert 2012/07/21
 798                 * When doing the WPS, the wps_ie_len won't equal to 0
 799                 * And the Wi-Fi driver shouldn't allow the data
 800                 * packet to be transmitted.
 801                 */
 802                if (padapter->securitypriv.wps_ie_len != 0) {
 803                        psta->ieee8021x_blocked = true;
 804                        padapter->securitypriv.wps_ie_len = 0;
 805                }
 806                /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info */
 807                /* if A-MPDU Rx is enabled, resetting  rx_ordering_ctrl wstart_b(indicate_seq) to default value = 0xffff */
 808                /* todo: check if AP can send A-MPDU packets */
 809                for (i = 0; i < 16; i++) {
 810                        /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
 811                        preorder_ctrl = &psta->recvreorder_ctrl[i];
 812                        preorder_ctrl->enable = false;
 813                        preorder_ctrl->indicate_seq = 0xffff;
 814                        preorder_ctrl->wend_b = 0xffff;
 815                        preorder_ctrl->wsize_b = 64;/* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */
 816                }
 817                bmc_sta = rtw_get_bcmc_stainfo(padapter);
 818                if (bmc_sta) {
 819                        for (i = 0; i < 16; i++) {
 820                                /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
 821                                preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
 822                                preorder_ctrl->enable = false;
 823                                preorder_ctrl->indicate_seq = 0xffff;
 824                                preorder_ctrl->wend_b = 0xffff;
 825                                preorder_ctrl->wsize_b = 64;/* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */
 826                        }
 827                }
 828                /* misc. */
 829                update_sta_info(padapter, psta);
 830        }
 831        return psta;
 832}
 833
 834/* pnetwork: returns from rtw_joinbss_event_callback */
 835/* ptarget_wlan: found from scanned_queue */
 836static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_network *ptarget_wlan, struct wlan_network  *pnetwork)
 837{
 838        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 839        struct wlan_network *cur_network = &pmlmepriv->cur_network;
 840
 841        /*  why not use ptarget_wlan?? */
 842        memcpy(&cur_network->network, &pnetwork->network, pnetwork->network.Length);
 843        /*  some ies in pnetwork is wrong, so we should use ptarget_wlan ies */
 844        cur_network->network.ie_length = ptarget_wlan->network.ie_length;
 845        memcpy(&cur_network->network.ies[0], &ptarget_wlan->network.ies[0], MAX_IE_SZ);
 846
 847        cur_network->aid = pnetwork->join_res;
 848
 849        rtw_set_signal_stat_timer(&padapter->recvpriv);
 850        padapter->recvpriv.signal_strength = ptarget_wlan->network.PhyInfo.SignalStrength;
 851        padapter->recvpriv.signal_qual = ptarget_wlan->network.PhyInfo.SignalQuality;
 852        /* the ptarget_wlan->network.Rssi is raw data, we use ptarget_wlan->network.PhyInfo.SignalStrength instead (has scaled) */
 853        padapter->recvpriv.rssi = translate_percentage_to_dbm(ptarget_wlan->network.PhyInfo.SignalStrength);
 854        rtw_set_signal_stat_timer(&padapter->recvpriv);
 855
 856        /* update fw_state will clr _FW_UNDER_LINKING here indirectly */
 857        switch (pnetwork->network.InfrastructureMode) {
 858        case Ndis802_11Infrastructure:
 859                if (pmlmepriv->fw_state & WIFI_UNDER_WPS)
 860                        pmlmepriv->fw_state = WIFI_STATION_STATE | WIFI_UNDER_WPS;
 861                else
 862                        pmlmepriv->fw_state = WIFI_STATION_STATE;
 863                break;
 864        case Ndis802_11IBSS:
 865                pmlmepriv->fw_state = WIFI_ADHOC_STATE;
 866                break;
 867        default:
 868                pmlmepriv->fw_state = WIFI_NULL_STATE;
 869                break;
 870        }
 871
 872        rtw_update_protection(padapter, (cur_network->network.ies) +
 873                              sizeof(struct ndis_802_11_fixed_ie),
 874                              (cur_network->network.ie_length));
 875        rtw_update_ht_cap(padapter, cur_network->network.ies, cur_network->network.ie_length);
 876}
 877
 878/* Notes: the function could be > passive_level (the same context as Rx tasklet) */
 879/* pnetwork: returns from rtw_joinbss_event_callback */
 880/* ptarget_wlan: found from scanned_queue */
 881/* if join_res > 0, for (fw_state == WIFI_STATION_STATE), we check if  "ptarget_sta" & "ptarget_wlan" exist. */
 882/* if join_res > 0, for (fw_state == WIFI_ADHOC_STATE), we only check if "ptarget_wlan" exist. */
 883/* if join_res > 0, update "cur_network->network" from "pnetwork->network" if (ptarget_wlan != NULL). */
 884
 885void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
 886{
 887        struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL;
 888        struct sta_priv *pstapriv = &adapter->stapriv;
 889        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 890        struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
 891        struct wlan_network *cur_network = &pmlmepriv->cur_network;
 892        struct wlan_network *pcur_wlan = NULL, *ptarget_wlan = NULL;
 893        unsigned int the_same_macaddr = false;
 894
 895        rtw_get_encrypt_decrypt_from_registrypriv(adapter);
 896
 897        the_same_macaddr = !memcmp(pnetwork->network.MacAddress, cur_network->network.MacAddress, ETH_ALEN);
 898
 899        pnetwork->network.Length = get_wlan_bssid_ex_sz(&pnetwork->network);
 900        if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
 901                return;
 902
 903        spin_lock_bh(&pmlmepriv->lock);
 904
 905        if (pnetwork->join_res > 0) {
 906                spin_lock_bh(&pmlmepriv->scanned_queue.lock);
 907                if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
 908                        /* s1. find ptarget_wlan */
 909                        if (check_fwstate(pmlmepriv, _FW_LINKED)) {
 910                                if (the_same_macaddr) {
 911                                        ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
 912                                } else {
 913                                        pcur_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
 914                                        if (pcur_wlan)
 915                                                pcur_wlan->fixed = false;
 916
 917                                        pcur_sta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
 918                                        if (pcur_sta) {
 919                                                spin_lock_bh(&pstapriv->sta_hash_lock);
 920                                                rtw_free_stainfo(adapter,  pcur_sta);
 921                                                spin_unlock_bh(&pstapriv->sta_hash_lock);
 922                                        }
 923
 924                                        ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
 925                                        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
 926                                                if (ptarget_wlan)
 927                                                        ptarget_wlan->fixed = true;
 928                                        }
 929                                }
 930                        } else {
 931                                ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
 932                                if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
 933                                        if (ptarget_wlan)
 934                                                ptarget_wlan->fixed = true;
 935                                }
 936                        }
 937
 938                        /* s2. update cur_network */
 939                        if (ptarget_wlan) {
 940                                rtw_joinbss_update_network(adapter, ptarget_wlan, pnetwork);
 941                        } else {
 942                                spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 943                                goto ignore_joinbss_callback;
 944                        }
 945
 946                        /* s3. find ptarget_sta & update ptarget_sta after update cur_network only for station mode */
 947                        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
 948                                ptarget_sta = rtw_joinbss_update_stainfo(adapter, pnetwork);
 949                                if (!ptarget_sta) {
 950                                        spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 951                                        goto ignore_joinbss_callback;
 952                                }
 953                        }
 954
 955                        /* s4. indicate connect */
 956                        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
 957                                rtw_indicate_connect(adapter);
 958                        }
 959
 960                        /* s5. Cancel assoc_timer */
 961                        del_timer_sync(&pmlmepriv->assoc_timer);
 962                } else {
 963                        spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 964                        goto ignore_joinbss_callback;
 965                }
 966
 967                spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 968
 969        } else if (pnetwork->join_res == -4) {
 970                rtw_reset_securitypriv(adapter);
 971                mod_timer(&pmlmepriv->assoc_timer,
 972                          jiffies + msecs_to_jiffies(1));
 973
 974                if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
 975                        _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
 976        } else { /* if join_res < 0 (join fails), then try again */
 977                mod_timer(&pmlmepriv->assoc_timer,
 978                          jiffies + msecs_to_jiffies(1));
 979                _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
 980        }
 981
 982ignore_joinbss_callback:
 983        spin_unlock_bh(&pmlmepriv->lock);
 984}
 985
 986void rtw_joinbss_event_callback(struct adapter *adapter, u8 *pbuf)
 987{
 988        struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
 989
 990        mlmeext_joinbss_event_callback(adapter, pnetwork->join_res);
 991
 992        rtw_os_xmit_schedule(adapter);
 993}
 994
 995static u8 search_max_mac_id(struct adapter *padapter)
 996{
 997        u8 mac_id;
 998#if defined(CONFIG_88EU_AP_MODE)
 999        u8 aid;
1000        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1001        struct sta_priv *pstapriv = &padapter->stapriv;
1002#endif
1003        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1004        struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1005
1006#if defined(CONFIG_88EU_AP_MODE)
1007        if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1008                for (aid = pstapriv->max_num_sta; aid > 0; aid--) {
1009                        if (pstapriv->sta_aid[aid - 1])
1010                                break;
1011                }
1012                mac_id = aid + 1;
1013        } else
1014#endif
1015        {/* adhoc  id =  31~2 */
1016                for (mac_id = NUM_STA - 1; mac_id >= IBSS_START_MAC_ID; mac_id--) {
1017                        if (pmlmeinfo->FW_sta_info[mac_id].status == 1)
1018                                break;
1019                }
1020        }
1021        return mac_id;
1022}
1023
1024/* FOR AP , AD-HOC mode */
1025void rtw_stassoc_hw_rpt(struct adapter *adapter, struct sta_info *psta)
1026{
1027        u16 media_status;
1028        u8 macid;
1029
1030        if (!psta)
1031                return;
1032
1033        macid = search_max_mac_id(adapter);
1034        rtw_hal_set_hwreg(adapter, HW_VAR_TX_RPT_MAX_MACID, (u8 *)&macid);
1035        media_status = (psta->mac_id << 8) | 1; /*   MACID|OPMODE:1 connect */
1036        rtw_hal_set_hwreg(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
1037}
1038
1039void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf)
1040{
1041        struct sta_info *psta;
1042        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1043        struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf;
1044        struct wlan_network *cur_network = &pmlmepriv->cur_network;
1045        struct wlan_network *ptarget_wlan = NULL;
1046
1047        if (!rtw_access_ctrl(adapter, pstassoc->macaddr))
1048                return;
1049
1050#if defined(CONFIG_88EU_AP_MODE)
1051        if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1052                psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
1053                if (psta) {
1054                        ap_sta_info_defer_update(adapter, psta);
1055                        rtw_stassoc_hw_rpt(adapter, psta);
1056                }
1057                return;
1058        }
1059#endif
1060        /* for AD-HOC mode */
1061        psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
1062        if (psta)
1063                /* the sta have been in sta_info_queue => do nothing */
1064                return; /* between drv has received this event before and  fw have not yet to set key to CAM_ENTRY) */
1065        psta = rtw_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
1066        if (!psta)
1067                return;
1068
1069        /* to do: init sta_info variable */
1070        psta->qos_option = 0;
1071        psta->mac_id = (uint)pstassoc->cam_id;
1072        /* for ad-hoc mode */
1073        rtw_hal_set_odm_var(adapter, HAL_ODM_STA_INFO, psta, true);
1074        rtw_stassoc_hw_rpt(adapter, psta);
1075        if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
1076                psta->dot118021XPrivacy = adapter->securitypriv.dot11PrivacyAlgrthm;
1077        psta->ieee8021x_blocked = false;
1078        spin_lock_bh(&pmlmepriv->lock);
1079        if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
1080            (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))) {
1081                if (adapter->stapriv.asoc_sta_count == 2) {
1082                        spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1083                        ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1084                        if (ptarget_wlan)
1085                                ptarget_wlan->fixed = true;
1086                        spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1087                        /*  a sta + bc/mc_stainfo (not Ibss_stainfo) */
1088                        rtw_indicate_connect(adapter);
1089                }
1090        }
1091        spin_unlock_bh(&pmlmepriv->lock);
1092        mlmeext_sta_add_event_callback(adapter, psta);
1093}
1094
1095void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
1096{
1097        int mac_id = -1;
1098        struct sta_info *psta;
1099        struct wlan_network *pwlan = NULL;
1100        struct wlan_bssid_ex *pdev_network = NULL;
1101        u8 *pibss = NULL;
1102        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1103        struct stadel_event *pstadel = (struct stadel_event *)pbuf;
1104        struct sta_priv *pstapriv = &adapter->stapriv;
1105        struct wlan_network *tgt_network = &pmlmepriv->cur_network;
1106
1107        psta = rtw_get_stainfo(&adapter->stapriv, pstadel->macaddr);
1108        if (psta)
1109                mac_id = psta->mac_id;
1110        else
1111                mac_id = pstadel->mac_id;
1112
1113        if (mac_id >= 0) {
1114                u16 media_status;
1115
1116                media_status = (mac_id << 8) | 0; /*   MACID|OPMODE:0 means disconnect */
1117                /* for STA, AP, ADHOC mode, report disconnect stauts to FW */
1118                rtw_hal_set_hwreg(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
1119        }
1120
1121        if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
1122                return;
1123
1124        mlmeext_sta_del_event_callback(adapter);
1125
1126        spin_lock_bh(&pmlmepriv->lock);
1127
1128        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
1129                if (pmlmepriv->to_roaming > 0)
1130                        pmlmepriv->to_roaming--; /*  this stadel_event is caused by roaming, decrease to_roaming */
1131                else if (pmlmepriv->to_roaming == 0)
1132                        pmlmepriv->to_roaming = adapter->registrypriv.max_roaming_times;
1133
1134                if (*((unsigned short *)(pstadel->rsvd)) != WLAN_REASON_EXPIRATION_CHK)
1135                        pmlmepriv->to_roaming = 0; /*  don't roam */
1136
1137                rtw_free_uc_swdec_pending_queue(adapter);
1138
1139                rtw_free_assoc_resources(adapter);
1140                rtw_indicate_disconnect(adapter);
1141                spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1142                /*  remove the network entry in scanned_queue */
1143                pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
1144                if (pwlan) {
1145                        pwlan->fixed = false;
1146                        rtw_free_network_nolock(pmlmepriv, pwlan);
1147                }
1148                spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1149                _rtw_roaming(adapter, tgt_network);
1150        }
1151        if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1152            check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1153                spin_lock_bh(&pstapriv->sta_hash_lock);
1154                rtw_free_stainfo(adapter,  psta);
1155                spin_unlock_bh(&pstapriv->sta_hash_lock);
1156
1157                if (adapter->stapriv.asoc_sta_count == 1) { /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
1158                        spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1159                        /* free old ibss network */
1160                        pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
1161                        if (pwlan) {
1162                                pwlan->fixed = false;
1163                                rtw_free_network_nolock(pmlmepriv, pwlan);
1164                        }
1165                        spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1166                        /* re-create ibss */
1167                        pdev_network = &adapter->registrypriv.dev_network;
1168                        pibss = adapter->registrypriv.dev_network.MacAddress;
1169
1170                        memcpy(pdev_network, &tgt_network->network, get_wlan_bssid_ex_sz(&tgt_network->network));
1171
1172                        memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
1173
1174                        rtw_update_registrypriv_dev_network(adapter);
1175
1176                        rtw_generate_random_ibss(pibss);
1177
1178                        if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1179                                set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
1180                                _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
1181                        }
1182
1183                        rtw_createbss_cmd(adapter);
1184                }
1185        }
1186        spin_unlock_bh(&pmlmepriv->lock);
1187}
1188
1189/*
1190 * _rtw_join_timeout_handler - Timeout/failure handler for CMD JoinBss
1191 * @adapter: pointer to struct adapter structure
1192 */
1193void _rtw_join_timeout_handler (struct timer_list *t)
1194{
1195        struct adapter *adapter = from_timer(adapter, t, mlmepriv.assoc_timer);
1196        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1197        int do_join_r;
1198
1199        if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
1200                return;
1201
1202        spin_lock_bh(&pmlmepriv->lock);
1203
1204        if (pmlmepriv->to_roaming > 0) { /*  join timeout caused by roaming */
1205                while (1) {
1206                        pmlmepriv->to_roaming--;
1207                        if (pmlmepriv->to_roaming != 0) { /* try another , */
1208                                do_join_r = rtw_do_join(adapter);
1209                                if (do_join_r != _SUCCESS)
1210                                        continue;
1211                                break;
1212                        }
1213                        rtw_indicate_disconnect(adapter);
1214                        break;
1215                }
1216        } else {
1217                rtw_indicate_disconnect(adapter);
1218                free_scanqueue(pmlmepriv);/*  */
1219        }
1220        spin_unlock_bh(&pmlmepriv->lock);
1221}
1222
1223/*
1224 * rtw_scan_timeout_handler - Timeout/Failure handler for CMD SiteSurvey
1225 * @adapter: pointer to struct adapter structure
1226 */
1227void rtw_scan_timeout_handler (struct timer_list *t)
1228{
1229        struct adapter *adapter = from_timer(adapter, t,
1230                                             mlmepriv.scan_to_timer);
1231        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1232
1233        spin_lock_bh(&pmlmepriv->lock);
1234        _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1235        spin_unlock_bh(&pmlmepriv->lock);
1236        rtw_indicate_scan_done(adapter, true);
1237}
1238
1239static void rtw_auto_scan_handler(struct adapter *padapter)
1240{
1241        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1242
1243        /* auto site survey per 60sec */
1244        if (pmlmepriv->scan_interval > 0) {
1245                pmlmepriv->scan_interval--;
1246                if (pmlmepriv->scan_interval == 0) {
1247                        rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
1248                        pmlmepriv->scan_interval = SCAN_INTERVAL;/*  30*2 sec = 60sec */
1249                }
1250        }
1251}
1252
1253void rtw_dynamic_check_timer_handlder(struct timer_list *t)
1254{
1255        struct adapter *adapter = from_timer(adapter, t,
1256                                             mlmepriv.dynamic_chk_timer);
1257        struct registry_priv *pregistrypriv = &adapter->registrypriv;
1258
1259        if (!adapter)
1260                return;
1261        if (!adapter->hw_init_completed)
1262                goto exit;
1263        if ((adapter->bDriverStopped) || (adapter->bSurpriseRemoved))
1264                goto exit;
1265        if (adapter->net_closed)
1266                goto exit;
1267        rtw_dynamic_chk_wk_cmd(adapter);
1268
1269        if (pregistrypriv->wifi_spec == 1) {
1270                /* auto site survey */
1271                rtw_auto_scan_handler(adapter);
1272        }
1273exit:
1274        mod_timer(&adapter->mlmepriv.dynamic_chk_timer,
1275                  jiffies + msecs_to_jiffies(2000));
1276}
1277
1278#define RTW_SCAN_RESULT_EXPIRE 2000
1279
1280/*
1281 * Select a new join candidate from the original @param candidate and @param competitor
1282 * @return true: candidate is updated
1283 * @return false: candidate is not updated
1284 */
1285static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv
1286        , struct wlan_network **candidate, struct wlan_network *competitor)
1287{
1288        int updated = false;
1289        unsigned long since_scan;
1290        struct adapter *adapter = container_of(pmlmepriv, struct adapter,
1291                                               mlmepriv);
1292
1293        /* check bssid, if needed */
1294        if (pmlmepriv->assoc_by_bssid) {
1295                if (memcmp(competitor->network.MacAddress, pmlmepriv->assoc_bssid, ETH_ALEN))
1296                        goto exit;
1297        }
1298
1299        /* check ssid, if needed */
1300        if (pmlmepriv->assoc_ssid.ssid_length) {
1301                if (competitor->network.ssid.ssid_length != pmlmepriv->assoc_ssid.ssid_length ||
1302                    memcmp(competitor->network.ssid.ssid, pmlmepriv->assoc_ssid.ssid, pmlmepriv->assoc_ssid.ssid_length))
1303                        goto exit;
1304        }
1305
1306        if (!rtw_is_desired_network(adapter, competitor))
1307                goto exit;
1308
1309        if (pmlmepriv->to_roaming) {
1310                since_scan = jiffies - competitor->last_scanned;
1311                if (jiffies_to_msecs(since_scan) >= RTW_SCAN_RESULT_EXPIRE ||
1312                    !is_same_ess(&competitor->network, &pmlmepriv->cur_network.network))
1313                        goto exit;
1314        }
1315
1316        if (!*candidate || (*candidate)->network.Rssi < competitor->network.Rssi) {
1317                *candidate = competitor;
1318                updated = true;
1319        }
1320
1321exit:
1322        return updated;
1323}
1324
1325/*
1326 * Calling context:
1327 * The caller of the sub-routine will be in critical section...
1328 * The caller must hold the following spinlock
1329 * pmlmepriv->lock
1330 */
1331
1332int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv)
1333{
1334        int ret;
1335        struct list_head *phead;
1336        struct adapter *adapter = container_of(pmlmepriv, struct adapter, mlmepriv);
1337        struct __queue *queue = &pmlmepriv->scanned_queue;
1338        struct wlan_network *pnetwork = NULL;
1339        struct wlan_network *candidate = NULL;
1340        u8 supp_ant_div = false;
1341
1342        spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1343        phead = get_list_head(queue);
1344        list_for_each(pmlmepriv->pscanned, phead) {
1345                pnetwork = list_entry(pmlmepriv->pscanned,
1346                                      struct wlan_network, list);
1347                rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork);
1348        }
1349        if (!candidate) {
1350                ret = _FAIL;
1351                goto exit;
1352        }
1353
1354        /*  check for situation of  _FW_LINKED */
1355        if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1356                rtw_disassoc_cmd(adapter, 0, true);
1357                rtw_indicate_disconnect(adapter);
1358                rtw_free_assoc_resources_locked(adapter);
1359        }
1360
1361        rtw_hal_get_def_var(adapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &(supp_ant_div));
1362        if (supp_ant_div) {
1363                u8 cur_ant;
1364
1365                rtw_hal_get_def_var(adapter, HAL_DEF_CURRENT_ANTENNA, &(cur_ant));
1366        }
1367
1368        ret = rtw_joinbss_cmd(adapter, candidate);
1369
1370exit:
1371        spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1372        return ret;
1373}
1374
1375int rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv)
1376{
1377        struct cmd_obj *pcmd;
1378        struct setauth_parm *psetauthparm;
1379        struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1380        int res = _SUCCESS;
1381
1382        pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1383        if (!pcmd) {
1384                res = _FAIL;  /* try again */
1385                goto exit;
1386        }
1387
1388        psetauthparm = kzalloc(sizeof(struct setauth_parm), GFP_KERNEL);
1389        if (!psetauthparm) {
1390                kfree(pcmd);
1391                res = _FAIL;
1392                goto exit;
1393        }
1394        psetauthparm->mode = (unsigned char)psecuritypriv->dot11AuthAlgrthm;
1395        pcmd->cmdcode = _SetAuth_CMD_;
1396        pcmd->parmbuf = (unsigned char *)psetauthparm;
1397        pcmd->cmdsz =  sizeof(struct setauth_parm);
1398        pcmd->rsp = NULL;
1399        pcmd->rspsz = 0;
1400        INIT_LIST_HEAD(&pcmd->list);
1401        res = rtw_enqueue_cmd(pcmdpriv, pcmd);
1402exit:
1403        return res;
1404}
1405
1406int rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, int keyid, u8 set_tx)
1407{
1408        u8 keylen;
1409        struct cmd_obj *pcmd;
1410        struct setkey_parm *psetkeyparm;
1411        struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1412        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1413        int res = _SUCCESS;
1414
1415        pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1416        if (!pcmd)
1417                return _FAIL;  /* try again */
1418
1419        psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
1420        if (!psetkeyparm) {
1421                res = _FAIL;
1422                goto err_free_cmd;
1423        }
1424
1425        if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
1426                psetkeyparm->algorithm = (unsigned char)psecuritypriv->dot118021XGrpPrivacy;
1427        else
1428                psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm;
1429        psetkeyparm->keyid = (u8)keyid;/* 0~3 */
1430        psetkeyparm->set_tx = set_tx;
1431        pmlmepriv->key_mask |= BIT(psetkeyparm->keyid);
1432
1433        switch (psetkeyparm->algorithm) {
1434        case _WEP40_:
1435                keylen = 5;
1436                memcpy(&psetkeyparm->key[0],
1437                       &psecuritypriv->dot11DefKey[keyid].skey[0], keylen);
1438                break;
1439        case _WEP104_:
1440                keylen = 13;
1441                memcpy(&psetkeyparm->key[0],
1442                       &psecuritypriv->dot11DefKey[keyid].skey[0], keylen);
1443                break;
1444        case _TKIP_:
1445                keylen = 16;
1446                memcpy(&psetkeyparm->key, &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1447                psetkeyparm->grpkey = 1;
1448                break;
1449        case _AES_:
1450                keylen = 16;
1451                memcpy(&psetkeyparm->key, &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1452                psetkeyparm->grpkey = 1;
1453                break;
1454        default:
1455                res = _FAIL;
1456                goto err_free_parm;
1457        }
1458        pcmd->cmdcode = _SetKey_CMD_;
1459        pcmd->parmbuf = (u8 *)psetkeyparm;
1460        pcmd->cmdsz =  sizeof(struct setkey_parm);
1461        pcmd->rsp = NULL;
1462        pcmd->rspsz = 0;
1463        INIT_LIST_HEAD(&pcmd->list);
1464        return rtw_enqueue_cmd(pcmdpriv, pcmd);
1465
1466err_free_parm:
1467        kfree(psetkeyparm);
1468err_free_cmd:
1469        kfree(pcmd);
1470        return res;
1471}
1472
1473/* adjust ies for rtw_joinbss_cmd in WMM */
1474int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len, uint initial_out_len)
1475{
1476        unsigned int ielength = 0;
1477        unsigned int i, j;
1478
1479        /* i = 12; after the fixed IE */
1480        for (i = 12; i < in_len; i += (in_ie[i + 1] + 2) /* to the next IE element */) {
1481                ielength = initial_out_len;
1482
1483                if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 && in_ie[i + 3] == 0x50  && in_ie[i + 4] == 0xF2 && in_ie[i + 5] == 0x02 && i + 5 < in_len) {
1484                        /* WMM element ID and OUI */
1485                        /* Append WMM IE to the last index of out_ie */
1486
1487                        for (j = i; j < i + 9; j++) {
1488                                out_ie[ielength] = in_ie[j];
1489                                ielength++;
1490                        }
1491                        out_ie[initial_out_len + 1] = 0x07;
1492                        out_ie[initial_out_len + 6] = 0x00;
1493                        out_ie[initial_out_len + 8] = 0x00;
1494                        break;
1495                }
1496        }
1497        return ielength;
1498}
1499
1500/*
1501 * Ported from 8185: IsInPreAuthKeyList().
1502 * (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.)
1503 * Added by Annie, 2006-05-07.
1504 * Search by BSSID,
1505 * Return Value:
1506 *              -1      :if there is no pre-auth key in the table
1507 *              >= 0    :if there is pre-auth key, and return the entry id
1508 */
1509static int SecIsInPMKIDList(struct adapter *Adapter, u8 *bssid)
1510{
1511        struct security_priv *psecuritypriv = &Adapter->securitypriv;
1512        int i = 0;
1513
1514        do {
1515                if ((psecuritypriv->PMKIDList[i].used) &&
1516                    (!memcmp(psecuritypriv->PMKIDList[i].bssid, bssid, ETH_ALEN)))
1517                        break;
1518        } while (++i < NUM_PMKID_CACHE);
1519
1520        if (i == NUM_PMKID_CACHE)
1521                i = -1;/*  Could not find. */
1522
1523        return i;
1524}
1525
1526/*  */
1527/*  Check the RSN IE length */
1528/*  If the RSN IE length <= 20, the RSN IE didn't include the PMKID information */
1529/*  0-11th element in the array are the fixed IE */
1530/*  12th element in the array is the IE */
1531/*  13th element in the array is the IE length */
1532/*  */
1533
1534static int rtw_append_pmkid(struct adapter *Adapter, int iEntry, u8 *ie, uint ie_len)
1535{
1536        struct security_priv *psecuritypriv = &Adapter->securitypriv;
1537
1538        if (ie[13] <= 20) {
1539                /*  The RSN IE didn't include the PMK ID, append the PMK information */
1540                ie[ie_len] = 1;
1541                ie_len++;
1542                ie[ie_len] = 0; /* PMKID count = 0x0100 */
1543                ie_len++;
1544                memcpy(&ie[ie_len], &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
1545
1546                ie_len += 16;
1547                ie[13] += 18;/* PMKID length = 2+16 */
1548        }
1549        return ie_len;
1550}
1551
1552int rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len)
1553{
1554        u8 authmode;
1555        uint ielength;
1556        int iEntry;
1557        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1558        struct security_priv *psecuritypriv = &adapter->securitypriv;
1559        uint ndisauthmode = psecuritypriv->ndisauthtype;
1560
1561        /* copy fixed ie only */
1562        memcpy(out_ie, in_ie, 12);
1563        ielength = 12;
1564        if ((ndisauthmode == Ndis802_11AuthModeWPA) ||
1565            (ndisauthmode == Ndis802_11AuthModeWPAPSK))
1566                authmode = WLAN_EID_VENDOR_SPECIFIC;
1567        else if ((ndisauthmode == Ndis802_11AuthModeWPA2) ||
1568                 (ndisauthmode == Ndis802_11AuthModeWPA2PSK))
1569                authmode = WLAN_EID_RSN;
1570        else
1571                authmode = 0x0;
1572
1573        if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
1574                memcpy(out_ie + ielength, psecuritypriv->wps_ie, psecuritypriv->wps_ie_len);
1575
1576                ielength += psecuritypriv->wps_ie_len;
1577        } else if ((authmode == WLAN_EID_VENDOR_SPECIFIC) || (authmode == WLAN_EID_RSN)) {
1578                /* copy RSN or SSN */
1579                memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0], psecuritypriv->supplicant_ie[1] + 2);
1580                ielength += psecuritypriv->supplicant_ie[1] + 2;
1581                rtw_report_sec_ie(adapter, authmode, psecuritypriv->supplicant_ie);
1582        }
1583
1584        iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
1585        if (iEntry >= 0 && authmode == WLAN_EID_RSN)
1586                ielength = rtw_append_pmkid(adapter, iEntry, out_ie, ielength);
1587
1588        return ielength;
1589}
1590
1591void rtw_init_registrypriv_dev_network(struct adapter *adapter)
1592{
1593        struct registry_priv *pregistrypriv = &adapter->registrypriv;
1594        struct eeprom_priv *peepriv = &adapter->eeprompriv;
1595        struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
1596        u8 *myhwaddr = myid(peepriv);
1597
1598        memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
1599
1600        memcpy(&pdev_network->ssid, &pregistrypriv->ssid, sizeof(struct ndis_802_11_ssid));
1601
1602        pdev_network->Configuration.Length = sizeof(struct ndis_802_11_config);
1603        pdev_network->Configuration.BeaconPeriod = 100;
1604        pdev_network->Configuration.FHConfig.Length = 0;
1605        pdev_network->Configuration.FHConfig.HopPattern = 0;
1606        pdev_network->Configuration.FHConfig.HopSet = 0;
1607        pdev_network->Configuration.FHConfig.DwellTime = 0;
1608}
1609
1610void rtw_update_registrypriv_dev_network(struct adapter *adapter)
1611{
1612        int sz = 0;
1613        struct registry_priv *pregistrypriv = &adapter->registrypriv;
1614        struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
1615        struct security_priv *psecuritypriv = &adapter->securitypriv;
1616        struct wlan_network *cur_network = &adapter->mlmepriv.cur_network;
1617
1618        pdev_network->Privacy = psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0; /*  adhoc no 802.1x */
1619
1620        pdev_network->Rssi = 0;
1621
1622        switch (pregistrypriv->wireless_mode) {
1623        case WIRELESS_11B:
1624                pdev_network->NetworkTypeInUse = Ndis802_11DS;
1625                break;
1626        case WIRELESS_11G:
1627        case WIRELESS_11BG:
1628        case WIRELESS_11_24N:
1629        case WIRELESS_11G_24N:
1630        case WIRELESS_11BG_24N:
1631                pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
1632                break;
1633        default:
1634                pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
1635                break;
1636        }
1637
1638        pdev_network->Configuration.DSConfig = pregistrypriv->channel;
1639
1640        if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
1641                pdev_network->Configuration.ATIMWindow = 0;
1642
1643        pdev_network->InfrastructureMode = cur_network->network.InfrastructureMode;
1644
1645        /*  1. Supported rates */
1646        /*  2. IE */
1647
1648        sz = rtw_generate_ie(pregistrypriv);
1649        pdev_network->ie_length = sz;
1650        pdev_network->Length = get_wlan_bssid_ex_sz(pdev_network);
1651
1652        /* notes: translate ie_length & Length after assign the Length to cmdsz in createbss_cmd(); */
1653        /* pdev_network->ie_length = cpu_to_le32(sz); */
1654}
1655
1656void rtw_get_encrypt_decrypt_from_registrypriv(struct adapter *adapter)
1657{
1658}
1659
1660/* the function is at passive_level */
1661void rtw_joinbss_reset(struct adapter *padapter)
1662{
1663        u8 threshold;
1664        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1665        struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1666
1667        /* todo: if you want to do something io/reg/hw setting before join_bss, please add code here */
1668        pmlmepriv->num_FortyMHzIntolerant = 0;
1669
1670        pmlmepriv->num_sta_no_ht = 0;
1671
1672        phtpriv->ampdu_enable = false;/* reset to disabled */
1673
1674        /*  TH = 1 => means that invalidate usb rx aggregation */
1675        /*  TH = 0 => means that validate usb rx aggregation, use init value. */
1676        if (phtpriv->ht_option) {
1677                if (padapter->registrypriv.wifi_spec == 1)
1678                        threshold = 1;
1679                else
1680                        threshold = 0;
1681                rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
1682        } else {
1683                threshold = 1;
1684                rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
1685        }
1686}
1687
1688/* the function is >= passive_level */
1689unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len)
1690{
1691        u32 ielen, out_len;
1692        enum ht_cap_ampdu_factor max_rx_ampdu_factor;
1693        unsigned char *p;
1694        unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
1695        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1696        struct qos_priv *pqospriv = &pmlmepriv->qospriv;
1697        struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1698        u32 rx_packet_offset, max_recvbuf_sz;
1699
1700        phtpriv->ht_option = false;
1701
1702        p = rtw_get_ie(in_ie + 12, WLAN_EID_HT_CAPABILITY, &ielen, in_len - 12);
1703
1704        if (p && ielen > 0) {
1705                struct ieee80211_ht_cap ht_cap;
1706
1707                if (pqospriv->qos_option == 0) {
1708                        out_len = *pout_len;
1709                        rtw_set_ie(out_ie + out_len, WLAN_EID_VENDOR_SPECIFIC,
1710                                   _WMM_IE_Length_, WMM_IE, pout_len);
1711
1712                        pqospriv->qos_option = 1;
1713                }
1714
1715                out_len = *pout_len;
1716
1717                memset(&ht_cap, 0, sizeof(struct ieee80211_ht_cap));
1718
1719                ht_cap.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
1720                                              IEEE80211_HT_CAP_SGI_20 |
1721                                              IEEE80211_HT_CAP_SGI_40 |
1722                                              IEEE80211_HT_CAP_TX_STBC |
1723                                              IEEE80211_HT_CAP_DSSSCCK40);
1724
1725                rtw_hal_get_def_var(padapter, HAL_DEF_RX_PACKET_OFFSET, &rx_packet_offset);
1726                rtw_hal_get_def_var(padapter, HAL_DEF_MAX_RECVBUF_SZ, &max_recvbuf_sz);
1727
1728                /*
1729                 * ampdu_params_info [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
1730                 * ampdu_params_info [4:2]:Min MPDU Start Spacing
1731                 */
1732
1733                rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
1734                ht_cap.ampdu_params_info = max_rx_ampdu_factor & 0x03;
1735
1736                if (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
1737                        ht_cap.ampdu_params_info |= IEEE80211_HT_AMPDU_PARM_DENSITY & (0x07 << 2);
1738                else
1739                        ht_cap.ampdu_params_info |= IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00;
1740
1741                rtw_set_ie(out_ie + out_len, WLAN_EID_HT_CAPABILITY,
1742                           sizeof(struct ieee80211_ht_cap),
1743                           (unsigned char *)&ht_cap, pout_len);
1744
1745                phtpriv->ht_option = true;
1746
1747                p = rtw_get_ie(in_ie + 12, WLAN_EID_HT_OPERATION, &ielen, in_len - 12);
1748                if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) {
1749                        out_len = *pout_len;
1750                        rtw_set_ie(out_ie + out_len, WLAN_EID_HT_OPERATION, ielen, p + 2, pout_len);
1751                }
1752        }
1753        return phtpriv->ht_option;
1754}
1755
1756/* the function is > passive_level (in critical_section) */
1757void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len)
1758{
1759        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1760        struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1761        struct registry_priv *pregistrypriv = &padapter->registrypriv;
1762        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1763        struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1764
1765        if (!phtpriv->ht_option)
1766                return;
1767
1768        if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable))
1769                return;
1770
1771        /* maybe needs check if ap supports rx ampdu. */
1772        if ((!phtpriv->ampdu_enable) && (pregistrypriv->ampdu_enable == 1)) {
1773                if (pregistrypriv->wifi_spec == 1)
1774                        phtpriv->ampdu_enable = false;
1775                else
1776                        phtpriv->ampdu_enable = true;
1777        } else if (pregistrypriv->ampdu_enable == 2) {
1778                phtpriv->ampdu_enable = true;
1779        }
1780
1781        /* update cur_bwmode & cur_ch_offset */
1782        if ((pregistrypriv->cbw40_enable) &&
1783            (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & BIT(1)) &&
1784            (pmlmeinfo->HT_info.infos[0] & BIT(2))) {
1785                int i;
1786
1787                /* update the MCS rates */
1788                for (i = 0; i < 16; i++)
1789                        ((u8 *)&pmlmeinfo->HT_caps.mcs)[i] &= MCS_rate_1R[i];
1790                /* switch to the 40M Hz mode according to the AP */
1791                pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
1792                switch ((pmlmeinfo->HT_info.infos[0] & 0x3)) {
1793                case HT_EXTCHNL_OFFSET_UPPER:
1794                        pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
1795                        break;
1796                case HT_EXTCHNL_OFFSET_LOWER:
1797                        pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
1798                        break;
1799                default:
1800                        pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
1801                        break;
1802                }
1803        }
1804
1805        /*  Config SM Power Save setting */
1806        pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & 0x0C) >> 2;
1807
1808        /*  Config current HT Protection mode. */
1809        pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;
1810}
1811
1812void rtw_issue_addbareq_cmd(struct adapter *padapter, struct xmit_frame *pxmitframe)
1813{
1814        u8 issued;
1815        int priority;
1816        struct sta_info *psta = NULL;
1817        struct ht_priv *phtpriv;
1818        struct pkt_attrib *pattrib = &pxmitframe->attrib;
1819
1820        if (is_multicast_ether_addr(pattrib->ra) ||
1821            padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod < 100)
1822                return;
1823
1824        priority = pattrib->priority;
1825
1826        if (pattrib->psta)
1827                psta = pattrib->psta;
1828        else
1829                psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
1830
1831        if (!psta)
1832                return;
1833
1834        phtpriv = &psta->htpriv;
1835
1836        if ((phtpriv->ht_option) && (phtpriv->ampdu_enable)) {
1837                issued = (phtpriv->agg_enable_bitmap >> priority) & 0x1;
1838                issued |= (phtpriv->candidate_tid_bitmap >> priority) & 0x1;
1839
1840                if (issued == 0) {
1841                        psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority);
1842                        rtw_addbareq_cmd(padapter, (u8)priority, pattrib->ra);
1843                }
1844        }
1845}
1846
1847void rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network)
1848{
1849        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1850
1851        spin_lock_bh(&pmlmepriv->lock);
1852        _rtw_roaming(padapter, tgt_network);
1853        spin_unlock_bh(&pmlmepriv->lock);
1854}
1855
1856void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network)
1857{
1858        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1859        int do_join_r;
1860        struct wlan_network *pnetwork;
1861
1862        if (tgt_network)
1863                pnetwork = tgt_network;
1864        else
1865                pnetwork = &pmlmepriv->cur_network;
1866
1867        if (pmlmepriv->to_roaming > 0) {
1868                memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.ssid, sizeof(struct ndis_802_11_ssid));
1869
1870                pmlmepriv->assoc_by_bssid = false;
1871
1872                while (1) {
1873                        do_join_r = rtw_do_join(padapter);
1874                        if (do_join_r == _SUCCESS)
1875                                break;
1876
1877                        pmlmepriv->to_roaming--;
1878
1879                        if (pmlmepriv->to_roaming > 0) {
1880                                continue;
1881                        } else {
1882                                rtw_indicate_disconnect(padapter);
1883                                break;
1884                        }
1885                }
1886        }
1887}
1888