Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /******************************************************************************
0003  * rtl871x_mlme.c
0004  *
0005  * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
0006  * Linux device driver for RTL8192SU
0007  *
0008  * Modifications for inclusion into the Linux staging tree are
0009  * Copyright(c) 2010 Larry Finger. All rights reserved.
0010  *
0011  * Contact information:
0012  * WLAN FAE <wlanfae@realtek.com>
0013  * Larry Finger <Larry.Finger@lwfinger.net>
0014  *
0015  ******************************************************************************/
0016 
0017 #define _RTL871X_MLME_C_
0018 
0019 #include <linux/etherdevice.h>
0020 
0021 #include "osdep_service.h"
0022 #include "drv_types.h"
0023 #include "recv_osdep.h"
0024 #include "xmit_osdep.h"
0025 #include "mlme_osdep.h"
0026 #include "sta_info.h"
0027 #include "wifi.h"
0028 #include "wlan_bssdef.h"
0029 
0030 static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len);
0031 
0032 int r8712_init_mlme_priv(struct _adapter *padapter)
0033 {
0034     sint    i;
0035     u8  *pbuf;
0036     struct wlan_network *pnetwork;
0037     struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
0038 
0039     memset((u8 *)pmlmepriv, 0, sizeof(struct mlme_priv));
0040     pmlmepriv->nic_hdl = (u8 *)padapter;
0041     pmlmepriv->pscanned = NULL;
0042     pmlmepriv->fw_state = 0;
0043     pmlmepriv->cur_network.network.InfrastructureMode =
0044                  Ndis802_11AutoUnknown;
0045     /* Maybe someday we should rename this variable to "active_mode"(Jeff)*/
0046     pmlmepriv->passive_mode = 1; /* 1: active, 0: passive. */
0047     spin_lock_init(&(pmlmepriv->lock));
0048     spin_lock_init(&(pmlmepriv->lock2));
0049     _init_queue(&(pmlmepriv->free_bss_pool));
0050     _init_queue(&(pmlmepriv->scanned_queue));
0051     set_scanned_network_val(pmlmepriv, 0);
0052     memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
0053     pbuf = kmalloc_array(MAX_BSS_CNT, sizeof(struct wlan_network),
0054                  GFP_ATOMIC);
0055     if (!pbuf)
0056         return -ENOMEM;
0057     pmlmepriv->free_bss_buf = pbuf;
0058     pnetwork = (struct wlan_network *)pbuf;
0059     for (i = 0; i < MAX_BSS_CNT; i++) {
0060         INIT_LIST_HEAD(&(pnetwork->list));
0061         list_add_tail(&(pnetwork->list),
0062                  &(pmlmepriv->free_bss_pool.queue));
0063         pnetwork++;
0064     }
0065     pmlmepriv->sitesurveyctrl.last_rx_pkts = 0;
0066     pmlmepriv->sitesurveyctrl.last_tx_pkts = 0;
0067     pmlmepriv->sitesurveyctrl.traffic_busy = false;
0068     /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
0069     r8712_init_mlme_timer(padapter);
0070     return 0;
0071 }
0072 
0073 struct wlan_network *_r8712_alloc_network(struct mlme_priv *pmlmepriv)
0074 {
0075     unsigned long irqL;
0076     struct wlan_network *pnetwork;
0077     struct  __queue *free_queue = &pmlmepriv->free_bss_pool;
0078 
0079     spin_lock_irqsave(&free_queue->lock, irqL);
0080     pnetwork = list_first_entry_or_null(&free_queue->queue,
0081                         struct wlan_network, list);
0082     if (pnetwork) {
0083         list_del_init(&pnetwork->list);
0084         pnetwork->last_scanned = jiffies;
0085         pmlmepriv->num_of_scanned++;
0086     }
0087     spin_unlock_irqrestore(&free_queue->lock, irqL);
0088     return pnetwork;
0089 }
0090 
0091 static void _free_network(struct mlme_priv *pmlmepriv,
0092               struct wlan_network *pnetwork)
0093 {
0094     u32 curr_time, delta_time;
0095     unsigned long irqL;
0096     struct  __queue *free_queue = &(pmlmepriv->free_bss_pool);
0097 
0098     if (!pnetwork)
0099         return;
0100     if (pnetwork->fixed)
0101         return;
0102     curr_time = jiffies;
0103     delta_time = (curr_time - (u32)pnetwork->last_scanned) / HZ;
0104     if (delta_time < SCANQUEUE_LIFETIME)
0105         return;
0106     spin_lock_irqsave(&free_queue->lock, irqL);
0107     list_del_init(&pnetwork->list);
0108     list_add_tail(&pnetwork->list, &free_queue->queue);
0109     pmlmepriv->num_of_scanned--;
0110     spin_unlock_irqrestore(&free_queue->lock, irqL);
0111 }
0112 
0113 static void free_network_nolock(struct mlme_priv *pmlmepriv,
0114               struct wlan_network *pnetwork)
0115 {
0116     struct  __queue *free_queue = &pmlmepriv->free_bss_pool;
0117 
0118     if (!pnetwork)
0119         return;
0120     if (pnetwork->fixed)
0121         return;
0122     list_del_init(&pnetwork->list);
0123     list_add_tail(&pnetwork->list, &free_queue->queue);
0124     pmlmepriv->num_of_scanned--;
0125 }
0126 
0127 /* return the wlan_network with the matching addr
0128  * Shall be called under atomic context...
0129  * to avoid possible racing condition...
0130  */
0131 static struct wlan_network *r8712_find_network(struct  __queue *scanned_queue,
0132                            u8 *addr)
0133 {
0134     unsigned long irqL;
0135     struct list_head *phead, *plist;
0136     struct wlan_network *pnetwork = NULL;
0137 
0138     if (is_zero_ether_addr(addr))
0139         return NULL;
0140     spin_lock_irqsave(&scanned_queue->lock, irqL);
0141     phead = &scanned_queue->queue;
0142     list_for_each(plist, phead) {
0143         pnetwork = list_entry(plist, struct wlan_network, list);
0144         if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN))
0145             break;
0146     }
0147     if (plist == phead)
0148         pnetwork = NULL;
0149     spin_unlock_irqrestore(&scanned_queue->lock, irqL);
0150     return pnetwork;
0151 }
0152 
0153 void r8712_free_network_queue(struct _adapter *padapter)
0154 {
0155     unsigned long irqL;
0156     struct list_head *phead, *plist;
0157     struct wlan_network *pnetwork;
0158     struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
0159     struct  __queue *scanned_queue = &pmlmepriv->scanned_queue;
0160 
0161     spin_lock_irqsave(&scanned_queue->lock, irqL);
0162     phead = &scanned_queue->queue;
0163     plist = phead->next;
0164     while (!end_of_queue_search(phead, plist)) {
0165         pnetwork = container_of(plist, struct wlan_network, list);
0166         plist = plist->next;
0167         _free_network(pmlmepriv, pnetwork);
0168     }
0169     spin_unlock_irqrestore(&scanned_queue->lock, irqL);
0170 }
0171 
0172 sint r8712_if_up(struct _adapter *padapter)
0173 {
0174     sint res;
0175 
0176     if (padapter->driver_stopped || padapter->surprise_removed ||
0177         !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
0178         res = false;
0179     } else {
0180         res = true;
0181     }
0182     return res;
0183 }
0184 
0185 void r8712_generate_random_ibss(u8 *pibss)
0186 {
0187     u32 curtime = jiffies;
0188 
0189     pibss[0] = 0x02; /*in ad-hoc mode bit1 must set to 1 */
0190     pibss[1] = 0x11;
0191     pibss[2] = 0x87;
0192     pibss[3] = (u8)(curtime & 0xff);
0193     pibss[4] = (u8)((curtime >> 8) & 0xff);
0194     pibss[5] = (u8)((curtime >> 16) & 0xff);
0195 }
0196 
0197 uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss)
0198 {
0199     return sizeof(*bss) + bss->IELength - MAX_IE_SZ;
0200 }
0201 
0202 u8 *r8712_get_capability_from_ie(u8 *ie)
0203 {
0204     return ie + 8 + 2;
0205 }
0206 
0207 void r8712_free_mlme_priv(struct mlme_priv *pmlmepriv)
0208 {
0209     kfree(pmlmepriv->free_bss_buf);
0210 }
0211 
0212 static struct   wlan_network *alloc_network(struct mlme_priv *pmlmepriv)
0213 {
0214     return _r8712_alloc_network(pmlmepriv);
0215 }
0216 
0217 int r8712_is_same_ibss(struct _adapter *adapter, struct wlan_network *pnetwork)
0218 {
0219     int ret = true;
0220     struct security_priv *psecuritypriv = &adapter->securitypriv;
0221 
0222     if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) &&
0223             (pnetwork->network.Privacy == cpu_to_le32(0)))
0224         ret = false;
0225     else if ((psecuritypriv->PrivacyAlgrthm == _NO_PRIVACY_) &&
0226          (pnetwork->network.Privacy == cpu_to_le32(1)))
0227         ret = false;
0228     else
0229         ret = true;
0230     return ret;
0231 
0232 }
0233 
0234 static int is_same_network(struct wlan_bssid_ex *src,
0235                struct wlan_bssid_ex *dst)
0236 {
0237     u16 s_cap, d_cap;
0238 
0239     memcpy((u8 *)&s_cap, r8712_get_capability_from_ie(src->IEs), 2);
0240     memcpy((u8 *)&d_cap, r8712_get_capability_from_ie(dst->IEs), 2);
0241     return (src->Ssid.SsidLength == dst->Ssid.SsidLength) &&
0242             (src->Configuration.DSConfig ==
0243             dst->Configuration.DSConfig) &&
0244             ((!memcmp(src->MacAddress, dst->MacAddress,
0245             ETH_ALEN))) &&
0246             ((!memcmp(src->Ssid.Ssid,
0247               dst->Ssid.Ssid,
0248               src->Ssid.SsidLength))) &&
0249             ((s_cap & WLAN_CAPABILITY_IBSS) ==
0250             (d_cap & WLAN_CAPABILITY_IBSS)) &&
0251             ((s_cap & WLAN_CAPABILITY_ESS) ==
0252             (d_cap & WLAN_CAPABILITY_ESS));
0253 
0254 }
0255 
0256 struct  wlan_network *r8712_get_oldest_wlan_network(
0257                 struct  __queue *scanned_queue)
0258 {
0259     struct list_head *plist, *phead;
0260     struct  wlan_network    *pwlan = NULL;
0261     struct  wlan_network    *oldest = NULL;
0262 
0263     phead = &scanned_queue->queue;
0264     plist = phead->next;
0265     while (1) {
0266         if (end_of_queue_search(phead, plist))
0267             break;
0268         pwlan = container_of(plist, struct wlan_network, list);
0269         if (!pwlan->fixed) {
0270             if (!oldest ||
0271                 time_after((unsigned long)oldest->last_scanned,
0272                        (unsigned long)pwlan->last_scanned))
0273                 oldest = pwlan;
0274         }
0275         plist = plist->next;
0276     }
0277     return oldest;
0278 }
0279 
0280 static void update_network(struct wlan_bssid_ex *dst,
0281                struct wlan_bssid_ex *src,
0282                struct _adapter *padapter)
0283 {
0284     u32 last_evm = 0, tmpVal;
0285     struct smooth_rssi_data *sqd = &padapter->recvpriv.signal_qual_data;
0286 
0287     if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) &&
0288         is_same_network(&(padapter->mlmepriv.cur_network.network), src)) {
0289         if (padapter->recvpriv.signal_qual_data.total_num++ >=
0290             PHY_LINKQUALITY_SLID_WIN_MAX) {
0291             padapter->recvpriv.signal_qual_data.total_num =
0292                    PHY_LINKQUALITY_SLID_WIN_MAX;
0293             last_evm = sqd->elements[sqd->index];
0294             padapter->recvpriv.signal_qual_data.total_val -=
0295                  last_evm;
0296         }
0297         padapter->recvpriv.signal_qual_data.total_val += src->Rssi;
0298 
0299         sqd->elements[sqd->index++] = src->Rssi;
0300         if (padapter->recvpriv.signal_qual_data.index >=
0301             PHY_LINKQUALITY_SLID_WIN_MAX)
0302             padapter->recvpriv.signal_qual_data.index = 0;
0303         /* <1> Showed on UI for user, in percentage. */
0304         tmpVal = padapter->recvpriv.signal_qual_data.total_val /
0305              padapter->recvpriv.signal_qual_data.total_num;
0306         padapter->recvpriv.signal = (u8)tmpVal;
0307 
0308         src->Rssi = padapter->recvpriv.signal;
0309     } else {
0310         src->Rssi = (src->Rssi + dst->Rssi) / 2;
0311     }
0312     memcpy((u8 *)dst, (u8 *)src, r8712_get_wlan_bssid_ex_sz(src));
0313 }
0314 
0315 static void update_current_network(struct _adapter *adapter,
0316                    struct wlan_bssid_ex *pnetwork)
0317 {
0318     struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
0319 
0320     if (is_same_network(&(pmlmepriv->cur_network.network), pnetwork)) {
0321         update_network(&(pmlmepriv->cur_network.network),
0322                    pnetwork, adapter);
0323         r8712_update_protection(adapter,
0324                    (pmlmepriv->cur_network.network.IEs) +
0325                    sizeof(struct NDIS_802_11_FIXED_IEs),
0326                    pmlmepriv->cur_network.network.IELength);
0327     }
0328 }
0329 
0330 /* Caller must hold pmlmepriv->lock first */
0331 static void update_scanned_network(struct _adapter *adapter,
0332                 struct wlan_bssid_ex *target)
0333 {
0334     struct list_head *plist, *phead;
0335 
0336     u32 bssid_ex_sz;
0337     struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
0338     struct  __queue *queue = &pmlmepriv->scanned_queue;
0339     struct wlan_network *pnetwork = NULL;
0340     struct wlan_network *oldest = NULL;
0341 
0342     phead = &queue->queue;
0343     plist = phead->next;
0344 
0345     while (1) {
0346         if (end_of_queue_search(phead, plist))
0347             break;
0348 
0349         pnetwork = container_of(plist, struct wlan_network, list);
0350         if (is_same_network(&pnetwork->network, target))
0351             break;
0352         if ((oldest == ((struct wlan_network *)0)) ||
0353             time_after((unsigned long)oldest->last_scanned,
0354                 (unsigned long)pnetwork->last_scanned))
0355             oldest = pnetwork;
0356 
0357         plist = plist->next;
0358     }
0359 
0360     /* If we didn't find a match, then get a new network slot to initialize
0361      * with this beacon's information
0362      */
0363     if (end_of_queue_search(phead, plist)) {
0364         if (list_empty(&pmlmepriv->free_bss_pool.queue)) {
0365             /* If there are no more slots, expire the oldest */
0366             pnetwork = oldest;
0367             target->Rssi = (pnetwork->network.Rssi +
0368                     target->Rssi) / 2;
0369             memcpy(&pnetwork->network, target,
0370                 r8712_get_wlan_bssid_ex_sz(target));
0371             pnetwork->last_scanned = jiffies;
0372         } else {
0373             /* Otherwise just pull from the free list */
0374             /* update scan_time */
0375             pnetwork = alloc_network(pmlmepriv);
0376             if (!pnetwork)
0377                 return;
0378             bssid_ex_sz = r8712_get_wlan_bssid_ex_sz(target);
0379             target->Length = bssid_ex_sz;
0380             memcpy(&pnetwork->network, target, bssid_ex_sz);
0381             list_add_tail(&pnetwork->list, &queue->queue);
0382         }
0383     } else {
0384         /* we have an entry and we are going to update it. But
0385          * this entry may be already expired. In this case we
0386          * do the same as we found a new net and call the new_net
0387          * handler
0388          */
0389         update_network(&pnetwork->network, target, adapter);
0390         pnetwork->last_scanned = jiffies;
0391     }
0392 }
0393 
0394 static void rtl8711_add_network(struct _adapter *adapter,
0395              struct wlan_bssid_ex *pnetwork)
0396 {
0397     unsigned long irqL;
0398     struct mlme_priv *pmlmepriv = &(((struct _adapter *)adapter)->mlmepriv);
0399     struct  __queue *queue = &pmlmepriv->scanned_queue;
0400 
0401     spin_lock_irqsave(&queue->lock, irqL);
0402     update_current_network(adapter, pnetwork);
0403     update_scanned_network(adapter, pnetwork);
0404     spin_unlock_irqrestore(&queue->lock, irqL);
0405 }
0406 
0407 /*select the desired network based on the capability of the (i)bss.
0408  * check items:     (1) security
0409  *          (2) network_type
0410  *          (3) WMM
0411  *          (4) HT
0412  *          (5) others
0413  */
0414 static int is_desired_network(struct _adapter *adapter,
0415                 struct wlan_network *pnetwork)
0416 {
0417     u8 wps_ie[512];
0418     uint wps_ielen;
0419     int bselected = true;
0420     struct  security_priv *psecuritypriv = &adapter->securitypriv;
0421 
0422     if (psecuritypriv->wps_phase) {
0423         if (r8712_get_wps_ie(pnetwork->network.IEs,
0424             pnetwork->network.IELength, wps_ie,
0425             &wps_ielen))
0426             return true;
0427         return false;
0428     }
0429     if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) &&
0430             (pnetwork->network.Privacy == 0))
0431         bselected = false;
0432     if (check_fwstate(&adapter->mlmepriv, WIFI_ADHOC_STATE)) {
0433         if (pnetwork->network.InfrastructureMode !=
0434             adapter->mlmepriv.cur_network.network.InfrastructureMode)
0435             bselected = false;
0436     }
0437     return bselected;
0438 }
0439 
0440 /* TODO: Perry : For Power Management */
0441 void r8712_atimdone_event_callback(struct _adapter *adapter, u8 *pbuf)
0442 {
0443 }
0444 
0445 void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf)
0446 {
0447     unsigned long flags;
0448     u32 len;
0449     struct wlan_bssid_ex *pnetwork;
0450     struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
0451 
0452     pnetwork = (struct wlan_bssid_ex *)pbuf;
0453 #ifdef __BIG_ENDIAN
0454     /* endian_convert */
0455     pnetwork->Length = le32_to_cpu(pnetwork->Length);
0456     pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength);
0457     pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy);
0458     pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi);
0459     pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse);
0460     pnetwork->Configuration.ATIMWindow =
0461          le32_to_cpu(pnetwork->Configuration.ATIMWindow);
0462     pnetwork->Configuration.BeaconPeriod =
0463          le32_to_cpu(pnetwork->Configuration.BeaconPeriod);
0464     pnetwork->Configuration.DSConfig =
0465          le32_to_cpu(pnetwork->Configuration.DSConfig);
0466     pnetwork->Configuration.FHConfig.DwellTime =
0467          le32_to_cpu(pnetwork->Configuration.FHConfig.DwellTime);
0468     pnetwork->Configuration.FHConfig.HopPattern =
0469          le32_to_cpu(pnetwork->Configuration.FHConfig.HopPattern);
0470     pnetwork->Configuration.FHConfig.HopSet =
0471          le32_to_cpu(pnetwork->Configuration.FHConfig.HopSet);
0472     pnetwork->Configuration.FHConfig.Length =
0473          le32_to_cpu(pnetwork->Configuration.FHConfig.Length);
0474     pnetwork->Configuration.Length =
0475          le32_to_cpu(pnetwork->Configuration.Length);
0476     pnetwork->InfrastructureMode =
0477          le32_to_cpu(pnetwork->InfrastructureMode);
0478     pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
0479 #endif
0480     len = r8712_get_wlan_bssid_ex_sz(pnetwork);
0481     if (len > sizeof(struct wlan_bssid_ex))
0482         return;
0483     spin_lock_irqsave(&pmlmepriv->lock2, flags);
0484     /* update IBSS_network 's timestamp */
0485     if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
0486         if (!memcmp(&(pmlmepriv->cur_network.network.MacAddress),
0487             pnetwork->MacAddress, ETH_ALEN)) {
0488             struct wlan_network *ibss_wlan = NULL;
0489 
0490             memcpy(pmlmepriv->cur_network.network.IEs,
0491                 pnetwork->IEs, 8);
0492             ibss_wlan = r8712_find_network(
0493                         &pmlmepriv->scanned_queue,
0494                         pnetwork->MacAddress);
0495             if (ibss_wlan) {
0496                 memcpy(ibss_wlan->network.IEs,
0497                     pnetwork->IEs, 8);
0498                 goto exit;
0499             }
0500         }
0501     }
0502     /* lock pmlmepriv->lock when you accessing network_q */
0503     if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
0504         if (pnetwork->Ssid.Ssid[0] != 0) {
0505             rtl8711_add_network(adapter, pnetwork);
0506         } else {
0507             pnetwork->Ssid.SsidLength = 8;
0508             memcpy(pnetwork->Ssid.Ssid, "<hidden>", 8);
0509             rtl8711_add_network(adapter, pnetwork);
0510         }
0511     }
0512 exit:
0513     spin_unlock_irqrestore(&pmlmepriv->lock2, flags);
0514 }
0515 
0516 void r8712_surveydone_event_callback(struct _adapter *adapter, u8 *pbuf)
0517 {
0518     unsigned long irqL;
0519     struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
0520 
0521     spin_lock_irqsave(&pmlmepriv->lock, irqL);
0522 
0523     if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
0524         del_timer(&pmlmepriv->scan_to_timer);
0525 
0526         _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
0527     }
0528 
0529     if (pmlmepriv->to_join) {
0530         if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
0531             if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
0532                 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
0533 
0534                 if (!r8712_select_and_join_from_scan(pmlmepriv)) {
0535                     mod_timer(&pmlmepriv->assoc_timer, jiffies +
0536                           msecs_to_jiffies(MAX_JOIN_TIMEOUT));
0537                 } else {
0538                     struct wlan_bssid_ex *pdev_network =
0539                       &(adapter->registrypriv.dev_network);
0540                     u8 *pibss =
0541                          adapter->registrypriv.dev_network.MacAddress;
0542                     pmlmepriv->fw_state ^= _FW_UNDER_SURVEY;
0543                     memcpy(&pdev_network->Ssid,
0544                         &pmlmepriv->assoc_ssid,
0545                         sizeof(struct
0546                              ndis_802_11_ssid));
0547                     r8712_update_registrypriv_dev_network
0548                         (adapter);
0549                     r8712_generate_random_ibss(pibss);
0550                     pmlmepriv->fw_state =
0551                          WIFI_ADHOC_MASTER_STATE;
0552                     pmlmepriv->to_join = false;
0553                 }
0554             }
0555         } else {
0556             pmlmepriv->to_join = false;
0557             set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
0558             if (!r8712_select_and_join_from_scan(pmlmepriv))
0559                 mod_timer(&pmlmepriv->assoc_timer, jiffies +
0560                       msecs_to_jiffies(MAX_JOIN_TIMEOUT));
0561             else
0562                 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
0563         }
0564     }
0565     spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
0566 }
0567 
0568 /*
0569  *r8712_free_assoc_resources: the caller has to lock pmlmepriv->lock
0570  */
0571 void r8712_free_assoc_resources(struct _adapter *adapter)
0572 {
0573     unsigned long irqL;
0574     struct wlan_network *pwlan = NULL;
0575     struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
0576     struct sta_priv *pstapriv = &adapter->stapriv;
0577     struct wlan_network *tgt_network = &pmlmepriv->cur_network;
0578 
0579     pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
0580                    tgt_network->network.MacAddress);
0581 
0582     if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) {
0583         struct sta_info *psta;
0584 
0585         psta = r8712_get_stainfo(&adapter->stapriv,
0586                      tgt_network->network.MacAddress);
0587 
0588         spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
0589         r8712_free_stainfo(adapter,  psta);
0590         spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
0591     }
0592 
0593     if (check_fwstate(pmlmepriv,
0594         WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
0595         r8712_free_all_stainfo(adapter);
0596     if (pwlan)
0597         pwlan->fixed = false;
0598 
0599     if (((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) &&
0600          (adapter->stapriv.asoc_sta_count == 1)))
0601         free_network_nolock(pmlmepriv, pwlan);
0602 }
0603 
0604 /*
0605  * r8712_indicate_connect: the caller has to lock pmlmepriv->lock
0606  */
0607 void r8712_indicate_connect(struct _adapter *padapter)
0608 {
0609     struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
0610 
0611     pmlmepriv->to_join = false;
0612     set_fwstate(pmlmepriv, _FW_LINKED);
0613     padapter->ledpriv.LedControlHandler(padapter, LED_CTL_LINK);
0614     r8712_os_indicate_connect(padapter);
0615     if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE)
0616         mod_timer(&pmlmepriv->dhcp_timer,
0617               jiffies + msecs_to_jiffies(60000));
0618 }
0619 
0620 /*
0621  * r8712_ind_disconnect: the caller has to lock pmlmepriv->lock
0622  */
0623 void r8712_ind_disconnect(struct _adapter *padapter)
0624 {
0625     struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
0626 
0627     if (check_fwstate(pmlmepriv, _FW_LINKED)) {
0628         _clr_fwstate_(pmlmepriv, _FW_LINKED);
0629         padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
0630         r8712_os_indicate_disconnect(padapter);
0631     }
0632     if (padapter->pwrctrlpriv.pwr_mode !=
0633         padapter->registrypriv.power_mgnt) {
0634         del_timer(&pmlmepriv->dhcp_timer);
0635         r8712_set_ps_mode(padapter, padapter->registrypriv.power_mgnt,
0636                   padapter->registrypriv.smart_ps);
0637     }
0638 }
0639 
0640 /*Notes:
0641  *pnetwork : returns from r8712_joinbss_event_callback
0642  *ptarget_wlan: found from scanned_queue
0643  *if join_res > 0, for (fw_state==WIFI_STATION_STATE), we check if
0644  *  "ptarget_sta" & "ptarget_wlan" exist.
0645  *if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), we only check
0646  * if "ptarget_wlan" exist.
0647  *if join_res > 0, update "cur_network->network" from
0648  * "pnetwork->network" if (ptarget_wlan !=NULL).
0649  */
0650 void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
0651 {
0652     unsigned long irqL = 0, irqL2;
0653     struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL;
0654     struct sta_priv *pstapriv = &adapter->stapriv;
0655     struct mlme_priv    *pmlmepriv = &adapter->mlmepriv;
0656     struct wlan_network *cur_network = &pmlmepriv->cur_network;
0657     struct wlan_network *pcur_wlan = NULL, *ptarget_wlan = NULL;
0658     unsigned int        the_same_macaddr = false;
0659     struct wlan_network *pnetwork;
0660 
0661     if (sizeof(struct list_head) == 4 * sizeof(u32)) {
0662         pnetwork = kmalloc(sizeof(struct wlan_network), GFP_ATOMIC);
0663         if (!pnetwork)
0664             return;
0665         memcpy((u8 *)pnetwork + 16, (u8 *)pbuf + 8,
0666                sizeof(struct wlan_network) - 16);
0667     } else {
0668         pnetwork = (struct wlan_network *)pbuf;
0669     }
0670 
0671 #ifdef __BIG_ENDIAN
0672     /* endian_convert */
0673     pnetwork->join_res = le32_to_cpu(pnetwork->join_res);
0674     pnetwork->network_type = le32_to_cpu(pnetwork->network_type);
0675     pnetwork->network.Length = le32_to_cpu(pnetwork->network.Length);
0676     pnetwork->network.Ssid.SsidLength =
0677          le32_to_cpu(pnetwork->network.Ssid.SsidLength);
0678     pnetwork->network.Privacy = le32_to_cpu(pnetwork->network.Privacy);
0679     pnetwork->network.Rssi = le32_to_cpu(pnetwork->network.Rssi);
0680     pnetwork->network.NetworkTypeInUse =
0681          le32_to_cpu(pnetwork->network.NetworkTypeInUse);
0682     pnetwork->network.Configuration.ATIMWindow =
0683          le32_to_cpu(pnetwork->network.Configuration.ATIMWindow);
0684     pnetwork->network.Configuration.BeaconPeriod =
0685          le32_to_cpu(pnetwork->network.Configuration.BeaconPeriod);
0686     pnetwork->network.Configuration.DSConfig =
0687          le32_to_cpu(pnetwork->network.Configuration.DSConfig);
0688     pnetwork->network.Configuration.FHConfig.DwellTime =
0689          le32_to_cpu(pnetwork->network.Configuration.FHConfig.DwellTime);
0690     pnetwork->network.Configuration.FHConfig.HopPattern =
0691          le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopPattern);
0692     pnetwork->network.Configuration.FHConfig.HopSet =
0693          le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopSet);
0694     pnetwork->network.Configuration.FHConfig.Length =
0695          le32_to_cpu(pnetwork->network.Configuration.FHConfig.Length);
0696     pnetwork->network.Configuration.Length =
0697          le32_to_cpu(pnetwork->network.Configuration.Length);
0698     pnetwork->network.InfrastructureMode =
0699          le32_to_cpu(pnetwork->network.InfrastructureMode);
0700     pnetwork->network.IELength = le32_to_cpu(pnetwork->network.IELength);
0701 #endif
0702 
0703     the_same_macaddr = !memcmp(pnetwork->network.MacAddress,
0704                    cur_network->network.MacAddress, ETH_ALEN);
0705     pnetwork->network.Length =
0706          r8712_get_wlan_bssid_ex_sz(&pnetwork->network);
0707     spin_lock_irqsave(&pmlmepriv->lock, irqL);
0708     if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
0709         goto ignore_joinbss_callback;
0710     if (pnetwork->join_res > 0) {
0711         if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
0712             /*s1. find ptarget_wlan*/
0713             if (check_fwstate(pmlmepriv, _FW_LINKED)) {
0714                 if (the_same_macaddr) {
0715                     ptarget_wlan =
0716                         r8712_find_network(&pmlmepriv->scanned_queue,
0717                         cur_network->network.MacAddress);
0718                 } else {
0719                     pcur_wlan =
0720                          r8712_find_network(&pmlmepriv->scanned_queue,
0721                          cur_network->network.MacAddress);
0722                     if (pcur_wlan)
0723                         pcur_wlan->fixed = false;
0724 
0725                     pcur_sta = r8712_get_stainfo(pstapriv,
0726                          cur_network->network.MacAddress);
0727                     spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL2);
0728                     r8712_free_stainfo(adapter, pcur_sta);
0729                     spin_unlock_irqrestore(&(pstapriv->sta_hash_lock), irqL2);
0730 
0731                     ptarget_wlan =
0732                          r8712_find_network(&pmlmepriv->scanned_queue,
0733                          pnetwork->network.MacAddress);
0734                     if (ptarget_wlan)
0735                         ptarget_wlan->fixed = true;
0736                 }
0737             } else {
0738                 ptarget_wlan = r8712_find_network(&pmlmepriv->scanned_queue,
0739                         pnetwork->network.MacAddress);
0740                 if (ptarget_wlan)
0741                     ptarget_wlan->fixed = true;
0742             }
0743 
0744             if (!ptarget_wlan) {
0745                 if (check_fwstate(pmlmepriv,
0746                     _FW_UNDER_LINKING))
0747                     pmlmepriv->fw_state ^=
0748                          _FW_UNDER_LINKING;
0749                 goto ignore_joinbss_callback;
0750             }
0751 
0752             /*s2. find ptarget_sta & update ptarget_sta*/
0753             if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
0754                 if (the_same_macaddr) {
0755                     ptarget_sta =
0756                          r8712_get_stainfo(pstapriv,
0757                          pnetwork->network.MacAddress);
0758                     if (!ptarget_sta)
0759                         ptarget_sta =
0760                          r8712_alloc_stainfo(pstapriv,
0761                          pnetwork->network.MacAddress);
0762                 } else {
0763                     ptarget_sta =
0764                          r8712_alloc_stainfo(pstapriv,
0765                          pnetwork->network.MacAddress);
0766                 }
0767                 if (ptarget_sta) /*update ptarget_sta*/ {
0768                     ptarget_sta->aid = pnetwork->join_res;
0769                     ptarget_sta->qos_option = 1;
0770                     ptarget_sta->mac_id = 5;
0771                     if (adapter->securitypriv.AuthAlgrthm == 2) {
0772                         adapter->securitypriv.binstallGrpkey = false;
0773                         adapter->securitypriv.busetkipkey = false;
0774                         adapter->securitypriv.bgrpkey_handshake = false;
0775                         ptarget_sta->ieee8021x_blocked = true;
0776                         ptarget_sta->XPrivacy = adapter->
0777                         securitypriv.PrivacyAlgrthm;
0778                         memset((u8 *)&ptarget_sta->x_UncstKey,
0779                              0,
0780                              sizeof(union Keytype));
0781                         memset((u8 *)&ptarget_sta->tkiprxmickey,
0782                              0,
0783                              sizeof(union Keytype));
0784                         memset((u8 *)&ptarget_sta->tkiptxmickey,
0785                              0,
0786                              sizeof(union Keytype));
0787                         memset((u8 *)&ptarget_sta->txpn, 0,
0788                              sizeof(union pn48));
0789                         memset((u8 *)&ptarget_sta->rxpn, 0,
0790                              sizeof(union pn48));
0791                     }
0792                 } else {
0793                     if (check_fwstate(pmlmepriv,
0794                         _FW_UNDER_LINKING))
0795                         pmlmepriv->fw_state ^=
0796                              _FW_UNDER_LINKING;
0797                     goto ignore_joinbss_callback;
0798                 }
0799             }
0800 
0801             /*s3. update cur_network & indicate connect*/
0802             memcpy(&cur_network->network, &pnetwork->network,
0803                 pnetwork->network.Length);
0804             cur_network->aid = pnetwork->join_res;
0805             /*update fw_state will clr _FW_UNDER_LINKING*/
0806             switch (pnetwork->network.InfrastructureMode) {
0807             case Ndis802_11Infrastructure:
0808                 pmlmepriv->fw_state = WIFI_STATION_STATE;
0809                 break;
0810             case Ndis802_11IBSS:
0811                 pmlmepriv->fw_state = WIFI_ADHOC_STATE;
0812                 break;
0813             default:
0814                 pmlmepriv->fw_state = WIFI_NULL_STATE;
0815                 break;
0816             }
0817             r8712_update_protection(adapter,
0818                       (cur_network->network.IEs) +
0819                       sizeof(struct NDIS_802_11_FIXED_IEs),
0820                       (cur_network->network.IELength));
0821             /*TODO: update HT_Capability*/
0822             update_ht_cap(adapter, cur_network->network.IEs,
0823                       cur_network->network.IELength);
0824             /*indicate connect*/
0825             if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
0826                 r8712_indicate_connect(adapter);
0827             del_timer(&pmlmepriv->assoc_timer);
0828         } else {
0829             goto ignore_joinbss_callback;
0830         }
0831     } else {
0832         if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
0833             mod_timer(&pmlmepriv->assoc_timer,
0834                   jiffies + msecs_to_jiffies(1));
0835             _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
0836         }
0837     }
0838 ignore_joinbss_callback:
0839     spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
0840     if (sizeof(struct list_head) == 4 * sizeof(u32))
0841         kfree(pnetwork);
0842 }
0843 
0844 void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf)
0845 {
0846     unsigned long irqL;
0847     struct sta_info *psta;
0848     struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
0849     struct stassoc_event *pstassoc  = (struct stassoc_event *)pbuf;
0850 
0851     /* to do: */
0852     if (!r8712_access_ctrl(&adapter->acl_list, pstassoc->macaddr))
0853         return;
0854     psta = r8712_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
0855     if (psta) {
0856         /*the sta have been in sta_info_queue => do nothing
0857          *(between drv has received this event before and
0858          * fw have not yet to set key to CAM_ENTRY)
0859          */
0860         return;
0861     }
0862 
0863     psta = r8712_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
0864     if (!psta)
0865         return;
0866     /* to do : init sta_info variable */
0867     psta->qos_option = 0;
0868     psta->mac_id = le32_to_cpu(pstassoc->cam_id);
0869     /* psta->aid = (uint)pstassoc->cam_id; */
0870 
0871     if (adapter->securitypriv.AuthAlgrthm == 2)
0872         psta->XPrivacy = adapter->securitypriv.PrivacyAlgrthm;
0873     psta->ieee8021x_blocked = false;
0874     spin_lock_irqsave(&pmlmepriv->lock, irqL);
0875     if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
0876         check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
0877         if (adapter->stapriv.asoc_sta_count == 2) {
0878             /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
0879             r8712_indicate_connect(adapter);
0880         }
0881     }
0882     spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
0883 }
0884 
0885 void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf)
0886 {
0887     unsigned long irqL, irqL2;
0888     struct sta_info *psta;
0889     struct wlan_network *pwlan = NULL;
0890     struct wlan_bssid_ex *pdev_network = NULL;
0891     u8 *pibss = NULL;
0892     struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
0893     struct stadel_event *pstadel = (struct stadel_event *)pbuf;
0894     struct sta_priv *pstapriv = &adapter->stapriv;
0895     struct wlan_network *tgt_network = &pmlmepriv->cur_network;
0896 
0897     spin_lock_irqsave(&pmlmepriv->lock, irqL2);
0898     if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
0899         r8712_ind_disconnect(adapter);
0900         r8712_free_assoc_resources(adapter);
0901     }
0902     if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE |
0903         WIFI_ADHOC_STATE)) {
0904         psta = r8712_get_stainfo(&adapter->stapriv, pstadel->macaddr);
0905         spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
0906         r8712_free_stainfo(adapter, psta);
0907         spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
0908         if (adapter->stapriv.asoc_sta_count == 1) {
0909             /*a sta + bc/mc_stainfo (not Ibss_stainfo) */
0910             pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
0911                 tgt_network->network.MacAddress);
0912             if (pwlan) {
0913                 pwlan->fixed = false;
0914                 free_network_nolock(pmlmepriv, pwlan);
0915             }
0916             /*re-create ibss*/
0917             pdev_network = &(adapter->registrypriv.dev_network);
0918             pibss = adapter->registrypriv.dev_network.MacAddress;
0919             memcpy(pdev_network, &tgt_network->network,
0920                 r8712_get_wlan_bssid_ex_sz(&tgt_network->network));
0921             memcpy(&pdev_network->Ssid,
0922                 &pmlmepriv->assoc_ssid,
0923                 sizeof(struct ndis_802_11_ssid));
0924             r8712_update_registrypriv_dev_network(adapter);
0925             r8712_generate_random_ibss(pibss);
0926             if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
0927                 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
0928                 set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
0929             }
0930         }
0931     }
0932     spin_unlock_irqrestore(&pmlmepriv->lock, irqL2);
0933 }
0934 
0935 void r8712_cpwm_event_callback(struct _adapter *adapter, u8 *pbuf)
0936 {
0937     struct reportpwrstate_parm *preportpwrstate =
0938              (struct reportpwrstate_parm *)pbuf;
0939 
0940     preportpwrstate->state |= (u8)(adapter->pwrctrlpriv.cpwm_tog + 0x80);
0941     r8712_cpwm_int_hdl(adapter, preportpwrstate);
0942 }
0943 
0944 /*  When the Netgear 3500 AP is with WPA2PSK-AES mode, it will send
0945  *   the ADDBA req frame with start seq control = 0 to wifi client after
0946  *   the WPA handshake and the seqence number of following data packet
0947  *  will be 0. In this case, the Rx reorder sequence is not longer than 0
0948  *   and the WiFi client will drop the data with seq number 0.
0949  *  So, the 8712 firmware has to inform driver with receiving the
0950  *   ADDBA-Req frame so that the driver can reset the
0951  *  sequence value of Rx reorder control.
0952  */
0953 void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf)
0954 {
0955     struct  ADDBA_Req_Report_parm *pAddbareq_pram =
0956              (struct ADDBA_Req_Report_parm *)pbuf;
0957     struct  sta_info *psta;
0958     struct  sta_priv *pstapriv = &adapter->stapriv;
0959     struct  recv_reorder_ctrl *precvreorder_ctrl = NULL;
0960 
0961     psta = r8712_get_stainfo(pstapriv, pAddbareq_pram->MacAddress);
0962     if (psta) {
0963         precvreorder_ctrl =
0964              &psta->recvreorder_ctrl[pAddbareq_pram->tid];
0965         /* set the indicate_seq to 0xffff so that the rx reorder
0966          * can store any following data packet.
0967          */
0968         precvreorder_ctrl->indicate_seq = 0xffff;
0969     }
0970 }
0971 
0972 void r8712_wpspbc_event_callback(struct _adapter *adapter, u8 *pbuf)
0973 {
0974     if (!adapter->securitypriv.wps_hw_pbc_pressed)
0975         adapter->securitypriv.wps_hw_pbc_pressed = true;
0976 }
0977 
0978 void _r8712_sitesurvey_ctrl_handler(struct _adapter *adapter)
0979 {
0980     struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
0981     struct sitesurvey_ctrl  *psitesurveyctrl = &pmlmepriv->sitesurveyctrl;
0982     struct registry_priv    *pregistrypriv = &adapter->registrypriv;
0983     u64 current_tx_pkts;
0984     uint current_rx_pkts;
0985 
0986     current_tx_pkts = (adapter->xmitpriv.tx_pkts) -
0987               (psitesurveyctrl->last_tx_pkts);
0988     current_rx_pkts = (adapter->recvpriv.rx_pkts) -
0989               (psitesurveyctrl->last_rx_pkts);
0990     psitesurveyctrl->last_tx_pkts = adapter->xmitpriv.tx_pkts;
0991     psitesurveyctrl->last_rx_pkts = adapter->recvpriv.rx_pkts;
0992     if ((current_tx_pkts > pregistrypriv->busy_thresh) ||
0993         (current_rx_pkts > pregistrypriv->busy_thresh))
0994         psitesurveyctrl->traffic_busy = true;
0995     else
0996         psitesurveyctrl->traffic_busy = false;
0997 }
0998 
0999 void _r8712_join_timeout_handler(struct _adapter *adapter)
1000 {
1001     unsigned long irqL;
1002     struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1003 
1004     if (adapter->driver_stopped || adapter->surprise_removed)
1005         return;
1006     spin_lock_irqsave(&pmlmepriv->lock, irqL);
1007     _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1008     pmlmepriv->to_join = false;
1009     if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1010         r8712_os_indicate_disconnect(adapter);
1011         _clr_fwstate_(pmlmepriv, _FW_LINKED);
1012     }
1013     if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt) {
1014         r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
1015                   adapter->registrypriv.smart_ps);
1016     }
1017     spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1018 }
1019 
1020 void r8712_scan_timeout_handler (struct _adapter *adapter)
1021 {
1022     unsigned long irqL;
1023     struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1024 
1025     spin_lock_irqsave(&pmlmepriv->lock, irqL);
1026     _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1027     pmlmepriv->to_join = false; /* scan fail, so clear to_join flag */
1028     spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1029 }
1030 
1031 void _r8712_dhcp_timeout_handler (struct _adapter *adapter)
1032 {
1033     if (adapter->driver_stopped || adapter->surprise_removed)
1034         return;
1035     if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt)
1036         r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
1037                 adapter->registrypriv.smart_ps);
1038 }
1039 
1040 int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv)
1041 {
1042     struct list_head *phead;
1043     unsigned char *dst_ssid, *src_ssid;
1044     struct _adapter *adapter;
1045     struct  __queue *queue = NULL;
1046     struct wlan_network *pnetwork = NULL;
1047     struct wlan_network *pnetwork_max_rssi = NULL;
1048 
1049     adapter = (struct _adapter *)pmlmepriv->nic_hdl;
1050     queue = &pmlmepriv->scanned_queue;
1051     phead = &queue->queue;
1052     pmlmepriv->pscanned = phead->next;
1053     while (1) {
1054         if (end_of_queue_search(phead, pmlmepriv->pscanned)) {
1055             if (pmlmepriv->assoc_by_rssi && pnetwork_max_rssi) {
1056                 pnetwork = pnetwork_max_rssi;
1057                 goto ask_for_joinbss;
1058             }
1059             return -EINVAL;
1060         }
1061         pnetwork = container_of(pmlmepriv->pscanned,
1062                     struct wlan_network, list);
1063         pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1064         if (pmlmepriv->assoc_by_bssid) {
1065             dst_ssid = pnetwork->network.MacAddress;
1066             src_ssid = pmlmepriv->assoc_bssid;
1067             if (!memcmp(dst_ssid, src_ssid, ETH_ALEN)) {
1068                 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1069                     if (is_same_network(&pmlmepriv->cur_network.network,
1070                         &pnetwork->network)) {
1071                         _clr_fwstate_(pmlmepriv,
1072                             _FW_UNDER_LINKING);
1073                         /*r8712_indicate_connect again*/
1074                         r8712_indicate_connect(adapter);
1075                         return 2;
1076                     }
1077                     r8712_disassoc_cmd(adapter);
1078                     r8712_ind_disconnect(adapter);
1079                     r8712_free_assoc_resources(adapter);
1080                 }
1081                 goto ask_for_joinbss;
1082             }
1083         } else if (pmlmepriv->assoc_ssid.SsidLength == 0) {
1084             goto ask_for_joinbss;
1085         }
1086         dst_ssid = pnetwork->network.Ssid.Ssid;
1087         src_ssid = pmlmepriv->assoc_ssid.Ssid;
1088         if ((pnetwork->network.Ssid.SsidLength ==
1089             pmlmepriv->assoc_ssid.SsidLength) &&
1090             (!memcmp(dst_ssid, src_ssid,
1091              pmlmepriv->assoc_ssid.SsidLength))) {
1092             if (pmlmepriv->assoc_by_rssi) {
1093                 /* if the ssid is the same, select the bss
1094                  * which has the max rssi
1095                  */
1096                 if (pnetwork_max_rssi) {
1097                     if (pnetwork->network.Rssi >
1098                         pnetwork_max_rssi->network.Rssi)
1099                         pnetwork_max_rssi = pnetwork;
1100                 } else {
1101                     pnetwork_max_rssi = pnetwork;
1102                 }
1103             } else if (is_desired_network(adapter, pnetwork)) {
1104                 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1105                     r8712_disassoc_cmd(adapter);
1106                     r8712_free_assoc_resources(adapter);
1107                 }
1108                 goto ask_for_joinbss;
1109             }
1110         }
1111     }
1112 
1113 ask_for_joinbss:
1114     return r8712_joinbss_cmd(adapter, pnetwork);
1115 }
1116 
1117 int r8712_set_auth(struct _adapter *adapter,
1118            struct security_priv *psecuritypriv)
1119 {
1120     struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1121     struct cmd_obj *pcmd;
1122     struct setauth_parm *psetauthparm;
1123 
1124     pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
1125     if (!pcmd)
1126         return -ENOMEM;
1127 
1128     psetauthparm = kzalloc(sizeof(*psetauthparm), GFP_ATOMIC);
1129     if (!psetauthparm) {
1130         kfree(pcmd);
1131         return -ENOMEM;
1132     }
1133     psetauthparm->mode = (u8)psecuritypriv->AuthAlgrthm;
1134     pcmd->cmdcode = _SetAuth_CMD_;
1135     pcmd->parmbuf = (unsigned char *)psetauthparm;
1136     pcmd->cmdsz = sizeof(struct setauth_parm);
1137     pcmd->rsp = NULL;
1138     pcmd->rspsz = 0;
1139     INIT_LIST_HEAD(&pcmd->list);
1140     r8712_enqueue_cmd(pcmdpriv, pcmd);
1141     return 0;
1142 }
1143 
1144 int r8712_set_key(struct _adapter *adapter,
1145           struct security_priv *psecuritypriv,
1146           sint keyid)
1147 {
1148     struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1149     struct cmd_obj *pcmd;
1150     struct setkey_parm *psetkeyparm;
1151     u8 keylen;
1152     int ret;
1153 
1154     pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
1155     if (!pcmd)
1156         return -ENOMEM;
1157     psetkeyparm = kzalloc(sizeof(*psetkeyparm), GFP_ATOMIC);
1158     if (!psetkeyparm) {
1159         ret = -ENOMEM;
1160         goto err_free_cmd;
1161     }
1162     if (psecuritypriv->AuthAlgrthm == 2) { /* 802.1X */
1163         psetkeyparm->algorithm =
1164              (u8)psecuritypriv->XGrpPrivacy;
1165     } else { /* WEP */
1166         psetkeyparm->algorithm =
1167              (u8)psecuritypriv->PrivacyAlgrthm;
1168     }
1169     psetkeyparm->keyid = (u8)keyid;
1170 
1171     switch (psetkeyparm->algorithm) {
1172     case _WEP40_:
1173         keylen = 5;
1174         memcpy(psetkeyparm->key,
1175             psecuritypriv->DefKey[keyid].skey, keylen);
1176         break;
1177     case _WEP104_:
1178         keylen = 13;
1179         memcpy(psetkeyparm->key,
1180             psecuritypriv->DefKey[keyid].skey, keylen);
1181         break;
1182     case _TKIP_:
1183         if (keyid < 1 || keyid > 2) {
1184             ret = -EINVAL;
1185             goto err_free_parm;
1186         }
1187         keylen = 16;
1188         memcpy(psetkeyparm->key,
1189             &psecuritypriv->XGrpKey[keyid - 1], keylen);
1190         psetkeyparm->grpkey = 1;
1191         break;
1192     case _AES_:
1193         if (keyid < 1 || keyid > 2) {
1194             ret = -EINVAL;
1195             goto err_free_parm;
1196         }
1197         keylen = 16;
1198         memcpy(psetkeyparm->key,
1199             &psecuritypriv->XGrpKey[keyid - 1], keylen);
1200         psetkeyparm->grpkey = 1;
1201         break;
1202     default:
1203         ret = -EINVAL;
1204         goto err_free_parm;
1205     }
1206     pcmd->cmdcode = _SetKey_CMD_;
1207     pcmd->parmbuf = (u8 *)psetkeyparm;
1208     pcmd->cmdsz =  (sizeof(struct setkey_parm));
1209     pcmd->rsp = NULL;
1210     pcmd->rspsz = 0;
1211     INIT_LIST_HEAD(&pcmd->list);
1212     r8712_enqueue_cmd(pcmdpriv, pcmd);
1213     return 0;
1214 
1215 err_free_parm:
1216     kfree(psetkeyparm);
1217 err_free_cmd:
1218     kfree(pcmd);
1219     return ret;
1220 }
1221 
1222 /* adjust IEs for r8712_joinbss_cmd in WMM */
1223 int r8712_restruct_wmm_ie(struct _adapter *adapter, u8 *in_ie, u8 *out_ie,
1224             uint in_len, uint initial_out_len)
1225 {
1226     unsigned int ielength = 0;
1227     unsigned int i, j;
1228 
1229     i = 12; /* after the fixed IE */
1230     while (i < in_len) {
1231         ielength = initial_out_len;
1232         if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 &&
1233             in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 &&
1234             in_ie[i + 5] == 0x02 && i + 5 < in_len) {
1235             /*WMM element ID and OUI*/
1236             for (j = i; j < i + 9; j++) {
1237                 out_ie[ielength] = in_ie[j];
1238                 ielength++;
1239             }
1240             out_ie[initial_out_len + 1] = 0x07;
1241             out_ie[initial_out_len + 6] = 0x00;
1242             out_ie[initial_out_len + 8] = 0x00;
1243             break;
1244         }
1245         i += (in_ie[i + 1] + 2); /* to the next IE element */
1246     }
1247     return ielength;
1248 }
1249 
1250 /*
1251  * Ported from 8185: IsInPreAuthKeyList().
1252  *
1253  * Search by BSSID,
1254  * Return Value:
1255  *  -1      :if there is no pre-auth key in the  table
1256  *  >=0     :if there is pre-auth key, and   return the entry id
1257  */
1258 static int SecIsInPMKIDList(struct _adapter *Adapter, u8 *bssid)
1259 {
1260     struct security_priv *p = &Adapter->securitypriv;
1261     int i;
1262 
1263     for (i = 0; i < NUM_PMKID_CACHE; i++)
1264         if (p->PMKIDList[i].bUsed && !memcmp(p->PMKIDList[i].Bssid, bssid, ETH_ALEN))
1265             return i;
1266     return -1;
1267 }
1268 
1269 sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
1270              u8 *out_ie, uint in_len)
1271 {
1272     u8 authmode = 0, match;
1273     u8 sec_ie[IW_CUSTOM_MAX], uncst_oui[4], bkup_ie[255];
1274     u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
1275     uint ielength, cnt, remove_cnt;
1276     int iEntry;
1277     struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1278     struct security_priv *psecuritypriv = &adapter->securitypriv;
1279     uint ndisauthmode = psecuritypriv->ndisauthtype;
1280     uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
1281 
1282     if ((ndisauthmode == Ndis802_11AuthModeWPA) ||
1283         (ndisauthmode == Ndis802_11AuthModeWPAPSK)) {
1284         authmode = _WPA_IE_ID_;
1285         uncst_oui[0] = 0x0;
1286         uncst_oui[1] = 0x50;
1287         uncst_oui[2] = 0xf2;
1288     }
1289     if ((ndisauthmode == Ndis802_11AuthModeWPA2) ||
1290         (ndisauthmode == Ndis802_11AuthModeWPA2PSK)) {
1291         authmode = _WPA2_IE_ID_;
1292         uncst_oui[0] = 0x0;
1293         uncst_oui[1] = 0x0f;
1294         uncst_oui[2] = 0xac;
1295     }
1296     switch (ndissecuritytype) {
1297     case Ndis802_11Encryption1Enabled:
1298     case Ndis802_11Encryption1KeyAbsent:
1299         uncst_oui[3] = 0x1;
1300         break;
1301     case Ndis802_11Encryption2Enabled:
1302     case Ndis802_11Encryption2KeyAbsent:
1303         uncst_oui[3] = 0x2;
1304         break;
1305     case Ndis802_11Encryption3Enabled:
1306     case Ndis802_11Encryption3KeyAbsent:
1307         uncst_oui[3] = 0x4;
1308         break;
1309     default:
1310         break;
1311     }
1312     /*Search required WPA or WPA2 IE and copy to sec_ie[] */
1313     cnt = 12;
1314     match = false;
1315     while (cnt < in_len) {
1316         if (in_ie[cnt] == authmode) {
1317             if ((authmode == _WPA_IE_ID_) &&
1318                 (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
1319                 memcpy(&sec_ie[0], &in_ie[cnt],
1320                     in_ie[cnt + 1] + 2);
1321                 match = true;
1322                 break;
1323             }
1324             if (authmode == _WPA2_IE_ID_) {
1325                 memcpy(&sec_ie[0], &in_ie[cnt],
1326                     in_ie[cnt + 1] + 2);
1327                 match = true;
1328                 break;
1329             }
1330             if (((authmode == _WPA_IE_ID_) &&
1331                  (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) ||
1332                  (authmode == _WPA2_IE_ID_))
1333                 memcpy(&bkup_ie[0], &in_ie[cnt],
1334                     in_ie[cnt + 1] + 2);
1335         }
1336         cnt += in_ie[cnt + 1] + 2; /*get next*/
1337     }
1338     /*restruct WPA IE or WPA2 IE in sec_ie[] */
1339     if (match) {
1340         if (sec_ie[0] == _WPA_IE_ID_) {
1341             /* parsing SSN IE to select required encryption
1342              * algorithm, and set the bc/mc encryption algorithm
1343              */
1344             while (true) {
1345                 /*check wpa_oui tag*/
1346                 if (memcmp(&sec_ie[2], &wpa_oui[0], 4)) {
1347                     match = false;
1348                     break;
1349                 }
1350                 if ((sec_ie[6] != 0x01) || (sec_ie[7] != 0x0)) {
1351                     /*IE Ver error*/
1352                     match = false;
1353                     break;
1354                 }
1355                 if (!memcmp(&sec_ie[8], &wpa_oui[0], 3)) {
1356                     /* get bc/mc encryption type (group
1357                      * key type)
1358                      */
1359                     switch (sec_ie[11]) {
1360                     case 0x0: /*none*/
1361                         psecuritypriv->XGrpPrivacy =
1362                                 _NO_PRIVACY_;
1363                         break;
1364                     case 0x1: /*WEP_40*/
1365                         psecuritypriv->XGrpPrivacy =
1366                                 _WEP40_;
1367                         break;
1368                     case 0x2: /*TKIP*/
1369                         psecuritypriv->XGrpPrivacy =
1370                                 _TKIP_;
1371                         break;
1372                     case 0x3: /*AESCCMP*/
1373                     case 0x4:
1374                         psecuritypriv->XGrpPrivacy =
1375                                 _AES_;
1376                         break;
1377                     case 0x5: /*WEP_104*/
1378                         psecuritypriv->XGrpPrivacy =
1379                                 _WEP104_;
1380                         break;
1381                     }
1382                 } else {
1383                     match = false;
1384                     break;
1385                 }
1386                 if (sec_ie[12] == 0x01) {
1387                     /*check the unicast encryption type*/
1388                     if (memcmp(&sec_ie[14],
1389                         &uncst_oui[0], 4)) {
1390                         match = false;
1391                         break;
1392 
1393                     } /*else the uncst_oui is match*/
1394                 } else { /*mixed mode, unicast_enc_type > 1*/
1395                     /*select the uncst_oui and remove
1396                      * the other uncst_oui
1397                      */
1398                     cnt = sec_ie[12];
1399                     remove_cnt = (cnt - 1) * 4;
1400                     sec_ie[12] = 0x01;
1401                     memcpy(&sec_ie[14], &uncst_oui[0], 4);
1402                     /*remove the other unicast suit*/
1403                     memcpy(&sec_ie[18],
1404                         &sec_ie[18 + remove_cnt],
1405                         sec_ie[1] - 18 + 2 -
1406                         remove_cnt);
1407                     sec_ie[1] = sec_ie[1] - remove_cnt;
1408                 }
1409                 break;
1410             }
1411         }
1412         if (authmode == _WPA2_IE_ID_) {
1413             /* parsing RSN IE to select required encryption
1414              * algorithm, and set the bc/mc encryption algorithm
1415              */
1416             while (true) {
1417                 if ((sec_ie[2] != 0x01) || (sec_ie[3] != 0x0)) {
1418                     /*IE Ver error*/
1419                     match = false;
1420                     break;
1421                 }
1422                 if (!memcmp(&sec_ie[4], &uncst_oui[0], 3)) {
1423                     /*get bc/mc encryption type*/
1424                     switch (sec_ie[7]) {
1425                     case 0x1: /*WEP_40*/
1426                         psecuritypriv->XGrpPrivacy =
1427                                 _WEP40_;
1428                         break;
1429                     case 0x2: /*TKIP*/
1430                         psecuritypriv->XGrpPrivacy =
1431                                 _TKIP_;
1432                         break;
1433                     case 0x4: /*AESWRAP*/
1434                         psecuritypriv->XGrpPrivacy =
1435                                 _AES_;
1436                         break;
1437                     case 0x5: /*WEP_104*/
1438                         psecuritypriv->XGrpPrivacy =
1439                                 _WEP104_;
1440                         break;
1441                     default: /*one*/
1442                         psecuritypriv->XGrpPrivacy =
1443                                 _NO_PRIVACY_;
1444                         break;
1445                     }
1446                 } else {
1447                     match = false;
1448                     break;
1449                 }
1450                 if (sec_ie[8] == 0x01) {
1451                     /*check the unicast encryption type*/
1452                     if (memcmp(&sec_ie[10],
1453                              &uncst_oui[0], 4)) {
1454                         match = false;
1455                         break;
1456                     } /*else the uncst_oui is match*/
1457                 } else { /*mixed mode, unicast_enc_type > 1*/
1458                     /*select the uncst_oui and remove the
1459                      * other uncst_oui
1460                      */
1461                     cnt = sec_ie[8];
1462                     remove_cnt = (cnt - 1) * 4;
1463                     sec_ie[8] = 0x01;
1464                     memcpy(&sec_ie[10], &uncst_oui[0], 4);
1465                     /*remove the other unicast suit*/
1466                     memcpy(&sec_ie[14],
1467                         &sec_ie[14 + remove_cnt],
1468                         (sec_ie[1] - 14 + 2 -
1469                         remove_cnt));
1470                     sec_ie[1] = sec_ie[1] - remove_cnt;
1471                 }
1472                 break;
1473             }
1474         }
1475     }
1476     if ((authmode == _WPA_IE_ID_) || (authmode == _WPA2_IE_ID_)) {
1477         /*copy fixed ie*/
1478         memcpy(out_ie, in_ie, 12);
1479         ielength = 12;
1480         /*copy RSN or SSN*/
1481         if (match) {
1482             memcpy(&out_ie[ielength], &sec_ie[0], sec_ie[1] + 2);
1483             ielength += sec_ie[1] + 2;
1484             if (authmode == _WPA2_IE_ID_) {
1485                 /*the Pre-Authentication bit should be zero*/
1486                 out_ie[ielength - 1] = 0;
1487                 out_ie[ielength - 2] = 0;
1488             }
1489             r8712_report_sec_ie(adapter, authmode, sec_ie);
1490         }
1491     } else {
1492         /*copy fixed ie only*/
1493         memcpy(out_ie, in_ie, 12);
1494         ielength = 12;
1495         if (psecuritypriv->wps_phase) {
1496             memcpy(out_ie + ielength, psecuritypriv->wps_ie,
1497                    psecuritypriv->wps_ie_len);
1498             ielength += psecuritypriv->wps_ie_len;
1499         }
1500     }
1501     iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
1502     if (iEntry < 0)
1503         return ielength;
1504     if (authmode == _WPA2_IE_ID_) {
1505         out_ie[ielength] = 1;
1506         ielength++;
1507         out_ie[ielength] = 0;   /*PMKID count = 0x0100*/
1508         ielength++;
1509         memcpy(&out_ie[ielength],
1510             &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
1511         ielength += 16;
1512         out_ie[13] += 18;/*PMKID length = 2+16*/
1513     }
1514     return ielength;
1515 }
1516 
1517 void r8712_init_registrypriv_dev_network(struct _adapter *adapter)
1518 {
1519     struct registry_priv *pregistrypriv = &adapter->registrypriv;
1520     struct eeprom_priv *peepriv = &adapter->eeprompriv;
1521     struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
1522     u8 *myhwaddr = myid(peepriv);
1523 
1524     memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
1525     memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
1526         sizeof(struct ndis_802_11_ssid));
1527     pdev_network->Configuration.Length =
1528              sizeof(struct NDIS_802_11_CONFIGURATION);
1529     pdev_network->Configuration.BeaconPeriod = 100;
1530     pdev_network->Configuration.FHConfig.Length = 0;
1531     pdev_network->Configuration.FHConfig.HopPattern = 0;
1532     pdev_network->Configuration.FHConfig.HopSet = 0;
1533     pdev_network->Configuration.FHConfig.DwellTime = 0;
1534 }
1535 
1536 void r8712_update_registrypriv_dev_network(struct _adapter *adapter)
1537 {
1538     int sz = 0;
1539     struct registry_priv    *pregistrypriv = &adapter->registrypriv;
1540     struct wlan_bssid_ex    *pdev_network = &pregistrypriv->dev_network;
1541     struct security_priv    *psecuritypriv = &adapter->securitypriv;
1542     struct wlan_network *cur_network = &adapter->mlmepriv.cur_network;
1543 
1544     pdev_network->Privacy = cpu_to_le32(psecuritypriv->PrivacyAlgrthm
1545                         > 0 ? 1 : 0); /* adhoc no 802.1x */
1546     pdev_network->Rssi = 0;
1547     switch (pregistrypriv->wireless_mode) {
1548     case WIRELESS_11B:
1549         pdev_network->NetworkTypeInUse = Ndis802_11DS;
1550         break;
1551     case WIRELESS_11G:
1552     case WIRELESS_11BG:
1553         pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
1554         break;
1555     case WIRELESS_11A:
1556         pdev_network->NetworkTypeInUse = Ndis802_11OFDM5;
1557         break;
1558     default:
1559         /* TODO */
1560         break;
1561     }
1562     pdev_network->Configuration.DSConfig = pregistrypriv->channel;
1563     if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
1564         pdev_network->Configuration.ATIMWindow = 3;
1565     pdev_network->InfrastructureMode = cur_network->network.InfrastructureMode;
1566     /* 1. Supported rates
1567      * 2. IE
1568      */
1569     sz = r8712_generate_ie(pregistrypriv);
1570     pdev_network->IELength = sz;
1571     pdev_network->Length = r8712_get_wlan_bssid_ex_sz(pdev_network);
1572 }
1573 
1574 /*the function is at passive_level*/
1575 void r8712_joinbss_reset(struct _adapter *padapter)
1576 {
1577     int i;
1578     struct mlme_priv    *pmlmepriv = &padapter->mlmepriv;
1579     struct ht_priv      *phtpriv = &pmlmepriv->htpriv;
1580 
1581     /* todo: if you want to do something io/reg/hw setting before join_bss,
1582      * please add code here
1583      */
1584     phtpriv->ampdu_enable = false;/*reset to disabled*/
1585     for (i = 0; i < 16; i++)
1586         phtpriv->baddbareq_issued[i] = false;/*reset it*/
1587     if (phtpriv->ht_option) {
1588         /* validate  usb rx aggregation */
1589         r8712_write8(padapter, 0x102500D9, 48);/*TH = 48 pages, 6k*/
1590     } else {
1591         /* invalidate  usb rx aggregation */
1592         /* TH=1 => means that invalidate usb rx aggregation */
1593         r8712_write8(padapter, 0x102500D9, 1);
1594     }
1595 }
1596 
1597 /*the function is >= passive_level*/
1598 unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie,
1599                      u8 *out_ie, uint in_len, uint *pout_len)
1600 {
1601     u32 ielen, out_len;
1602     unsigned char *p;
1603     struct ieee80211_ht_cap ht_capie;
1604     unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
1605     struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1606     struct qos_priv *pqospriv = &pmlmepriv->qospriv;
1607     struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1608 
1609     phtpriv->ht_option = 0;
1610     p = r8712_get_ie(in_ie + 12, WLAN_EID_HT_CAPABILITY, &ielen, in_len - 12);
1611     if (p && (ielen > 0)) {
1612         if (pqospriv->qos_option == 0) {
1613             out_len = *pout_len;
1614             r8712_set_ie(out_ie + out_len, WLAN_EID_VENDOR_SPECIFIC,
1615                      _WMM_IE_Length_, WMM_IE, pout_len);
1616             pqospriv->qos_option = 1;
1617         }
1618         out_len = *pout_len;
1619         memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
1620         ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
1621                     IEEE80211_HT_CAP_SGI_20 |
1622                     IEEE80211_HT_CAP_SGI_40 |
1623                     IEEE80211_HT_CAP_TX_STBC |
1624                     IEEE80211_HT_CAP_MAX_AMSDU |
1625                     IEEE80211_HT_CAP_DSSSCCK40);
1626         ht_capie.ampdu_params_info = (IEEE80211_HT_AMPDU_PARM_FACTOR &
1627                 0x03) | (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00);
1628         r8712_set_ie(out_ie + out_len, WLAN_EID_HT_CAPABILITY,
1629                  sizeof(struct ieee80211_ht_cap),
1630                  (unsigned char *)&ht_capie, pout_len);
1631         phtpriv->ht_option = 1;
1632     }
1633     return phtpriv->ht_option;
1634 }
1635 
1636 /* the function is > passive_level (in critical_section) */
1637 static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len)
1638 {
1639     u8 *p, max_ampdu_sz;
1640     int i;
1641     uint len;
1642     struct sta_info *bmc_sta, *psta;
1643     struct ieee80211_ht_cap *pht_capie;
1644     struct recv_reorder_ctrl *preorder_ctrl;
1645     struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1646     struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1647     struct registry_priv *pregistrypriv = &padapter->registrypriv;
1648     struct wlan_network *pcur_network = &(pmlmepriv->cur_network);
1649 
1650     if (!phtpriv->ht_option)
1651         return;
1652     /* maybe needs check if ap supports rx ampdu. */
1653     if (!phtpriv->ampdu_enable &&
1654         (pregistrypriv->ampdu_enable == 1))
1655         phtpriv->ampdu_enable = true;
1656     /*check Max Rx A-MPDU Size*/
1657     len = 0;
1658     p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
1659                 WLAN_EID_HT_CAPABILITY,
1660                 &len, ie_len -
1661                 sizeof(struct NDIS_802_11_FIXED_IEs));
1662     if (p && len > 0) {
1663         pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1664         max_ampdu_sz = (pht_capie->ampdu_params_info &
1665                 IEEE80211_HT_AMPDU_PARM_FACTOR);
1666         /* max_ampdu_sz (kbytes); */
1667         max_ampdu_sz = 1 << (max_ampdu_sz + 3);
1668         phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
1669     }
1670     /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info
1671      * if A-MPDU Rx is enabled, resetting rx_ordering_ctrl
1672      * wstart_b(indicate_seq) to default value=0xffff
1673      * todo: check if AP can send A-MPDU packets
1674      */
1675     bmc_sta = r8712_get_bcmc_stainfo(padapter);
1676     if (bmc_sta) {
1677         for (i = 0; i < 16; i++) {
1678             preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
1679             preorder_ctrl->indicate_seq = 0xffff;
1680             preorder_ctrl->wend_b = 0xffff;
1681         }
1682     }
1683     psta = r8712_get_stainfo(&padapter->stapriv,
1684                  pcur_network->network.MacAddress);
1685     if (psta) {
1686         for (i = 0; i < 16; i++) {
1687             preorder_ctrl = &psta->recvreorder_ctrl[i];
1688             preorder_ctrl->indicate_seq = 0xffff;
1689             preorder_ctrl->wend_b = 0xffff;
1690         }
1691     }
1692     len = 0;
1693     p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
1694            WLAN_EID_HT_OPERATION, &len,
1695            ie_len - sizeof(struct NDIS_802_11_FIXED_IEs));
1696 }
1697 
1698 void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority)
1699 {
1700     struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1701     struct ht_priv   *phtpriv = &pmlmepriv->htpriv;
1702 
1703     if ((phtpriv->ht_option == 1) && (phtpriv->ampdu_enable)) {
1704         if (!phtpriv->baddbareq_issued[priority]) {
1705             r8712_addbareq_cmd(padapter, (u8)priority);
1706             phtpriv->baddbareq_issued[priority] = true;
1707         }
1708     }
1709 }