linux/drivers/staging/rtl8712/rtl871x_mlme.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/******************************************************************************
   3 * rtl871x_mlme.c
   4 *
   5 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
   6 * Linux device driver for RTL8192SU
   7 *
   8 * Modifications for inclusion into the Linux staging tree are
   9 * Copyright(c) 2010 Larry Finger. All rights reserved.
  10 *
  11 * Contact information:
  12 * WLAN FAE <wlanfae@realtek.com>
  13 * Larry Finger <Larry.Finger@lwfinger.net>
  14 *
  15 ******************************************************************************/
  16
  17#define _RTL871X_MLME_C_
  18
  19#include <linux/etherdevice.h>
  20
  21#include "osdep_service.h"
  22#include "drv_types.h"
  23#include "recv_osdep.h"
  24#include "xmit_osdep.h"
  25#include "mlme_osdep.h"
  26#include "sta_info.h"
  27#include "wifi.h"
  28#include "wlan_bssdef.h"
  29
  30static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len);
  31
  32int r8712_init_mlme_priv(struct _adapter *padapter)
  33{
  34        sint    i;
  35        u8      *pbuf;
  36        struct wlan_network     *pnetwork;
  37        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
  38
  39        memset((u8 *)pmlmepriv, 0, sizeof(struct mlme_priv));
  40        pmlmepriv->nic_hdl = (u8 *)padapter;
  41        pmlmepriv->pscanned = NULL;
  42        pmlmepriv->fw_state = 0;
  43        pmlmepriv->cur_network.network.InfrastructureMode =
  44                                 Ndis802_11AutoUnknown;
  45        /* Maybe someday we should rename this variable to "active_mode"(Jeff)*/
  46        pmlmepriv->passive_mode = 1; /* 1: active, 0: passive. */
  47        spin_lock_init(&(pmlmepriv->lock));
  48        spin_lock_init(&(pmlmepriv->lock2));
  49        _init_queue(&(pmlmepriv->free_bss_pool));
  50        _init_queue(&(pmlmepriv->scanned_queue));
  51        set_scanned_network_val(pmlmepriv, 0);
  52        memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
  53        pbuf = kmalloc_array(MAX_BSS_CNT, sizeof(struct wlan_network),
  54                             GFP_ATOMIC);
  55        if (!pbuf)
  56                return -ENOMEM;
  57        pmlmepriv->free_bss_buf = pbuf;
  58        pnetwork = (struct wlan_network *)pbuf;
  59        for (i = 0; i < MAX_BSS_CNT; i++) {
  60                INIT_LIST_HEAD(&(pnetwork->list));
  61                list_add_tail(&(pnetwork->list),
  62                                 &(pmlmepriv->free_bss_pool.queue));
  63                pnetwork++;
  64        }
  65        pmlmepriv->sitesurveyctrl.last_rx_pkts = 0;
  66        pmlmepriv->sitesurveyctrl.last_tx_pkts = 0;
  67        pmlmepriv->sitesurveyctrl.traffic_busy = false;
  68        /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
  69        r8712_init_mlme_timer(padapter);
  70        return 0;
  71}
  72
  73struct wlan_network *_r8712_alloc_network(struct mlme_priv *pmlmepriv)
  74{
  75        unsigned long irqL;
  76        struct wlan_network *pnetwork;
  77        struct  __queue *free_queue = &pmlmepriv->free_bss_pool;
  78
  79        spin_lock_irqsave(&free_queue->lock, irqL);
  80        pnetwork = list_first_entry_or_null(&free_queue->queue,
  81                                            struct wlan_network, list);
  82        if (pnetwork) {
  83                list_del_init(&pnetwork->list);
  84                pnetwork->last_scanned = jiffies;
  85                pmlmepriv->num_of_scanned++;
  86        }
  87        spin_unlock_irqrestore(&free_queue->lock, irqL);
  88        return pnetwork;
  89}
  90
  91static void _free_network(struct mlme_priv *pmlmepriv,
  92                          struct wlan_network *pnetwork)
  93{
  94        u32 curr_time, delta_time;
  95        unsigned long irqL;
  96        struct  __queue *free_queue = &(pmlmepriv->free_bss_pool);
  97
  98        if (!pnetwork)
  99                return;
 100        if (pnetwork->fixed)
 101                return;
 102        curr_time = jiffies;
 103        delta_time = (curr_time - (u32)pnetwork->last_scanned) / HZ;
 104        if (delta_time < SCANQUEUE_LIFETIME)
 105                return;
 106        spin_lock_irqsave(&free_queue->lock, irqL);
 107        list_del_init(&pnetwork->list);
 108        list_add_tail(&pnetwork->list, &free_queue->queue);
 109        pmlmepriv->num_of_scanned--;
 110        spin_unlock_irqrestore(&free_queue->lock, irqL);
 111}
 112
 113static void free_network_nolock(struct mlme_priv *pmlmepriv,
 114                          struct wlan_network *pnetwork)
 115{
 116        struct  __queue *free_queue = &pmlmepriv->free_bss_pool;
 117
 118        if (!pnetwork)
 119                return;
 120        if (pnetwork->fixed)
 121                return;
 122        list_del_init(&pnetwork->list);
 123        list_add_tail(&pnetwork->list, &free_queue->queue);
 124        pmlmepriv->num_of_scanned--;
 125}
 126
 127/* return the wlan_network with the matching addr
 128 * Shall be called under atomic context...
 129 * to avoid possible racing condition...
 130 */
 131static struct wlan_network *r8712_find_network(struct  __queue *scanned_queue,
 132                                               u8 *addr)
 133{
 134        unsigned long irqL;
 135        struct list_head *phead, *plist;
 136        struct wlan_network *pnetwork = NULL;
 137
 138        if (is_zero_ether_addr(addr))
 139                return NULL;
 140        spin_lock_irqsave(&scanned_queue->lock, irqL);
 141        phead = &scanned_queue->queue;
 142        list_for_each(plist, phead) {
 143                pnetwork = list_entry(plist, struct wlan_network, list);
 144                if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN))
 145                        break;
 146        }
 147        if (plist == phead)
 148                pnetwork = NULL;
 149        spin_unlock_irqrestore(&scanned_queue->lock, irqL);
 150        return pnetwork;
 151}
 152
 153void r8712_free_network_queue(struct _adapter *padapter)
 154{
 155        unsigned long irqL;
 156        struct list_head *phead, *plist;
 157        struct wlan_network *pnetwork;
 158        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 159        struct  __queue *scanned_queue = &pmlmepriv->scanned_queue;
 160
 161        spin_lock_irqsave(&scanned_queue->lock, irqL);
 162        phead = &scanned_queue->queue;
 163        plist = phead->next;
 164        while (!end_of_queue_search(phead, plist)) {
 165                pnetwork = container_of(plist, struct wlan_network, list);
 166                plist = plist->next;
 167                _free_network(pmlmepriv, pnetwork);
 168        }
 169        spin_unlock_irqrestore(&scanned_queue->lock, irqL);
 170}
 171
 172sint r8712_if_up(struct _adapter *padapter)
 173{
 174        sint res;
 175
 176        if (padapter->driver_stopped || padapter->surprise_removed ||
 177            !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
 178                res = false;
 179        } else {
 180                res = true;
 181        }
 182        return res;
 183}
 184
 185void r8712_generate_random_ibss(u8 *pibss)
 186{
 187        u32 curtime = jiffies;
 188
 189        pibss[0] = 0x02; /*in ad-hoc mode bit1 must set to 1 */
 190        pibss[1] = 0x11;
 191        pibss[2] = 0x87;
 192        pibss[3] = (u8)(curtime & 0xff);
 193        pibss[4] = (u8)((curtime >> 8) & 0xff);
 194        pibss[5] = (u8)((curtime >> 16) & 0xff);
 195}
 196
 197uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss)
 198{
 199        return sizeof(*bss) + bss->IELength - MAX_IE_SZ;
 200}
 201
 202u8 *r8712_get_capability_from_ie(u8 *ie)
 203{
 204        return ie + 8 + 2;
 205}
 206
 207void r8712_free_mlme_priv(struct mlme_priv *pmlmepriv)
 208{
 209        kfree(pmlmepriv->free_bss_buf);
 210}
 211
 212static struct   wlan_network *alloc_network(struct mlme_priv *pmlmepriv)
 213{
 214        return _r8712_alloc_network(pmlmepriv);
 215}
 216
 217int r8712_is_same_ibss(struct _adapter *adapter, struct wlan_network *pnetwork)
 218{
 219        int ret = true;
 220        struct security_priv *psecuritypriv = &adapter->securitypriv;
 221
 222        if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) &&
 223                    (pnetwork->network.Privacy == cpu_to_le32(0)))
 224                ret = false;
 225        else if ((psecuritypriv->PrivacyAlgrthm == _NO_PRIVACY_) &&
 226                 (pnetwork->network.Privacy == cpu_to_le32(1)))
 227                ret = false;
 228        else
 229                ret = true;
 230        return ret;
 231
 232}
 233
 234static int is_same_network(struct wlan_bssid_ex *src,
 235                           struct wlan_bssid_ex *dst)
 236{
 237        u16 s_cap, d_cap;
 238
 239        memcpy((u8 *)&s_cap, r8712_get_capability_from_ie(src->IEs), 2);
 240        memcpy((u8 *)&d_cap, r8712_get_capability_from_ie(dst->IEs), 2);
 241        return (src->Ssid.SsidLength == dst->Ssid.SsidLength) &&
 242                        (src->Configuration.DSConfig ==
 243                        dst->Configuration.DSConfig) &&
 244                        ((!memcmp(src->MacAddress, dst->MacAddress,
 245                        ETH_ALEN))) &&
 246                        ((!memcmp(src->Ssid.Ssid,
 247                          dst->Ssid.Ssid,
 248                          src->Ssid.SsidLength))) &&
 249                        ((s_cap & WLAN_CAPABILITY_IBSS) ==
 250                        (d_cap & WLAN_CAPABILITY_IBSS)) &&
 251                        ((s_cap & WLAN_CAPABILITY_ESS) ==
 252                        (d_cap & WLAN_CAPABILITY_ESS));
 253
 254}
 255
 256struct  wlan_network *r8712_get_oldest_wlan_network(
 257                                struct  __queue *scanned_queue)
 258{
 259        struct list_head *plist, *phead;
 260        struct  wlan_network    *pwlan = NULL;
 261        struct  wlan_network    *oldest = NULL;
 262
 263        phead = &scanned_queue->queue;
 264        plist = phead->next;
 265        while (1) {
 266                if (end_of_queue_search(phead, plist))
 267                        break;
 268                pwlan = container_of(plist, struct wlan_network, list);
 269                if (!pwlan->fixed) {
 270                        if (!oldest ||
 271                            time_after((unsigned long)oldest->last_scanned,
 272                                       (unsigned long)pwlan->last_scanned))
 273                                oldest = pwlan;
 274                }
 275                plist = plist->next;
 276        }
 277        return oldest;
 278}
 279
 280static void update_network(struct wlan_bssid_ex *dst,
 281                           struct wlan_bssid_ex *src,
 282                           struct _adapter *padapter)
 283{
 284        u32 last_evm = 0, tmpVal;
 285        struct smooth_rssi_data *sqd = &padapter->recvpriv.signal_qual_data;
 286
 287        if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) &&
 288            is_same_network(&(padapter->mlmepriv.cur_network.network), src)) {
 289                if (padapter->recvpriv.signal_qual_data.total_num++ >=
 290                    PHY_LINKQUALITY_SLID_WIN_MAX) {
 291                        padapter->recvpriv.signal_qual_data.total_num =
 292                                   PHY_LINKQUALITY_SLID_WIN_MAX;
 293                        last_evm = sqd->elements[sqd->index];
 294                        padapter->recvpriv.signal_qual_data.total_val -=
 295                                 last_evm;
 296                }
 297                padapter->recvpriv.signal_qual_data.total_val += src->Rssi;
 298
 299                sqd->elements[sqd->index++] = src->Rssi;
 300                if (padapter->recvpriv.signal_qual_data.index >=
 301                    PHY_LINKQUALITY_SLID_WIN_MAX)
 302                        padapter->recvpriv.signal_qual_data.index = 0;
 303                /* <1> Showed on UI for user, in percentage. */
 304                tmpVal = padapter->recvpriv.signal_qual_data.total_val /
 305                         padapter->recvpriv.signal_qual_data.total_num;
 306                padapter->recvpriv.signal = (u8)tmpVal;
 307
 308                src->Rssi = padapter->recvpriv.signal;
 309        } else {
 310                src->Rssi = (src->Rssi + dst->Rssi) / 2;
 311        }
 312        memcpy((u8 *)dst, (u8 *)src, r8712_get_wlan_bssid_ex_sz(src));
 313}
 314
 315static void update_current_network(struct _adapter *adapter,
 316                                   struct wlan_bssid_ex *pnetwork)
 317{
 318        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 319
 320        if (is_same_network(&(pmlmepriv->cur_network.network), pnetwork)) {
 321                update_network(&(pmlmepriv->cur_network.network),
 322                               pnetwork, adapter);
 323                r8712_update_protection(adapter,
 324                               (pmlmepriv->cur_network.network.IEs) +
 325                               sizeof(struct NDIS_802_11_FIXED_IEs),
 326                               pmlmepriv->cur_network.network.IELength);
 327        }
 328}
 329
 330/* Caller must hold pmlmepriv->lock first */
 331static void update_scanned_network(struct _adapter *adapter,
 332                            struct wlan_bssid_ex *target)
 333{
 334        struct list_head *plist, *phead;
 335
 336        u32 bssid_ex_sz;
 337        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 338        struct  __queue *queue = &pmlmepriv->scanned_queue;
 339        struct wlan_network *pnetwork = NULL;
 340        struct wlan_network *oldest = NULL;
 341
 342        phead = &queue->queue;
 343        plist = phead->next;
 344
 345        while (1) {
 346                if (end_of_queue_search(phead, plist))
 347                        break;
 348
 349                pnetwork = container_of(plist, struct wlan_network, list);
 350                if (is_same_network(&pnetwork->network, target))
 351                        break;
 352                if ((oldest == ((struct wlan_network *)0)) ||
 353                    time_after((unsigned long)oldest->last_scanned,
 354                                (unsigned long)pnetwork->last_scanned))
 355                        oldest = pnetwork;
 356
 357                plist = plist->next;
 358        }
 359
 360        /* If we didn't find a match, then get a new network slot to initialize
 361         * with this beacon's information
 362         */
 363        if (end_of_queue_search(phead, plist)) {
 364                if (list_empty(&pmlmepriv->free_bss_pool.queue)) {
 365                        /* If there are no more slots, expire the oldest */
 366                        pnetwork = oldest;
 367                        target->Rssi = (pnetwork->network.Rssi +
 368                                        target->Rssi) / 2;
 369                        memcpy(&pnetwork->network, target,
 370                                r8712_get_wlan_bssid_ex_sz(target));
 371                        pnetwork->last_scanned = jiffies;
 372                } else {
 373                        /* Otherwise just pull from the free list */
 374                        /* update scan_time */
 375                        pnetwork = alloc_network(pmlmepriv);
 376                        if (!pnetwork)
 377                                return;
 378                        bssid_ex_sz = r8712_get_wlan_bssid_ex_sz(target);
 379                        target->Length = bssid_ex_sz;
 380                        memcpy(&pnetwork->network, target, bssid_ex_sz);
 381                        list_add_tail(&pnetwork->list, &queue->queue);
 382                }
 383        } else {
 384                /* we have an entry and we are going to update it. But
 385                 * this entry may be already expired. In this case we
 386                 * do the same as we found a new net and call the new_net
 387                 * handler
 388                 */
 389                update_network(&pnetwork->network, target, adapter);
 390                pnetwork->last_scanned = jiffies;
 391        }
 392}
 393
 394static void rtl8711_add_network(struct _adapter *adapter,
 395                         struct wlan_bssid_ex *pnetwork)
 396{
 397        unsigned long irqL;
 398        struct mlme_priv *pmlmepriv = &(((struct _adapter *)adapter)->mlmepriv);
 399        struct  __queue *queue = &pmlmepriv->scanned_queue;
 400
 401        spin_lock_irqsave(&queue->lock, irqL);
 402        update_current_network(adapter, pnetwork);
 403        update_scanned_network(adapter, pnetwork);
 404        spin_unlock_irqrestore(&queue->lock, irqL);
 405}
 406
 407/*select the desired network based on the capability of the (i)bss.
 408 * check items:         (1) security
 409 *                      (2) network_type
 410 *                      (3) WMM
 411 *                      (4) HT
 412 *                      (5) others
 413 */
 414static int is_desired_network(struct _adapter *adapter,
 415                                struct wlan_network *pnetwork)
 416{
 417        u8 wps_ie[512];
 418        uint wps_ielen;
 419        int bselected = true;
 420        struct  security_priv *psecuritypriv = &adapter->securitypriv;
 421
 422        if (psecuritypriv->wps_phase) {
 423                if (r8712_get_wps_ie(pnetwork->network.IEs,
 424                    pnetwork->network.IELength, wps_ie,
 425                    &wps_ielen))
 426                        return true;
 427                return false;
 428        }
 429        if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) &&
 430                    (pnetwork->network.Privacy == 0))
 431                bselected = false;
 432        if (check_fwstate(&adapter->mlmepriv, WIFI_ADHOC_STATE)) {
 433                if (pnetwork->network.InfrastructureMode !=
 434                        adapter->mlmepriv.cur_network.network.
 435                        InfrastructureMode)
 436                        bselected = false;
 437        }
 438        return bselected;
 439}
 440
 441/* TODO: Perry : For Power Management */
 442void r8712_atimdone_event_callback(struct _adapter *adapter, u8 *pbuf)
 443{
 444}
 445
 446void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf)
 447{
 448        unsigned long flags;
 449        u32 len;
 450        struct wlan_bssid_ex *pnetwork;
 451        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 452
 453        pnetwork = (struct wlan_bssid_ex *)pbuf;
 454#ifdef __BIG_ENDIAN
 455        /* endian_convert */
 456        pnetwork->Length = le32_to_cpu(pnetwork->Length);
 457        pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength);
 458        pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy);
 459        pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi);
 460        pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse);
 461        pnetwork->Configuration.ATIMWindow =
 462                 le32_to_cpu(pnetwork->Configuration.ATIMWindow);
 463        pnetwork->Configuration.BeaconPeriod =
 464                 le32_to_cpu(pnetwork->Configuration.BeaconPeriod);
 465        pnetwork->Configuration.DSConfig =
 466                 le32_to_cpu(pnetwork->Configuration.DSConfig);
 467        pnetwork->Configuration.FHConfig.DwellTime =
 468                 le32_to_cpu(pnetwork->Configuration.FHConfig.DwellTime);
 469        pnetwork->Configuration.FHConfig.HopPattern =
 470                 le32_to_cpu(pnetwork->Configuration.FHConfig.HopPattern);
 471        pnetwork->Configuration.FHConfig.HopSet =
 472                 le32_to_cpu(pnetwork->Configuration.FHConfig.HopSet);
 473        pnetwork->Configuration.FHConfig.Length =
 474                 le32_to_cpu(pnetwork->Configuration.FHConfig.Length);
 475        pnetwork->Configuration.Length =
 476                 le32_to_cpu(pnetwork->Configuration.Length);
 477        pnetwork->InfrastructureMode =
 478                 le32_to_cpu(pnetwork->InfrastructureMode);
 479        pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
 480#endif
 481        len = r8712_get_wlan_bssid_ex_sz(pnetwork);
 482        if (len > sizeof(struct wlan_bssid_ex))
 483                return;
 484        spin_lock_irqsave(&pmlmepriv->lock2, flags);
 485        /* update IBSS_network 's timestamp */
 486        if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
 487                if (!memcmp(&(pmlmepriv->cur_network.network.MacAddress),
 488                    pnetwork->MacAddress, ETH_ALEN)) {
 489                        struct wlan_network *ibss_wlan = NULL;
 490
 491                        memcpy(pmlmepriv->cur_network.network.IEs,
 492                                pnetwork->IEs, 8);
 493                        ibss_wlan = r8712_find_network(
 494                                                &pmlmepriv->scanned_queue,
 495                                                pnetwork->MacAddress);
 496                        if (ibss_wlan) {
 497                                memcpy(ibss_wlan->network.IEs,
 498                                        pnetwork->IEs, 8);
 499                                goto exit;
 500                        }
 501                }
 502        }
 503        /* lock pmlmepriv->lock when you accessing network_q */
 504        if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
 505                if (pnetwork->Ssid.Ssid[0] != 0) {
 506                        rtl8711_add_network(adapter, pnetwork);
 507                } else {
 508                        pnetwork->Ssid.SsidLength = 8;
 509                        memcpy(pnetwork->Ssid.Ssid, "<hidden>", 8);
 510                        rtl8711_add_network(adapter, pnetwork);
 511                }
 512        }
 513exit:
 514        spin_unlock_irqrestore(&pmlmepriv->lock2, flags);
 515}
 516
 517void r8712_surveydone_event_callback(struct _adapter *adapter, u8 *pbuf)
 518{
 519        unsigned long irqL;
 520        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 521
 522        spin_lock_irqsave(&pmlmepriv->lock, irqL);
 523
 524        if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
 525                del_timer(&pmlmepriv->scan_to_timer);
 526
 527                _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
 528        }
 529
 530        if (pmlmepriv->to_join) {
 531                if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
 532                        if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
 533                                set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
 534
 535                                if (!r8712_select_and_join_from_scan(pmlmepriv)) {
 536                                        mod_timer(&pmlmepriv->assoc_timer, jiffies +
 537                                                  msecs_to_jiffies(MAX_JOIN_TIMEOUT));
 538                                } else {
 539                                        struct wlan_bssid_ex *pdev_network =
 540                                          &(adapter->registrypriv.dev_network);
 541                                        u8 *pibss =
 542                                                 adapter->registrypriv.
 543                                                        dev_network.MacAddress;
 544                                        pmlmepriv->fw_state ^= _FW_UNDER_SURVEY;
 545                                        memcpy(&pdev_network->Ssid,
 546                                                &pmlmepriv->assoc_ssid,
 547                                                sizeof(struct
 548                                                         ndis_802_11_ssid));
 549                                        r8712_update_registrypriv_dev_network
 550                                                (adapter);
 551                                        r8712_generate_random_ibss(pibss);
 552                                        pmlmepriv->fw_state =
 553                                                 WIFI_ADHOC_MASTER_STATE;
 554                                        pmlmepriv->to_join = false;
 555                                }
 556                        }
 557                } else {
 558                        pmlmepriv->to_join = false;
 559                        set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
 560                        if (!r8712_select_and_join_from_scan(pmlmepriv))
 561                                mod_timer(&pmlmepriv->assoc_timer, jiffies +
 562                                          msecs_to_jiffies(MAX_JOIN_TIMEOUT));
 563                        else
 564                                _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
 565                }
 566        }
 567        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 568}
 569
 570/*
 571 *r8712_free_assoc_resources: the caller has to lock pmlmepriv->lock
 572 */
 573void r8712_free_assoc_resources(struct _adapter *adapter)
 574{
 575        unsigned long irqL;
 576        struct wlan_network *pwlan = NULL;
 577        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 578        struct sta_priv *pstapriv = &adapter->stapriv;
 579        struct wlan_network *tgt_network = &pmlmepriv->cur_network;
 580
 581        pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
 582                                   tgt_network->network.MacAddress);
 583
 584        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) {
 585                struct sta_info *psta;
 586
 587                psta = r8712_get_stainfo(&adapter->stapriv,
 588                                         tgt_network->network.MacAddress);
 589
 590                spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
 591                r8712_free_stainfo(adapter,  psta);
 592                spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
 593        }
 594
 595        if (check_fwstate(pmlmepriv,
 596            WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
 597                r8712_free_all_stainfo(adapter);
 598        if (pwlan)
 599                pwlan->fixed = false;
 600
 601        if (((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) &&
 602             (adapter->stapriv.asoc_sta_count == 1)))
 603                free_network_nolock(pmlmepriv, pwlan);
 604}
 605
 606/*
 607 * r8712_indicate_connect: the caller has to lock pmlmepriv->lock
 608 */
 609void r8712_indicate_connect(struct _adapter *padapter)
 610{
 611        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 612
 613        pmlmepriv->to_join = false;
 614        set_fwstate(pmlmepriv, _FW_LINKED);
 615        padapter->ledpriv.LedControlHandler(padapter, LED_CTL_LINK);
 616        r8712_os_indicate_connect(padapter);
 617        if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE)
 618                mod_timer(&pmlmepriv->dhcp_timer,
 619                          jiffies + msecs_to_jiffies(60000));
 620}
 621
 622/*
 623 * r8712_ind_disconnect: the caller has to lock pmlmepriv->lock
 624 */
 625void r8712_ind_disconnect(struct _adapter *padapter)
 626{
 627        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 628
 629        if (check_fwstate(pmlmepriv, _FW_LINKED)) {
 630                _clr_fwstate_(pmlmepriv, _FW_LINKED);
 631                padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
 632                r8712_os_indicate_disconnect(padapter);
 633        }
 634        if (padapter->pwrctrlpriv.pwr_mode !=
 635            padapter->registrypriv.power_mgnt) {
 636                del_timer(&pmlmepriv->dhcp_timer);
 637                r8712_set_ps_mode(padapter, padapter->registrypriv.power_mgnt,
 638                                  padapter->registrypriv.smart_ps);
 639        }
 640}
 641
 642/*Notes:
 643 *pnetwork : returns from r8712_joinbss_event_callback
 644 *ptarget_wlan: found from scanned_queue
 645 *if join_res > 0, for (fw_state==WIFI_STATION_STATE), we check if
 646 *  "ptarget_sta" & "ptarget_wlan" exist.
 647 *if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), we only check
 648 * if "ptarget_wlan" exist.
 649 *if join_res > 0, update "cur_network->network" from
 650 * "pnetwork->network" if (ptarget_wlan !=NULL).
 651 */
 652void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
 653{
 654        unsigned long irqL = 0, irqL2;
 655        struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL;
 656        struct sta_priv *pstapriv = &adapter->stapriv;
 657        struct mlme_priv        *pmlmepriv = &adapter->mlmepriv;
 658        struct wlan_network     *cur_network = &pmlmepriv->cur_network;
 659        struct wlan_network     *pcur_wlan = NULL, *ptarget_wlan = NULL;
 660        unsigned int            the_same_macaddr = false;
 661        struct wlan_network *pnetwork;
 662
 663        if (sizeof(struct list_head) == 4 * sizeof(u32)) {
 664                pnetwork = kmalloc(sizeof(struct wlan_network), GFP_ATOMIC);
 665                if (!pnetwork)
 666                        return;
 667                memcpy((u8 *)pnetwork + 16, (u8 *)pbuf + 8,
 668                       sizeof(struct wlan_network) - 16);
 669        } else {
 670                pnetwork = (struct wlan_network *)pbuf;
 671        }
 672
 673#ifdef __BIG_ENDIAN
 674        /* endian_convert */
 675        pnetwork->join_res = le32_to_cpu(pnetwork->join_res);
 676        pnetwork->network_type = le32_to_cpu(pnetwork->network_type);
 677        pnetwork->network.Length = le32_to_cpu(pnetwork->network.Length);
 678        pnetwork->network.Ssid.SsidLength =
 679                 le32_to_cpu(pnetwork->network.Ssid.SsidLength);
 680        pnetwork->network.Privacy = le32_to_cpu(pnetwork->network.Privacy);
 681        pnetwork->network.Rssi = le32_to_cpu(pnetwork->network.Rssi);
 682        pnetwork->network.NetworkTypeInUse =
 683                 le32_to_cpu(pnetwork->network.NetworkTypeInUse);
 684        pnetwork->network.Configuration.ATIMWindow =
 685                 le32_to_cpu(pnetwork->network.Configuration.ATIMWindow);
 686        pnetwork->network.Configuration.BeaconPeriod =
 687                 le32_to_cpu(pnetwork->network.Configuration.BeaconPeriod);
 688        pnetwork->network.Configuration.DSConfig =
 689                 le32_to_cpu(pnetwork->network.Configuration.DSConfig);
 690        pnetwork->network.Configuration.FHConfig.DwellTime =
 691                 le32_to_cpu(pnetwork->network.Configuration.FHConfig.
 692                             DwellTime);
 693        pnetwork->network.Configuration.FHConfig.HopPattern =
 694                 le32_to_cpu(pnetwork->network.Configuration.
 695                             FHConfig.HopPattern);
 696        pnetwork->network.Configuration.FHConfig.HopSet =
 697                 le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopSet);
 698        pnetwork->network.Configuration.FHConfig.Length =
 699                 le32_to_cpu(pnetwork->network.Configuration.FHConfig.Length);
 700        pnetwork->network.Configuration.Length =
 701                 le32_to_cpu(pnetwork->network.Configuration.Length);
 702        pnetwork->network.InfrastructureMode =
 703                 le32_to_cpu(pnetwork->network.InfrastructureMode);
 704        pnetwork->network.IELength = le32_to_cpu(pnetwork->network.IELength);
 705#endif
 706
 707        the_same_macaddr = !memcmp(pnetwork->network.MacAddress,
 708                                   cur_network->network.MacAddress, ETH_ALEN);
 709        pnetwork->network.Length =
 710                 r8712_get_wlan_bssid_ex_sz(&pnetwork->network);
 711        spin_lock_irqsave(&pmlmepriv->lock, irqL);
 712        if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
 713                goto ignore_joinbss_callback;
 714        if (pnetwork->join_res > 0) {
 715                if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
 716                        /*s1. find ptarget_wlan*/
 717                        if (check_fwstate(pmlmepriv, _FW_LINKED)) {
 718                                if (the_same_macaddr) {
 719                                        ptarget_wlan =
 720                                            r8712_find_network(&pmlmepriv->
 721                                            scanned_queue,
 722                                            cur_network->network.MacAddress);
 723                                } else {
 724                                        pcur_wlan =
 725                                             r8712_find_network(&pmlmepriv->
 726                                             scanned_queue,
 727                                             cur_network->network.MacAddress);
 728                                        if (pcur_wlan)
 729                                                pcur_wlan->fixed = false;
 730
 731                                        pcur_sta = r8712_get_stainfo(pstapriv,
 732                                             cur_network->network.MacAddress);
 733                                        spin_lock_irqsave(&pstapriv->
 734                                                sta_hash_lock, irqL2);
 735                                        r8712_free_stainfo(adapter, pcur_sta);
 736                                        spin_unlock_irqrestore(&(pstapriv->
 737                                                sta_hash_lock), irqL2);
 738
 739                                        ptarget_wlan =
 740                                                 r8712_find_network(&pmlmepriv->
 741                                                 scanned_queue,
 742                                                 pnetwork->network.
 743                                                 MacAddress);
 744                                        if (ptarget_wlan)
 745                                                ptarget_wlan->fixed = true;
 746                                }
 747                        } else {
 748                                ptarget_wlan = r8712_find_network(&pmlmepriv->
 749                                                scanned_queue,
 750                                                pnetwork->network.MacAddress);
 751                                if (ptarget_wlan)
 752                                        ptarget_wlan->fixed = true;
 753                        }
 754
 755                        if (!ptarget_wlan) {
 756                                if (check_fwstate(pmlmepriv,
 757                                        _FW_UNDER_LINKING))
 758                                        pmlmepriv->fw_state ^=
 759                                                 _FW_UNDER_LINKING;
 760                                goto ignore_joinbss_callback;
 761                        }
 762
 763                        /*s2. find ptarget_sta & update ptarget_sta*/
 764                        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
 765                                if (the_same_macaddr) {
 766                                        ptarget_sta =
 767                                                 r8712_get_stainfo(pstapriv,
 768                                                 pnetwork->network.MacAddress);
 769                                        if (!ptarget_sta)
 770                                                ptarget_sta =
 771                                                 r8712_alloc_stainfo(pstapriv,
 772                                                 pnetwork->network.MacAddress);
 773                                } else {
 774                                        ptarget_sta =
 775                                                 r8712_alloc_stainfo(pstapriv,
 776                                                 pnetwork->network.MacAddress);
 777                                }
 778                                if (ptarget_sta) /*update ptarget_sta*/ {
 779                                        ptarget_sta->aid = pnetwork->join_res;
 780                                        ptarget_sta->qos_option = 1;
 781                                        ptarget_sta->mac_id = 5;
 782                                        if (adapter->securitypriv.
 783                                            AuthAlgrthm == 2) {
 784                                                adapter->securitypriv.
 785                                                        binstallGrpkey =
 786                                                         false;
 787                                                adapter->securitypriv.
 788                                                        busetkipkey =
 789                                                         false;
 790                                                adapter->securitypriv.
 791                                                        bgrpkey_handshake =
 792                                                         false;
 793                                                ptarget_sta->ieee8021x_blocked
 794                                                         = true;
 795                                                ptarget_sta->XPrivacy =
 796                                                         adapter->securitypriv.
 797                                                         PrivacyAlgrthm;
 798                                                memset((u8 *)&ptarget_sta->
 799                                                         x_UncstKey,
 800                                                         0,
 801                                                         sizeof(union Keytype));
 802                                                memset((u8 *)&ptarget_sta->
 803                                                         tkiprxmickey,
 804                                                         0,
 805                                                         sizeof(union Keytype));
 806                                                memset((u8 *)&ptarget_sta->
 807                                                         tkiptxmickey,
 808                                                         0,
 809                                                         sizeof(union Keytype));
 810                                                memset((u8 *)&ptarget_sta->
 811                                                         txpn, 0,
 812                                                         sizeof(union pn48));
 813                                                memset((u8 *)&ptarget_sta->
 814                                                         rxpn, 0,
 815                                                         sizeof(union pn48));
 816                                        }
 817                                } else {
 818                                        if (check_fwstate(pmlmepriv,
 819                                            _FW_UNDER_LINKING))
 820                                                pmlmepriv->fw_state ^=
 821                                                         _FW_UNDER_LINKING;
 822                                        goto ignore_joinbss_callback;
 823                                }
 824                        }
 825
 826                        /*s3. update cur_network & indicate connect*/
 827                        memcpy(&cur_network->network, &pnetwork->network,
 828                                pnetwork->network.Length);
 829                        cur_network->aid = pnetwork->join_res;
 830                        /*update fw_state will clr _FW_UNDER_LINKING*/
 831                        switch (pnetwork->network.InfrastructureMode) {
 832                        case Ndis802_11Infrastructure:
 833                                pmlmepriv->fw_state = WIFI_STATION_STATE;
 834                                break;
 835                        case Ndis802_11IBSS:
 836                                pmlmepriv->fw_state = WIFI_ADHOC_STATE;
 837                                break;
 838                        default:
 839                                pmlmepriv->fw_state = WIFI_NULL_STATE;
 840                                break;
 841                        }
 842                        r8712_update_protection(adapter,
 843                                          (cur_network->network.IEs) +
 844                                          sizeof(struct NDIS_802_11_FIXED_IEs),
 845                                          (cur_network->network.IELength));
 846                        /*TODO: update HT_Capability*/
 847                        update_ht_cap(adapter, cur_network->network.IEs,
 848                                      cur_network->network.IELength);
 849                        /*indicate connect*/
 850                        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
 851                                r8712_indicate_connect(adapter);
 852                        del_timer(&pmlmepriv->assoc_timer);
 853                } else {
 854                        goto ignore_joinbss_callback;
 855                }
 856        } else {
 857                if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
 858                        mod_timer(&pmlmepriv->assoc_timer,
 859                                  jiffies + msecs_to_jiffies(1));
 860                        _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
 861                }
 862        }
 863ignore_joinbss_callback:
 864        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 865        if (sizeof(struct list_head) == 4 * sizeof(u32))
 866                kfree(pnetwork);
 867}
 868
 869void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf)
 870{
 871        unsigned long irqL;
 872        struct sta_info *psta;
 873        struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
 874        struct stassoc_event *pstassoc  = (struct stassoc_event *)pbuf;
 875
 876        /* to do: */
 877        if (!r8712_access_ctrl(&adapter->acl_list, pstassoc->macaddr))
 878                return;
 879        psta = r8712_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
 880        if (psta) {
 881                /*the sta have been in sta_info_queue => do nothing
 882                 *(between drv has received this event before and
 883                 * fw have not yet to set key to CAM_ENTRY)
 884                 */
 885                return;
 886        }
 887
 888        psta = r8712_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
 889        if (!psta)
 890                return;
 891        /* to do : init sta_info variable */
 892        psta->qos_option = 0;
 893        psta->mac_id = le32_to_cpu(pstassoc->cam_id);
 894        /* psta->aid = (uint)pstassoc->cam_id; */
 895
 896        if (adapter->securitypriv.AuthAlgrthm == 2)
 897                psta->XPrivacy = adapter->securitypriv.PrivacyAlgrthm;
 898        psta->ieee8021x_blocked = false;
 899        spin_lock_irqsave(&pmlmepriv->lock, irqL);
 900        if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
 901            check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
 902                if (adapter->stapriv.asoc_sta_count == 2) {
 903                        /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
 904                        r8712_indicate_connect(adapter);
 905                }
 906        }
 907        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 908}
 909
 910void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf)
 911{
 912        unsigned long irqL, irqL2;
 913        struct sta_info *psta;
 914        struct wlan_network *pwlan = NULL;
 915        struct wlan_bssid_ex *pdev_network = NULL;
 916        u8 *pibss = NULL;
 917        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 918        struct stadel_event *pstadel = (struct stadel_event *)pbuf;
 919        struct sta_priv *pstapriv = &adapter->stapriv;
 920        struct wlan_network *tgt_network = &pmlmepriv->cur_network;
 921
 922        spin_lock_irqsave(&pmlmepriv->lock, irqL2);
 923        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
 924                r8712_ind_disconnect(adapter);
 925                r8712_free_assoc_resources(adapter);
 926        }
 927        if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE |
 928            WIFI_ADHOC_STATE)) {
 929                psta = r8712_get_stainfo(&adapter->stapriv, pstadel->macaddr);
 930                spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
 931                r8712_free_stainfo(adapter, psta);
 932                spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
 933                if (adapter->stapriv.asoc_sta_count == 1) {
 934                        /*a sta + bc/mc_stainfo (not Ibss_stainfo) */
 935                        pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
 936                                tgt_network->network.MacAddress);
 937                        if (pwlan) {
 938                                pwlan->fixed = false;
 939                                free_network_nolock(pmlmepriv, pwlan);
 940                        }
 941                        /*re-create ibss*/
 942                        pdev_network = &(adapter->registrypriv.dev_network);
 943                        pibss = adapter->registrypriv.dev_network.MacAddress;
 944                        memcpy(pdev_network, &tgt_network->network,
 945                                r8712_get_wlan_bssid_ex_sz(&tgt_network->
 946                                                        network));
 947                        memcpy(&pdev_network->Ssid,
 948                                &pmlmepriv->assoc_ssid,
 949                                sizeof(struct ndis_802_11_ssid));
 950                        r8712_update_registrypriv_dev_network(adapter);
 951                        r8712_generate_random_ibss(pibss);
 952                        if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
 953                                _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
 954                                set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
 955                        }
 956                }
 957        }
 958        spin_unlock_irqrestore(&pmlmepriv->lock, irqL2);
 959}
 960
 961void r8712_cpwm_event_callback(struct _adapter *adapter, u8 *pbuf)
 962{
 963        struct reportpwrstate_parm *preportpwrstate =
 964                         (struct reportpwrstate_parm *)pbuf;
 965
 966        preportpwrstate->state |= (u8)(adapter->pwrctrlpriv.cpwm_tog + 0x80);
 967        r8712_cpwm_int_hdl(adapter, preportpwrstate);
 968}
 969
 970/*      When the Netgear 3500 AP is with WPA2PSK-AES mode, it will send
 971 *       the ADDBA req frame with start seq control = 0 to wifi client after
 972 *       the WPA handshake and the seqence number of following data packet
 973 *      will be 0. In this case, the Rx reorder sequence is not longer than 0
 974 *       and the WiFi client will drop the data with seq number 0.
 975 *      So, the 8712 firmware has to inform driver with receiving the
 976 *       ADDBA-Req frame so that the driver can reset the
 977 *      sequence value of Rx reorder control.
 978 */
 979void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf)
 980{
 981        struct  ADDBA_Req_Report_parm *pAddbareq_pram =
 982                         (struct ADDBA_Req_Report_parm *)pbuf;
 983        struct  sta_info *psta;
 984        struct  sta_priv *pstapriv = &adapter->stapriv;
 985        struct  recv_reorder_ctrl *precvreorder_ctrl = NULL;
 986
 987        psta = r8712_get_stainfo(pstapriv, pAddbareq_pram->MacAddress);
 988        if (psta) {
 989                precvreorder_ctrl =
 990                         &psta->recvreorder_ctrl[pAddbareq_pram->tid];
 991                /* set the indicate_seq to 0xffff so that the rx reorder
 992                 * can store any following data packet.
 993                 */
 994                precvreorder_ctrl->indicate_seq = 0xffff;
 995        }
 996}
 997
 998void r8712_wpspbc_event_callback(struct _adapter *adapter, u8 *pbuf)
 999{
1000        if (!adapter->securitypriv.wps_hw_pbc_pressed)
1001                adapter->securitypriv.wps_hw_pbc_pressed = true;
1002}
1003
1004void _r8712_sitesurvey_ctrl_handler(struct _adapter *adapter)
1005{
1006        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1007        struct sitesurvey_ctrl  *psitesurveyctrl = &pmlmepriv->sitesurveyctrl;
1008        struct registry_priv    *pregistrypriv = &adapter->registrypriv;
1009        u64 current_tx_pkts;
1010        uint current_rx_pkts;
1011
1012        current_tx_pkts = (adapter->xmitpriv.tx_pkts) -
1013                          (psitesurveyctrl->last_tx_pkts);
1014        current_rx_pkts = (adapter->recvpriv.rx_pkts) -
1015                          (psitesurveyctrl->last_rx_pkts);
1016        psitesurveyctrl->last_tx_pkts = adapter->xmitpriv.tx_pkts;
1017        psitesurveyctrl->last_rx_pkts = adapter->recvpriv.rx_pkts;
1018        if ((current_tx_pkts > pregistrypriv->busy_thresh) ||
1019            (current_rx_pkts > pregistrypriv->busy_thresh))
1020                psitesurveyctrl->traffic_busy = true;
1021        else
1022                psitesurveyctrl->traffic_busy = false;
1023}
1024
1025void _r8712_join_timeout_handler(struct _adapter *adapter)
1026{
1027        unsigned long irqL;
1028        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1029
1030        if (adapter->driver_stopped || adapter->surprise_removed)
1031                return;
1032        spin_lock_irqsave(&pmlmepriv->lock, irqL);
1033        _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1034        pmlmepriv->to_join = false;
1035        if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1036                r8712_os_indicate_disconnect(adapter);
1037                _clr_fwstate_(pmlmepriv, _FW_LINKED);
1038        }
1039        if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt) {
1040                r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
1041                                  adapter->registrypriv.smart_ps);
1042        }
1043        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1044}
1045
1046void r8712_scan_timeout_handler (struct _adapter *adapter)
1047{
1048        unsigned long irqL;
1049        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1050
1051        spin_lock_irqsave(&pmlmepriv->lock, irqL);
1052        _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1053        pmlmepriv->to_join = false;     /* scan fail, so clear to_join flag */
1054        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1055}
1056
1057void _r8712_dhcp_timeout_handler (struct _adapter *adapter)
1058{
1059        if (adapter->driver_stopped || adapter->surprise_removed)
1060                return;
1061        if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt)
1062                r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
1063                            adapter->registrypriv.smart_ps);
1064}
1065
1066int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv)
1067{
1068        struct list_head *phead;
1069        unsigned char *dst_ssid, *src_ssid;
1070        struct _adapter *adapter;
1071        struct  __queue *queue = NULL;
1072        struct wlan_network *pnetwork = NULL;
1073        struct wlan_network *pnetwork_max_rssi = NULL;
1074
1075        adapter = (struct _adapter *)pmlmepriv->nic_hdl;
1076        queue = &pmlmepriv->scanned_queue;
1077        phead = &queue->queue;
1078        pmlmepriv->pscanned = phead->next;
1079        while (1) {
1080                if (end_of_queue_search(phead, pmlmepriv->pscanned)) {
1081                        if (pmlmepriv->assoc_by_rssi && pnetwork_max_rssi) {
1082                                pnetwork = pnetwork_max_rssi;
1083                                goto ask_for_joinbss;
1084                        }
1085                        return -EINVAL;
1086                }
1087                pnetwork = container_of(pmlmepriv->pscanned,
1088                                        struct wlan_network, list);
1089                pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1090                if (pmlmepriv->assoc_by_bssid) {
1091                        dst_ssid = pnetwork->network.MacAddress;
1092                        src_ssid = pmlmepriv->assoc_bssid;
1093                        if (!memcmp(dst_ssid, src_ssid, ETH_ALEN)) {
1094                                if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1095                                        if (is_same_network(&pmlmepriv->
1096                                            cur_network.network,
1097                                            &pnetwork->network)) {
1098                                                _clr_fwstate_(pmlmepriv,
1099                                                        _FW_UNDER_LINKING);
1100                                                /*r8712_indicate_connect again*/
1101                                                r8712_indicate_connect(adapter);
1102                                                return 2;
1103                                        }
1104                                        r8712_disassoc_cmd(adapter);
1105                                        r8712_ind_disconnect(adapter);
1106                                        r8712_free_assoc_resources(adapter);
1107                                }
1108                                goto ask_for_joinbss;
1109                        }
1110                } else if (pmlmepriv->assoc_ssid.SsidLength == 0) {
1111                        goto ask_for_joinbss;
1112                }
1113                dst_ssid = pnetwork->network.Ssid.Ssid;
1114                src_ssid = pmlmepriv->assoc_ssid.Ssid;
1115                if ((pnetwork->network.Ssid.SsidLength ==
1116                    pmlmepriv->assoc_ssid.SsidLength) &&
1117                    (!memcmp(dst_ssid, src_ssid,
1118                     pmlmepriv->assoc_ssid.SsidLength))) {
1119                        if (pmlmepriv->assoc_by_rssi) {
1120                                /* if the ssid is the same, select the bss
1121                                 * which has the max rssi
1122                                 */
1123                                if (pnetwork_max_rssi) {
1124                                        if (pnetwork->network.Rssi >
1125                                            pnetwork_max_rssi->network.Rssi)
1126                                                pnetwork_max_rssi = pnetwork;
1127                                } else {
1128                                        pnetwork_max_rssi = pnetwork;
1129                                }
1130                        } else if (is_desired_network(adapter, pnetwork)) {
1131                                if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1132                                        r8712_disassoc_cmd(adapter);
1133                                        r8712_free_assoc_resources(adapter);
1134                                }
1135                                goto ask_for_joinbss;
1136                        }
1137                }
1138        }
1139
1140ask_for_joinbss:
1141        return r8712_joinbss_cmd(adapter, pnetwork);
1142}
1143
1144int r8712_set_auth(struct _adapter *adapter,
1145                   struct security_priv *psecuritypriv)
1146{
1147        struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1148        struct cmd_obj *pcmd;
1149        struct setauth_parm *psetauthparm;
1150
1151        pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
1152        if (!pcmd)
1153                return -ENOMEM;
1154
1155        psetauthparm = kzalloc(sizeof(*psetauthparm), GFP_ATOMIC);
1156        if (!psetauthparm) {
1157                kfree(pcmd);
1158                return -ENOMEM;
1159        }
1160        psetauthparm->mode = (u8)psecuritypriv->AuthAlgrthm;
1161        pcmd->cmdcode = _SetAuth_CMD_;
1162        pcmd->parmbuf = (unsigned char *)psetauthparm;
1163        pcmd->cmdsz = sizeof(struct setauth_parm);
1164        pcmd->rsp = NULL;
1165        pcmd->rspsz = 0;
1166        INIT_LIST_HEAD(&pcmd->list);
1167        r8712_enqueue_cmd(pcmdpriv, pcmd);
1168        return 0;
1169}
1170
1171int r8712_set_key(struct _adapter *adapter,
1172                  struct security_priv *psecuritypriv,
1173                  sint keyid)
1174{
1175        struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1176        struct cmd_obj *pcmd;
1177        struct setkey_parm *psetkeyparm;
1178        u8 keylen;
1179        int ret;
1180
1181        pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
1182        if (!pcmd)
1183                return -ENOMEM;
1184        psetkeyparm = kzalloc(sizeof(*psetkeyparm), GFP_ATOMIC);
1185        if (!psetkeyparm) {
1186                ret = -ENOMEM;
1187                goto err_free_cmd;
1188        }
1189        if (psecuritypriv->AuthAlgrthm == 2) { /* 802.1X */
1190                psetkeyparm->algorithm =
1191                         (u8)psecuritypriv->XGrpPrivacy;
1192        } else { /* WEP */
1193                psetkeyparm->algorithm =
1194                         (u8)psecuritypriv->PrivacyAlgrthm;
1195        }
1196        psetkeyparm->keyid = (u8)keyid;
1197
1198        switch (psetkeyparm->algorithm) {
1199        case _WEP40_:
1200                keylen = 5;
1201                memcpy(psetkeyparm->key,
1202                        psecuritypriv->DefKey[keyid].skey, keylen);
1203                break;
1204        case _WEP104_:
1205                keylen = 13;
1206                memcpy(psetkeyparm->key,
1207                        psecuritypriv->DefKey[keyid].skey, keylen);
1208                break;
1209        case _TKIP_:
1210                if (keyid < 1 || keyid > 2) {
1211                        ret = -EINVAL;
1212                        goto err_free_parm;
1213                }
1214                keylen = 16;
1215                memcpy(psetkeyparm->key,
1216                        &psecuritypriv->XGrpKey[keyid - 1], keylen);
1217                psetkeyparm->grpkey = 1;
1218                break;
1219        case _AES_:
1220                if (keyid < 1 || keyid > 2) {
1221                        ret = -EINVAL;
1222                        goto err_free_parm;
1223                }
1224                keylen = 16;
1225                memcpy(psetkeyparm->key,
1226                        &psecuritypriv->XGrpKey[keyid - 1], keylen);
1227                psetkeyparm->grpkey = 1;
1228                break;
1229        default:
1230                ret = -EINVAL;
1231                goto err_free_parm;
1232        }
1233        pcmd->cmdcode = _SetKey_CMD_;
1234        pcmd->parmbuf = (u8 *)psetkeyparm;
1235        pcmd->cmdsz =  (sizeof(struct setkey_parm));
1236        pcmd->rsp = NULL;
1237        pcmd->rspsz = 0;
1238        INIT_LIST_HEAD(&pcmd->list);
1239        r8712_enqueue_cmd(pcmdpriv, pcmd);
1240        return 0;
1241
1242err_free_parm:
1243        kfree(psetkeyparm);
1244err_free_cmd:
1245        kfree(pcmd);
1246        return ret;
1247}
1248
1249/* adjust IEs for r8712_joinbss_cmd in WMM */
1250int r8712_restruct_wmm_ie(struct _adapter *adapter, u8 *in_ie, u8 *out_ie,
1251                    uint in_len, uint initial_out_len)
1252{
1253        unsigned int ielength = 0;
1254        unsigned int i, j;
1255
1256        i = 12; /* after the fixed IE */
1257        while (i < in_len) {
1258                ielength = initial_out_len;
1259                if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 &&
1260                    in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 &&
1261                    in_ie[i + 5] == 0x02 && i + 5 < in_len) {
1262                        /*WMM element ID and OUI*/
1263                        for (j = i; j < i + 9; j++) {
1264                                out_ie[ielength] = in_ie[j];
1265                                ielength++;
1266                        }
1267                        out_ie[initial_out_len + 1] = 0x07;
1268                        out_ie[initial_out_len + 6] = 0x00;
1269                        out_ie[initial_out_len + 8] = 0x00;
1270                        break;
1271                }
1272                i += (in_ie[i + 1] + 2); /* to the next IE element */
1273        }
1274        return ielength;
1275}
1276
1277/*
1278 * Ported from 8185: IsInPreAuthKeyList().
1279 *
1280 * Search by BSSID,
1281 * Return Value:
1282 *      -1              :if there is no pre-auth key in the  table
1283 *      >=0             :if there is pre-auth key, and   return the entry id
1284 */
1285static int SecIsInPMKIDList(struct _adapter *Adapter, u8 *bssid)
1286{
1287        struct security_priv *psecuritypriv = &Adapter->securitypriv;
1288        int i = 0;
1289
1290        do {
1291                if (psecuritypriv->PMKIDList[i].bUsed &&
1292                   (!memcmp(psecuritypriv->PMKIDList[i].Bssid,
1293                            bssid, ETH_ALEN)))
1294                        break;
1295                i++;
1296
1297        } while (i < NUM_PMKID_CACHE);
1298
1299        if (i == NUM_PMKID_CACHE) {
1300                i = -1; /* Could not find. */
1301        } else {
1302                ; /* There is one Pre-Authentication Key for the
1303                   * specific BSSID.
1304                   */
1305        }
1306        return i;
1307}
1308
1309sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
1310                     u8 *out_ie, uint in_len)
1311{
1312        u8 authmode = 0, match;
1313        u8 sec_ie[IW_CUSTOM_MAX], uncst_oui[4], bkup_ie[255];
1314        u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
1315        uint ielength, cnt, remove_cnt;
1316        int iEntry;
1317        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1318        struct security_priv *psecuritypriv = &adapter->securitypriv;
1319        uint ndisauthmode = psecuritypriv->ndisauthtype;
1320        uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
1321
1322        if ((ndisauthmode == Ndis802_11AuthModeWPA) ||
1323            (ndisauthmode == Ndis802_11AuthModeWPAPSK)) {
1324                authmode = _WPA_IE_ID_;
1325                uncst_oui[0] = 0x0;
1326                uncst_oui[1] = 0x50;
1327                uncst_oui[2] = 0xf2;
1328        }
1329        if ((ndisauthmode == Ndis802_11AuthModeWPA2) ||
1330            (ndisauthmode == Ndis802_11AuthModeWPA2PSK)) {
1331                authmode = _WPA2_IE_ID_;
1332                uncst_oui[0] = 0x0;
1333                uncst_oui[1] = 0x0f;
1334                uncst_oui[2] = 0xac;
1335        }
1336        switch (ndissecuritytype) {
1337        case Ndis802_11Encryption1Enabled:
1338        case Ndis802_11Encryption1KeyAbsent:
1339                uncst_oui[3] = 0x1;
1340                break;
1341        case Ndis802_11Encryption2Enabled:
1342        case Ndis802_11Encryption2KeyAbsent:
1343                uncst_oui[3] = 0x2;
1344                break;
1345        case Ndis802_11Encryption3Enabled:
1346        case Ndis802_11Encryption3KeyAbsent:
1347                uncst_oui[3] = 0x4;
1348                break;
1349        default:
1350                break;
1351        }
1352        /*Search required WPA or WPA2 IE and copy to sec_ie[] */
1353        cnt = 12;
1354        match = false;
1355        while (cnt < in_len) {
1356                if (in_ie[cnt] == authmode) {
1357                        if ((authmode == _WPA_IE_ID_) &&
1358                            (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
1359                                memcpy(&sec_ie[0], &in_ie[cnt],
1360                                        in_ie[cnt + 1] + 2);
1361                                match = true;
1362                                break;
1363                        }
1364                        if (authmode == _WPA2_IE_ID_) {
1365                                memcpy(&sec_ie[0], &in_ie[cnt],
1366                                        in_ie[cnt + 1] + 2);
1367                                match = true;
1368                                break;
1369                        }
1370                        if (((authmode == _WPA_IE_ID_) &&
1371                             (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) ||
1372                             (authmode == _WPA2_IE_ID_))
1373                                memcpy(&bkup_ie[0], &in_ie[cnt],
1374                                        in_ie[cnt + 1] + 2);
1375                }
1376                cnt += in_ie[cnt + 1] + 2; /*get next*/
1377        }
1378        /*restruct WPA IE or WPA2 IE in sec_ie[] */
1379        if (match) {
1380                if (sec_ie[0] == _WPA_IE_ID_) {
1381                        /* parsing SSN IE to select required encryption
1382                         * algorithm, and set the bc/mc encryption algorithm
1383                         */
1384                        while (true) {
1385                                /*check wpa_oui tag*/
1386                                if (memcmp(&sec_ie[2], &wpa_oui[0], 4)) {
1387                                        match = false;
1388                                        break;
1389                                }
1390                                if ((sec_ie[6] != 0x01) || (sec_ie[7] != 0x0)) {
1391                                        /*IE Ver error*/
1392                                        match = false;
1393                                        break;
1394                                }
1395                                if (!memcmp(&sec_ie[8], &wpa_oui[0], 3)) {
1396                                        /* get bc/mc encryption type (group
1397                                         * key type)
1398                                         */
1399                                        switch (sec_ie[11]) {
1400                                        case 0x0: /*none*/
1401                                                psecuritypriv->XGrpPrivacy =
1402                                                                _NO_PRIVACY_;
1403                                                break;
1404                                        case 0x1: /*WEP_40*/
1405                                                psecuritypriv->XGrpPrivacy =
1406                                                                _WEP40_;
1407                                                break;
1408                                        case 0x2: /*TKIP*/
1409                                                psecuritypriv->XGrpPrivacy =
1410                                                                _TKIP_;
1411                                                break;
1412                                        case 0x3: /*AESCCMP*/
1413                                        case 0x4:
1414                                                psecuritypriv->XGrpPrivacy =
1415                                                                _AES_;
1416                                                break;
1417                                        case 0x5: /*WEP_104*/
1418                                                psecuritypriv->XGrpPrivacy =
1419                                                                _WEP104_;
1420                                                break;
1421                                        }
1422                                } else {
1423                                        match = false;
1424                                        break;
1425                                }
1426                                if (sec_ie[12] == 0x01) {
1427                                        /*check the unicast encryption type*/
1428                                        if (memcmp(&sec_ie[14],
1429                                            &uncst_oui[0], 4)) {
1430                                                match = false;
1431                                                break;
1432
1433                                        } /*else the uncst_oui is match*/
1434                                } else { /*mixed mode, unicast_enc_type > 1*/
1435                                        /*select the uncst_oui and remove
1436                                         * the other uncst_oui
1437                                         */
1438                                        cnt = sec_ie[12];
1439                                        remove_cnt = (cnt - 1) * 4;
1440                                        sec_ie[12] = 0x01;
1441                                        memcpy(&sec_ie[14], &uncst_oui[0], 4);
1442                                        /*remove the other unicast suit*/
1443                                        memcpy(&sec_ie[18],
1444                                                &sec_ie[18 + remove_cnt],
1445                                                sec_ie[1] - 18 + 2 -
1446                                                remove_cnt);
1447                                        sec_ie[1] = sec_ie[1] - remove_cnt;
1448                                }
1449                                break;
1450                        }
1451                }
1452                if (authmode == _WPA2_IE_ID_) {
1453                        /* parsing RSN IE to select required encryption
1454                         * algorithm, and set the bc/mc encryption algorithm
1455                         */
1456                        while (true) {
1457                                if ((sec_ie[2] != 0x01) || (sec_ie[3] != 0x0)) {
1458                                        /*IE Ver error*/
1459                                        match = false;
1460                                        break;
1461                                }
1462                                if (!memcmp(&sec_ie[4], &uncst_oui[0], 3)) {
1463                                        /*get bc/mc encryption type*/
1464                                        switch (sec_ie[7]) {
1465                                        case 0x1: /*WEP_40*/
1466                                                psecuritypriv->XGrpPrivacy =
1467                                                                _WEP40_;
1468                                                break;
1469                                        case 0x2: /*TKIP*/
1470                                                psecuritypriv->XGrpPrivacy =
1471                                                                _TKIP_;
1472                                                break;
1473                                        case 0x4: /*AESWRAP*/
1474                                                psecuritypriv->XGrpPrivacy =
1475                                                                _AES_;
1476                                                break;
1477                                        case 0x5: /*WEP_104*/
1478                                                psecuritypriv->XGrpPrivacy =
1479                                                                _WEP104_;
1480                                                break;
1481                                        default: /*one*/
1482                                                psecuritypriv->XGrpPrivacy =
1483                                                                _NO_PRIVACY_;
1484                                                break;
1485                                        }
1486                                } else {
1487                                        match = false;
1488                                        break;
1489                                }
1490                                if (sec_ie[8] == 0x01) {
1491                                        /*check the unicast encryption type*/
1492                                        if (memcmp(&sec_ie[10],
1493                                                     &uncst_oui[0], 4)) {
1494                                                match = false;
1495                                                break;
1496                                        } /*else the uncst_oui is match*/
1497                                } else { /*mixed mode, unicast_enc_type > 1*/
1498                                        /*select the uncst_oui and remove the
1499                                         * other uncst_oui
1500                                         */
1501                                        cnt = sec_ie[8];
1502                                        remove_cnt = (cnt - 1) * 4;
1503                                        sec_ie[8] = 0x01;
1504                                        memcpy(&sec_ie[10], &uncst_oui[0], 4);
1505                                        /*remove the other unicast suit*/
1506                                        memcpy(&sec_ie[14],
1507                                                &sec_ie[14 + remove_cnt],
1508                                                (sec_ie[1] - 14 + 2 -
1509                                                remove_cnt));
1510                                        sec_ie[1] = sec_ie[1] - remove_cnt;
1511                                }
1512                                break;
1513                        }
1514                }
1515        }
1516        if ((authmode == _WPA_IE_ID_) || (authmode == _WPA2_IE_ID_)) {
1517                /*copy fixed ie*/
1518                memcpy(out_ie, in_ie, 12);
1519                ielength = 12;
1520                /*copy RSN or SSN*/
1521                if (match) {
1522                        memcpy(&out_ie[ielength], &sec_ie[0], sec_ie[1] + 2);
1523                        ielength += sec_ie[1] + 2;
1524                        if (authmode == _WPA2_IE_ID_) {
1525                                /*the Pre-Authentication bit should be zero*/
1526                                out_ie[ielength - 1] = 0;
1527                                out_ie[ielength - 2] = 0;
1528                        }
1529                        r8712_report_sec_ie(adapter, authmode, sec_ie);
1530                }
1531        } else {
1532                /*copy fixed ie only*/
1533                memcpy(out_ie, in_ie, 12);
1534                ielength = 12;
1535                if (psecuritypriv->wps_phase) {
1536                        memcpy(out_ie + ielength, psecuritypriv->wps_ie,
1537                               psecuritypriv->wps_ie_len);
1538                        ielength += psecuritypriv->wps_ie_len;
1539                }
1540        }
1541        iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
1542        if (iEntry < 0)
1543                return ielength;
1544        if (authmode == _WPA2_IE_ID_) {
1545                out_ie[ielength] = 1;
1546                ielength++;
1547                out_ie[ielength] = 0;   /*PMKID count = 0x0100*/
1548                ielength++;
1549                memcpy(&out_ie[ielength],
1550                        &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
1551                ielength += 16;
1552                out_ie[13] += 18;/*PMKID length = 2+16*/
1553        }
1554        return ielength;
1555}
1556
1557void r8712_init_registrypriv_dev_network(struct _adapter *adapter)
1558{
1559        struct registry_priv *pregistrypriv = &adapter->registrypriv;
1560        struct eeprom_priv *peepriv = &adapter->eeprompriv;
1561        struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
1562        u8 *myhwaddr = myid(peepriv);
1563
1564        memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
1565        memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
1566                sizeof(struct ndis_802_11_ssid));
1567        pdev_network->Configuration.Length =
1568                         sizeof(struct NDIS_802_11_CONFIGURATION);
1569        pdev_network->Configuration.BeaconPeriod = 100;
1570        pdev_network->Configuration.FHConfig.Length = 0;
1571        pdev_network->Configuration.FHConfig.HopPattern = 0;
1572        pdev_network->Configuration.FHConfig.HopSet = 0;
1573        pdev_network->Configuration.FHConfig.DwellTime = 0;
1574}
1575
1576void r8712_update_registrypriv_dev_network(struct _adapter *adapter)
1577{
1578        int sz = 0;
1579        struct registry_priv    *pregistrypriv = &adapter->registrypriv;
1580        struct wlan_bssid_ex    *pdev_network = &pregistrypriv->dev_network;
1581        struct security_priv    *psecuritypriv = &adapter->securitypriv;
1582        struct wlan_network     *cur_network = &adapter->mlmepriv.cur_network;
1583
1584        pdev_network->Privacy = cpu_to_le32(psecuritypriv->PrivacyAlgrthm
1585                                            > 0 ? 1 : 0); /* adhoc no 802.1x */
1586        pdev_network->Rssi = 0;
1587        switch (pregistrypriv->wireless_mode) {
1588        case WIRELESS_11B:
1589                pdev_network->NetworkTypeInUse = Ndis802_11DS;
1590                break;
1591        case WIRELESS_11G:
1592        case WIRELESS_11BG:
1593                pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
1594                break;
1595        case WIRELESS_11A:
1596                pdev_network->NetworkTypeInUse = Ndis802_11OFDM5;
1597                break;
1598        default:
1599                /* TODO */
1600                break;
1601        }
1602        pdev_network->Configuration.DSConfig = pregistrypriv->channel;
1603        if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
1604                pdev_network->Configuration.ATIMWindow = 3;
1605        pdev_network->InfrastructureMode = cur_network->network.InfrastructureMode;
1606        /* 1. Supported rates
1607         * 2. IE
1608         */
1609        sz = r8712_generate_ie(pregistrypriv);
1610        pdev_network->IELength = sz;
1611        pdev_network->Length = r8712_get_wlan_bssid_ex_sz(pdev_network);
1612}
1613
1614/*the function is at passive_level*/
1615void r8712_joinbss_reset(struct _adapter *padapter)
1616{
1617        int i;
1618        struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
1619        struct ht_priv          *phtpriv = &pmlmepriv->htpriv;
1620
1621        /* todo: if you want to do something io/reg/hw setting before join_bss,
1622         * please add code here
1623         */
1624        phtpriv->ampdu_enable = false;/*reset to disabled*/
1625        for (i = 0; i < 16; i++)
1626                phtpriv->baddbareq_issued[i] = false;/*reset it*/
1627        if (phtpriv->ht_option) {
1628                /* validate  usb rx aggregation */
1629                r8712_write8(padapter, 0x102500D9, 48);/*TH = 48 pages, 6k*/
1630        } else {
1631                /* invalidate  usb rx aggregation */
1632                /* TH=1 => means that invalidate usb rx aggregation */
1633                r8712_write8(padapter, 0x102500D9, 1);
1634        }
1635}
1636
1637/*the function is >= passive_level*/
1638unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie,
1639                                     u8 *out_ie, uint in_len, uint *pout_len)
1640{
1641        u32 ielen, out_len;
1642        unsigned char *p;
1643        struct ieee80211_ht_cap ht_capie;
1644        unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
1645        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1646        struct qos_priv *pqospriv = &pmlmepriv->qospriv;
1647        struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1648
1649        phtpriv->ht_option = 0;
1650        p = r8712_get_ie(in_ie + 12, WLAN_EID_HT_CAPABILITY, &ielen, in_len - 12);
1651        if (p && (ielen > 0)) {
1652                if (pqospriv->qos_option == 0) {
1653                        out_len = *pout_len;
1654                        r8712_set_ie(out_ie + out_len, WLAN_EID_VENDOR_SPECIFIC,
1655                                     _WMM_IE_Length_, WMM_IE, pout_len);
1656                        pqospriv->qos_option = 1;
1657                }
1658                out_len = *pout_len;
1659                memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
1660                ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
1661                                    IEEE80211_HT_CAP_SGI_20 |
1662                                    IEEE80211_HT_CAP_SGI_40 |
1663                                    IEEE80211_HT_CAP_TX_STBC |
1664                                    IEEE80211_HT_CAP_MAX_AMSDU |
1665                                    IEEE80211_HT_CAP_DSSSCCK40);
1666                ht_capie.ampdu_params_info = (IEEE80211_HT_AMPDU_PARM_FACTOR &
1667                                0x03) | (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00);
1668                r8712_set_ie(out_ie + out_len, WLAN_EID_HT_CAPABILITY,
1669                             sizeof(struct ieee80211_ht_cap),
1670                             (unsigned char *)&ht_capie, pout_len);
1671                phtpriv->ht_option = 1;
1672        }
1673        return phtpriv->ht_option;
1674}
1675
1676/* the function is > passive_level (in critical_section) */
1677static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len)
1678{
1679        u8 *p, max_ampdu_sz;
1680        int i;
1681        uint len;
1682        struct sta_info *bmc_sta, *psta;
1683        struct ieee80211_ht_cap *pht_capie;
1684        struct recv_reorder_ctrl *preorder_ctrl;
1685        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1686        struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1687        struct registry_priv *pregistrypriv = &padapter->registrypriv;
1688        struct wlan_network *pcur_network = &(pmlmepriv->cur_network);
1689
1690        if (!phtpriv->ht_option)
1691                return;
1692        /* maybe needs check if ap supports rx ampdu. */
1693        if (!phtpriv->ampdu_enable &&
1694            (pregistrypriv->ampdu_enable == 1))
1695                phtpriv->ampdu_enable = true;
1696        /*check Max Rx A-MPDU Size*/
1697        len = 0;
1698        p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
1699                                WLAN_EID_HT_CAPABILITY,
1700                                &len, ie_len -
1701                                sizeof(struct NDIS_802_11_FIXED_IEs));
1702        if (p && len > 0) {
1703                pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1704                max_ampdu_sz = (pht_capie->ampdu_params_info &
1705                                IEEE80211_HT_AMPDU_PARM_FACTOR);
1706                /* max_ampdu_sz (kbytes); */
1707                max_ampdu_sz = 1 << (max_ampdu_sz + 3);
1708                phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
1709        }
1710        /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info
1711         * if A-MPDU Rx is enabled, resetting rx_ordering_ctrl
1712         * wstart_b(indicate_seq) to default value=0xffff
1713         * todo: check if AP can send A-MPDU packets
1714         */
1715        bmc_sta = r8712_get_bcmc_stainfo(padapter);
1716        if (bmc_sta) {
1717                for (i = 0; i < 16; i++) {
1718                        preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
1719                        preorder_ctrl->indicate_seq = 0xffff;
1720                        preorder_ctrl->wend_b = 0xffff;
1721                }
1722        }
1723        psta = r8712_get_stainfo(&padapter->stapriv,
1724                                 pcur_network->network.MacAddress);
1725        if (psta) {
1726                for (i = 0; i < 16; i++) {
1727                        preorder_ctrl = &psta->recvreorder_ctrl[i];
1728                        preorder_ctrl->indicate_seq = 0xffff;
1729                        preorder_ctrl->wend_b = 0xffff;
1730                }
1731        }
1732        len = 0;
1733        p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
1734                   WLAN_EID_HT_OPERATION, &len,
1735                   ie_len - sizeof(struct NDIS_802_11_FIXED_IEs));
1736}
1737
1738void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority)
1739{
1740        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1741        struct ht_priv   *phtpriv = &pmlmepriv->htpriv;
1742
1743        if ((phtpriv->ht_option == 1) && (phtpriv->ampdu_enable)) {
1744                if (!phtpriv->baddbareq_issued[priority]) {
1745                        r8712_addbareq_cmd(padapter, (u8)priority);
1746                        phtpriv->baddbareq_issued[priority] = true;
1747                }
1748        }
1749}
1750