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