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