GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / staging / rtl8723bs / core / rtw_mlme_ext.c
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 #include <drv_types.h>
8 #include <rtw_debug.h>
9 #include <rtw_wifi_regd.h>
10 #include <hal_btcoex.h>
11 #include <linux/kernel.h>
12 #include <asm/unaligned.h>
13
14 static struct mlme_handler mlme_sta_tbl[] = {
15         {WIFI_ASSOCREQ,         "OnAssocReq",   &OnAssocReq},
16         {WIFI_ASSOCRSP,         "OnAssocRsp",   &OnAssocRsp},
17         {WIFI_REASSOCREQ,       "OnReAssocReq", &OnAssocReq},
18         {WIFI_REASSOCRSP,       "OnReAssocRsp", &OnAssocRsp},
19         {WIFI_PROBEREQ,         "OnProbeReq",   &OnProbeReq},
20         {WIFI_PROBERSP,         "OnProbeRsp",           &OnProbeRsp},
21
22         /*----------------------------------------------------------
23                                         below 2 are reserved
24         -----------------------------------------------------------*/
25         {0,                                     "DoReserved",           &DoReserved},
26         {0,                                     "DoReserved",           &DoReserved},
27         {WIFI_BEACON,           "OnBeacon",             &OnBeacon},
28         {WIFI_ATIM,                     "OnATIM",               &OnAtim},
29         {WIFI_DISASSOC,         "OnDisassoc",           &OnDisassoc},
30         {WIFI_AUTH,                     "OnAuth",               &OnAuthClient},
31         {WIFI_DEAUTH,           "OnDeAuth",             &OnDeAuth},
32         {WIFI_ACTION,           "OnAction",             &OnAction},
33         {WIFI_ACTION_NOACK, "OnActionNoAck",    &OnAction},
34 };
35
36 static struct action_handler OnAction_tbl[] = {
37         {RTW_WLAN_CATEGORY_SPECTRUM_MGMT,        "ACTION_SPECTRUM_MGMT", on_action_spct},
38         {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &DoReserved},
39         {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &DoReserved},
40         {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back},
41         {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public},
42         {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved},
43         {RTW_WLAN_CATEGORY_FT, "ACTION_FT",     &DoReserved},
44         {RTW_WLAN_CATEGORY_HT,  "ACTION_HT",    &OnAction_ht},
45         {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &OnAction_sa_query},
46         {RTW_WLAN_CATEGORY_UNPROTECTED_WNM, "ACTION_UNPROTECTED_WNM", &DoReserved},
47         {RTW_WLAN_CATEGORY_SELF_PROTECTED, "ACTION_SELF_PROTECTED", &DoReserved},
48         {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &DoReserved},
49         {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &DoReserved},
50 };
51
52 static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
53
54 /**************************************************
55 OUI definitions for the vendor specific IE
56 ***************************************************/
57 unsigned char RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
58 unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
59 unsigned char WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
60 unsigned char P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};
61 unsigned char WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A};
62
63 unsigned char WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
64 unsigned char WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
65
66 static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
67
68 /********************************************************
69 ChannelPlan definitions
70 *********************************************************/
71 static struct rt_channel_plan_2g        RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
72         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},              /*  0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
73         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},              /*  0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
74         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},                      /*  0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
75         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},  /*  0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
76         {{10, 11, 12, 13}, 4},                                          /*  0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
77         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},  /*  0x05, RT_CHANNEL_DOMAIN_2G_GLOBAL , Passive scan CH 12, 13, 14 */
78         {{}, 0},                                                                /*  0x06, RT_CHANNEL_DOMAIN_2G_NULL */
79 };
80
81 static struct rt_channel_plan_map       RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
82         /*  0x00 ~ 0x1F , Old Define ===== */
83         {0x02}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
84         {0x02}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
85         {0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
86         {0x01}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
87         {0x01}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
88         {0x03}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
89         {0x03}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
90         {0x01}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
91         {0x03}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
92         {0x03}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
93         {0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
94         {0x02}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
95         {0x01}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
96         {0x02}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
97         {0x02}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
98         {0x02}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
99         {0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
100         {0x02}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
101         {0x01}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
102         {0x00}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
103         {0x02}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
104         {0x00}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
105         {0x00}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
106         {0x03}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
107         {0x06}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
108         {0x02}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
109         {0x00}, /* 0x1A, */
110         {0x00}, /* 0x1B, */
111         {0x00}, /* 0x1C, */
112         {0x00}, /* 0x1D, */
113         {0x00}, /* 0x1E, */
114         {0x06}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
115         /*  0x20 ~ 0x7F , New Define ===== */
116         {0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
117         {0x01}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
118         {0x02}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
119         {0x03}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
120         {0x04}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
121         {0x02}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
122         {0x00}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
123         {0x03}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
124         {0x00}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
125         {0x00}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
126         {0x00}, /* 0x2A, */
127         {0x00}, /* 0x2B, */
128         {0x00}, /* 0x2C, */
129         {0x00}, /* 0x2D, */
130         {0x00}, /* 0x2E, */
131         {0x00}, /* 0x2F, */
132         {0x00}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
133         {0x00}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
134         {0x00}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
135         {0x00}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
136         {0x02}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
137         {0x00}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
138         {0x00}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
139         {0x03}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
140         {0x03}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
141         {0x02}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
142         {0x00}, /* 0x3A, */
143         {0x00}, /* 0x3B, */
144         {0x00}, /* 0x3C, */
145         {0x00}, /* 0x3D, */
146         {0x00}, /* 0x3E, */
147         {0x00}, /* 0x3F, */
148         {0x02}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
149         {0x05}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_NULL */
150         {0x01}, /* 0x42, RT_CHANNEL_DOMAIN_ETSI1_ETSI4 */
151         {0x02}, /* 0x43, RT_CHANNEL_DOMAIN_FCC1_FCC2 */
152         {0x02}, /* 0x44, RT_CHANNEL_DOMAIN_FCC1_NCC3 */
153         {0x00}, /* 0x45, RT_CHANNEL_DOMAIN_WORLD_ETSI5 */
154         {0x02}, /* 0x46, RT_CHANNEL_DOMAIN_FCC1_FCC8 */
155         {0x00}, /* 0x47, RT_CHANNEL_DOMAIN_WORLD_ETSI6 */
156         {0x00}, /* 0x48, RT_CHANNEL_DOMAIN_WORLD_ETSI7 */
157         {0x00}, /* 0x49, RT_CHANNEL_DOMAIN_WORLD_ETSI8 */
158         {0x00}, /* 0x50, RT_CHANNEL_DOMAIN_WORLD_ETSI9 */
159         {0x00}, /* 0x51, RT_CHANNEL_DOMAIN_WORLD_ETSI10 */
160         {0x00}, /* 0x52, RT_CHANNEL_DOMAIN_WORLD_ETSI11 */
161         {0x02}, /* 0x53, RT_CHANNEL_DOMAIN_FCC1_NCC4 */
162         {0x00}, /* 0x54, RT_CHANNEL_DOMAIN_WORLD_ETSI12 */
163         {0x02}, /* 0x55, RT_CHANNEL_DOMAIN_FCC1_FCC9 */
164         {0x00}, /* 0x56, RT_CHANNEL_DOMAIN_WORLD_ETSI13 */
165         {0x02}, /* 0x57, RT_CHANNEL_DOMAIN_FCC1_FCC10 */
166 };
167
168  /* use the combination for max channel numbers */
169 static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03};
170
171 /* Search the @param ch in given @param ch_set
172  * @ch_set: the given channel set
173  * @ch: the given channel number
174  *
175  * return the index of channel_num in channel_set, -1 if not found
176  */
177 int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch)
178 {
179         int i;
180
181         for (i = 0; ch_set[i].ChannelNum != 0; i++) {
182                 if (ch == ch_set[i].ChannelNum)
183                         break;
184         }
185
186         if (i >= ch_set[i].ChannelNum)
187                 return -1;
188         return i;
189 }
190
191 /****************************************************************************
192
193 Following are the initialization functions for WiFi MLME
194
195 *****************************************************************************/
196
197 int init_hw_mlme_ext(struct adapter *padapter)
198 {
199         struct  mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
200
201         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
202         return _SUCCESS;
203 }
204
205 void init_mlme_default_rate_set(struct adapter *padapter)
206 {
207         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
208
209         unsigned char mixed_datarate[NumRates] = {_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_, _48M_RATE_, _54M_RATE_, 0xff};
210         unsigned char mixed_basicrate[NumRates] = {_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, _12M_RATE_, _24M_RATE_, 0xff,};
211         unsigned char supported_mcs_set[16] = {0xff, 0xff, 0x00, 0x00, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
212
213         memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
214         memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
215
216         memcpy(pmlmeext->default_supported_mcs_set, supported_mcs_set, sizeof(pmlmeext->default_supported_mcs_set));
217 }
218
219 static void init_mlme_ext_priv_value(struct adapter *padapter)
220 {
221         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
222         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
223
224         atomic_set(&pmlmeext->event_seq, 0);
225         pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */
226         pmlmeext->sa_query_seq = 0;
227         pmlmeext->mgnt_80211w_IPN = 0;
228         pmlmeext->mgnt_80211w_IPN_rx = 0;
229         pmlmeext->cur_channel = padapter->registrypriv.channel;
230         pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
231         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
232
233         pmlmeext->retry = 0;
234
235         pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
236
237         init_mlme_default_rate_set(padapter);
238
239         pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
240         pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
241         pmlmeext->sitesurvey_res.channel_idx = 0;
242         pmlmeext->sitesurvey_res.bss_cnt = 0;
243         pmlmeext->scan_abort = false;
244
245         pmlmeinfo->state = WIFI_FW_NULL_STATE;
246         pmlmeinfo->reauth_count = 0;
247         pmlmeinfo->reassoc_count = 0;
248         pmlmeinfo->link_count = 0;
249         pmlmeinfo->auth_seq = 0;
250         pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
251         pmlmeinfo->key_index = 0;
252         pmlmeinfo->iv = 0;
253
254         pmlmeinfo->enc_algo = _NO_PRIVACY_;
255         pmlmeinfo->authModeToggle = 0;
256
257         memset(pmlmeinfo->chg_txt, 0, 128);
258
259         pmlmeinfo->slotTime = SHORT_SLOT_TIME;
260         pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
261
262         pmlmeinfo->dialogToken = 0;
263
264         pmlmeext->action_public_rxseq = 0xffff;
265         pmlmeext->action_public_dialog_token = 0xff;
266 }
267
268 static int has_channel(struct rt_channel_info *channel_set,
269                                            u8 chanset_size,
270                                            u8 chan)
271 {
272         int i;
273
274         for (i = 0; i < chanset_size; i++)
275                 if (channel_set[i].ChannelNum == chan)
276                         return 1;
277
278         return 0;
279 }
280
281 static void init_channel_list(struct adapter *padapter, struct rt_channel_info *channel_set,
282                                                           u8 chanset_size,
283                                                           struct p2p_channels *channel_list)
284 {
285
286         static const struct p2p_oper_class_map op_class[] = {
287                 { IEEE80211G,  81,   1,  13,  1, BW20 },
288                 { IEEE80211G,  82,  14,  14,  1, BW20 },
289                 { IEEE80211A, 115,  36,  48,  4, BW20 },
290                 { IEEE80211A, 116,  36,  44,  8, BW40PLUS },
291                 { IEEE80211A, 117,  40,  48,  8, BW40MINUS },
292                 { IEEE80211A, 124, 149, 161,  4, BW20 },
293                 { IEEE80211A, 125, 149, 169,  4, BW20 },
294                 { IEEE80211A, 126, 149, 157,  8, BW40PLUS },
295                 { IEEE80211A, 127, 153, 161,  8, BW40MINUS },
296                 { -1, 0, 0, 0, 0, BW20 }
297         };
298
299         int cla, op;
300
301         cla = 0;
302
303         for (op = 0; op_class[op].op_class; op++) {
304                 u8 ch;
305                 const struct p2p_oper_class_map *o = &op_class[op];
306                 struct p2p_reg_class *reg = NULL;
307
308                 for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
309                         if (!has_channel(channel_set, chanset_size, ch))
310                                 continue;
311
312                         if ((padapter->registrypriv.ht_enable == 0) && (o->inc == 8))
313                                 continue;
314
315                         if ((0 < (padapter->registrypriv.bw_mode & 0xf0)) &&
316                                 ((o->bw == BW40MINUS) || (o->bw == BW40PLUS)))
317                                 continue;
318
319                         if (!reg) {
320                                 reg = &channel_list->reg_class[cla];
321                                 cla++;
322                                 reg->reg_class = o->op_class;
323                                 reg->channels = 0;
324                         }
325                         reg->channel[reg->channels] = ch;
326                         reg->channels++;
327                 }
328         }
329         channel_list->reg_classes = cla;
330
331 }
332
333 static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, struct rt_channel_info *channel_set)
334 {
335         u8 index, chanset_size = 0;
336         u8 b2_4GBand = false;
337         u8 Index2G = 0;
338
339         memset(channel_set, 0, sizeof(struct rt_channel_info)*MAX_CHANNEL_NUM);
340
341         if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE)
342                 return chanset_size;
343
344         if (is_supported_24g(padapter->registrypriv.wireless_mode)) {
345                 b2_4GBand = true;
346                 if (ChannelPlan == RT_CHANNEL_DOMAIN_REALTEK_DEFINE)
347                         Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
348                 else
349                         Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
350         }
351
352         if (b2_4GBand) {
353                 for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) {
354                         channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index];
355
356                         if ((ChannelPlan == RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN) ||/* Channel 1~11 is active, and 12~14 is passive */
357                                 (ChannelPlan == RT_CHANNEL_DOMAIN_GLOBAL_NULL)) {
358                                 if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11)
359                                         channel_set[chanset_size].ScanType = SCAN_ACTIVE;
360                                 else if ((channel_set[chanset_size].ChannelNum  >= 12 && channel_set[chanset_size].ChannelNum  <= 14))
361                                         channel_set[chanset_size].ScanType  = SCAN_PASSIVE;
362                         } else if (ChannelPlan == RT_CHANNEL_DOMAIN_WORLD_WIDE_13 ||
363                                  Index2G == RT_CHANNEL_DOMAIN_2G_WORLD) { /*  channel 12~13, passive scan */
364                                 if (channel_set[chanset_size].ChannelNum <= 11)
365                                         channel_set[chanset_size].ScanType = SCAN_ACTIVE;
366                                 else
367                                         channel_set[chanset_size].ScanType = SCAN_PASSIVE;
368                         } else
369                                 channel_set[chanset_size].ScanType = SCAN_ACTIVE;
370
371                         chanset_size++;
372                 }
373         }
374
375         return chanset_size;
376 }
377
378 void init_mlme_ext_priv(struct adapter *padapter)
379 {
380         struct registry_priv *pregistrypriv = &padapter->registrypriv;
381         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
382         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
383         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
384
385         pmlmeext->padapter = padapter;
386
387         /* fill_fwpriv(padapter, &(pmlmeext->fwpriv)); */
388
389         init_mlme_ext_priv_value(padapter);
390         pmlmeinfo->accept_addba_req = pregistrypriv->accept_addba_req;
391
392         init_mlme_ext_timer(padapter);
393
394         init_mlme_ap_info(padapter);
395
396         pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set);
397         init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
398         pmlmeext->last_scan_time = 0;
399         pmlmeext->chan_scan_time = SURVEY_TO;
400         pmlmeext->mlmeext_init = true;
401         pmlmeext->active_keep_alive_check = true;
402
403 #ifdef DBG_FIXED_CHAN
404         pmlmeext->fixed_chan = 0xFF;
405 #endif
406 }
407
408 void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext)
409 {
410         struct adapter *padapter = pmlmeext->padapter;
411
412         if (!padapter)
413                 return;
414
415         if (padapter->bDriverStopped) {
416                 del_timer_sync(&pmlmeext->survey_timer);
417                 del_timer_sync(&pmlmeext->link_timer);
418                 /* del_timer_sync(&pmlmeext->ADDBA_timer); */
419         }
420 }
421
422 static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame)
423 {
424         u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
425         u8 *pframe = precv_frame->u.hdr.rx_data;
426
427         if (ptable->func) {
428                 /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
429                 if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
430                     memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
431                         return;
432
433                 ptable->func(padapter, precv_frame);
434         }
435 }
436
437 void mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame)
438 {
439         int index;
440         struct mlme_handler *ptable;
441         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
442         u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
443         u8 *pframe = precv_frame->u.hdr.rx_data;
444         struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe));
445         struct dvobj_priv *psdpriv = padapter->dvobj;
446         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
447
448         if (GetFrameType(pframe) != WIFI_MGT_TYPE)
449                 return;
450
451         /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
452         if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
453                 memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) {
454                 return;
455         }
456
457         ptable = mlme_sta_tbl;
458
459         index = GetFrameSubType(pframe) >> 4;
460
461         if (index >= ARRAY_SIZE(mlme_sta_tbl))
462                 return;
463
464         ptable += index;
465
466         if (psta) {
467                 if (GetRetry(pframe)) {
468                         if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum) {
469                                 /* drop the duplicate management frame */
470                                 pdbgpriv->dbg_rx_dup_mgt_frame_drop_count++;
471                                 return;
472                         }
473                 }
474                 psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num;
475         }
476
477         switch (GetFrameSubType(pframe)) {
478         case WIFI_AUTH:
479                 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
480                         ptable->func = &OnAuth;
481                 else
482                         ptable->func = &OnAuthClient;
483                 fallthrough;
484         case WIFI_ASSOCREQ:
485         case WIFI_REASSOCREQ:
486                 _mgt_dispatcher(padapter, ptable, precv_frame);
487                 break;
488         case WIFI_PROBEREQ:
489                 _mgt_dispatcher(padapter, ptable, precv_frame);
490                 break;
491         case WIFI_BEACON:
492                 _mgt_dispatcher(padapter, ptable, precv_frame);
493                 break;
494         case WIFI_ACTION:
495                 /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) */
496                 _mgt_dispatcher(padapter, ptable, precv_frame);
497                 break;
498         default:
499                 _mgt_dispatcher(padapter, ptable, precv_frame);
500                 break;
501         }
502 }
503
504 /****************************************************************************
505
506 Following are the callback functions for each subtype of the management frames
507
508 *****************************************************************************/
509
510 unsigned int OnProbeReq(struct adapter *padapter, union recv_frame *precv_frame)
511 {
512         unsigned int    ielen;
513         unsigned char *p;
514         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
515         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
516         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
517         struct wlan_bssid_ex    *cur = &pmlmeinfo->network;
518         u8 *pframe = precv_frame->u.hdr.rx_data;
519         uint len = precv_frame->u.hdr.len;
520         u8 is_valid_p2p_probereq = false;
521
522         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
523                 return _SUCCESS;
524
525         if (check_fwstate(pmlmepriv, _FW_LINKED) == false &&
526                 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE) == false) {
527                 return _SUCCESS;
528         }
529
530         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, WLAN_EID_SSID, (int *)&ielen,
531                         len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
532
533
534         /* check (wildcard) SSID */
535         if (p) {
536                 if (is_valid_p2p_probereq)
537                         goto _issue_probersp;
538
539                 if ((ielen != 0 && false == !memcmp((void *)(p+2), (void *)cur->ssid.ssid, cur->ssid.ssid_length))
540                         || (ielen == 0 && pmlmeinfo->hidden_ssid_mode)
541                 )
542                         return _SUCCESS;
543
544 _issue_probersp:
545                 if ((check_fwstate(pmlmepriv, _FW_LINKED) &&
546                      pmlmepriv->cur_network.join_res) ||
547                     check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
548                         issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq);
549         }
550
551         return _SUCCESS;
552
553 }
554
555 unsigned int OnProbeRsp(struct adapter *padapter, union recv_frame *precv_frame)
556 {
557         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
558
559         if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
560                 report_survey_event(padapter, precv_frame);
561                 return _SUCCESS;
562         }
563
564         return _SUCCESS;
565
566 }
567
568 unsigned int OnBeacon(struct adapter *padapter, union recv_frame *precv_frame)
569 {
570         int cam_idx;
571         struct sta_info *psta;
572         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
573         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
574         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
575         struct sta_priv *pstapriv = &padapter->stapriv;
576         u8 *pframe = precv_frame->u.hdr.rx_data;
577         uint len = precv_frame->u.hdr.len;
578         struct wlan_bssid_ex *pbss;
579         int ret = _SUCCESS;
580         u8 *p = NULL;
581         u32 ielen = 0;
582
583         p = rtw_get_ie(pframe + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_, WLAN_EID_EXT_SUPP_RATES, &ielen, precv_frame->u.hdr.len - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_);
584         if (p && ielen > 0) {
585                 if ((*(p + 1 + ielen) == 0x2D) && (*(p + 2 + ielen) != 0x2D))
586                         /* Invalid value 0x2D is detected in Extended Supported Rates (ESR) IE. Try to fix the IE length to avoid failed Beacon parsing. */
587                         *(p + 1) = ielen - 1;
588         }
589
590         if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
591                 report_survey_event(padapter, precv_frame);
592                 return _SUCCESS;
593         }
594
595         if (!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) {
596                 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
597                         /* we should update current network before auth, or some IE is wrong */
598                         pbss = rtw_malloc(sizeof(struct wlan_bssid_ex));
599                         if (pbss) {
600                                 if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
601                                         update_network(&(pmlmepriv->cur_network.network), pbss, padapter, true);
602                                         rtw_get_bcn_info(&(pmlmepriv->cur_network));
603                                 }
604                                 kfree(pbss);
605                         }
606
607                         /* check the vendor of the assoc AP */
608                         pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct ieee80211_hdr_3addr), len-sizeof(struct ieee80211_hdr_3addr));
609
610                         /* update TSF Value */
611                         update_TSF(pmlmeext, pframe, len);
612
613                         /* reset for adaptive_early_32k */
614                         pmlmeext->adaptive_tsf_done = false;
615                         pmlmeext->DrvBcnEarly = 0xff;
616                         pmlmeext->DrvBcnTimeOut = 0xff;
617                         pmlmeext->bcn_cnt = 0;
618                         memset(pmlmeext->bcn_delay_cnt, 0, sizeof(pmlmeext->bcn_delay_cnt));
619                         memset(pmlmeext->bcn_delay_ratio, 0, sizeof(pmlmeext->bcn_delay_ratio));
620
621                         /* start auth */
622                         start_clnt_auth(padapter);
623
624                         return _SUCCESS;
625                 }
626
627                 if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
628                         psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
629                         if (psta) {
630                                 ret = rtw_check_bcn_info(padapter, pframe, len);
631                                 if (!ret) {
632                                         netdev_dbg(padapter->pnetdev,
633                                                    "ap has changed, disconnect now\n ");
634                                         receive_disconnect(padapter,
635                                                            pmlmeinfo->network.mac_address, 0);
636                                         return _SUCCESS;
637                                 }
638                                 /* update WMM, ERP in the beacon */
639                                 /* todo: the timer is used instead of the number of the beacon received */
640                                 if ((sta_rx_pkts(psta) & 0xf) == 0)
641                                         update_beacon_info(padapter, pframe, len, psta);
642
643                                 adaptive_early_32k(pmlmeext, pframe, len);
644                         }
645                 } else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
646                         psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
647                         if (psta) {
648                                 /* update WMM, ERP in the beacon */
649                                 /* todo: the timer is used instead of the number of the beacon received */
650                                 if ((sta_rx_pkts(psta) & 0xf) == 0)
651                                         update_beacon_info(padapter, pframe, len, psta);
652                         } else {
653                                 /* allocate a new CAM entry for IBSS station */
654                                 cam_idx = allocate_fw_sta_entry(padapter);
655                                 if (cam_idx == NUM_STA)
656                                         goto _END_ONBEACON_;
657
658                                 /* get supported rate */
659                                 if (update_sta_support_rate(padapter, (pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_), (len - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_), cam_idx) == _FAIL) {
660                                         pmlmeinfo->FW_sta_info[cam_idx].status = 0;
661                                         goto _END_ONBEACON_;
662                                 }
663
664                                 /* update TSF Value */
665                                 update_TSF(pmlmeext, pframe, len);
666
667                                 /* report sta add event */
668                                 report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx);
669                         }
670                 }
671         }
672
673 _END_ONBEACON_:
674
675         return _SUCCESS;
676
677 }
678
679 unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame)
680 {
681         unsigned int    auth_mode, seq, ie_len;
682         unsigned char *sa, *p;
683         u16 algorithm;
684         int     status;
685         static struct sta_info stat;
686         struct  sta_info *pstat = NULL;
687         struct  sta_priv *pstapriv = &padapter->stapriv;
688         struct security_priv *psecuritypriv = &padapter->securitypriv;
689         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
690         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
691         u8 *pframe = precv_frame->u.hdr.rx_data;
692         uint len = precv_frame->u.hdr.len;
693         u8 offset = 0;
694
695         if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
696                 return _FAIL;
697
698         sa = GetAddr2Ptr(pframe);
699
700         auth_mode = psecuritypriv->dot11AuthAlgrthm;
701
702         if (GetPrivacy(pframe)) {
703                 u8 *iv;
704                 struct rx_pkt_attrib     *prxattrib = &(precv_frame->u.hdr.attrib);
705
706                 prxattrib->hdrlen = WLAN_HDR_A3_LEN;
707                 prxattrib->encrypt = _WEP40_;
708
709                 iv = pframe+prxattrib->hdrlen;
710                 prxattrib->key_index = ((iv[3]>>6)&0x3);
711
712                 prxattrib->iv_len = 4;
713                 prxattrib->icv_len = 4;
714
715                 rtw_wep_decrypt(padapter, (u8 *)precv_frame);
716
717                 offset = 4;
718         }
719
720         algorithm = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset));
721         seq     = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));
722
723         if (auth_mode == 2 &&
724                         psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
725                         psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
726                 auth_mode = 0;
727
728         if ((algorithm > 0 && auth_mode == 0) ||        /*  rx a shared-key auth but shared not enabled */
729                 (algorithm == 0 && auth_mode == 1)) {   /*  rx a open-system auth but shared-key is enabled */
730
731                 status = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
732
733                 goto auth_fail;
734         }
735
736         if (rtw_access_ctrl(padapter, sa) == false) {
737                 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
738                 goto auth_fail;
739         }
740
741         pstat = rtw_get_stainfo(pstapriv, sa);
742         if (!pstat) {
743
744                 /*  allocate a new one */
745                 pstat = rtw_alloc_stainfo(pstapriv, sa);
746                 if (!pstat) {
747                         status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
748                         goto auth_fail;
749                 }
750
751                 pstat->state = WIFI_FW_AUTH_NULL;
752                 pstat->auth_seq = 0;
753
754                 /* pstat->flags = 0; */
755                 /* pstat->capability = 0; */
756         } else {
757
758                 spin_lock_bh(&pstapriv->asoc_list_lock);
759                 if (list_empty(&pstat->asoc_list) == false) {
760                         list_del_init(&pstat->asoc_list);
761                         pstapriv->asoc_list_cnt--;
762                         if (pstat->expire_to > 0) {
763                                 /* TODO: STA re_auth within expire_to */
764                         }
765                 }
766                 spin_unlock_bh(&pstapriv->asoc_list_lock);
767
768                 if (seq == 1) {
769                         /* TODO: STA re_auth and auth timeout */
770                 }
771         }
772
773         spin_lock_bh(&pstapriv->auth_list_lock);
774         if (list_empty(&pstat->auth_list)) {
775
776                 list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
777                 pstapriv->auth_list_cnt++;
778         }
779         spin_unlock_bh(&pstapriv->auth_list_lock);
780
781         if (pstat->auth_seq == 0)
782                 pstat->expire_to = pstapriv->auth_to;
783
784
785         if ((pstat->auth_seq + 1) != seq) {
786                 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
787                 goto auth_fail;
788         }
789
790         if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2 || auth_mode == 3)) {
791                 if (seq == 1) {
792                         pstat->state &= ~WIFI_FW_AUTH_NULL;
793                         pstat->state |= WIFI_FW_AUTH_SUCCESS;
794                         pstat->expire_to = pstapriv->assoc_to;
795                         pstat->authalg = algorithm;
796                 } else {
797                         status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
798                         goto auth_fail;
799                 }
800         } else { /*  shared system or auto authentication */
801                 if (seq == 1) {
802                         /* prepare for the challenging txt... */
803                         memset((void *)pstat->chg_txt, 78, 128);
804
805                         pstat->state &= ~WIFI_FW_AUTH_NULL;
806                         pstat->state |= WIFI_FW_AUTH_STATE;
807                         pstat->authalg = algorithm;
808                 } else if (seq == 3) {
809
810                         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, WLAN_EID_CHALLENGE, (int *)&ie_len,
811                                         len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
812
813                         if (!p || ie_len <= 0) {
814                                 status = WLAN_STATUS_CHALLENGE_FAIL;
815                                 goto auth_fail;
816                         }
817
818                         if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
819                                 pstat->state &= (~WIFI_FW_AUTH_STATE);
820                                 pstat->state |= WIFI_FW_AUTH_SUCCESS;
821                                 /*  challenging txt is correct... */
822                                 pstat->expire_to =  pstapriv->assoc_to;
823                         } else {
824                                 status = WLAN_STATUS_CHALLENGE_FAIL;
825                                 goto auth_fail;
826                         }
827                 } else {
828                         status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
829                         goto auth_fail;
830                 }
831         }
832
833
834         /*  Now, we are going to issue_auth... */
835         pstat->auth_seq = seq + 1;
836
837         issue_auth(padapter, pstat, (unsigned short)(WLAN_STATUS_SUCCESS));
838
839         if (pstat->state & WIFI_FW_AUTH_SUCCESS)
840                 pstat->auth_seq = 0;
841
842
843         return _SUCCESS;
844
845 auth_fail:
846
847         if (pstat)
848                 rtw_free_stainfo(padapter, pstat);
849
850         pstat = &stat;
851         memset((char *)pstat, '\0', sizeof(stat));
852         pstat->auth_seq = 2;
853         memcpy(pstat->hwaddr, sa, 6);
854
855         issue_auth(padapter, pstat, (unsigned short)status);
856
857         return _FAIL;
858
859 }
860
861 unsigned int OnAuthClient(struct adapter *padapter, union recv_frame *precv_frame)
862 {
863         unsigned int    seq, len, status, offset;
864         unsigned char *p;
865         unsigned int    go2asoc = 0;
866         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
867         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
868         u8 *pframe = precv_frame->u.hdr.rx_data;
869         uint pkt_len = precv_frame->u.hdr.len;
870
871         /* check A1 matches or not */
872         if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
873                 return _SUCCESS;
874
875         if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
876                 return _SUCCESS;
877
878         offset = (GetPrivacy(pframe)) ? 4 : 0;
879
880         seq     = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));
881         status  = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 4));
882
883         if (status != 0) {
884                 if (status == 13) { /*  pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
885                         if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
886                                 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
887                         else
888                                 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
889                         /* pmlmeinfo->reauth_count = 0; */
890                 }
891
892                 set_link_timer(pmlmeext, 1);
893                 goto authclnt_fail;
894         }
895
896         if (seq == 2) {
897                 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
898                          /*  legendary shared system */
899                         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, WLAN_EID_CHALLENGE, (int *)&len,
900                                 pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
901
902                         if (!p)
903                                 goto authclnt_fail;
904
905                         memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
906                         pmlmeinfo->auth_seq = 3;
907                         issue_auth(padapter, NULL, 0);
908                         set_link_timer(pmlmeext, REAUTH_TO);
909
910                         return _SUCCESS;
911                 }
912                 /* open system */
913                 go2asoc = 1;
914         } else if (seq == 4) {
915                 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
916                         go2asoc = 1;
917                 else
918                         goto authclnt_fail;
919         } else {
920                 /*  this is also illegal */
921                 goto authclnt_fail;
922         }
923
924         if (go2asoc) {
925                 netdev_dbg(padapter->pnetdev, "auth success, start assoc\n");
926                 start_clnt_assoc(padapter);
927                 return _SUCCESS;
928         }
929
930 authclnt_fail:
931
932         /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */
933
934         return _FAIL;
935
936 }
937
938 unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
939 {
940         u16 capab_info;
941         struct rtw_ieee802_11_elems elems;
942         struct sta_info *pstat;
943         unsigned char   *p, *pos, *wpa_ie;
944         unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
945         int             i, ie_len, wpa_ie_len, left;
946         unsigned char   supportRate[16];
947         int                                     supportRateNum;
948         unsigned short          status = WLAN_STATUS_SUCCESS;
949         unsigned short          frame_type, ie_offset = 0;
950         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
951         struct security_priv *psecuritypriv = &padapter->securitypriv;
952         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
953         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
954         struct wlan_bssid_ex    *cur = &(pmlmeinfo->network);
955         struct sta_priv *pstapriv = &padapter->stapriv;
956         u8 *pframe = precv_frame->u.hdr.rx_data;
957         uint pkt_len = precv_frame->u.hdr.len;
958
959         if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
960                 return _FAIL;
961
962         frame_type = GetFrameSubType(pframe);
963         if (frame_type == WIFI_ASSOCREQ) 
964                 ie_offset = _ASOCREQ_IE_OFFSET_;
965         else /*  WIFI_REASSOCREQ */
966                 ie_offset = _REASOCREQ_IE_OFFSET_;
967
968
969         if (pkt_len < sizeof(struct ieee80211_hdr_3addr) + ie_offset)
970                 return _FAIL;
971
972         pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
973         if (!pstat) {
974                 status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
975                 goto asoc_class2_error;
976         }
977
978         capab_info = get_unaligned_le16(pframe + WLAN_HDR_A3_LEN);
979         /* capab_info = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN)); */
980
981         left = pkt_len - (sizeof(struct ieee80211_hdr_3addr) + ie_offset);
982         pos = pframe + (sizeof(struct ieee80211_hdr_3addr) + ie_offset);
983
984         /*  check if this stat has been successfully authenticated/assocated */
985         if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) {
986                 if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) {
987                         status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
988                         goto asoc_class2_error;
989                 } else {
990                         pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
991                         pstat->state |= WIFI_FW_ASSOC_STATE;
992                 }
993         } else {
994                 pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
995                 pstat->state |= WIFI_FW_ASSOC_STATE;
996         }
997
998
999         pstat->capability = capab_info;
1000
1001         /* now parse all ieee802_11 ie to point to elems */
1002         if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
1003             !elems.ssid) {
1004                 status = WLAN_STATUS_CHALLENGE_FAIL;
1005                 goto OnAssocReqFail;
1006         }
1007
1008         /*  now we should check all the fields... */
1009         /*  checking SSID */
1010         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_SSID, &ie_len,
1011                 pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1012
1013         if (!p || ie_len == 0) {
1014                 /*  broadcast ssid, however it is not allowed in assocreq */
1015                 status = WLAN_STATUS_CHALLENGE_FAIL;
1016                 goto OnAssocReqFail;
1017         } else {
1018                 /*  check if ssid match */
1019                 if (memcmp((void *)(p+2), cur->ssid.ssid, cur->ssid.ssid_length))
1020                         status = WLAN_STATUS_CHALLENGE_FAIL;
1021
1022                 if (ie_len != cur->ssid.ssid_length)
1023                         status = WLAN_STATUS_CHALLENGE_FAIL;
1024         }
1025
1026         if (status != WLAN_STATUS_SUCCESS)
1027                 goto OnAssocReqFail;
1028
1029         /*  check if the supported rate is ok */
1030         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_SUPP_RATES, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1031         if (!p) {
1032                 /*  use our own rate set as statoin used */
1033                 /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
1034                 /* supportRateNum = AP_BSSRATE_LEN; */
1035
1036                 status = WLAN_STATUS_CHALLENGE_FAIL;
1037                 goto OnAssocReqFail;
1038         } else {
1039                 memcpy(supportRate, p+2, ie_len);
1040                 supportRateNum = ie_len;
1041
1042                 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_EXT_SUPP_RATES, &ie_len,
1043                                 pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1044                 if (p) {
1045
1046                         if (supportRateNum <= sizeof(supportRate)) {
1047                                 memcpy(supportRate+supportRateNum, p+2, ie_len);
1048                                 supportRateNum += ie_len;
1049                         }
1050                 }
1051         }
1052
1053         /* todo: mask supportRate between AP & STA -> move to update raid */
1054         /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
1055
1056         /* update station supportRate */
1057         pstat->bssratelen = supportRateNum;
1058         memcpy(pstat->bssrateset, supportRate, supportRateNum);
1059         UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
1060
1061         /* check RSN/WPA/WPS */
1062         pstat->dot8021xalg = 0;
1063         pstat->wpa_psk = 0;
1064         pstat->wpa_group_cipher = 0;
1065         pstat->wpa2_group_cipher = 0;
1066         pstat->wpa_pairwise_cipher = 0;
1067         pstat->wpa2_pairwise_cipher = 0;
1068         memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
1069         if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
1070
1071                 int group_cipher = 0, pairwise_cipher = 0;
1072
1073                 wpa_ie = elems.rsn_ie;
1074                 wpa_ie_len = elems.rsn_ie_len;
1075
1076                 if (rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1077                         pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
1078                         pstat->wpa_psk |= BIT(1);
1079
1080                         pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher;
1081                         pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher;
1082
1083                         if (!pstat->wpa2_group_cipher)
1084                                 status = WLAN_STATUS_INVALID_GROUP_CIPHER;
1085
1086                         if (!pstat->wpa2_pairwise_cipher)
1087                                 status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
1088                 } else {
1089                         status = WLAN_STATUS_INVALID_IE;
1090                 }
1091
1092         } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
1093
1094                 int group_cipher = 0, pairwise_cipher = 0;
1095
1096                 wpa_ie = elems.wpa_ie;
1097                 wpa_ie_len = elems.wpa_ie_len;
1098
1099                 if (rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1100                         pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
1101                         pstat->wpa_psk |= BIT(0);
1102
1103                         pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher;
1104                         pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher;
1105
1106                         if (!pstat->wpa_group_cipher)
1107                                 status = WLAN_STATUS_INVALID_GROUP_CIPHER;
1108
1109                         if (!pstat->wpa_pairwise_cipher)
1110                                 status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
1111
1112                 } else {
1113                         status = WLAN_STATUS_INVALID_IE;
1114                 }
1115
1116         } else {
1117                 wpa_ie = NULL;
1118                 wpa_ie_len = 0;
1119         }
1120
1121         if (status != WLAN_STATUS_SUCCESS)
1122                 goto OnAssocReqFail;
1123
1124         pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
1125         if (!wpa_ie) {
1126                 if (elems.wps_ie) {
1127                         pstat->flags |= WLAN_STA_WPS;
1128                         /* wpabuf_free(sta->wps_ie); */
1129                         /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */
1130                         /*                              elems.wps_ie_len - 4); */
1131                 } else {
1132                         pstat->flags |= WLAN_STA_MAYBE_WPS;
1133                 }
1134
1135
1136                 /*  AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
1137                 /*  that the selected registrar of AP is _FLASE */
1138                 if ((psecuritypriv->wpa_psk > 0)
1139                         && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) {
1140                         if (pmlmepriv->wps_beacon_ie) {
1141                                 u8 selected_registrar = 0;
1142
1143                                 rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL);
1144
1145                                 if (!selected_registrar) {
1146                                         status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1147
1148                                         goto OnAssocReqFail;
1149                                 }
1150                         }
1151                 }
1152
1153         } else {
1154                 int copy_len;
1155
1156                 if (psecuritypriv->wpa_psk == 0) {
1157                         status = WLAN_STATUS_INVALID_IE;
1158
1159                         goto OnAssocReqFail;
1160
1161                 }
1162
1163                 if (elems.wps_ie) {
1164                         pstat->flags |= WLAN_STA_WPS;
1165                         copy_len = 0;
1166                 } else {
1167                         copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)):(wpa_ie_len+2);
1168                 }
1169
1170
1171                 if (copy_len > 0)
1172                         memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
1173
1174         }
1175
1176
1177         /*  check if there is WMM IE & support WWM-PS */
1178         pstat->flags &= ~WLAN_STA_WME;
1179         pstat->qos_option = 0;
1180         pstat->qos_info = 0;
1181         pstat->has_legacy_ac = true;
1182         pstat->uapsd_vo = 0;
1183         pstat->uapsd_vi = 0;
1184         pstat->uapsd_be = 0;
1185         pstat->uapsd_bk = 0;
1186         if (pmlmepriv->qospriv.qos_option) {
1187                 p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
1188                 for (;;) {
1189                         p = rtw_get_ie(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1190                         if (p) {
1191                                 if (!memcmp(p+2, WMM_IE, 6)) {
1192
1193                                         pstat->flags |= WLAN_STA_WME;
1194
1195                                         pstat->qos_option = 1;
1196                                         pstat->qos_info = *(p+8);
1197
1198                                         pstat->max_sp_len = (pstat->qos_info>>5)&0x3;
1199
1200                                         if ((pstat->qos_info&0xf) != 0xf)
1201                                                 pstat->has_legacy_ac = true;
1202                                         else
1203                                                 pstat->has_legacy_ac = false;
1204
1205                                         if (pstat->qos_info&0xf) {
1206                                                 if (pstat->qos_info&BIT(0))
1207                                                         pstat->uapsd_vo = BIT(0)|BIT(1);
1208                                                 else
1209                                                         pstat->uapsd_vo = 0;
1210
1211                                                 if (pstat->qos_info&BIT(1))
1212                                                         pstat->uapsd_vi = BIT(0)|BIT(1);
1213                                                 else
1214                                                         pstat->uapsd_vi = 0;
1215
1216                                                 if (pstat->qos_info&BIT(2))
1217                                                         pstat->uapsd_bk = BIT(0)|BIT(1);
1218                                                 else
1219                                                         pstat->uapsd_bk = 0;
1220
1221                                                 if (pstat->qos_info&BIT(3))
1222                                                         pstat->uapsd_be = BIT(0)|BIT(1);
1223                                                 else
1224                                                         pstat->uapsd_be = 0;
1225
1226                                         }
1227
1228                                         break;
1229                                 }
1230                         } else {
1231                                 break;
1232                         }
1233                         p = p + ie_len + 2;
1234                 }
1235         }
1236
1237         /* save HT capabilities in the sta object */
1238         memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap));
1239         if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap)) {
1240                 pstat->flags |= WLAN_STA_HT;
1241
1242                 pstat->flags |= WLAN_STA_WME;
1243
1244                 memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct ieee80211_ht_cap));
1245
1246         } else
1247                 pstat->flags &= ~WLAN_STA_HT;
1248
1249
1250         if ((pmlmepriv->htpriv.ht_option == false) && (pstat->flags&WLAN_STA_HT)) {
1251                 status = WLAN_STATUS_CHALLENGE_FAIL;
1252                 goto OnAssocReqFail;
1253         }
1254
1255
1256         if ((pstat->flags & WLAN_STA_HT) &&
1257                     ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
1258                       (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP))) {
1259                 /* status = WLAN_STATUS_CIPHER_SUITE_REJECTED; */
1260                 /* goto OnAssocReqFail; */
1261         }
1262         pstat->flags |= WLAN_STA_NONERP;
1263         for (i = 0; i < pstat->bssratelen; i++) {
1264                 if ((pstat->bssrateset[i] & 0x7f) > 22) {
1265                         pstat->flags &= ~WLAN_STA_NONERP;
1266                         break;
1267                 }
1268         }
1269
1270         if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1271                 pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
1272         else
1273                 pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1274
1275
1276
1277         if (status != WLAN_STATUS_SUCCESS)
1278                 goto OnAssocReqFail;
1279
1280         /* TODO: identify_proprietary_vendor_ie(); */
1281         /*  Realtek proprietary IE */
1282         /*  identify if this is Broadcom sta */
1283         /*  identify if this is ralink sta */
1284         /*  Customer proprietary IE */
1285
1286
1287
1288         /* get a unique AID */
1289         if (pstat->aid == 0) {
1290                 for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
1291                         if (!pstapriv->sta_aid[pstat->aid - 1])
1292                                 break;
1293
1294                 /* if (pstat->aid > NUM_STA) { */
1295                 if (pstat->aid > pstapriv->max_num_sta) {
1296
1297                         pstat->aid = 0;
1298
1299                         status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1300
1301                         goto OnAssocReqFail;
1302
1303
1304                 } else {
1305                         pstapriv->sta_aid[pstat->aid - 1] = pstat;
1306                 }
1307         }
1308
1309
1310         pstat->state &= (~WIFI_FW_ASSOC_STATE);
1311         pstat->state |= WIFI_FW_ASSOC_SUCCESS;
1312
1313         spin_lock_bh(&pstapriv->auth_list_lock);
1314         if (!list_empty(&pstat->auth_list)) {
1315                 list_del_init(&pstat->auth_list);
1316                 pstapriv->auth_list_cnt--;
1317         }
1318         spin_unlock_bh(&pstapriv->auth_list_lock);
1319
1320         spin_lock_bh(&pstapriv->asoc_list_lock);
1321         if (list_empty(&pstat->asoc_list)) {
1322                 pstat->expire_to = pstapriv->expire_to;
1323                 list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
1324                 pstapriv->asoc_list_cnt++;
1325         }
1326         spin_unlock_bh(&pstapriv->asoc_list_lock);
1327
1328         /*  now the station is qualified to join our BSS... */
1329         if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (status == WLAN_STATUS_SUCCESS)) {
1330                 /* 1 bss_cap_update & sta_info_update */
1331                 bss_cap_update_on_sta_join(padapter, pstat);
1332                 sta_info_update(padapter, pstat);
1333
1334                 /* 2 issue assoc rsp before notify station join event. */
1335                 if (frame_type == WIFI_ASSOCREQ)
1336                         issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1337                 else
1338                         issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1339
1340                 spin_lock_bh(&pstat->lock);
1341                 kfree(pstat->passoc_req);
1342                 pstat->assoc_req_len = 0;
1343                 pstat->passoc_req =  rtw_zmalloc(pkt_len);
1344                 if (pstat->passoc_req) {
1345                         memcpy(pstat->passoc_req, pframe, pkt_len);
1346                         pstat->assoc_req_len = pkt_len;
1347                 }
1348                 spin_unlock_bh(&pstat->lock);
1349
1350                 /* 3-(1) report sta add event */
1351                 report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
1352         }
1353
1354         return _SUCCESS;
1355
1356 asoc_class2_error:
1357
1358         issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
1359
1360         return _FAIL;
1361
1362 OnAssocReqFail:
1363
1364         pstat->aid = 0;
1365         if (frame_type == WIFI_ASSOCREQ)
1366                 issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1367         else
1368                 issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1369
1370         return _FAIL;
1371 }
1372
1373 unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame)
1374 {
1375         uint i;
1376         int res;
1377         unsigned short  status;
1378         struct ndis_80211_var_ie *pIE;
1379         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1380         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1381         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1382         /* struct wlan_bssid_ex                 *cur_network = &(pmlmeinfo->network); */
1383         u8 *pframe = precv_frame->u.hdr.rx_data;
1384         uint pkt_len = precv_frame->u.hdr.len;
1385
1386         /* check A1 matches or not */
1387         if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
1388                 return _SUCCESS;
1389
1390         if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
1391                 return _SUCCESS;
1392
1393         if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
1394                 return _SUCCESS;
1395
1396         del_timer_sync(&pmlmeext->link_timer);
1397
1398         /* status */
1399         status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2));
1400         if (status > 0) {
1401                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
1402                 res = -4;
1403                 goto report_assoc_result;
1404         }
1405
1406         /* get capabilities */
1407         pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1408
1409         /* set slot time */
1410         pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20;
1411
1412         /* AID */
1413         res = pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff);
1414
1415         /* following are moved to join event callback function */
1416         /* to handle HT, WMM, rate adaptive, update MAC reg */
1417         /* for not to handle the synchronous IO in the tasklet */
1418         for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) {
1419                 pIE = (struct ndis_80211_var_ie *)(pframe + i);
1420
1421                 switch (pIE->element_id) {
1422                 case WLAN_EID_VENDOR_SPECIFIC:
1423                         if (!memcmp(pIE->data, WMM_PARA_OUI, 6))        /* WMM */
1424                                 WMM_param_handler(padapter, pIE);
1425                         break;
1426
1427                 case WLAN_EID_HT_CAPABILITY:    /* HT caps */
1428                         HT_caps_handler(padapter, pIE);
1429                         break;
1430
1431                 case WLAN_EID_HT_OPERATION:     /* HT info */
1432                         HT_info_handler(padapter, pIE);
1433                         break;
1434
1435                 case WLAN_EID_ERP_INFO:
1436                         ERP_IE_handler(padapter, pIE);
1437                         break;
1438
1439                 default:
1440                         break;
1441                 }
1442
1443                 i += (pIE->length + 2);
1444         }
1445
1446         pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
1447         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
1448
1449         /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
1450         UpdateBrateTbl(padapter, pmlmeinfo->network.supported_rates);
1451
1452 report_assoc_result:
1453         if (res > 0)
1454                 rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);
1455         else
1456                 rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
1457
1458         report_join_res(padapter, res);
1459
1460         return _SUCCESS;
1461 }
1462
1463 unsigned int OnDeAuth(struct adapter *padapter, union recv_frame *precv_frame)
1464 {
1465         unsigned short  reason;
1466         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1467         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1468         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1469         u8 *pframe = precv_frame->u.hdr.rx_data;
1470         int ignore_received_deauth = 0;
1471
1472         /* check A3 */
1473         if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
1474                 return _SUCCESS;
1475
1476         reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1477
1478         if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1479                 struct sta_info *psta;
1480                 struct sta_priv *pstapriv = &padapter->stapriv;
1481
1482                 /* rtw_free_stainfo(padapter, psta); */
1483
1484                 netdev_dbg(padapter->pnetdev,
1485                            "ap recv deauth reason code(%d) sta:%pM\n", reason,
1486                            GetAddr2Ptr(pframe));
1487
1488                 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1489                 if (psta) {
1490                         u8 updated = false;
1491
1492                         spin_lock_bh(&pstapriv->asoc_list_lock);
1493                         if (list_empty(&psta->asoc_list) == false) {
1494                                 list_del_init(&psta->asoc_list);
1495                                 pstapriv->asoc_list_cnt--;
1496                                 updated = ap_free_sta(padapter, psta, false, reason);
1497
1498                         }
1499                         spin_unlock_bh(&pstapriv->asoc_list_lock);
1500
1501                         associated_clients_update(padapter, updated);
1502                 }
1503
1504
1505                 return _SUCCESS;
1506         }
1507
1508         /*      Commented by Albert 20130604 */
1509         /*      Before sending the auth frame to start the STA/GC mode connection with AP/GO, */
1510         /*      we will send the deauth first. */
1511         /*      However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth. */
1512         /*      Added the following code to avoid this case. */
1513         if ((pmlmeinfo->state & WIFI_FW_AUTH_STATE) ||
1514             (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)) {
1515                 if (reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA) {
1516                         ignore_received_deauth = 1;
1517                 } else if (reason == WLAN_REASON_PREV_AUTH_NOT_VALID) {
1518                         /*  TODO: 802.11r */
1519                         ignore_received_deauth = 1;
1520                 }
1521         }
1522
1523         netdev_dbg(padapter->pnetdev,
1524                    "sta recv deauth reason code(%d) sta:%pM, ignore = %d\n",
1525                    reason, GetAddr3Ptr(pframe),
1526                    ignore_received_deauth);
1527
1528         if (ignore_received_deauth == 0)
1529                 receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
1530
1531         pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1532         return _SUCCESS;
1533 }
1534
1535 unsigned int OnDisassoc(struct adapter *padapter, union recv_frame *precv_frame)
1536 {
1537         unsigned short  reason;
1538         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1539         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1540         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1541         u8 *pframe = precv_frame->u.hdr.rx_data;
1542
1543         /* check A3 */
1544         if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
1545                 return _SUCCESS;
1546
1547         reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1548
1549         if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1550                 struct sta_info *psta;
1551                 struct sta_priv *pstapriv = &padapter->stapriv;
1552
1553                 /* rtw_free_stainfo(padapter, psta); */
1554
1555                 netdev_dbg(padapter->pnetdev,
1556                            "ap recv disassoc reason code(%d) sta:%pM\n",
1557                            reason, GetAddr2Ptr(pframe));
1558
1559                 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1560                 if (psta) {
1561                         u8 updated = false;
1562
1563                         spin_lock_bh(&pstapriv->asoc_list_lock);
1564                         if (list_empty(&psta->asoc_list) == false) {
1565                                 list_del_init(&psta->asoc_list);
1566                                 pstapriv->asoc_list_cnt--;
1567                                 updated = ap_free_sta(padapter, psta, false, reason);
1568
1569                         }
1570                         spin_unlock_bh(&pstapriv->asoc_list_lock);
1571
1572                         associated_clients_update(padapter, updated);
1573                 }
1574
1575                 return _SUCCESS;
1576         }
1577         netdev_dbg(padapter->pnetdev,
1578                    "sta recv disassoc reason code(%d) sta:%pM\n",
1579                    reason, GetAddr3Ptr(pframe));
1580
1581         receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
1582
1583         pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1584         return _SUCCESS;
1585
1586 }
1587
1588 unsigned int OnAtim(struct adapter *padapter, union recv_frame *precv_frame)
1589 {
1590         return _SUCCESS;
1591 }
1592
1593 unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_frame)
1594 {
1595         struct sta_info *psta = NULL;
1596         struct sta_priv *pstapriv = &padapter->stapriv;
1597         u8 *pframe = precv_frame->u.hdr.rx_data;
1598         u8 *frame_body = (u8 *)(pframe + sizeof(struct ieee80211_hdr_3addr));
1599         u8 category;
1600         u8 action;
1601
1602         psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1603
1604         if (!psta)
1605                 goto exit;
1606
1607         category = frame_body[0];
1608         if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)
1609                 goto exit;
1610
1611         action = frame_body[1];
1612         switch (action) {
1613         case WLAN_ACTION_SPCT_MSR_REQ:
1614         case WLAN_ACTION_SPCT_MSR_RPRT:
1615         case WLAN_ACTION_SPCT_TPC_REQ:
1616         case WLAN_ACTION_SPCT_TPC_RPRT:
1617         case WLAN_ACTION_SPCT_CHL_SWITCH:
1618                 break;
1619         default:
1620                 break;
1621         }
1622
1623 exit:
1624         return _FAIL;
1625 }
1626
1627 unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_frame)
1628 {
1629         u8 *addr;
1630         struct sta_info *psta = NULL;
1631         struct recv_reorder_ctrl *preorder_ctrl;
1632         unsigned char   *frame_body;
1633         unsigned char   category, action;
1634         unsigned short  tid, status;
1635         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1636         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1637         u8 *pframe = precv_frame->u.hdr.rx_data;
1638         struct sta_priv *pstapriv = &padapter->stapriv;
1639
1640         /* check RA matches or not */
1641         if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
1642                 return _SUCCESS;
1643
1644         if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1645                 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
1646                         return _SUCCESS;
1647
1648         addr = GetAddr2Ptr(pframe);
1649         psta = rtw_get_stainfo(pstapriv, addr);
1650
1651         if (!psta)
1652                 return _SUCCESS;
1653
1654         frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
1655
1656         category = frame_body[0];
1657         if (category == RTW_WLAN_CATEGORY_BACK) {/*  representing Block Ack */
1658                 if (!pmlmeinfo->HT_enable)
1659                         return _SUCCESS;
1660
1661                 action = frame_body[1];
1662                 switch (action) {
1663                 case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
1664
1665                         memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request));
1666                         /* process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), GetAddr3Ptr(pframe)); */
1667                         process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr);
1668
1669                         if (pmlmeinfo->accept_addba_req)
1670                                 issue_action_BA(padapter, addr, WLAN_ACTION_ADDBA_RESP, 0);
1671                         else
1672                                 issue_action_BA(padapter, addr, WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */
1673
1674                         break;
1675
1676                 case WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
1677                         status = get_unaligned_le16(&frame_body[3]);
1678                         tid = ((frame_body[5] >> 2) & 0x7);
1679
1680                         if (status == 0) {
1681                                 /* successful */
1682                                 psta->htpriv.agg_enable_bitmap |= BIT(tid);
1683                                 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
1684                         } else {
1685                                 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
1686                         }
1687
1688                         if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
1689                                 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
1690                                 psta->expire_to = pstapriv->expire_to;
1691                                 psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
1692                         }
1693
1694                         break;
1695
1696                 case WLAN_ACTION_DELBA: /* DELBA */
1697                         if ((frame_body[3] & BIT(3)) == 0) {
1698                                 psta->htpriv.agg_enable_bitmap &=
1699                                         ~BIT((frame_body[3] >> 4) & 0xf);
1700                                 psta->htpriv.candidate_tid_bitmap &=
1701                                         ~BIT((frame_body[3] >> 4) & 0xf);
1702                         } else if ((frame_body[3] & BIT(3)) == BIT(3)) {
1703                                 tid = (frame_body[3] >> 4) & 0x0F;
1704
1705                                 preorder_ctrl =  &psta->recvreorder_ctrl[tid];
1706                                 preorder_ctrl->enable = false;
1707                                 preorder_ctrl->indicate_seq = 0xffff;
1708                         }
1709                         /* todo: how to notify the host while receiving DELETE BA */
1710                         break;
1711
1712                 default:
1713                         break;
1714                 }
1715         }
1716         return _SUCCESS;
1717 }
1718
1719 static s32 rtw_action_public_decache(union recv_frame *recv_frame, s32 token)
1720 {
1721         struct adapter *adapter = recv_frame->u.hdr.adapter;
1722         struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
1723         u8 *frame = recv_frame->u.hdr.rx_data;
1724         u16 seq_ctrl = ((recv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
1725                 (recv_frame->u.hdr.attrib.frag_num & 0xf);
1726
1727         if (GetRetry(frame)) {
1728                 if (token >= 0) {
1729                         if ((seq_ctrl == mlmeext->action_public_rxseq)
1730                                 && (token == mlmeext->action_public_dialog_token))
1731                                 return _FAIL;
1732                 } else {
1733                         if (seq_ctrl == mlmeext->action_public_rxseq)
1734                                 return _FAIL;
1735                 }
1736         }
1737
1738         mlmeext->action_public_rxseq = seq_ctrl;
1739
1740         if (token >= 0)
1741                 mlmeext->action_public_dialog_token = token;
1742
1743         return _SUCCESS;
1744 }
1745
1746 static unsigned int on_action_public_p2p(union recv_frame *precv_frame)
1747 {
1748         u8 *pframe = precv_frame->u.hdr.rx_data;
1749         u8 *frame_body;
1750         u8 dialogToken = 0;
1751
1752         frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
1753
1754         dialogToken = frame_body[7];
1755
1756         if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
1757                 return _FAIL;
1758
1759         return _SUCCESS;
1760 }
1761
1762 static unsigned int on_action_public_vendor(union recv_frame *precv_frame)
1763 {
1764         unsigned int ret = _FAIL;
1765         u8 *pframe = precv_frame->u.hdr.rx_data;
1766         u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
1767
1768         if (!memcmp(frame_body + 2, P2P_OUI, 4))
1769                 ret = on_action_public_p2p(precv_frame);
1770
1771         return ret;
1772 }
1773
1774 static unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action)
1775 {
1776         unsigned int ret = _FAIL;
1777         u8 *pframe = precv_frame->u.hdr.rx_data;
1778         uint frame_len = precv_frame->u.hdr.len;
1779         u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
1780         u8 token;
1781         struct adapter *adapter = precv_frame->u.hdr.adapter;
1782         char msg[64];
1783
1784         token = frame_body[2];
1785
1786         if (rtw_action_public_decache(precv_frame, token) == _FAIL)
1787                 goto exit;
1788
1789         scnprintf(msg, sizeof(msg), "%s(token:%u)", action_public_str(action), token);
1790         rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg);
1791
1792         ret = _SUCCESS;
1793
1794 exit:
1795         return ret;
1796 }
1797
1798 unsigned int on_action_public(struct adapter *padapter, union recv_frame *precv_frame)
1799 {
1800         unsigned int ret = _FAIL;
1801         u8 *pframe = precv_frame->u.hdr.rx_data;
1802         u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
1803         u8 category, action;
1804
1805         /* check RA matches or not */
1806         if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
1807                 goto exit;
1808
1809         category = frame_body[0];
1810         if (category != RTW_WLAN_CATEGORY_PUBLIC)
1811                 goto exit;
1812
1813         action = frame_body[1];
1814         switch (action) {
1815         case ACT_PUBLIC_VENDOR:
1816                 ret = on_action_public_vendor(precv_frame);
1817                 break;
1818         default:
1819                 ret = on_action_public_default(precv_frame, action);
1820                 break;
1821         }
1822
1823 exit:
1824         return ret;
1825 }
1826
1827 unsigned int OnAction_ht(struct adapter *padapter, union recv_frame *precv_frame)
1828 {
1829         u8 *pframe = precv_frame->u.hdr.rx_data;
1830         u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
1831         u8 category, action;
1832
1833         /* check RA matches or not */
1834         if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
1835                 goto exit;
1836
1837         category = frame_body[0];
1838         if (category != RTW_WLAN_CATEGORY_HT)
1839                 goto exit;
1840
1841         action = frame_body[1];
1842         switch (action) {
1843         case WLAN_HT_ACTION_COMPRESSED_BF:
1844                 break;
1845         default:
1846                 break;
1847         }
1848
1849 exit:
1850
1851         return _SUCCESS;
1852 }
1853
1854 unsigned int OnAction_sa_query(struct adapter *padapter, union recv_frame *precv_frame)
1855 {
1856         u8 *pframe = precv_frame->u.hdr.rx_data;
1857         struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
1858         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1859         unsigned short tid;
1860
1861         switch (pframe[WLAN_HDR_A3_LEN+1]) {
1862         case 0: /* SA Query req */
1863                 memcpy(&tid, &pframe[WLAN_HDR_A3_LEN+2], sizeof(unsigned short));
1864                 issue_action_SA_Query(padapter, GetAddr2Ptr(pframe), 1, tid);
1865                 break;
1866
1867         case 1: /* SA Query rsp */
1868                 del_timer_sync(&pmlmeext->sa_query_timer);
1869                 break;
1870         default:
1871                 break;
1872         }
1873         if (0) {
1874                 int pp;
1875
1876                 printk("pattrib->pktlen = %d =>", pattrib->pkt_len);
1877                 for (pp = 0; pp < pattrib->pkt_len; pp++)
1878                         printk(" %02x ", pframe[pp]);
1879                 printk("\n");
1880         }
1881
1882         return _SUCCESS;
1883 }
1884
1885 unsigned int OnAction(struct adapter *padapter, union recv_frame *precv_frame)
1886 {
1887         int i;
1888         unsigned char category;
1889         struct action_handler *ptable;
1890         unsigned char *frame_body;
1891         u8 *pframe = precv_frame->u.hdr.rx_data;
1892
1893         frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
1894
1895         category = frame_body[0];
1896
1897         for (i = 0; i < ARRAY_SIZE(OnAction_tbl); i++) {
1898                 ptable = &OnAction_tbl[i];
1899
1900                 if (category == ptable->num)
1901                         ptable->func(padapter, precv_frame);
1902
1903         }
1904
1905         return _SUCCESS;
1906
1907 }
1908
1909 unsigned int DoReserved(struct adapter *padapter, union recv_frame *precv_frame)
1910 {
1911         return _SUCCESS;
1912 }
1913
1914 static struct xmit_frame *_alloc_mgtxmitframe(struct xmit_priv *pxmitpriv, bool once)
1915 {
1916         struct xmit_frame *pmgntframe;
1917         struct xmit_buf *pxmitbuf;
1918
1919         if (once)
1920                 pmgntframe = rtw_alloc_xmitframe_once(pxmitpriv);
1921         else
1922                 pmgntframe = rtw_alloc_xmitframe_ext(pxmitpriv);
1923
1924         if (!pmgntframe)
1925                 goto exit;
1926
1927         pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);
1928         if (!pxmitbuf) {
1929                 rtw_free_xmitframe(pxmitpriv, pmgntframe);
1930                 pmgntframe = NULL;
1931                 goto exit;
1932         }
1933
1934         pmgntframe->frame_tag = MGNT_FRAMETAG;
1935         pmgntframe->pxmitbuf = pxmitbuf;
1936         pmgntframe->buf_addr = pxmitbuf->pbuf;
1937         pxmitbuf->priv_data = pmgntframe;
1938
1939 exit:
1940         return pmgntframe;
1941
1942 }
1943
1944 inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
1945 {
1946         return _alloc_mgtxmitframe(pxmitpriv, false);
1947 }
1948
1949 /****************************************************************************
1950
1951 Following are some TX functions for WiFi MLME
1952
1953 *****************************************************************************/
1954
1955 void update_mgnt_tx_rate(struct adapter *padapter, u8 rate)
1956 {
1957         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1958
1959         pmlmeext->tx_rate = rate;
1960 }
1961
1962 void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib)
1963 {
1964         u8 wireless_mode;
1965         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1966
1967         /* memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib)); */
1968
1969         pattrib->hdrlen = 24;
1970         pattrib->nr_frags = 1;
1971         pattrib->priority = 7;
1972         pattrib->mac_id = 0;
1973         pattrib->qsel = 0x12;
1974
1975         pattrib->pktlen = 0;
1976
1977         if (pmlmeext->tx_rate == IEEE80211_CCK_RATE_1MB)
1978                 wireless_mode = WIRELESS_11B;
1979         else
1980                 wireless_mode = WIRELESS_11G;
1981         pattrib->raid =  rtw_get_mgntframe_raid(padapter, wireless_mode);
1982         pattrib->rate = pmlmeext->tx_rate;
1983
1984         pattrib->encrypt = _NO_PRIVACY_;
1985         pattrib->bswenc = false;
1986
1987         pattrib->qos_en = false;
1988         pattrib->ht_en = false;
1989         pattrib->bwmode = CHANNEL_WIDTH_20;
1990         pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
1991         pattrib->sgi = false;
1992
1993         pattrib->seqnum = pmlmeext->mgnt_seq;
1994
1995         pattrib->retry_ctrl = true;
1996
1997         pattrib->mbssid = 0;
1998
1999 }
2000
2001 void update_mgntframe_attrib_addr(struct adapter *padapter, struct xmit_frame *pmgntframe)
2002 {
2003         u8 *pframe;
2004         struct pkt_attrib       *pattrib = &pmgntframe->attrib;
2005
2006         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2007
2008         memcpy(pattrib->ra, GetAddr1Ptr(pframe), ETH_ALEN);
2009         memcpy(pattrib->ta, GetAddr2Ptr(pframe), ETH_ALEN);
2010 }
2011
2012 void dump_mgntframe(struct adapter *padapter, struct xmit_frame *pmgntframe)
2013 {
2014         if (padapter->bSurpriseRemoved ||
2015                 padapter->bDriverStopped) {
2016                 rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
2017                 rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
2018                 return;
2019         }
2020
2021         rtw_hal_mgnt_xmit(padapter, pmgntframe);
2022 }
2023
2024 s32 dump_mgntframe_and_wait(struct adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)
2025 {
2026         s32 ret = _FAIL;
2027         unsigned long irqL;
2028         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2029         struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
2030         struct submit_ctx sctx;
2031
2032         if (padapter->bSurpriseRemoved ||
2033                 padapter->bDriverStopped) {
2034                 rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
2035                 rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
2036                 return ret;
2037         }
2038
2039         rtw_sctx_init(&sctx, timeout_ms);
2040         pxmitbuf->sctx = &sctx;
2041
2042         ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
2043
2044         if (ret == _SUCCESS)
2045                 ret = rtw_sctx_wait(&sctx);
2046
2047         spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
2048         pxmitbuf->sctx = NULL;
2049         spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
2050
2051         return ret;
2052 }
2053
2054 s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmgntframe)
2055 {
2056         static u8 seq_no;
2057         s32 ret = _FAIL;
2058         u32 timeout_ms = 500;/*   500ms */
2059         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2060
2061         if (padapter->bSurpriseRemoved ||
2062                 padapter->bDriverStopped) {
2063                 rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
2064                 rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
2065                 return -1;
2066         }
2067
2068         if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex) == 0) {
2069                 pxmitpriv->ack_tx = true;
2070                 pxmitpriv->seq_no = seq_no++;
2071                 pmgntframe->ack_report = 1;
2072                 if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS)
2073                         ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
2074
2075                 pxmitpriv->ack_tx = false;
2076                 mutex_unlock(&pxmitpriv->ack_tx_mutex);
2077         }
2078
2079         return ret;
2080 }
2081
2082 static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
2083 {
2084         u8 *ssid_ie;
2085         signed int ssid_len_ori;
2086         int len_diff = 0;
2087
2088         ssid_ie = rtw_get_ie(ies,  WLAN_EID_SSID, &ssid_len_ori, ies_len);
2089
2090         if (ssid_ie && ssid_len_ori > 0) {
2091                 switch (hidden_ssid_mode) {
2092                 case 1:
2093                 {
2094                         u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
2095                         u32 remain_len = 0;
2096
2097                         remain_len = ies_len - (next_ie-ies);
2098
2099                         ssid_ie[1] = 0;
2100                         memcpy(ssid_ie+2, next_ie, remain_len);
2101                         len_diff -= ssid_len_ori;
2102
2103                         break;
2104                 }
2105                 case 2:
2106                         memset(&ssid_ie[2], 0, ssid_len_ori);
2107                         break;
2108                 default:
2109                         break;
2110         }
2111         }
2112
2113         return len_diff;
2114 }
2115
2116 void issue_beacon(struct adapter *padapter, int timeout_ms)
2117 {
2118         struct xmit_frame       *pmgntframe;
2119         struct pkt_attrib       *pattrib;
2120         unsigned char *pframe;
2121         struct ieee80211_hdr *pwlanhdr;
2122         __le16 *fctrl;
2123         unsigned int    rate_len;
2124         struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
2125         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2126         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2127         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2128         struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
2129
2130         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2131         if (!pmgntframe)
2132                 return;
2133
2134         spin_lock_bh(&pmlmepriv->bcn_update_lock);
2135
2136         /* update attribute */
2137         pattrib = &pmgntframe->attrib;
2138         update_mgntframe_attrib(padapter, pattrib);
2139         pattrib->qsel = 0x10;
2140
2141         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2142
2143         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2144         pwlanhdr = (struct ieee80211_hdr *)pframe;
2145
2146
2147         fctrl = &(pwlanhdr->frame_control);
2148         *(fctrl) = 0;
2149
2150         eth_broadcast_addr(pwlanhdr->addr1);
2151         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2152         memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
2153
2154         SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
2155         /* pmlmeext->mgnt_seq++; */
2156         SetFrameSubType(pframe, WIFI_BEACON);
2157
2158         pframe += sizeof(struct ieee80211_hdr_3addr);
2159         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2160
2161         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
2162                 {
2163                         int len_diff;
2164
2165                         memcpy(pframe, cur_network->ies, cur_network->ie_length);
2166                         len_diff = update_hidden_ssid(pframe+_BEACON_IE_OFFSET_,
2167                                                       cur_network->ie_length-_BEACON_IE_OFFSET_,
2168                                                       pmlmeinfo->hidden_ssid_mode);
2169                         pframe += (cur_network->ie_length+len_diff);
2170                         pattrib->pktlen += (cur_network->ie_length+len_diff);
2171                 }
2172
2173                 {
2174                         u8 *wps_ie;
2175                         uint wps_ielen;
2176                         u8 sr = 0;
2177
2178                         wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_,
2179                                 pattrib->pktlen-sizeof(struct ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen);
2180                         if (wps_ie && wps_ielen > 0)
2181                                 rtw_get_wps_attr_content(wps_ie,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
2182                         if (sr != 0)
2183                                 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
2184                         else
2185                                 _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
2186                 }
2187
2188                 goto _issue_bcn;
2189
2190         }
2191
2192         /* below for ad-hoc mode */
2193
2194         /* timestamp will be inserted by hardware */
2195         pframe += 8;
2196         pattrib->pktlen += 8;
2197
2198         /*  beacon interval: 2 bytes */
2199
2200         memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
2201
2202         pframe += 2;
2203         pattrib->pktlen += 2;
2204
2205         /*  capability info: 2 bytes */
2206
2207         memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
2208
2209         pframe += 2;
2210         pattrib->pktlen += 2;
2211
2212         /*  SSID */
2213         pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pattrib->pktlen);
2214
2215         /*  supported rates... */
2216         rate_len = rtw_get_rateset_len(cur_network->supported_rates);
2217         pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->supported_rates, &pattrib->pktlen);
2218
2219         /*  DS parameter set */
2220         pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->configuration.ds_config), &pattrib->pktlen);
2221
2222         /* if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */
2223         {
2224                 u8 erpinfo = 0;
2225                 u32 ATIMWindow;
2226                 /*  IBSS Parameter Set... */
2227                 /* ATIMWindow = cur->configuration.ATIMWindow; */
2228                 ATIMWindow = 0;
2229                 pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
2230
2231                 /* ERP IE */
2232                 pframe = rtw_set_ie(pframe, WLAN_EID_ERP_INFO, 1, &erpinfo, &pattrib->pktlen);
2233         }
2234
2235
2236         /*  EXTERNDED SUPPORTED RATE */
2237         if (rate_len > 8)
2238                 pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->supported_rates + 8), &pattrib->pktlen);
2239
2240
2241         /* todo:HT for adhoc */
2242
2243 _issue_bcn:
2244
2245         pmlmepriv->update_bcn = false;
2246
2247         spin_unlock_bh(&pmlmepriv->bcn_update_lock);
2248
2249         if ((pattrib->pktlen + TXDESC_SIZE) > 512)
2250                 return;
2251
2252         pattrib->last_txcmdsz = pattrib->pktlen;
2253
2254         if (timeout_ms > 0)
2255                 dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
2256         else
2257                 dump_mgntframe(padapter, pmgntframe);
2258
2259 }
2260
2261 void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq)
2262 {
2263         struct xmit_frame                       *pmgntframe;
2264         struct pkt_attrib                       *pattrib;
2265         unsigned char                           *pframe;
2266         struct ieee80211_hdr    *pwlanhdr;
2267         __le16 *fctrl;
2268         unsigned char                           *mac, *bssid;
2269         struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
2270
2271         u8 *pwps_ie;
2272         uint wps_ielen;
2273         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2274         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2275         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2276         struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
2277         unsigned int    rate_len;
2278
2279         if (!da)
2280                 return;
2281
2282         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2283         if (!pmgntframe)
2284                 return;
2285
2286         /* update attribute */
2287         pattrib = &pmgntframe->attrib;
2288         update_mgntframe_attrib(padapter, pattrib);
2289
2290         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2291
2292         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2293         pwlanhdr = (struct ieee80211_hdr *)pframe;
2294
2295         mac = myid(&(padapter->eeprompriv));
2296         bssid = cur_network->mac_address;
2297
2298         fctrl = &(pwlanhdr->frame_control);
2299         *(fctrl) = 0;
2300         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
2301         memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
2302         memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
2303
2304         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2305         pmlmeext->mgnt_seq++;
2306         SetFrameSubType(fctrl, WIFI_PROBERSP);
2307
2308         pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2309         pattrib->pktlen = pattrib->hdrlen;
2310         pframe += pattrib->hdrlen;
2311
2312
2313         if (cur_network->ie_length > MAX_IE_SZ)
2314                 return;
2315
2316         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
2317                 pwps_ie = rtw_get_wps_ie(cur_network->ies+_FIXED_IE_LENGTH_, cur_network->ie_length-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
2318
2319                 /* inerset & update wps_probe_resp_ie */
2320                 if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) {
2321                         uint wps_offset, remainder_ielen;
2322                         u8 *premainder_ie;
2323
2324                         wps_offset = (uint)(pwps_ie - cur_network->ies);
2325
2326                         premainder_ie = pwps_ie + wps_ielen;
2327
2328                         remainder_ielen = cur_network->ie_length - wps_offset - wps_ielen;
2329
2330                         memcpy(pframe, cur_network->ies, wps_offset);
2331                         pframe += wps_offset;
2332                         pattrib->pktlen += wps_offset;
2333
2334                         wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
2335                         if ((wps_offset+wps_ielen+2) <= MAX_IE_SZ) {
2336                                 memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2);
2337                                 pframe += wps_ielen+2;
2338                                 pattrib->pktlen += wps_ielen+2;
2339                         }
2340
2341                         if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) {
2342                                 memcpy(pframe, premainder_ie, remainder_ielen);
2343                                 pframe += remainder_ielen;
2344                                 pattrib->pktlen += remainder_ielen;
2345                         }
2346                 } else {
2347                         memcpy(pframe, cur_network->ies, cur_network->ie_length);
2348                         pframe += cur_network->ie_length;
2349                         pattrib->pktlen += cur_network->ie_length;
2350                 }
2351
2352                 /* retrieve SSID IE from cur_network->ssid */
2353                 {
2354                         u8 *ssid_ie;
2355                         signed int ssid_ielen;
2356                         signed int ssid_ielen_diff;
2357                         u8 *buf;
2358                         u8 *ies = pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr);
2359
2360                         buf = rtw_zmalloc(MAX_IE_SZ);
2361                         if (!buf)
2362                                 return;
2363
2364                         ssid_ie = rtw_get_ie(ies+_FIXED_IE_LENGTH_, WLAN_EID_SSID, &ssid_ielen,
2365                                 (pframe-ies)-_FIXED_IE_LENGTH_);
2366
2367                         ssid_ielen_diff = cur_network->ssid.ssid_length - ssid_ielen;
2368
2369                         if (ssid_ie &&  cur_network->ssid.ssid_length) {
2370                                 uint remainder_ielen;
2371                                 u8 *remainder_ie;
2372
2373                                 remainder_ie = ssid_ie+2;
2374                                 remainder_ielen = (pframe-remainder_ie);
2375
2376                                 if (remainder_ielen > MAX_IE_SZ) {
2377                                         netdev_warn(padapter->pnetdev,
2378                                                     FUNC_ADPT_FMT " remainder_ielen > MAX_IE_SZ\n",
2379                                                     FUNC_ADPT_ARG(padapter));
2380                                         remainder_ielen = MAX_IE_SZ;
2381                                 }
2382
2383                                 memcpy(buf, remainder_ie, remainder_ielen);
2384                                 memcpy(remainder_ie+ssid_ielen_diff, buf, remainder_ielen);
2385                                 *(ssid_ie+1) = cur_network->ssid.ssid_length;
2386                                 memcpy(ssid_ie+2, cur_network->ssid.ssid, cur_network->ssid.ssid_length);
2387
2388                                 pframe += ssid_ielen_diff;
2389                                 pattrib->pktlen += ssid_ielen_diff;
2390                         }
2391                         kfree(buf);
2392                 }
2393         } else {
2394                 /* timestamp will be inserted by hardware */
2395                 pframe += 8;
2396                 pattrib->pktlen += 8;
2397
2398                 /*  beacon interval: 2 bytes */
2399
2400                 memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
2401
2402                 pframe += 2;
2403                 pattrib->pktlen += 2;
2404
2405                 /*  capability info: 2 bytes */
2406
2407                 memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
2408
2409                 pframe += 2;
2410                 pattrib->pktlen += 2;
2411
2412                 /* below for ad-hoc mode */
2413
2414                 /*  SSID */
2415                 pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pattrib->pktlen);
2416
2417                 /*  supported rates... */
2418                 rate_len = rtw_get_rateset_len(cur_network->supported_rates);
2419                 pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->supported_rates, &pattrib->pktlen);
2420
2421                 /*  DS parameter set */
2422                 pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->configuration.ds_config), &pattrib->pktlen);
2423
2424                 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
2425                         u8 erpinfo = 0;
2426                         u32 ATIMWindow;
2427                         /*  IBSS Parameter Set... */
2428                         /* ATIMWindow = cur->configuration.ATIMWindow; */
2429                         ATIMWindow = 0;
2430                         pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
2431
2432                         /* ERP IE */
2433                         pframe = rtw_set_ie(pframe, WLAN_EID_ERP_INFO, 1, &erpinfo, &pattrib->pktlen);
2434                 }
2435
2436
2437                 /*  EXTERNDED SUPPORTED RATE */
2438                 if (rate_len > 8)
2439                         pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->supported_rates + 8), &pattrib->pktlen);
2440
2441
2442                 /* todo:HT for adhoc */
2443
2444         }
2445
2446         pattrib->last_txcmdsz = pattrib->pktlen;
2447
2448
2449         dump_mgntframe(padapter, pmgntframe);
2450
2451         return;
2452
2453 }
2454
2455 static int _issue_probereq(struct adapter *padapter,
2456                            struct ndis_802_11_ssid *pssid,
2457                            u8 *da, u8 ch, bool append_wps, bool wait_ack)
2458 {
2459         int ret = _FAIL;
2460         struct xmit_frame               *pmgntframe;
2461         struct pkt_attrib               *pattrib;
2462         unsigned char           *pframe;
2463         struct ieee80211_hdr    *pwlanhdr;
2464         __le16 *fctrl;
2465         unsigned char           *mac;
2466         unsigned char           bssrate[NumRates];
2467         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
2468         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2469         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2470         int     bssrate_len = 0;
2471
2472         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2473         if (!pmgntframe)
2474                 goto exit;
2475
2476         /* update attribute */
2477         pattrib = &pmgntframe->attrib;
2478         update_mgntframe_attrib(padapter, pattrib);
2479
2480
2481         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2482
2483         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2484         pwlanhdr = (struct ieee80211_hdr *)pframe;
2485
2486         mac = myid(&(padapter->eeprompriv));
2487
2488         fctrl = &(pwlanhdr->frame_control);
2489         *(fctrl) = 0;
2490
2491         if (da) {
2492                 /*      unicast probe request frame */
2493                 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
2494                 memcpy(pwlanhdr->addr3, da, ETH_ALEN);
2495         } else {
2496                 /*      broadcast probe request frame */
2497                 eth_broadcast_addr(pwlanhdr->addr1);
2498                 eth_broadcast_addr(pwlanhdr->addr3);
2499         }
2500
2501         memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
2502
2503         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2504         pmlmeext->mgnt_seq++;
2505         SetFrameSubType(pframe, WIFI_PROBEREQ);
2506
2507         pframe += sizeof(struct ieee80211_hdr_3addr);
2508         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2509
2510         if (pssid)
2511                 pframe = rtw_set_ie(pframe, WLAN_EID_SSID, pssid->ssid_length, pssid->ssid, &(pattrib->pktlen));
2512         else
2513                 pframe = rtw_set_ie(pframe, WLAN_EID_SSID, 0, NULL, &(pattrib->pktlen));
2514
2515         get_rate_set(padapter, bssrate, &bssrate_len);
2516
2517         if (bssrate_len > 8) {
2518                 pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, bssrate, &(pattrib->pktlen));
2519                 pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
2520         } else {
2521                 pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, bssrate_len, bssrate, &(pattrib->pktlen));
2522         }
2523
2524         if (ch)
2525                 pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, &ch, &pattrib->pktlen);
2526
2527         if (append_wps) {
2528                 /* add wps_ie for wps2.0 */
2529                 if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) {
2530                         memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
2531                         pframe += pmlmepriv->wps_probe_req_ie_len;
2532                         pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
2533                 }
2534         }
2535
2536         pattrib->last_txcmdsz = pattrib->pktlen;
2537
2538         if (wait_ack) {
2539                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
2540         } else {
2541                 dump_mgntframe(padapter, pmgntframe);
2542                 ret = _SUCCESS;
2543         }
2544
2545 exit:
2546         return ret;
2547 }
2548
2549 inline void issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da)
2550 {
2551         _issue_probereq(padapter, pssid, da, 0, 1, false);
2552 }
2553
2554 int issue_probereq_ex(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, u8 ch, bool append_wps,
2555         int try_cnt, int wait_ms)
2556 {
2557         int ret;
2558         int i = 0;
2559
2560         do {
2561                 ret = _issue_probereq(padapter, pssid, da, ch, append_wps,
2562                                       wait_ms > 0);
2563
2564                 i++;
2565
2566                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
2567                         break;
2568
2569                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
2570                         msleep(wait_ms);
2571
2572         } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
2573
2574         if (ret != _FAIL) {
2575                 ret = _SUCCESS;
2576                 #ifndef DBG_XMIT_ACK
2577                 goto exit;
2578                 #endif
2579         }
2580
2581 exit:
2582         return ret;
2583 }
2584
2585 /*  if psta == NULL, indicate we are station(client) now... */
2586 void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status)
2587 {
2588         struct xmit_frame                       *pmgntframe;
2589         struct pkt_attrib                       *pattrib;
2590         unsigned char                           *pframe;
2591         struct ieee80211_hdr    *pwlanhdr;
2592         __le16 *fctrl;
2593         unsigned int                                    val32;
2594         unsigned short                          val16;
2595         int use_shared_key = 0;
2596         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
2597         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2598         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2599         __le16 le_tmp;
2600
2601         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2602         if (!pmgntframe)
2603                 return;
2604
2605         /* update attribute */
2606         pattrib = &pmgntframe->attrib;
2607         update_mgntframe_attrib(padapter, pattrib);
2608
2609         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2610
2611         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2612         pwlanhdr = (struct ieee80211_hdr *)pframe;
2613
2614         fctrl = &(pwlanhdr->frame_control);
2615         *(fctrl) = 0;
2616
2617         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2618         pmlmeext->mgnt_seq++;
2619         SetFrameSubType(pframe, WIFI_AUTH);
2620
2621         pframe += sizeof(struct ieee80211_hdr_3addr);
2622         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2623
2624
2625         if (psta) { /*  for AP mode */
2626                 memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN);
2627                 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2628                 memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
2629
2630                 /*  setting auth algo number */
2631                 val16 = (u16)psta->authalg;
2632
2633                 if (status != WLAN_STATUS_SUCCESS)
2634                         val16 = 0;
2635
2636                 if (val16)
2637                         use_shared_key = 1;
2638
2639                 le_tmp = cpu_to_le16(val16);
2640
2641                 pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2642
2643                 /*  setting auth seq number */
2644                 val16 = (u16)psta->auth_seq;
2645                 le_tmp = cpu_to_le16(val16);
2646                 pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2647
2648                 /*  setting status code... */
2649                 val16 = status;
2650                 le_tmp = cpu_to_le16(val16);
2651                 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2652
2653                 /*  added challenging text... */
2654                 if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
2655                         pframe = rtw_set_ie(pframe, WLAN_EID_CHALLENGE, 128, psta->chg_txt, &(pattrib->pktlen));
2656
2657         } else {
2658                 memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
2659                 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
2660                 memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
2661
2662                 /*  setting auth algo number */
2663                 val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/*  0:OPEN System, 1:Shared key */
2664                 if (val16)
2665                         use_shared_key = 1;
2666                 le_tmp = cpu_to_le16(val16);
2667
2668                 /* setting IV for auth seq #3 */
2669                 if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
2670                         __le32 le_tmp32;
2671
2672                         val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30));
2673                         le_tmp32 = cpu_to_le32(val32);
2674                         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&le_tmp32, &(pattrib->pktlen));
2675
2676                         pattrib->iv_len = 4;
2677                 }
2678
2679                 pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2680
2681                 /*  setting auth seq number */
2682                 le_tmp = cpu_to_le16(pmlmeinfo->auth_seq);
2683                 pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2684
2685
2686                 /*  setting status code... */
2687                 le_tmp = cpu_to_le16(status);
2688                 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2689
2690                 /*  then checking to see if sending challenging text... */
2691                 if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
2692                         pframe = rtw_set_ie(pframe, WLAN_EID_CHALLENGE, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen));
2693
2694                         SetPrivacy(fctrl);
2695
2696                         pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2697
2698                         pattrib->encrypt = _WEP40_;
2699
2700                         pattrib->icv_len = 4;
2701
2702                         pattrib->pktlen += pattrib->icv_len;
2703
2704                 }
2705
2706         }
2707
2708         pattrib->last_txcmdsz = pattrib->pktlen;
2709
2710         rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
2711         dump_mgntframe(padapter, pmgntframe);
2712 }
2713
2714
2715 void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type)
2716 {
2717         struct xmit_frame       *pmgntframe;
2718         struct ieee80211_hdr    *pwlanhdr;
2719         struct pkt_attrib *pattrib;
2720         unsigned char *pbuf, *pframe;
2721         unsigned short val;
2722         __le16 *fctrl;
2723         struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
2724         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2725         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2726         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2727         struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
2728         u8 *ie = pnetwork->ies;
2729         __le16 lestatus, le_tmp;
2730
2731         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2732         if (!pmgntframe)
2733                 return;
2734
2735         /* update attribute */
2736         pattrib = &pmgntframe->attrib;
2737         update_mgntframe_attrib(padapter, pattrib);
2738
2739
2740         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2741
2742         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2743         pwlanhdr = (struct ieee80211_hdr *)pframe;
2744
2745         fctrl = &(pwlanhdr->frame_control);
2746         *(fctrl) = 0;
2747
2748         memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN);
2749         memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN);
2750         memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
2751
2752
2753         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2754         pmlmeext->mgnt_seq++;
2755         if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
2756                 SetFrameSubType(pwlanhdr, pkt_type);
2757         else
2758                 return;
2759
2760         pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2761         pattrib->pktlen += pattrib->hdrlen;
2762         pframe += pattrib->hdrlen;
2763
2764         /* capability */
2765         val = *(unsigned short *)rtw_get_capability_from_ie(ie);
2766
2767         pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_, (unsigned char *)&val, &(pattrib->pktlen));
2768
2769         lestatus = cpu_to_le16(status);
2770         pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&lestatus, &(pattrib->pktlen));
2771
2772         le_tmp = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
2773         pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2774
2775         if (pstat->bssratelen <= 8) {
2776                 pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen));
2777         } else {
2778                 pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, pstat->bssrateset, &(pattrib->pktlen));
2779                 pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (pstat->bssratelen-8), pstat->bssrateset+8, &(pattrib->pktlen));
2780         }
2781
2782         if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
2783                 uint ie_len = 0;
2784
2785                 /* FILL HT CAP INFO IE */
2786                 /* p = hostapd_eid_ht_capabilities_info(hapd, p); */
2787                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_CAPABILITY, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_));
2788                 if (pbuf && ie_len > 0) {
2789                         memcpy(pframe, pbuf, ie_len+2);
2790                         pframe += (ie_len+2);
2791                         pattrib->pktlen += (ie_len+2);
2792                 }
2793
2794                 /* FILL HT ADD INFO IE */
2795                 /* p = hostapd_eid_ht_operation(hapd, p); */
2796                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_OPERATION, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_));
2797                 if (pbuf && ie_len > 0) {
2798                         memcpy(pframe, pbuf, ie_len+2);
2799                         pframe += (ie_len+2);
2800                         pattrib->pktlen += (ie_len+2);
2801                 }
2802
2803         }
2804
2805         /* FILL WMM IE */
2806         if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) {
2807                 uint ie_len = 0;
2808                 unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
2809
2810                 for (pbuf = ie + _BEACON_IE_OFFSET_; ; pbuf += (ie_len + 2)) {
2811                         pbuf = rtw_get_ie(pbuf, WLAN_EID_VENDOR_SPECIFIC, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2)));
2812                         if (pbuf && !memcmp(pbuf+2, WMM_PARA_IE, 6)) {
2813                                 memcpy(pframe, pbuf, ie_len+2);
2814                                 pframe += (ie_len+2);
2815                                 pattrib->pktlen += (ie_len+2);
2816
2817                                 break;
2818                         }
2819
2820                         if (!pbuf || ie_len == 0)
2821                                 break;
2822                 }
2823
2824         }
2825
2826         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
2827                 pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, REALTEK_96B_IE, &(pattrib->pktlen));
2828
2829         /* add WPS IE ie for wps 2.0 */
2830         if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) {
2831                 memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
2832
2833                 pframe += pmlmepriv->wps_assoc_resp_ie_len;
2834                 pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
2835         }
2836
2837         pattrib->last_txcmdsz = pattrib->pktlen;
2838
2839         dump_mgntframe(padapter, pmgntframe);
2840 }
2841
2842 void issue_assocreq(struct adapter *padapter)
2843 {
2844         int ret = _FAIL;
2845         struct xmit_frame                               *pmgntframe;
2846         struct pkt_attrib                               *pattrib;
2847         unsigned char                           *pframe;
2848         struct ieee80211_hdr                    *pwlanhdr;
2849         __le16 *fctrl;
2850         __le16 val16;
2851         unsigned int                                    i, j, index = 0;
2852         unsigned char bssrate[NumRates], sta_bssrate[NumRates];
2853         struct ndis_80211_var_ie *pIE;
2854         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
2855         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2856         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2857         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2858         int     bssrate_len = 0, sta_bssrate_len = 0;
2859         u8 vs_ie_length = 0;
2860
2861         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2862         if (!pmgntframe)
2863                 goto exit;
2864
2865         /* update attribute */
2866         pattrib = &pmgntframe->attrib;
2867         update_mgntframe_attrib(padapter, pattrib);
2868
2869         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2870
2871         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2872         pwlanhdr = (struct ieee80211_hdr *)pframe;
2873
2874         fctrl = &(pwlanhdr->frame_control);
2875         *(fctrl) = 0;
2876         memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
2877         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2878         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
2879
2880         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2881         pmlmeext->mgnt_seq++;
2882         SetFrameSubType(pframe, WIFI_ASSOCREQ);
2883
2884         pframe += sizeof(struct ieee80211_hdr_3addr);
2885         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2886
2887         /* caps */
2888         memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.ies), 2);
2889
2890         pframe += 2;
2891         pattrib->pktlen += 2;
2892
2893         /* listen interval */
2894         /* todo: listen interval for power saving */
2895         val16 = cpu_to_le16(3);
2896         memcpy(pframe, (unsigned char *)&val16, 2);
2897         pframe += 2;
2898         pattrib->pktlen += 2;
2899
2900         /* SSID */
2901         pframe = rtw_set_ie(pframe, WLAN_EID_SSID,  pmlmeinfo->network.ssid.ssid_length, pmlmeinfo->network.ssid.ssid, &(pattrib->pktlen));
2902
2903         /* supported rate & extended supported rate */
2904
2905         /*  Check if the AP's supported rates are also supported by STA. */
2906         get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
2907
2908         if (pmlmeext->cur_channel == 14) /*  for JAPAN, channel 14 can only uses B Mode(CCK) */
2909                 sta_bssrate_len = 4;
2910
2911
2912         /* for (i = 0; i < sta_bssrate_len; i++) { */
2913         /*  */
2914
2915         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
2916                 if (pmlmeinfo->network.supported_rates[i] == 0)
2917                         break;
2918         }
2919
2920
2921         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
2922                 if (pmlmeinfo->network.supported_rates[i] == 0)
2923                         break;
2924
2925
2926                 /*  Check if the AP's supported rates are also supported by STA. */
2927                 for (j = 0; j < sta_bssrate_len; j++) {
2928                          /*  Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
2929                         if ((pmlmeinfo->network.supported_rates[i] | IEEE80211_BASIC_RATE_MASK)
2930                                         == (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK))
2931                                 break;
2932                 }
2933
2934                 if (j != sta_bssrate_len)
2935                         /*  the rate is supported by STA */
2936                         bssrate[index++] = pmlmeinfo->network.supported_rates[i];
2937         }
2938
2939         bssrate_len = index;
2940
2941         if (bssrate_len == 0) {
2942                 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
2943                 rtw_free_xmitframe(pxmitpriv, pmgntframe);
2944                 goto exit; /* don't connect to AP if no joint supported rate */
2945         }
2946
2947
2948         if (bssrate_len > 8) {
2949                 pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, bssrate, &(pattrib->pktlen));
2950                 pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
2951         } else
2952                 pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, bssrate_len, bssrate, &(pattrib->pktlen));
2953
2954         /* vendor specific IE, such as WPA, WMM, WPS */
2955         for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.ie_length;) {
2956                 pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.ies + i);
2957
2958                 switch (pIE->element_id) {
2959                 case WLAN_EID_VENDOR_SPECIFIC:
2960                         if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
2961                                         (!memcmp(pIE->data, WMM_OUI, 4)) ||
2962                                         (!memcmp(pIE->data, WPS_OUI, 4))) {
2963                                 vs_ie_length = pIE->length;
2964                                 if ((!padapter->registrypriv.wifi_spec) && (!memcmp(pIE->data, WPS_OUI, 4))) {
2965                                         /* Commented by Kurt 20110629
2966                                          * In some older APs, WPS handshake
2967                                          * would be fail if we append vendor
2968                                          * extensions information to AP
2969                                          */
2970
2971                                         vs_ie_length = 14;
2972                                 }
2973
2974                                 pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, vs_ie_length, pIE->data, &(pattrib->pktlen));
2975                         }
2976                         break;
2977
2978                 case WLAN_EID_RSN:
2979                         pframe = rtw_set_ie(pframe, WLAN_EID_RSN, pIE->length, pIE->data, &(pattrib->pktlen));
2980                         break;
2981                 case WLAN_EID_HT_CAPABILITY:
2982                         if (padapter->mlmepriv.htpriv.ht_option) {
2983                                 if (!(is_ap_in_tkip(padapter))) {
2984                                         memcpy(&(pmlmeinfo->HT_caps), pIE->data, sizeof(struct HT_caps_element));
2985                                         pframe = rtw_set_ie(pframe, WLAN_EID_HT_CAPABILITY, pIE->length, (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen));
2986                                 }
2987                         }
2988                         break;
2989
2990                 case WLAN_EID_EXT_CAPABILITY:
2991                         if (padapter->mlmepriv.htpriv.ht_option)
2992                                 pframe = rtw_set_ie(pframe, WLAN_EID_EXT_CAPABILITY, pIE->length, pIE->data, &(pattrib->pktlen));
2993                         break;
2994                 default:
2995                         break;
2996                 }
2997
2998                 i += (pIE->length + 2);
2999         }
3000
3001         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
3002                 pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, REALTEK_96B_IE, &(pattrib->pktlen));
3003
3004
3005         pattrib->last_txcmdsz = pattrib->pktlen;
3006         dump_mgntframe(padapter, pmgntframe);
3007
3008         ret = _SUCCESS;
3009
3010 exit:
3011         if (ret == _SUCCESS)
3012                 rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
3013         else
3014                 rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
3015 }
3016
3017 /* when wait_ack is true, this function should be called at process context */
3018 static int _issue_nulldata(struct adapter *padapter, unsigned char *da,
3019                            unsigned int power_mode, bool wait_ack)
3020 {
3021         int ret = _FAIL;
3022         struct xmit_frame                       *pmgntframe;
3023         struct pkt_attrib                       *pattrib;
3024         unsigned char                           *pframe;
3025         struct ieee80211_hdr    *pwlanhdr;
3026         __le16 *fctrl;
3027         struct xmit_priv *pxmitpriv;
3028         struct mlme_ext_priv *pmlmeext;
3029         struct mlme_ext_info *pmlmeinfo;
3030
3031         if (!padapter)
3032                 goto exit;
3033
3034         pxmitpriv = &(padapter->xmitpriv);
3035         pmlmeext = &(padapter->mlmeextpriv);
3036         pmlmeinfo = &(pmlmeext->mlmext_info);
3037
3038         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3039         if (!pmgntframe)
3040                 goto exit;
3041
3042         /* update attribute */
3043         pattrib = &pmgntframe->attrib;
3044         update_mgntframe_attrib(padapter, pattrib);
3045         pattrib->retry_ctrl = false;
3046
3047         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3048
3049         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3050         pwlanhdr = (struct ieee80211_hdr *)pframe;
3051
3052         fctrl = &(pwlanhdr->frame_control);
3053         *(fctrl) = 0;
3054
3055         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
3056                 SetFrDs(fctrl);
3057         else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
3058                 SetToDs(fctrl);
3059
3060         if (power_mode)
3061                 SetPwrMgt(fctrl);
3062
3063         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3064         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3065         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3066
3067         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3068         pmlmeext->mgnt_seq++;
3069         SetFrameSubType(pframe, WIFI_DATA_NULL);
3070
3071         pframe += sizeof(struct ieee80211_hdr_3addr);
3072         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3073
3074         pattrib->last_txcmdsz = pattrib->pktlen;
3075
3076         if (wait_ack) {
3077                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3078         } else {
3079                 dump_mgntframe(padapter, pmgntframe);
3080                 ret = _SUCCESS;
3081         }
3082
3083 exit:
3084         return ret;
3085 }
3086
3087 /*
3088  * [IMPORTANT] Don't call this function in interrupt context
3089  *
3090  * When wait_ms > 0, this function should be called at process context
3091  * da == NULL for station mode
3092  */
3093 int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
3094 {
3095         int ret;
3096         int i = 0;
3097         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3098         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3099         struct sta_info *psta;
3100
3101
3102         /* da == NULL, assume it's null data for sta to ap*/
3103         if (!da)
3104                 da = get_my_bssid(&(pmlmeinfo->network));
3105
3106         psta = rtw_get_stainfo(&padapter->stapriv, da);
3107         if (psta) {
3108                 if (power_mode)
3109                         rtw_hal_macid_sleep(padapter, psta->mac_id);
3110                 else
3111                         rtw_hal_macid_wakeup(padapter, psta->mac_id);
3112         } else {
3113                 rtw_warn_on(1);
3114         }
3115
3116         do {
3117                 ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0);
3118
3119                 i++;
3120
3121                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3122                         break;
3123
3124                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3125                         msleep(wait_ms);
3126
3127         } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3128
3129         if (ret != _FAIL) {
3130                 ret = _SUCCESS;
3131                 #ifndef DBG_XMIT_ACK
3132                 goto exit;
3133                 #endif
3134         }
3135
3136 exit:
3137         return ret;
3138 }
3139
3140 /*
3141  * [IMPORTANT] This function run in interrupt context
3142  *
3143  * The null data packet would be sent without power bit,
3144  * and not guarantee success.
3145  */
3146 s32 issue_nulldata_in_interrupt(struct adapter *padapter, u8 *da)
3147 {
3148         struct mlme_ext_priv *pmlmeext;
3149         struct mlme_ext_info *pmlmeinfo;
3150
3151
3152         pmlmeext = &padapter->mlmeextpriv;
3153         pmlmeinfo = &pmlmeext->mlmext_info;
3154
3155         /* da == NULL, assume it's null data for sta to ap*/
3156         if (!da)
3157                 da = get_my_bssid(&(pmlmeinfo->network));
3158
3159         return _issue_nulldata(padapter, da, 0, false);
3160 }
3161
3162 /* when wait_ack is true, this function should be called at process context */
3163 static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da,
3164                                u16 tid, bool wait_ack)
3165 {
3166         int ret = _FAIL;
3167         struct xmit_frame                       *pmgntframe;
3168         struct pkt_attrib                       *pattrib;
3169         unsigned char                           *pframe;
3170         struct ieee80211_hdr    *pwlanhdr;
3171         __le16 *fctrl;
3172         u16 *qc;
3173         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
3174         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3175         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3176
3177         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3178         if (!pmgntframe)
3179                 goto exit;
3180
3181         /* update attribute */
3182         pattrib = &pmgntframe->attrib;
3183         update_mgntframe_attrib(padapter, pattrib);
3184
3185         pattrib->hdrlen += 2;
3186         pattrib->qos_en = true;
3187         pattrib->eosp = 1;
3188         pattrib->ack_policy = 0;
3189         pattrib->mdata = 0;
3190
3191         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3192
3193         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3194         pwlanhdr = (struct ieee80211_hdr *)pframe;
3195
3196         fctrl = &(pwlanhdr->frame_control);
3197         *(fctrl) = 0;
3198
3199         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
3200                 SetFrDs(fctrl);
3201         else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
3202                 SetToDs(fctrl);
3203
3204         qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
3205
3206         SetPriority(qc, tid);
3207
3208         SetEOSP(qc, pattrib->eosp);
3209
3210         SetAckpolicy(qc, pattrib->ack_policy);
3211
3212         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3213         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3214         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3215
3216         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3217         pmlmeext->mgnt_seq++;
3218         SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
3219
3220         pframe += sizeof(struct ieee80211_qos_hdr);
3221         pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
3222
3223         pattrib->last_txcmdsz = pattrib->pktlen;
3224
3225         if (wait_ack) {
3226                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3227         } else {
3228                 dump_mgntframe(padapter, pmgntframe);
3229                 ret = _SUCCESS;
3230         }
3231
3232 exit:
3233         return ret;
3234 }
3235
3236 /* when wait_ms >0 , this function should be called at process context */
3237 /* da == NULL for station mode */
3238 int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
3239 {
3240         int ret;
3241         int i = 0;
3242         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3243         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3244
3245         /* da == NULL, assume it's null data for sta to ap*/
3246         if (!da)
3247                 da = get_my_bssid(&(pmlmeinfo->network));
3248
3249         do {
3250                 ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0);
3251
3252                 i++;
3253
3254                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3255                         break;
3256
3257                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3258                         msleep(wait_ms);
3259
3260         } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3261
3262         if (ret != _FAIL) {
3263                 ret = _SUCCESS;
3264                 #ifndef DBG_XMIT_ACK
3265                 goto exit;
3266                 #endif
3267         }
3268
3269 exit:
3270         return ret;
3271 }
3272
3273 static int _issue_deauth(struct adapter *padapter, unsigned char *da,
3274                          unsigned short reason, bool wait_ack)
3275 {
3276         struct xmit_frame                       *pmgntframe;
3277         struct pkt_attrib                       *pattrib;
3278         unsigned char                           *pframe;
3279         struct ieee80211_hdr    *pwlanhdr;
3280         __le16 *fctrl;
3281         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
3282         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3283         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3284         int ret = _FAIL;
3285         __le16 le_tmp;
3286
3287         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3288         if (!pmgntframe)
3289                 goto exit;
3290
3291         /* update attribute */
3292         pattrib = &pmgntframe->attrib;
3293         update_mgntframe_attrib(padapter, pattrib);
3294         pattrib->retry_ctrl = false;
3295
3296         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3297
3298         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3299         pwlanhdr = (struct ieee80211_hdr *)pframe;
3300
3301         fctrl = &(pwlanhdr->frame_control);
3302         *(fctrl) = 0;
3303
3304         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3305         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3306         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3307
3308         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3309         pmlmeext->mgnt_seq++;
3310         SetFrameSubType(pframe, WIFI_DEAUTH);
3311
3312         pframe += sizeof(struct ieee80211_hdr_3addr);
3313         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3314
3315         le_tmp = cpu_to_le16(reason);
3316         pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3317
3318         pattrib->last_txcmdsz = pattrib->pktlen;
3319
3320
3321         if (wait_ack) {
3322                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3323         } else {
3324                 dump_mgntframe(padapter, pmgntframe);
3325                 ret = _SUCCESS;
3326         }
3327
3328 exit:
3329         return ret;
3330 }
3331
3332 int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason)
3333 {
3334         return _issue_deauth(padapter, da, reason, false);
3335 }
3336
3337 int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason, int try_cnt,
3338         int wait_ms)
3339 {
3340         int ret;
3341         int i = 0;
3342
3343         do {
3344                 ret = _issue_deauth(padapter, da, reason, wait_ms > 0);
3345
3346                 i++;
3347
3348                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3349                         break;
3350
3351                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3352                         mdelay(wait_ms);
3353
3354         } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3355
3356         if (ret != _FAIL) {
3357                 ret = _SUCCESS;
3358                 #ifndef DBG_XMIT_ACK
3359                 goto exit;
3360                 #endif
3361         }
3362
3363 exit:
3364         return ret;
3365 }
3366
3367 void issue_action_SA_Query(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short tid)
3368 {
3369         u8 category = RTW_WLAN_CATEGORY_SA_QUERY;
3370         struct xmit_frame               *pmgntframe;
3371         struct pkt_attrib               *pattrib;
3372         u8                      *pframe;
3373         struct ieee80211_hdr    *pwlanhdr;
3374         __le16 *fctrl;
3375         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
3376         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3377         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3378         __le16 le_tmp;
3379
3380         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3381         if (!pmgntframe)
3382                 return;
3383
3384         /* update attribute */
3385         pattrib = &pmgntframe->attrib;
3386         update_mgntframe_attrib(padapter, pattrib);
3387
3388         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3389
3390         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3391         pwlanhdr = (struct ieee80211_hdr *)pframe;
3392
3393         fctrl = &(pwlanhdr->frame_control);
3394         *(fctrl) = 0;
3395
3396         if (raddr)
3397                 memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3398         else
3399                 memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3400         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3401         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3402
3403         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3404         pmlmeext->mgnt_seq++;
3405         SetFrameSubType(pframe, WIFI_ACTION);
3406
3407         pframe += sizeof(struct ieee80211_hdr_3addr);
3408         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3409
3410         pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
3411         pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
3412
3413         switch (action) {
3414         case 0: /* SA Query req */
3415                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&pmlmeext->sa_query_seq, &pattrib->pktlen);
3416                 pmlmeext->sa_query_seq++;
3417                 /* send sa query request to AP, AP should reply sa query response in 1 second */
3418                 set_sa_query_timer(pmlmeext, 1000);
3419                 break;
3420
3421         case 1: /* SA Query rsp */
3422                 le_tmp = cpu_to_le16(tid);
3423                 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&le_tmp, &pattrib->pktlen);
3424                 break;
3425         default:
3426                 break;
3427         }
3428
3429         pattrib->last_txcmdsz = pattrib->pktlen;
3430
3431         dump_mgntframe(padapter, pmgntframe);
3432 }
3433
3434 void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status)
3435 {
3436         u8 category = RTW_WLAN_CATEGORY_BACK;
3437         u16 start_seq;
3438         u16 BA_para_set;
3439         u16 reason_code;
3440         u16 BA_timeout_value;
3441         u16 BA_starting_seqctrl = 0;
3442         enum ieee80211_max_ampdu_length_exp max_rx_ampdu_factor;
3443         struct xmit_frame               *pmgntframe;
3444         struct pkt_attrib               *pattrib;
3445         u8                      *pframe;
3446         struct ieee80211_hdr    *pwlanhdr;
3447         __le16 *fctrl;
3448         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
3449         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3450         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3451         struct sta_info         *psta;
3452         struct sta_priv         *pstapriv = &padapter->stapriv;
3453         struct registry_priv    *pregpriv = &padapter->registrypriv;
3454         __le16 le_tmp;
3455
3456         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3457         if (!pmgntframe)
3458                 return;
3459
3460         /* update attribute */
3461         pattrib = &pmgntframe->attrib;
3462         update_mgntframe_attrib(padapter, pattrib);
3463
3464         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3465
3466         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3467         pwlanhdr = (struct ieee80211_hdr *)pframe;
3468
3469         fctrl = &(pwlanhdr->frame_control);
3470         *(fctrl) = 0;
3471
3472         /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */
3473         memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3474         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3475         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3476
3477         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3478         pmlmeext->mgnt_seq++;
3479         SetFrameSubType(pframe, WIFI_ACTION);
3480
3481         pframe += sizeof(struct ieee80211_hdr_3addr);
3482         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3483
3484         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3485         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3486
3487         if (category == 3) {
3488                 switch (action) {
3489                 case 0: /* ADDBA req */
3490                         do {
3491                                 pmlmeinfo->dialogToken++;
3492                         } while (pmlmeinfo->dialogToken == 0);
3493                         pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen));
3494
3495                         if (hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter)) {
3496                                 /*  A-MSDU NOT Supported */
3497                                 BA_para_set = 0;
3498                                 /*  immediate Block Ack */
3499                                 BA_para_set |= BIT(1) & IEEE80211_ADDBA_PARAM_POLICY_MASK;
3500                                 /*  TID */
3501                                 BA_para_set |= (status << 2) & IEEE80211_ADDBA_PARAM_TID_MASK;
3502                                 /*  max buffer size is 8 MSDU */
3503                                 BA_para_set |= (8 << 6) & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3504                         } else {
3505                                 BA_para_set = (0x1002 | ((status & 0xf) << 2)); /* immediate ack & 64 buffer size */
3506                         }
3507                         le_tmp = cpu_to_le16(BA_para_set);
3508                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3509
3510                         BA_timeout_value = 5000;/*  5ms */
3511                         le_tmp = cpu_to_le16(BA_timeout_value);
3512                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3513
3514                         /* if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.mac_address)) != NULL) */
3515                         psta = rtw_get_stainfo(pstapriv, raddr);
3516                         if (psta) {
3517                                 start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1;
3518
3519                                 psta->BA_starting_seqctrl[status & 0x07] = start_seq;
3520
3521                                 BA_starting_seqctrl = start_seq << 4;
3522                         }
3523
3524                         le_tmp = cpu_to_le16(BA_starting_seqctrl);
3525                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3526                         break;
3527
3528                 case 1: /* ADDBA rsp */
3529                         pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen));
3530                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen));
3531                         if (padapter->driver_rx_ampdu_factor != 0xFF)
3532                                 max_rx_ampdu_factor =
3533                                   (enum ieee80211_max_ampdu_length_exp)padapter->driver_rx_ampdu_factor;
3534                         else
3535                                 rtw_hal_get_def_var(padapter,
3536                                                     HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
3537
3538                         if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_64K)
3539                                 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
3540                         else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_32K)
3541                                 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); /* 32 buffer size */
3542                         else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_16K)
3543                                 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); /* 16 buffer size */
3544                         else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_8K)
3545                                 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); /* 8 buffer size */
3546                         else
3547                                 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
3548
3549                         if (hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter) &&
3550                             padapter->driver_rx_ampdu_factor == 0xFF) {
3551                                 /*  max buffer size is 8 MSDU */
3552                                 BA_para_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3553                                 BA_para_set |= (8 << 6) & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3554                         }
3555
3556                         if (pregpriv->ampdu_amsdu == 0)/* disabled */
3557                                 le_tmp = cpu_to_le16(BA_para_set & ~BIT(0));
3558                         else if (pregpriv->ampdu_amsdu == 1)/* enabled */
3559                                 le_tmp = cpu_to_le16(BA_para_set | BIT(0));
3560                         else /* auto */
3561                                 le_tmp = cpu_to_le16(BA_para_set);
3562
3563                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3564                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen));
3565                         break;
3566                 case 2:/* DELBA */
3567                         BA_para_set = (status & 0x1F) << 3;
3568                         le_tmp = cpu_to_le16(BA_para_set);
3569                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3570
3571                         reason_code = 37;
3572                         le_tmp = cpu_to_le16(reason_code);
3573                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3574                         break;
3575                 default:
3576                         break;
3577                 }
3578         }
3579
3580         pattrib->last_txcmdsz = pattrib->pktlen;
3581
3582         dump_mgntframe(padapter, pmgntframe);
3583 }
3584
3585 static void issue_action_BSSCoexistPacket(struct adapter *padapter)
3586 {
3587         struct list_head                *plist, *phead;
3588         unsigned char category, action;
3589         struct xmit_frame                       *pmgntframe;
3590         struct pkt_attrib                       *pattrib;
3591         unsigned char                   *pframe;
3592         struct ieee80211_hdr    *pwlanhdr;
3593         __le16 *fctrl;
3594         struct  wlan_network    *pnetwork = NULL;
3595         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
3596         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3597         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3598         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3599         struct __queue          *queue  = &(pmlmepriv->scanned_queue);
3600         u8 InfoContent[16] = {0};
3601         u8 ICS[8][15];
3602
3603         if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
3604                 return;
3605
3606         if (true == pmlmeinfo->bwmode_updated)
3607                 return;
3608
3609         category = RTW_WLAN_CATEGORY_PUBLIC;
3610         action = ACT_PUBLIC_BSSCOEXIST;
3611
3612         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3613         if (!pmgntframe)
3614                 return;
3615
3616         /* update attribute */
3617         pattrib = &pmgntframe->attrib;
3618         update_mgntframe_attrib(padapter, pattrib);
3619
3620         memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3621
3622         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3623         pwlanhdr = (struct ieee80211_hdr *)pframe;
3624
3625         fctrl = &(pwlanhdr->frame_control);
3626         *(fctrl) = 0;
3627
3628         memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3629         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3630         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3631
3632         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3633         pmlmeext->mgnt_seq++;
3634         SetFrameSubType(pframe, WIFI_ACTION);
3635
3636         pframe += sizeof(struct ieee80211_hdr_3addr);
3637         pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3638
3639         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3640         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3641
3642
3643         /*  */
3644         if (pmlmepriv->num_FortyMHzIntolerant > 0) {
3645                 u8 iedata = 0;
3646
3647                 iedata |= BIT(2);/* 20 MHz BSS Width Request */
3648
3649                 pframe = rtw_set_ie(pframe, WLAN_EID_BSS_COEX_2040,  1, &iedata, &(pattrib->pktlen));
3650
3651         }
3652
3653
3654         /*  */
3655         memset(ICS, 0, sizeof(ICS));
3656         if (pmlmepriv->num_sta_no_ht > 0) {
3657                 int i;
3658
3659                 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3660
3661                 phead = get_list_head(queue);
3662                 plist = get_next(phead);
3663
3664                 while (1) {
3665                         int len;
3666                         u8 *p;
3667                         struct wlan_bssid_ex *pbss_network;
3668
3669                         if (phead == plist)
3670                                 break;
3671
3672                         pnetwork = container_of(plist, struct wlan_network, list);
3673
3674                         plist = get_next(plist);
3675
3676                         pbss_network = (struct wlan_bssid_ex *)&pnetwork->network;
3677
3678                         p = rtw_get_ie(pbss_network->ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, pbss_network->ie_length - _FIXED_IE_LENGTH_);
3679                         if (!p || len == 0) {/* non-HT */
3680
3681                                 if (pbss_network->configuration.ds_config <= 0)
3682                                         continue;
3683
3684                                 ICS[0][pbss_network->configuration.ds_config] = 1;
3685
3686                                 if (ICS[0][0] == 0)
3687                                         ICS[0][0] = 1;
3688                         }
3689
3690                 }
3691
3692                 spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
3693
3694
3695                 for (i = 0; i < 8; i++) {
3696                         if (ICS[i][0] == 1) {
3697                                 int j, k = 0;
3698
3699                                 InfoContent[k] = i;
3700                                 /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
3701                                 k++;
3702
3703                                 for (j = 1; j <= 14; j++) {
3704                                         if (ICS[i][j] == 1) {
3705                                                 if (k < 16) {
3706                                                         InfoContent[k] = j; /* channel number */
3707                                                         /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
3708                                                         k++;
3709                                                 }
3710                                         }
3711                                 }
3712
3713                                 pframe = rtw_set_ie(pframe, WLAN_EID_BSS_INTOLERANT_CHL_REPORT, k, InfoContent, &(pattrib->pktlen));
3714
3715                         }
3716
3717                 }
3718
3719
3720         }
3721
3722
3723         pattrib->last_txcmdsz = pattrib->pktlen;
3724
3725         dump_mgntframe(padapter, pmgntframe);
3726 }
3727
3728 unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr)
3729 {
3730         struct sta_priv *pstapriv = &padapter->stapriv;
3731         struct sta_info *psta = NULL;
3732         /* struct recv_reorder_ctrl *preorder_ctrl; */
3733         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3734         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3735         u16 tid;
3736
3737         if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
3738                 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
3739                         return _SUCCESS;
3740
3741         psta = rtw_get_stainfo(pstapriv, addr);
3742         if (!psta)
3743                 return _SUCCESS;
3744
3745         if (initiator == 0) {/*  recipient */
3746                 for (tid = 0; tid < MAXTID; tid++) {
3747                         if (psta->recvreorder_ctrl[tid].enable) {
3748                                 issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
3749                                 psta->recvreorder_ctrl[tid].enable = false;
3750                                 psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
3751                         }
3752                 }
3753         } else if (initiator == 1) {/*  originator */
3754                 for (tid = 0; tid < MAXTID; tid++) {
3755                         if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
3756                                 issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
3757                                 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
3758                                 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
3759
3760                         }
3761                 }
3762         }
3763
3764         return _SUCCESS;
3765
3766 }
3767
3768 unsigned int send_beacon(struct adapter *padapter)
3769 {
3770         u8 bxmitok = false;
3771         int     issue = 0;
3772         int poll = 0;
3773
3774         rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
3775         rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
3776         do {
3777                 issue_beacon(padapter, 100);
3778                 issue++;
3779                 do {
3780                         cond_resched();
3781                         rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
3782                         poll++;
3783                 } while ((poll%10) != 0 && false == bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
3784
3785         } while (false == bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
3786
3787         if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
3788                 return _FAIL;
3789
3790         if (!bxmitok)
3791                 return _FAIL;
3792         else
3793                 return _SUCCESS;
3794 }
3795
3796 /****************************************************************************
3797
3798 Following are some utility functions for WiFi MLME
3799
3800 *****************************************************************************/
3801
3802 void site_survey(struct adapter *padapter)
3803 {
3804         unsigned char   survey_channel = 0, val8;
3805         enum rt_scan_type       ScanType = SCAN_PASSIVE;
3806         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3807         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3808         u32 initialgain = 0;
3809         u32 channel_scan_time_ms = 0;
3810
3811         {
3812                 struct rtw_ieee80211_channel *ch;
3813
3814                 if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
3815                         ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
3816                         survey_channel = ch->hw_value;
3817                         ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
3818                 }
3819         }
3820
3821         if (survey_channel != 0) {
3822                 /* PAUSE 4-AC Queue when site_survey */
3823                 /* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
3824                 /* val8 |= 0x0f; */
3825                 /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
3826                 if (pmlmeext->sitesurvey_res.channel_idx == 0) {
3827 #ifdef DBG_FIXED_CHAN
3828                         if (pmlmeext->fixed_chan != 0xff)
3829                                 set_channel_bwmode(padapter, pmlmeext->fixed_chan, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3830                         else
3831 #endif
3832                                 set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3833                 } else {
3834 #ifdef DBG_FIXED_CHAN
3835                         if (pmlmeext->fixed_chan != 0xff)
3836                                 SelectChannel(padapter, pmlmeext->fixed_chan);
3837                         else
3838 #endif
3839                                 SelectChannel(padapter, survey_channel);
3840                 }
3841
3842                 if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */
3843                         {
3844                                 int i;
3845
3846                                 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
3847                                         if (pmlmeext->sitesurvey_res.ssid[i].ssid_length) {
3848                                                 /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
3849                                                 if (padapter->registrypriv.wifi_spec)
3850                                                         issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
3851                                                 else
3852                                                         issue_probereq_ex(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL, 0, 0, 0, 0);
3853                                                 issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
3854                                         }
3855                                 }
3856
3857                                 if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
3858                                         /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
3859                                         if (padapter->registrypriv.wifi_spec)
3860                                                 issue_probereq(padapter, NULL, NULL);
3861                                         else
3862                                                 issue_probereq_ex(padapter, NULL, NULL, 0, 0, 0, 0);
3863                                         issue_probereq(padapter, NULL, NULL);
3864                                 }
3865                         }
3866                 }
3867
3868                 channel_scan_time_ms = pmlmeext->chan_scan_time;
3869
3870                 set_survey_timer(pmlmeext, channel_scan_time_ms);
3871         } else {
3872
3873                 /*      channel number is 0 or this channel is not valid. */
3874
3875                 {
3876                         pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
3877
3878                         /* switch back to the original channel */
3879                         /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
3880
3881                         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
3882
3883                         /* flush 4-AC Queue after site_survey */
3884                         /* val8 = 0; */
3885                         /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
3886
3887                         /* config MSR */
3888                         Set_MSR(padapter, (pmlmeinfo->state & 0x3));
3889
3890                         initialgain = 0xff; /* restore RX GAIN */
3891                         rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
3892                         /* turn on dynamic functions */
3893                         Restore_DM_Func_Flag(padapter);
3894                         /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
3895
3896                         if (is_client_associated_to_ap(padapter))
3897                                 issue_nulldata(padapter, NULL, 0, 3, 500);
3898
3899                         val8 = 0; /* survey done */
3900                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3901
3902                         report_surveydone_event(padapter);
3903
3904                         pmlmeext->chan_scan_time = SURVEY_TO;
3905                         pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
3906
3907                         issue_action_BSSCoexistPacket(padapter);
3908                         issue_action_BSSCoexistPacket(padapter);
3909                         issue_action_BSSCoexistPacket(padapter);
3910                 }
3911         }
3912
3913         return;
3914
3915 }
3916
3917 /* collect bss info from Beacon and Probe request/response frames. */
3918 u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, struct wlan_bssid_ex *bssid)
3919 {
3920         int     i;
3921         u32 len;
3922         u8 *p;
3923         u16 val16, subtype;
3924         u8 *pframe = precv_frame->u.hdr.rx_data;
3925         u32 packet_len = precv_frame->u.hdr.len;
3926         u8 ie_offset;
3927         struct registry_priv *pregistrypriv = &padapter->registrypriv;
3928         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3929         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3930         __le32 le32_tmp;
3931
3932         len = packet_len - sizeof(struct ieee80211_hdr_3addr);
3933
3934         if (len > MAX_IE_SZ)
3935                 return _FAIL;
3936
3937         memset(bssid, 0, sizeof(struct wlan_bssid_ex));
3938
3939         subtype = GetFrameSubType(pframe);
3940
3941         if (subtype == WIFI_BEACON) {
3942                 bssid->reserved[0] = 1;
3943                 ie_offset = _BEACON_IE_OFFSET_;
3944         } else {
3945                 /*  FIXME : more type */
3946                 if (subtype == WIFI_PROBERSP) {
3947                         ie_offset = _PROBERSP_IE_OFFSET_;
3948                         bssid->reserved[0] = 3;
3949                 } else if (subtype == WIFI_PROBEREQ) {
3950                         ie_offset = _PROBEREQ_IE_OFFSET_;
3951                         bssid->reserved[0] = 2;
3952                 } else {
3953                         bssid->reserved[0] = 0;
3954                         ie_offset = _FIXED_IE_LENGTH_;
3955                 }
3956         }
3957
3958         bssid->length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
3959
3960         /* below is to copy the information element */
3961         bssid->ie_length = len;
3962         memcpy(bssid->ies, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->ie_length);
3963
3964         /* get the signal strength */
3965         bssid->rssi = precv_frame->u.hdr.attrib.phy_info.RecvSignalPower; /*  in dBM.raw data */
3966         bssid->phy_info.signal_quality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;/* in percentage */
3967         bssid->phy_info.signal_strength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;/* in percentage */
3968
3969         /*  checking SSID */
3970         p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_SSID, &len, bssid->ie_length - ie_offset);
3971         if (!p)
3972                 return _FAIL;
3973
3974         if (*(p + 1)) {
3975                 if (len > NDIS_802_11_LENGTH_SSID)
3976                         return _FAIL;
3977
3978                 memcpy(bssid->ssid.ssid, (p + 2), *(p + 1));
3979                 bssid->ssid.ssid_length = *(p + 1);
3980         } else
3981                 bssid->ssid.ssid_length = 0;
3982
3983         memset(bssid->supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
3984
3985         /* checking rate info... */
3986         i = 0;
3987         p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_SUPP_RATES, &len, bssid->ie_length - ie_offset);
3988         if (p) {
3989                 if (len > NDIS_802_11_LENGTH_RATES_EX)
3990                         return _FAIL;
3991
3992                 memcpy(bssid->supported_rates, (p + 2), len);
3993                 i = len;
3994         }
3995
3996         p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_EXT_SUPP_RATES, &len, bssid->ie_length - ie_offset);
3997         if (p) {
3998                 if (len > (NDIS_802_11_LENGTH_RATES_EX-i))
3999                         return _FAIL;
4000
4001                 memcpy(bssid->supported_rates + i, (p + 2), len);
4002         }
4003
4004         bssid->network_type_in_use = Ndis802_11OFDM24;
4005
4006         if (bssid->ie_length < 12)
4007                 return _FAIL;
4008
4009         /*  Checking for ds_config */
4010         p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_DS_PARAMS, &len, bssid->ie_length - ie_offset);
4011
4012         bssid->configuration.ds_config = 0;
4013         bssid->configuration.length = 0;
4014
4015         if (p) {
4016                 bssid->configuration.ds_config = *(p + 2);
4017         } else {
4018                 /*  In 5G, some ap do not have DSSET IE */
4019                 /*  checking HT info for channel */
4020                 p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_HT_OPERATION, &len, bssid->ie_length - ie_offset);
4021                 if (p) {
4022                         struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
4023
4024                         bssid->configuration.ds_config = HT_info->primary_channel;
4025                 } else { /*  use current channel */
4026                         bssid->configuration.ds_config = rtw_get_oper_ch(padapter);
4027                 }
4028         }
4029
4030         memcpy(&le32_tmp, rtw_get_beacon_interval_from_ie(bssid->ies), 2);
4031         bssid->configuration.beacon_period = le32_to_cpu(le32_tmp);
4032
4033         val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
4034
4035         if (val16 & BIT(0)) {
4036                 bssid->infrastructure_mode = Ndis802_11Infrastructure;
4037                 memcpy(bssid->mac_address, GetAddr2Ptr(pframe), ETH_ALEN);
4038         } else {
4039                 bssid->infrastructure_mode = Ndis802_11IBSS;
4040                 memcpy(bssid->mac_address, GetAddr3Ptr(pframe), ETH_ALEN);
4041         }
4042
4043         if (val16 & BIT(4))
4044                 bssid->privacy = 1;
4045         else
4046                 bssid->privacy = 0;
4047
4048         bssid->configuration.atim_window = 0;
4049
4050         /* 20/40 BSS Coexistence check */
4051         if ((pregistrypriv->wifi_spec == 1) && (false == pmlmeinfo->bwmode_updated)) {
4052                 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4053
4054                 p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_HT_CAPABILITY, &len, bssid->ie_length - ie_offset);
4055                 if (p && len > 0) {
4056                         struct HT_caps_element  *pHT_caps;
4057
4058                         pHT_caps = (struct HT_caps_element      *)(p + 2);
4059
4060                         if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & BIT(14))
4061                                 pmlmepriv->num_FortyMHzIntolerant++;
4062                 } else
4063                         pmlmepriv->num_sta_no_ht++;
4064         }
4065
4066         /*  mark bss info receiving from nearby channel as signal_quality 101 */
4067         if (bssid->configuration.ds_config != rtw_get_oper_ch(padapter))
4068                 bssid->phy_info.signal_quality = 101;
4069
4070         return _SUCCESS;
4071 }
4072
4073 void start_create_ibss(struct adapter *padapter)
4074 {
4075         unsigned short  caps;
4076         u8 val8;
4077         u8 join_type;
4078         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4079         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4080         struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
4081
4082         pmlmeext->cur_channel = (u8)pnetwork->configuration.ds_config;
4083         pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
4084
4085         /* update wireless mode */
4086         update_wireless_mode(padapter);
4087
4088         /* update capability */
4089         caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
4090         update_capinfo(padapter, caps);
4091         if (caps&WLAN_CAPABILITY_IBSS) {/* adhoc master */
4092                 val8 = 0xcf;
4093                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
4094
4095                 rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
4096
4097                 /* switch channel */
4098                 /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
4099                 set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
4100
4101                 beacon_timing_control(padapter);
4102
4103                 /* set msr to WIFI_FW_ADHOC_STATE */
4104                 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
4105                 Set_MSR(padapter, (pmlmeinfo->state & 0x3));
4106
4107                 /* issue beacon */
4108                 if (send_beacon(padapter) == _FAIL) {
4109                         report_join_res(padapter, -1);
4110                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
4111                 } else {
4112                         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.mac_address);
4113                         join_type = 0;
4114                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4115
4116                         report_join_res(padapter, 1);
4117                         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
4118                         rtw_indicate_connect(padapter);
4119                 }
4120         } else {
4121                 return;
4122         }
4123         /* update bc/mc sta_info */
4124         update_bmc_sta(padapter);
4125
4126 }
4127
4128 void start_clnt_join(struct adapter *padapter)
4129 {
4130         unsigned short  caps;
4131         u8 val8;
4132         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4133         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4134         struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
4135         int beacon_timeout;
4136
4137         /* update wireless mode */
4138         update_wireless_mode(padapter);
4139
4140         /* update capability */
4141         caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
4142         update_capinfo(padapter, caps);
4143         if (caps&WLAN_CAPABILITY_ESS) {
4144                 Set_MSR(padapter, WIFI_FW_STATION_STATE);
4145
4146                 val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
4147
4148                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
4149
4150                 /*  Because of AP's not receiving deauth before */
4151                 /*  AP may: 1)not response auth or 2)deauth us after link is complete */
4152                 /*  issue deauth before issuing auth to deal with the situation */
4153
4154                 /*      Commented by Albert 2012/07/21 */
4155                 /*      For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
4156                 {
4157                                 /* To avoid connecting to AP fail during resume process, change retry count from 5 to 1 */
4158                                 issue_deauth_ex(padapter, pnetwork->mac_address, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
4159                 }
4160
4161                 /* here wait for receiving the beacon to start auth */
4162                 /* and enable a timer */
4163                 beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
4164                 set_link_timer(pmlmeext, beacon_timeout);
4165                 _set_timer(&padapter->mlmepriv.assoc_timer,
4166                         (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout);
4167
4168                 pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
4169         } else if (caps&WLAN_CAPABILITY_IBSS) { /* adhoc client */
4170                 Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
4171
4172                 val8 = 0xcf;
4173                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
4174
4175                 beacon_timing_control(padapter);
4176
4177                 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
4178
4179                 report_join_res(padapter, 1);
4180         } else {
4181                 return;
4182         }
4183
4184 }
4185
4186 void start_clnt_auth(struct adapter *padapter)
4187 {
4188         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4189         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4190
4191         del_timer_sync(&pmlmeext->link_timer);
4192
4193         pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
4194         pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
4195
4196         pmlmeinfo->auth_seq = 1;
4197         pmlmeinfo->reauth_count = 0;
4198         pmlmeinfo->reassoc_count = 0;
4199         pmlmeinfo->link_count = 0;
4200         pmlmeext->retry = 0;
4201
4202
4203         netdev_dbg(padapter->pnetdev, "start auth\n");
4204         issue_auth(padapter, NULL, 0);
4205
4206         set_link_timer(pmlmeext, REAUTH_TO);
4207
4208 }
4209
4210
4211 void start_clnt_assoc(struct adapter *padapter)
4212 {
4213         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4214         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4215
4216         del_timer_sync(&pmlmeext->link_timer);
4217
4218         pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
4219         pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
4220
4221         issue_assocreq(padapter);
4222
4223         set_link_timer(pmlmeext, REASSOC_TO);
4224 }
4225
4226 unsigned int receive_disconnect(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
4227 {
4228         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4229         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4230
4231         /* check A3 */
4232         if (!(!memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
4233                 return _SUCCESS;
4234
4235         if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
4236                 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
4237                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
4238                         report_del_sta_event(padapter, MacAddr, reason);
4239
4240                 } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
4241                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
4242                         report_join_res(padapter, -2);
4243                 }
4244         }
4245
4246         return _SUCCESS;
4247 }
4248
4249 static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid)
4250 {
4251         struct registry_priv *pregistrypriv;
4252         struct mlme_ext_priv *pmlmeext;
4253         struct rt_channel_info *chplan_new;
4254         u8 channel;
4255         u8 i;
4256
4257
4258         pregistrypriv = &padapter->registrypriv;
4259         pmlmeext = &padapter->mlmeextpriv;
4260
4261         /*  Adjust channel plan by AP Country IE */
4262         if (pregistrypriv->enable80211d &&
4263                 (!pmlmeext->update_channel_plan_by_ap_done)) {
4264                 u8 *ie, *p;
4265                 u32 len;
4266                 struct rt_channel_plan chplan_ap;
4267                 struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
4268                 u8 country[4];
4269                 u8 fcn; /*  first channel number */
4270                 u8 noc; /*  number of channel */
4271                 u8 j, k;
4272
4273                 ie = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_COUNTRY, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
4274                 if (!ie)
4275                         return;
4276                 if (len < 6)
4277                         return;
4278
4279                 ie += 2;
4280                 p = ie;
4281                 ie += len;
4282
4283                 memset(country, 0, 4);
4284                 memcpy(country, p, 3);
4285                 p += 3;
4286
4287                 i = 0;
4288                 while ((ie - p) >= 3) {
4289                         fcn = *(p++);
4290                         noc = *(p++);
4291                         p++;
4292
4293                         for (j = 0; j < noc; j++) {
4294                                 if (fcn <= 14)
4295                                         channel = fcn + j; /*  2.4 GHz */
4296                                 else
4297                                         channel = fcn + j*4; /*  5 GHz */
4298
4299                                 chplan_ap.Channel[i++] = channel;
4300                         }
4301                 }
4302                 chplan_ap.Len = i;
4303
4304                 memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
4305
4306                 memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
4307                 chplan_new = pmlmeext->channel_set;
4308
4309                 i = j = k = 0;
4310                 if (pregistrypriv->wireless_mode & WIRELESS_11G) {
4311                         do {
4312                                 if ((i == MAX_CHANNEL_NUM) ||
4313                                         (chplan_sta[i].ChannelNum == 0) ||
4314                                         (chplan_sta[i].ChannelNum > 14))
4315                                         break;
4316
4317                                 if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
4318                                         break;
4319
4320                                 if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
4321                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4322                                         chplan_new[k].ScanType = SCAN_ACTIVE;
4323                                         i++;
4324                                         j++;
4325                                         k++;
4326                                 } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
4327                                         chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4328 /*                                      chplan_new[k].ScanType = chplan_sta[i].ScanType; */
4329                                         chplan_new[k].ScanType = SCAN_PASSIVE;
4330                                         i++;
4331                                         k++;
4332                                 } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
4333                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4334                                         chplan_new[k].ScanType = SCAN_ACTIVE;
4335                                         j++;
4336                                         k++;
4337                                 }
4338                         } while (1);
4339
4340                         /*  change AP not support channel to Passive scan */
4341                         while ((i < MAX_CHANNEL_NUM) &&
4342                                 (chplan_sta[i].ChannelNum != 0) &&
4343                                 (chplan_sta[i].ChannelNum <= 14)) {
4344
4345                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4346 /*                              chplan_new[k].ScanType = chplan_sta[i].ScanType; */
4347                                 chplan_new[k].ScanType = SCAN_PASSIVE;
4348                                 i++;
4349                                 k++;
4350                         }
4351
4352                         /*  add channel AP supported */
4353                         while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
4354                                 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4355                                 chplan_new[k].ScanType = SCAN_ACTIVE;
4356                                 j++;
4357                                 k++;
4358                         }
4359                 } else {
4360                         /*  keep original STA 2.4G channel plan */
4361                         while ((i < MAX_CHANNEL_NUM) &&
4362                                 (chplan_sta[i].ChannelNum != 0) &&
4363                                 (chplan_sta[i].ChannelNum <= 14)) {
4364                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4365                                 chplan_new[k].ScanType = chplan_sta[i].ScanType;
4366                                 i++;
4367                                 k++;
4368                         }
4369
4370                         /*  skip AP 2.4G channel plan */
4371                         while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))
4372                                 j++;
4373                 }
4374
4375                 pmlmeext->update_channel_plan_by_ap_done = 1;
4376         }
4377
4378         /*  If channel is used by AP, set channel scan type to active */
4379         channel = bssid->configuration.ds_config;
4380         chplan_new = pmlmeext->channel_set;
4381         i = 0;
4382         while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
4383                 if (chplan_new[i].ChannelNum == channel) {
4384                         if (chplan_new[i].ScanType == SCAN_PASSIVE)
4385                                 chplan_new[i].ScanType = SCAN_ACTIVE;
4386                         break;
4387                 }
4388                 i++;
4389         }
4390 }
4391
4392 /****************************************************************************
4393
4394 Following are the functions to report events
4395
4396 *****************************************************************************/
4397
4398 void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame)
4399 {
4400         struct cmd_obj *pcmd_obj;
4401         u8 *pevtcmd;
4402         u32 cmdsz;
4403         struct survey_event     *psurvey_evt;
4404         struct C2HEvent_Header *pc2h_evt_hdr;
4405         struct mlme_ext_priv *pmlmeext;
4406         struct cmd_priv *pcmdpriv;
4407         /* u8 *pframe = precv_frame->u.hdr.rx_data; */
4408         /* uint len = precv_frame->u.hdr.len; */
4409
4410         if (!padapter)
4411                 return;
4412
4413         pmlmeext = &padapter->mlmeextpriv;
4414         pcmdpriv = &padapter->cmdpriv;
4415
4416         pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
4417         if (!pcmd_obj)
4418                 return;
4419
4420         cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
4421         pevtcmd = rtw_zmalloc(cmdsz);
4422         if (!pevtcmd) {
4423                 kfree(pcmd_obj);
4424                 return;
4425         }
4426
4427         INIT_LIST_HEAD(&pcmd_obj->list);
4428
4429         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4430         pcmd_obj->cmdsz = cmdsz;
4431         pcmd_obj->parmbuf = pevtcmd;
4432
4433         pcmd_obj->rsp = NULL;
4434         pcmd_obj->rspsz  = 0;
4435
4436         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4437         pc2h_evt_hdr->len = sizeof(struct survey_event);
4438         pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
4439         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4440
4441         psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4442
4443         if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) {
4444                 kfree(pcmd_obj);
4445                 kfree(pevtcmd);
4446                 return;
4447         }
4448
4449         process_80211d(padapter, &psurvey_evt->bss);
4450
4451         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4452
4453         pmlmeext->sitesurvey_res.bss_cnt++;
4454
4455         return;
4456
4457 }
4458
4459 void report_surveydone_event(struct adapter *padapter)
4460 {
4461         struct cmd_obj *pcmd_obj;
4462         u8 *pevtcmd;
4463         u32 cmdsz;
4464         struct surveydone_event *psurveydone_evt;
4465         struct C2HEvent_Header  *pc2h_evt_hdr;
4466         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4467         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4468
4469         pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
4470         if (!pcmd_obj)
4471                 return;
4472
4473         cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
4474         pevtcmd = rtw_zmalloc(cmdsz);
4475         if (!pevtcmd) {
4476                 kfree(pcmd_obj);
4477                 return;
4478         }
4479
4480         INIT_LIST_HEAD(&pcmd_obj->list);
4481
4482         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4483         pcmd_obj->cmdsz = cmdsz;
4484         pcmd_obj->parmbuf = pevtcmd;
4485
4486         pcmd_obj->rsp = NULL;
4487         pcmd_obj->rspsz  = 0;
4488
4489         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4490         pc2h_evt_hdr->len = sizeof(struct surveydone_event);
4491         pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
4492         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4493
4494         psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4495         psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
4496
4497         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4498
4499         return;
4500
4501 }
4502
4503 void report_join_res(struct adapter *padapter, int res)
4504 {
4505         struct cmd_obj *pcmd_obj;
4506         u8 *pevtcmd;
4507         u32 cmdsz;
4508         struct joinbss_event            *pjoinbss_evt;
4509         struct C2HEvent_Header  *pc2h_evt_hdr;
4510         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4511         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4512         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4513
4514         pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
4515         if (!pcmd_obj)
4516                 return;
4517
4518         cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
4519         pevtcmd = rtw_zmalloc(cmdsz);
4520         if (!pevtcmd) {
4521                 kfree(pcmd_obj);
4522                 return;
4523         }
4524
4525         INIT_LIST_HEAD(&pcmd_obj->list);
4526
4527         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4528         pcmd_obj->cmdsz = cmdsz;
4529         pcmd_obj->parmbuf = pevtcmd;
4530
4531         pcmd_obj->rsp = NULL;
4532         pcmd_obj->rspsz  = 0;
4533
4534         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4535         pc2h_evt_hdr->len = sizeof(struct joinbss_event);
4536         pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
4537         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4538
4539         pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4540         memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
4541         pjoinbss_evt->network.join_res  = pjoinbss_evt->network.aid = res;
4542
4543
4544         rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
4545
4546
4547         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4548
4549         return;
4550
4551 }
4552
4553 void report_wmm_edca_update(struct adapter *padapter)
4554 {
4555         struct cmd_obj *pcmd_obj;
4556         u8 *pevtcmd;
4557         u32 cmdsz;
4558         struct wmm_event                *pwmm_event;
4559         struct C2HEvent_Header  *pc2h_evt_hdr;
4560         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4561         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4562
4563         pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
4564         if (!pcmd_obj)
4565                 return;
4566
4567         cmdsz = (sizeof(struct wmm_event) + sizeof(struct C2HEvent_Header));
4568         pevtcmd = rtw_zmalloc(cmdsz);
4569         if (!pevtcmd) {
4570                 kfree(pcmd_obj);
4571                 return;
4572         }
4573
4574         INIT_LIST_HEAD(&pcmd_obj->list);
4575
4576         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4577         pcmd_obj->cmdsz = cmdsz;
4578         pcmd_obj->parmbuf = pevtcmd;
4579
4580         pcmd_obj->rsp = NULL;
4581         pcmd_obj->rspsz  = 0;
4582
4583         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4584         pc2h_evt_hdr->len = sizeof(struct wmm_event);
4585         pc2h_evt_hdr->ID = GEN_EVT_CODE(_WMM);
4586         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4587
4588         pwmm_event = (struct wmm_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4589         pwmm_event->wmm = 0;
4590
4591         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4592
4593         return;
4594
4595 }
4596
4597 void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
4598 {
4599         struct cmd_obj *pcmd_obj;
4600         u8 *pevtcmd;
4601         u32 cmdsz;
4602         struct sta_info *psta;
4603         int     mac_id;
4604         struct stadel_event                     *pdel_sta_evt;
4605         struct C2HEvent_Header  *pc2h_evt_hdr;
4606         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4607         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4608
4609         pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
4610         if (!pcmd_obj)
4611                 return;
4612
4613         cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
4614         pevtcmd = rtw_zmalloc(cmdsz);
4615         if (!pevtcmd) {
4616                 kfree(pcmd_obj);
4617                 return;
4618         }
4619
4620         INIT_LIST_HEAD(&pcmd_obj->list);
4621
4622         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4623         pcmd_obj->cmdsz = cmdsz;
4624         pcmd_obj->parmbuf = pevtcmd;
4625
4626         pcmd_obj->rsp = NULL;
4627         pcmd_obj->rspsz  = 0;
4628
4629         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4630         pc2h_evt_hdr->len = sizeof(struct stadel_event);
4631         pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
4632         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4633
4634         pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4635         memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN);
4636         memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);
4637
4638
4639         psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
4640         if (psta)
4641                 mac_id = (int)psta->mac_id;
4642         else
4643                 mac_id = (-1);
4644
4645         pdel_sta_evt->mac_id = mac_id;
4646
4647         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4648 }
4649
4650 void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx)
4651 {
4652         struct cmd_obj *pcmd_obj;
4653         u8 *pevtcmd;
4654         u32 cmdsz;
4655         struct stassoc_event            *padd_sta_evt;
4656         struct C2HEvent_Header  *pc2h_evt_hdr;
4657         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4658         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4659
4660         pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
4661         if (!pcmd_obj)
4662                 return;
4663
4664         cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
4665         pevtcmd = rtw_zmalloc(cmdsz);
4666         if (!pevtcmd) {
4667                 kfree(pcmd_obj);
4668                 return;
4669         }
4670
4671         INIT_LIST_HEAD(&pcmd_obj->list);
4672
4673         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4674         pcmd_obj->cmdsz = cmdsz;
4675         pcmd_obj->parmbuf = pevtcmd;
4676
4677         pcmd_obj->rsp = NULL;
4678         pcmd_obj->rspsz  = 0;
4679
4680         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4681         pc2h_evt_hdr->len = sizeof(struct stassoc_event);
4682         pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
4683         pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4684
4685         padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4686         memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN);
4687         padd_sta_evt->cam_id = cam_idx;
4688
4689         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4690 }
4691
4692 /****************************************************************************
4693
4694 Following are the event callback functions
4695
4696 *****************************************************************************/
4697
4698 /* for sta/adhoc mode */
4699 void update_sta_info(struct adapter *padapter, struct sta_info *psta)
4700 {
4701         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4702         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4703         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4704
4705         /* ERP */
4706         VCS_update(padapter, psta);
4707
4708         /* HT */
4709         if (pmlmepriv->htpriv.ht_option) {
4710                 psta->htpriv.ht_option = true;
4711
4712                 psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
4713
4714                 psta->htpriv.rx_ampdu_min_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para&IEEE80211_HT_CAP_AMPDU_DENSITY)>>2;
4715
4716                 if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_20))
4717                         psta->htpriv.sgi_20m = true;
4718
4719                 if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_40))
4720                         psta->htpriv.sgi_40m = true;
4721
4722                 psta->qos_option = true;
4723
4724                 psta->htpriv.ldpc_cap = pmlmepriv->htpriv.ldpc_cap;
4725                 psta->htpriv.stbc_cap = pmlmepriv->htpriv.stbc_cap;
4726                 psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap;
4727
4728                 memcpy(&psta->htpriv.ht_cap, &pmlmeinfo->HT_caps, sizeof(struct ieee80211_ht_cap));
4729         } else {
4730                 psta->htpriv.ht_option = false;
4731
4732                 psta->htpriv.ampdu_enable = false;
4733
4734                 psta->htpriv.sgi_20m = false;
4735                 psta->htpriv.sgi_40m = false;
4736                 psta->qos_option = false;
4737
4738         }
4739
4740         psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
4741
4742         psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
4743         psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
4744
4745         psta->bw_mode = pmlmeext->cur_bwmode;
4746
4747         /* QoS */
4748         if (pmlmepriv->qospriv.qos_option)
4749                 psta->qos_option = true;
4750
4751         update_ldpc_stbc_cap(psta);
4752
4753         spin_lock_bh(&psta->lock);
4754         psta->state = _FW_LINKED;
4755         spin_unlock_bh(&psta->lock);
4756
4757 }
4758
4759 static void rtw_mlmeext_disconnect(struct adapter *padapter)
4760 {
4761         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
4762         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4763         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4764         struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
4765
4766         /* set_opmode_cmd(padapter, infra_client_with_mlme); */
4767
4768         /* For safety, prevent from keeping macid sleep.
4769          * If we can sure all power mode enter/leave are paired,
4770          * this check can be removed.
4771          * Lucas@20131113
4772          */
4773         /* wakeup macid after disconnect. */
4774         {
4775                 struct sta_info *psta;
4776
4777                 psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(pnetwork));
4778                 if (psta)
4779                         rtw_hal_macid_wakeup(padapter, psta->mac_id);
4780         }
4781
4782         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
4783         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
4784
4785         /* set MSR to no link state -> infra. mode */
4786         Set_MSR(padapter, _HW_STATE_STATION_);
4787
4788         pmlmeinfo->state = WIFI_FW_NULL_STATE;
4789
4790         /* switch to the 20M Hz mode after disconnect */
4791         pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
4792         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
4793
4794         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4795
4796         flush_all_cam_entry(padapter);
4797
4798         del_timer_sync(&pmlmeext->link_timer);
4799
4800         /* pmlmepriv->LinkDetectInfo.TrafficBusyState = false; */
4801         pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
4802         pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
4803
4804 }
4805
4806 void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
4807 {
4808         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4809         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4810         struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
4811         struct sta_priv         *pstapriv = &padapter->stapriv;
4812         u8 join_type;
4813         struct sta_info *psta;
4814
4815         if (join_res < 0) {
4816                 join_type = 1;
4817                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4818                 rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
4819
4820                 return;
4821         }
4822
4823         if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
4824                 /* update bc/mc sta_info */
4825                 update_bmc_sta(padapter);
4826
4827
4828         /* turn on dynamic functions */
4829         Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
4830
4831         /*  update IOT-related issue */
4832         update_IOT_info(padapter);
4833
4834         rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->supported_rates);
4835
4836         /* BCN interval */
4837         rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
4838
4839         /* update capability */
4840         update_capinfo(padapter, pmlmeinfo->capability);
4841
4842         /* WMM, Update EDCA param */
4843         WMMOnAssocRsp(padapter);
4844
4845         /* HT */
4846         HTOnAssocRsp(padapter);
4847
4848         /* Set cur_channel&cur_bwmode&cur_ch_offset */
4849         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4850
4851         psta = rtw_get_stainfo(pstapriv, cur_network->mac_address);
4852         if (psta) { /* only for infra. mode */
4853
4854                 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
4855
4856                 psta->wireless_mode = pmlmeext->cur_wireless_mode;
4857
4858                 /* set per sta rate after updating HT cap. */
4859                 set_sta_rate(padapter, psta);
4860
4861                 rtw_sta_media_status_rpt(padapter, psta, 1);
4862
4863                 /* wakeup macid after join bss successfully to ensure
4864                         the subsequent data frames can be sent out normally */
4865                 rtw_hal_macid_wakeup(padapter, psta->mac_id);
4866         }
4867
4868         join_type = 2;
4869         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4870
4871         if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
4872                 /*  correcting TSF */
4873                 correct_TSF(padapter, pmlmeext);
4874
4875                 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
4876         }
4877
4878         if (get_iface_type(padapter) == IFACE_PORT0)
4879                 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
4880 }
4881
4882 /* currently only adhoc mode will go here */
4883 void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta)
4884 {
4885         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
4886         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4887         u8 join_type;
4888
4889         if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
4890                 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { /* adhoc master or sta_count>1 */
4891
4892                         /* nothing to do */
4893                 } else { /* adhoc client */
4894                         /* update TSF Value */
4895                         /* update_TSF(pmlmeext, pframe, len); */
4896
4897                         /*  correcting TSF */
4898                         correct_TSF(padapter, pmlmeext);
4899
4900                         /* start beacon */
4901                         if (send_beacon(padapter) == _FAIL) {
4902                                 pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
4903
4904                                 pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
4905
4906                                 return;
4907                         }
4908
4909                         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
4910
4911                 }
4912
4913                 join_type = 2;
4914                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4915         }
4916
4917         pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
4918
4919         psta->bssratelen = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates);
4920         memcpy(psta->bssrateset, pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates, psta->bssratelen);
4921
4922         /* update adhoc sta_info */
4923         update_sta_info(padapter, psta);
4924
4925         rtw_hal_update_sta_rate_mask(padapter, psta);
4926
4927         /*  ToDo: HT for Ad-hoc */
4928         psta->wireless_mode = rtw_check_network_type(psta->bssrateset, psta->bssratelen, pmlmeext->cur_channel);
4929         psta->raid = networktype_to_raid_ex(padapter, psta);
4930
4931         /* rate radaptive */
4932         Update_RA_Entry(padapter, psta);
4933 }
4934
4935 void mlmeext_sta_del_event_callback(struct adapter *padapter)
4936 {
4937         if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter))
4938                 rtw_mlmeext_disconnect(padapter);
4939 }
4940
4941 /****************************************************************************
4942
4943 Following are the functions for the timer handlers
4944
4945 *****************************************************************************/
4946 void _linked_info_dump(struct adapter *padapter)
4947 {
4948         int i;
4949         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4950         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4951         int UndecoratedSmoothedPWDB;
4952         struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
4953
4954         if (padapter->bLinkInfoDump) {
4955
4956                 if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
4957                         rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);
4958
4959                 for (i = 0; i < NUM_STA; i++) {
4960                         if (pdvobj->macid[i]) {
4961                                 if (i != 1) /* skip bc/mc sta */
4962                                         /*   tx info ============ */
4963                                         rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, &i);
4964                         }
4965                 }
4966                 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_RX_INFO_DUMP, NULL);
4967         }
4968 }
4969
4970 static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta)
4971 {
4972         u8 ret = false;
4973
4974         if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta))
4975                 && sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta)
4976                 && sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta)
4977         ) {
4978                 ret = false;
4979         } else {
4980                 ret = true;
4981         }
4982
4983         sta_update_last_rx_pkts(psta);
4984
4985         return ret;
4986 }
4987
4988 void linked_status_chk(struct adapter *padapter)
4989 {
4990         u32 i;
4991         struct sta_info         *psta;
4992         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
4993         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4994         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4995         struct sta_priv         *pstapriv = &padapter->stapriv;
4996
4997
4998         if (is_client_associated_to_ap(padapter)) {
4999                 /* linked infrastructure client mode */
5000
5001                 int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
5002                 int rx_chk_limit;
5003                 int link_count_limit;
5004
5005                 #if defined(DBG_ROAMING_TEST)
5006                 rx_chk_limit = 1;
5007                 #else
5008                 rx_chk_limit = 8;
5009                 #endif
5010                 link_count_limit = 7; /*  16 sec */
5011
5012                 /*  Marked by Kurt 20130715 */
5013                 /*  For WiDi 3.5 and latered on, they don't ask WiDi sink to do roaming, so we could not check rx limit that strictly. */
5014                 /*  todo: To check why we under miracast session, rx_chk would be false */
5015                 psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.mac_address);
5016                 if (psta) {
5017                         if (chk_ap_is_alive(padapter, psta) == false)
5018                                 rx_chk = _FAIL;
5019
5020                         if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
5021                                 tx_chk = _FAIL;
5022
5023                         {
5024                                 if (rx_chk != _SUCCESS) {
5025                                         if (pmlmeext->retry == 0) {
5026                                                 issue_probereq_ex(padapter, &pmlmeinfo->network.ssid, pmlmeinfo->network.mac_address, 0, 0, 0, 0);
5027                                                 issue_probereq_ex(padapter, &pmlmeinfo->network.ssid, pmlmeinfo->network.mac_address, 0, 0, 0, 0);
5028                                                 issue_probereq_ex(padapter, &pmlmeinfo->network.ssid, pmlmeinfo->network.mac_address, 0, 0, 0, 0);
5029                                         }
5030                                 }
5031
5032                                 if (tx_chk != _SUCCESS &&
5033                                     pmlmeinfo->link_count++ == link_count_limit)
5034                                         tx_chk = issue_nulldata_in_interrupt(padapter, NULL);
5035                         }
5036
5037                         if (rx_chk == _FAIL) {
5038                                 pmlmeext->retry++;
5039                                 if (pmlmeext->retry > rx_chk_limit) {
5040                                         netdev_dbg(padapter->pnetdev,
5041                                                    FUNC_ADPT_FMT " disconnect or roaming\n",
5042                                                    FUNC_ADPT_ARG(padapter));
5043                                         receive_disconnect(padapter, pmlmeinfo->network.mac_address
5044                                                 , WLAN_REASON_EXPIRATION_CHK);
5045                                         return;
5046                                 }
5047                         } else {
5048                                 pmlmeext->retry = 0;
5049                         }
5050
5051                         if (tx_chk == _FAIL) {
5052                                 pmlmeinfo->link_count %= (link_count_limit+1);
5053                         } else {
5054                                 pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
5055                                 pmlmeinfo->link_count = 0;
5056                         }
5057
5058                 } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.mac_address)) != NULL) */
5059         } else if (is_client_associated_to_ibss(padapter)) {
5060                 /* linked IBSS mode */
5061                 /* for each assoc list entry to check the rx pkt counter */
5062                 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
5063                         if (pmlmeinfo->FW_sta_info[i].status == 1) {
5064                                 psta = pmlmeinfo->FW_sta_info[i].psta;
5065
5066                                 if (psta == NULL)
5067                                         continue;
5068
5069                                 if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) {
5070
5071                                         if (pmlmeinfo->FW_sta_info[i].retry < 3) {
5072                                                 pmlmeinfo->FW_sta_info[i].retry++;
5073                                         } else {
5074                                                 pmlmeinfo->FW_sta_info[i].retry = 0;
5075                                                 pmlmeinfo->FW_sta_info[i].status = 0;
5076                                                 report_del_sta_event(padapter, psta->hwaddr
5077                                                         , 65535/*  indicate disconnect caused by no rx */
5078                                                 );
5079                                         }
5080                                 } else {
5081                                         pmlmeinfo->FW_sta_info[i].retry = 0;
5082                                         pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
5083                                 }
5084                         }
5085                 }
5086
5087                 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
5088
5089         }
5090
5091 }
5092
5093 void survey_timer_hdl(struct timer_list *t)
5094 {
5095         struct adapter *padapter =
5096                 from_timer(padapter, t, mlmeextpriv.survey_timer);
5097         struct cmd_obj  *ph2c;
5098         struct sitesurvey_parm  *psurveyPara;
5099         struct cmd_priv                                 *pcmdpriv = &padapter->cmdpriv;
5100         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5101
5102         /* issue rtw_sitesurvey_cmd */
5103         if (pmlmeext->sitesurvey_res.state > SCAN_START) {
5104                 if (pmlmeext->sitesurvey_res.state ==  SCAN_PROCESS)
5105                         pmlmeext->sitesurvey_res.channel_idx++;
5106
5107                 if (pmlmeext->scan_abort) {
5108                         pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
5109
5110                         pmlmeext->scan_abort = false;/* reset */
5111                 }
5112
5113                 ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
5114                 if (!ph2c)
5115                         return;
5116
5117                 psurveyPara = rtw_zmalloc(sizeof(struct sitesurvey_parm));
5118                 if (!psurveyPara) {
5119                         kfree(ph2c);
5120                         return;
5121                 }
5122
5123                 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
5124                 rtw_enqueue_cmd(pcmdpriv, ph2c);
5125         }
5126 }
5127
5128 void link_timer_hdl(struct timer_list *t)
5129 {
5130         struct adapter *padapter =
5131                 from_timer(padapter, t, mlmeextpriv.link_timer);
5132         /* static unsigned int          rx_pkt = 0; */
5133         /* static u64                           tx_cnt = 0; */
5134         /* struct xmit_priv     *pxmitpriv = &(padapter->xmitpriv); */
5135         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5136         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5137         /* struct sta_priv      *pstapriv = &padapter->stapriv; */
5138
5139
5140         if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
5141                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
5142                 report_join_res(padapter, -3);
5143         } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
5144                 /* re-auth timer */
5145                 if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
5146                         pmlmeinfo->state = 0;
5147                         report_join_res(padapter, -1);
5148                         return;
5149                 }
5150
5151                 pmlmeinfo->auth_seq = 1;
5152                 issue_auth(padapter, NULL, 0);
5153                 set_link_timer(pmlmeext, REAUTH_TO);
5154         } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
5155                 /* re-assoc timer */
5156                 if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
5157                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
5158                         report_join_res(padapter, -2);
5159                         return;
5160                 }
5161
5162                 issue_assocreq(padapter);
5163                 set_link_timer(pmlmeext, REASSOC_TO);
5164         }
5165 }
5166
5167 void addba_timer_hdl(struct timer_list *t)
5168 {
5169         struct sta_info *psta = from_timer(psta, t, addba_retry_timer);
5170         struct ht_priv *phtpriv;
5171
5172         if (!psta)
5173                 return;
5174
5175         phtpriv = &psta->htpriv;
5176
5177         if (phtpriv->ht_option && phtpriv->ampdu_enable) {
5178                 if (phtpriv->candidate_tid_bitmap)
5179                         phtpriv->candidate_tid_bitmap = 0x0;
5180
5181         }
5182 }
5183
5184 void sa_query_timer_hdl(struct timer_list *t)
5185 {
5186         struct adapter *padapter =
5187                 from_timer(padapter, t, mlmeextpriv.sa_query_timer);
5188         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5189         /* disconnect */
5190         spin_lock_bh(&pmlmepriv->lock);
5191
5192         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
5193                 rtw_disassoc_cmd(padapter, 0, true);
5194                 rtw_indicate_disconnect(padapter);
5195                 rtw_free_assoc_resources(padapter, 1);
5196         }
5197
5198         spin_unlock_bh(&pmlmepriv->lock);
5199 }
5200
5201 u8 NULL_hdl(struct adapter *padapter, u8 *pbuf)
5202 {
5203         return H2C_SUCCESS;
5204 }
5205
5206 u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf)
5207 {
5208         u8 type;
5209         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5210         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5211         struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
5212
5213         if (psetop->mode == Ndis802_11APMode) {
5214                 pmlmeinfo->state = WIFI_FW_AP_STATE;
5215                 type = _HW_STATE_AP_;
5216                 /* start_ap_mode(padapter); */
5217         } else if (psetop->mode == Ndis802_11Infrastructure) {
5218                 pmlmeinfo->state &= ~(BIT(0)|BIT(1));/*  clear state */
5219                 pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to     STATION_STATE */
5220                 type = _HW_STATE_STATION_;
5221         } else if (psetop->mode == Ndis802_11IBSS) {
5222                 type = _HW_STATE_ADHOC_;
5223         } else {
5224                 type = _HW_STATE_NOLINK_;
5225         }
5226
5227         rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
5228         /* Set_MSR(padapter, type); */
5229
5230         if (psetop->mode == Ndis802_11APMode) {
5231                 /*  Do this after port switch to */
5232                 /*  prevent from downloading rsvd page to wrong port */
5233                 rtw_btcoex_MediaStatusNotify(padapter, 1); /* connect */
5234         }
5235
5236         return H2C_SUCCESS;
5237
5238 }
5239
5240 u8 createbss_hdl(struct adapter *padapter, u8 *pbuf)
5241 {
5242         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5243         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5244         struct wlan_bssid_ex    *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
5245         struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
5246         /* u32 initialgain; */
5247
5248         if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
5249                 start_bss_network(padapter);
5250                 return H2C_SUCCESS;
5251         }
5252
5253         /* below is for ad-hoc master */
5254         if (pparm->network.infrastructure_mode == Ndis802_11IBSS) {
5255                 rtw_joinbss_reset(padapter);
5256
5257                 pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
5258                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5259                 pmlmeinfo->ERP_enable = 0;
5260                 pmlmeinfo->WMM_enable = 0;
5261                 pmlmeinfo->HT_enable = 0;
5262                 pmlmeinfo->HT_caps_enable = 0;
5263                 pmlmeinfo->HT_info_enable = 0;
5264                 pmlmeinfo->agg_enable_bitmap = 0;
5265                 pmlmeinfo->candidate_tid_bitmap = 0;
5266
5267                 /* disable dynamic functions, such as high power, DIG */
5268                 Save_DM_Func_Flag(padapter);
5269                 Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
5270
5271                 /* config the initial gain under linking, need to write the BB registers */
5272                 /* initialgain = 0x1E; */
5273                 /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
5274
5275                 /* cancel link timer */
5276                 del_timer_sync(&pmlmeext->link_timer);
5277
5278                 /* clear CAM */
5279                 flush_all_cam_entry(padapter);
5280
5281                 memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, ie_length));
5282                 pnetwork->ie_length = ((struct wlan_bssid_ex *)pbuf)->ie_length;
5283
5284                 if (pnetwork->ie_length > MAX_IE_SZ)/* Check pbuf->ie_length */
5285                         return H2C_PARAMETERS_ERROR;
5286
5287                 memcpy(pnetwork->ies, ((struct wlan_bssid_ex *)pbuf)->ies, pnetwork->ie_length);
5288
5289                 start_create_ibss(padapter);
5290
5291         }
5292
5293         return H2C_SUCCESS;
5294
5295 }
5296
5297 u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
5298 {
5299         u8 join_type;
5300         struct ndis_80211_var_ie *pIE;
5301         struct registry_priv *pregpriv = &padapter->registrypriv;
5302         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5303         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5304         struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
5305         u32 i;
5306         u8 cbw40_enable = 0;
5307         /* u32 initialgain; */
5308         /* u32 acparm; */
5309         u8 ch, bw, offset;
5310
5311         /* check already connecting to AP or not */
5312         if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
5313                 if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
5314                         issue_deauth_ex(padapter, pnetwork->mac_address, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
5315                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
5316
5317                 /* clear CAM */
5318                 flush_all_cam_entry(padapter);
5319
5320                 del_timer_sync(&pmlmeext->link_timer);
5321
5322                 /* set MSR to nolink -> infra. mode */
5323                 /* Set_MSR(padapter, _HW_STATE_NOLINK_); */
5324                 Set_MSR(padapter, _HW_STATE_STATION_);
5325
5326
5327                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
5328         }
5329
5330         rtw_joinbss_reset(padapter);
5331
5332         pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
5333         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5334         pmlmeinfo->ERP_enable = 0;
5335         pmlmeinfo->WMM_enable = 0;
5336         pmlmeinfo->HT_enable = 0;
5337         pmlmeinfo->HT_caps_enable = 0;
5338         pmlmeinfo->HT_info_enable = 0;
5339         pmlmeinfo->agg_enable_bitmap = 0;
5340         pmlmeinfo->candidate_tid_bitmap = 0;
5341         pmlmeinfo->bwmode_updated = false;
5342         /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */
5343         pmlmeinfo->VHT_enable = 0;
5344
5345         memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, ie_length));
5346         pnetwork->ie_length = ((struct wlan_bssid_ex *)pbuf)->ie_length;
5347
5348         if (pnetwork->ie_length > MAX_IE_SZ)/* Check pbuf->ie_length */
5349                 return H2C_PARAMETERS_ERROR;
5350
5351         memcpy(pnetwork->ies, ((struct wlan_bssid_ex *)pbuf)->ies, pnetwork->ie_length);
5352
5353         pmlmeext->cur_channel = (u8)pnetwork->configuration.ds_config;
5354         pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
5355
5356         /* Check AP vendor to move rtw_joinbss_cmd() */
5357         /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->ies, pnetwork->ie_length); */
5358
5359         /* sizeof(struct ndis_802_11_fix_ie) */
5360         for (i = _FIXED_IE_LENGTH_; i < pnetwork->ie_length;) {
5361                 pIE = (struct ndis_80211_var_ie *)(pnetwork->ies + i);
5362
5363                 switch (pIE->element_id) {
5364                 case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */
5365                         if (!memcmp(pIE->data, WMM_OUI, 4))
5366                                 WMM_param_handler(padapter, pIE);
5367                         break;
5368
5369                 case WLAN_EID_HT_CAPABILITY:    /* Get HT Cap IE. */
5370                         pmlmeinfo->HT_caps_enable = 1;
5371                         break;
5372
5373                 case WLAN_EID_HT_OPERATION:     /* Get HT Info IE. */
5374                         pmlmeinfo->HT_info_enable = 1;
5375
5376                         /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */
5377                         {
5378                                 struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
5379
5380                                 if (pnetwork->configuration.ds_config <= 14) {
5381                                         if ((pregpriv->bw_mode & 0x0f) > CHANNEL_WIDTH_20)
5382                                                 cbw40_enable = 1;
5383                                 }
5384
5385                                 if ((cbw40_enable) && (pht_info->infos[0] & BIT(2))) {
5386                                         /* switch to the 40M Hz mode according to the AP */
5387                                         pmlmeext->cur_bwmode = CHANNEL_WIDTH_40;
5388                                         switch (pht_info->infos[0] & 0x3) {
5389                                         case 1:
5390                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
5391                                                 break;
5392
5393                                         case 3:
5394                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
5395                                                 break;
5396
5397                                         default:
5398                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5399                                                 pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
5400                                                 break;
5401                                         }
5402                                 }
5403                         }
5404                         break;
5405                 default:
5406                         break;
5407                 }
5408
5409                 i += (pIE->length + 2);
5410         }
5411
5412         /* check channel, bandwidth, offset and switch */
5413         if (rtw_chk_start_clnt_join(padapter, &ch, &bw, &offset) == _FAIL) {
5414                 report_join_res(padapter, (-4));
5415                 return H2C_SUCCESS;
5416         }
5417
5418         /* disable dynamic functions, such as high power, DIG */
5419         /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); */
5420
5421         /* config the initial gain under linking, need to write the BB registers */
5422         /* initialgain = 0x1E; */
5423         /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
5424
5425         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.mac_address);
5426         join_type = 0;
5427         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
5428         rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
5429
5430         set_channel_bwmode(padapter, ch, offset, bw);
5431
5432         /* cancel link timer */
5433         del_timer_sync(&pmlmeext->link_timer);
5434
5435         start_clnt_join(padapter);
5436
5437         return H2C_SUCCESS;
5438
5439 }
5440
5441 u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)
5442 {
5443         struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
5444         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5445         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5446         struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
5447         u8 val8;
5448
5449         if (is_client_associated_to_ap(padapter))
5450                         issue_deauth_ex(padapter, pnetwork->mac_address, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
5451
5452         if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
5453                 /* Stop BCN */
5454                 val8 = 0;
5455                 rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
5456         }
5457
5458         rtw_mlmeext_disconnect(padapter);
5459
5460         rtw_free_uc_swdec_pending_queue(padapter);
5461
5462         return  H2C_SUCCESS;
5463 }
5464
5465 static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_channel *out,
5466         u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
5467 {
5468         int i, j;
5469         int set_idx;
5470         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5471
5472         /* clear first */
5473         memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
5474
5475         /* acquire channels from in */
5476         j = 0;
5477         for (i = 0; i < in_num; i++) {
5478
5479                 set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value);
5480                 if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED)
5481                         && set_idx >= 0
5482                 ) {
5483                         if (j >= out_num) {
5484                                 netdev_dbg(padapter->pnetdev,
5485                                            FUNC_ADPT_FMT " out_num:%u not enough\n",
5486                                            FUNC_ADPT_ARG(padapter), out_num);
5487                                 break;
5488                         }
5489
5490                         memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
5491
5492                         if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
5493                                 out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
5494
5495                         j++;
5496                 }
5497                 if (j >= out_num)
5498                         break;
5499         }
5500
5501         /* if out is empty, use channel_set as default */
5502         if (j == 0) {
5503                 for (i = 0; i < pmlmeext->max_chan_nums; i++) {
5504
5505                         if (j >= out_num) {
5506                                 netdev_dbg(padapter->pnetdev,
5507                                            FUNC_ADPT_FMT " out_num:%u not enough\n",
5508                                            FUNC_ADPT_ARG(padapter),
5509                                            out_num);
5510                                 break;
5511                         }
5512
5513                         out[j].hw_value = pmlmeext->channel_set[i].ChannelNum;
5514
5515                         if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
5516                                 out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
5517
5518                         j++;
5519                 }
5520         }
5521
5522         return j;
5523 }
5524
5525 u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf)
5526 {
5527         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5528         struct sitesurvey_parm  *pparm = (struct sitesurvey_parm *)pbuf;
5529         u8 bdelayscan = false;
5530         u8 val8;
5531         u32 initialgain;
5532         u32 i;
5533
5534         if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
5535                 pmlmeext->sitesurvey_res.state = SCAN_START;
5536                 pmlmeext->sitesurvey_res.bss_cnt = 0;
5537                 pmlmeext->sitesurvey_res.channel_idx = 0;
5538
5539                 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
5540                         if (pparm->ssid[i].ssid_length) {
5541                                 memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid, pparm->ssid[i].ssid, IW_ESSID_MAX_SIZE);
5542                                 pmlmeext->sitesurvey_res.ssid[i].ssid_length = pparm->ssid[i].ssid_length;
5543                         } else {
5544                                 pmlmeext->sitesurvey_res.ssid[i].ssid_length = 0;
5545                         }
5546                 }
5547
5548                 pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter
5549                         , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT
5550                         , pparm->ch, pparm->ch_num
5551                 );
5552
5553                 pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
5554
5555                 /* issue null data if associating to the AP */
5556                 if (is_client_associated_to_ap(padapter)) {
5557                         pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
5558
5559                         issue_nulldata(padapter, NULL, 1, 3, 500);
5560
5561                         bdelayscan = true;
5562                 }
5563                 if (bdelayscan) {
5564                         /* delay 50ms to protect nulldata(1). */
5565                         set_survey_timer(pmlmeext, 50);
5566                         return H2C_SUCCESS;
5567                 }
5568         }
5569
5570         if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
5571                 /* disable dynamic functions, such as high power, DIG */
5572                 Save_DM_Func_Flag(padapter);
5573                 Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
5574
5575                 /* config the initial gain under scanning, need to write the BB
5576                  * registers
5577                  */
5578                 initialgain = 0x1e;
5579
5580                 rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
5581
5582                 /* set MSR to no link state */
5583                 Set_MSR(padapter, _HW_STATE_NOLINK_);
5584
5585                 val8 = 1; /* under site survey */
5586                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
5587
5588                 pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
5589         }
5590
5591         site_survey(padapter);
5592
5593         return H2C_SUCCESS;
5594
5595 }
5596
5597 u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf)
5598 {
5599         struct setauth_parm             *pparm = (struct setauth_parm *)pbuf;
5600         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5601         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5602
5603         if (pparm->mode < 4)
5604                 pmlmeinfo->auth_algo = pparm->mode;
5605
5606         return  H2C_SUCCESS;
5607 }
5608
5609 u8 setkey_hdl(struct adapter *padapter, u8 *pbuf)
5610 {
5611         u16 ctrl = 0;
5612         s16 cam_id = 0;
5613         struct setkey_parm              *pparm = (struct setkey_parm *)pbuf;
5614         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5615         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5616         unsigned char null_addr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
5617         u8 *addr;
5618
5619         /* main tx key for wep. */
5620         if (pparm->set_tx)
5621                 pmlmeinfo->key_index = pparm->keyid;
5622
5623         cam_id = rtw_camid_alloc(padapter, NULL, pparm->keyid);
5624
5625         if (cam_id < 0) {
5626         } else {
5627                 if (cam_id > 3) /* not default key, searched by A2 */
5628                         addr = get_bssid(&padapter->mlmepriv);
5629                 else
5630                         addr = null_addr;
5631
5632                 ctrl = BIT(15) | BIT6 | ((pparm->algorithm) << 2) | pparm->keyid;
5633                 write_cam(padapter, cam_id, ctrl, addr, pparm->key);
5634                 netdev_dbg(padapter->pnetdev,
5635                            "set group key camid:%d, addr:%pM, kid:%d, type:%s\n",
5636                            cam_id, MAC_ARG(addr), pparm->keyid,
5637                            security_type_str(pparm->algorithm));
5638         }
5639
5640         if (cam_id >= 0 && cam_id <= 3)
5641                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8 *)true);
5642
5643         /* allow multicast packets to driver */
5644         padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr);
5645
5646         return H2C_SUCCESS;
5647 }
5648
5649 u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf)
5650 {
5651         u16 ctrl = 0;
5652         s16 cam_id = 0;
5653         u8 ret = H2C_SUCCESS;
5654         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5655         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5656         struct set_stakey_parm  *pparm = (struct set_stakey_parm *)pbuf;
5657         struct sta_priv *pstapriv = &padapter->stapriv;
5658         struct sta_info *psta;
5659
5660         if (pparm->algorithm == _NO_PRIVACY_)
5661                 goto write_to_cam;
5662
5663         psta = rtw_get_stainfo(pstapriv, pparm->addr);
5664         if (!psta) {
5665                 netdev_dbg(padapter->pnetdev, "%s sta:%pM not found\n",
5666                            __func__, MAC_ARG(pparm->addr));
5667                 ret = H2C_REJECTED;
5668                 goto exit;
5669         }
5670
5671         pmlmeinfo->enc_algo = pparm->algorithm;
5672         cam_id = rtw_camid_alloc(padapter, psta, 0);
5673         if (cam_id < 0)
5674                 goto exit;
5675
5676 write_to_cam:
5677         if (pparm->algorithm == _NO_PRIVACY_) {
5678                 while ((cam_id = rtw_camid_search(padapter, pparm->addr, -1)) >= 0) {
5679                         netdev_dbg(padapter->pnetdev,
5680                                    "clear key for addr:%pM, camid:%d\n",
5681                                    MAC_ARG(pparm->addr), cam_id);
5682                         clear_cam_entry(padapter, cam_id);
5683                         rtw_camid_free(padapter, cam_id);
5684                 }
5685         } else {
5686                 netdev_dbg(padapter->pnetdev,
5687                            "set pairwise key camid:%d, addr:%pM, kid:%d, type:%s\n",
5688                            cam_id, MAC_ARG(pparm->addr), pparm->keyid,
5689                            security_type_str(pparm->algorithm));
5690                 ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
5691                 write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
5692         }
5693         ret = H2C_SUCCESS_RSP;
5694
5695 exit:
5696         return ret;
5697 }
5698
5699 u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf)
5700 {
5701         struct addBaReq_parm    *pparm = (struct addBaReq_parm *)pbuf;
5702         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5703         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5704
5705         struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
5706
5707         if (!psta)
5708                 return  H2C_SUCCESS;
5709
5710         if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
5711                 ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
5712                 /* pmlmeinfo->ADDBA_retry_count = 0; */
5713                 /* pmlmeinfo->candidate_tid_bitmap |= (0x1 << pparm->tid); */
5714                 /* psta->htpriv.candidate_tid_bitmap |= BIT(pparm->tid); */
5715                 issue_action_BA(padapter, pparm->addr, WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
5716                 /* _set_timer(&pmlmeext->ADDBA_timer, ADDBA_TO); */
5717                 _set_timer(&psta->addba_retry_timer, ADDBA_TO);
5718         } else {
5719                 psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
5720         }
5721         return  H2C_SUCCESS;
5722 }
5723
5724
5725 u8 chk_bmc_sleepq_cmd(struct adapter *padapter)
5726 {
5727         struct cmd_obj *ph2c;
5728         struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
5729         u8 res = _SUCCESS;
5730
5731         ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
5732         if (!ph2c) {
5733                 res = _FAIL;
5734                 goto exit;
5735         }
5736
5737         init_h2fwcmd_w_parm_no_parm_rsp(ph2c, GEN_CMD_CODE(_ChkBMCSleepq));
5738
5739         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
5740
5741 exit:
5742         return res;
5743 }
5744
5745 u8 set_tx_beacon_cmd(struct adapter *padapter)
5746 {
5747         struct cmd_obj  *ph2c;
5748         struct Tx_Beacon_param  *ptxBeacon_parm;
5749         struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
5750         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5751         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5752         u8 res = _SUCCESS;
5753         int len_diff = 0;
5754
5755         ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
5756         if (!ph2c) {
5757                 res = _FAIL;
5758                 goto exit;
5759         }
5760
5761         ptxBeacon_parm = rtw_zmalloc(sizeof(struct Tx_Beacon_param));
5762         if (!ptxBeacon_parm) {
5763                 kfree(ph2c);
5764                 res = _FAIL;
5765                 goto exit;
5766         }
5767
5768         memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
5769
5770         len_diff = update_hidden_ssid(ptxBeacon_parm->network.ies+_BEACON_IE_OFFSET_,
5771                                       ptxBeacon_parm->network.ie_length-_BEACON_IE_OFFSET_,
5772                                       pmlmeinfo->hidden_ssid_mode);
5773         ptxBeacon_parm->network.ie_length += len_diff;
5774
5775         init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
5776
5777         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
5778
5779 exit:
5780         return res;
5781 }
5782
5783 static struct fwevent wlanevents[] = {
5784         {0, rtw_dummy_event_callback},  /*0*/
5785         {0, NULL},
5786         {0, NULL},
5787         {0, NULL},
5788         {0, NULL},
5789         {0, NULL},
5790         {0, NULL},
5791         {0, NULL},
5792         {0, &rtw_survey_event_callback},                /*8*/
5793         {sizeof(struct surveydone_event), &rtw_surveydone_event_callback},      /*9*/
5794
5795         {0, &rtw_joinbss_event_callback},               /*10*/
5796         {sizeof(struct stassoc_event), &rtw_stassoc_event_callback},
5797         {sizeof(struct stadel_event), &rtw_stadel_event_callback},
5798         {0, &rtw_atimdone_event_callback},
5799         {0, rtw_dummy_event_callback},
5800         {0, NULL},      /*15*/
5801         {0, NULL},
5802         {0, NULL},
5803         {0, NULL},
5804         {0, rtw_fwdbg_event_callback},
5805         {0, NULL},       /*20*/
5806         {0, NULL},
5807         {0, NULL},
5808         {0, &rtw_cpwm_event_callback},
5809         {0, NULL},
5810         {0, &rtw_wmm_event_callback},
5811
5812 };
5813
5814 u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf)
5815 {
5816         u8 evt_code;
5817         u16 evt_sz;
5818         uint    *peventbuf;
5819         void (*event_callback)(struct adapter *dev, u8 *pbuf);
5820         struct evt_priv *pevt_priv = &(padapter->evtpriv);
5821
5822         if (!pbuf)
5823                 goto _abort_event_;
5824
5825         peventbuf = (uint *)pbuf;
5826         evt_sz = (u16)(*peventbuf&0xffff);
5827         evt_code = (u8)((*peventbuf>>16)&0xff);
5828
5829         /*  checking if event code is valid */
5830         if (evt_code >= MAX_C2HEVT)
5831                 goto _abort_event_;
5832
5833         /*  checking if event size match the event parm size */
5834         if ((wlanevents[evt_code].parmsize != 0) &&
5835                         (wlanevents[evt_code].parmsize != evt_sz))
5836                 goto _abort_event_;
5837
5838         atomic_inc(&pevt_priv->event_seq);
5839
5840         peventbuf += 2;
5841
5842         if (peventbuf) {
5843                 event_callback = wlanevents[evt_code].event_callback;
5844                 event_callback(padapter, (u8 *)peventbuf);
5845
5846                 pevt_priv->evt_done_cnt++;
5847         }
5848
5849
5850 _abort_event_:
5851
5852
5853         return H2C_SUCCESS;
5854
5855 }
5856
5857 u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf)
5858 {
5859         if (!pbuf)
5860                 return H2C_PARAMETERS_ERROR;
5861
5862         return H2C_SUCCESS;
5863 }
5864
5865 u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf)
5866 {
5867         struct sta_info *psta_bmc;
5868         struct list_head *xmitframe_plist, *xmitframe_phead, *tmp;
5869         struct xmit_frame *pxmitframe = NULL;
5870         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5871         struct sta_priv  *pstapriv = &padapter->stapriv;
5872
5873         /* for BC/MC Frames */
5874         psta_bmc = rtw_get_bcmc_stainfo(padapter);
5875         if (!psta_bmc)
5876                 return H2C_SUCCESS;
5877
5878         if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len > 0)) {
5879                 msleep(10);/*  10ms, ATIM(HIQ) Windows */
5880
5881                 /* spin_lock_bh(&psta_bmc->sleep_q.lock); */
5882                 spin_lock_bh(&pxmitpriv->lock);
5883
5884                 xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
5885                 list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) {
5886                         pxmitframe = list_entry(xmitframe_plist,
5887                                                 struct xmit_frame, list);
5888
5889                         list_del_init(&pxmitframe->list);
5890
5891                         psta_bmc->sleepq_len--;
5892                         if (psta_bmc->sleepq_len > 0)
5893                                 pxmitframe->attrib.mdata = 1;
5894                         else
5895                                 pxmitframe->attrib.mdata = 0;
5896
5897                         pxmitframe->attrib.triggered = 1;
5898
5899                         if (xmitframe_hiq_filter(pxmitframe))
5900                                 pxmitframe->attrib.qsel = 0x11;/* HIQ */
5901
5902                         rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
5903                 }
5904
5905                 /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
5906                 spin_unlock_bh(&pxmitpriv->lock);
5907
5908                 /* check hi queue and bmc_sleepq */
5909                 rtw_chk_hi_queue_cmd(padapter);
5910         }
5911
5912         return H2C_SUCCESS;
5913 }
5914
5915 u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf)
5916 {
5917         if (send_beacon(padapter) == _FAIL)
5918                 return H2C_PARAMETERS_ERROR;
5919
5920         /* tx bc/mc frames after update TIM */
5921         chk_bmc_sleepq_hdl(padapter, NULL);
5922
5923         return H2C_SUCCESS;
5924 }
5925
5926 int rtw_chk_start_clnt_join(struct adapter *padapter, u8 *ch, u8 *bw, u8 *offset)
5927 {
5928         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5929         unsigned char cur_ch = pmlmeext->cur_channel;
5930         unsigned char cur_bw = pmlmeext->cur_bwmode;
5931         unsigned char cur_ch_offset = pmlmeext->cur_ch_offset;
5932         bool connect_allow = true;
5933
5934         if (!ch || !bw || !offset) {
5935                 rtw_warn_on(1);
5936                 connect_allow = false;
5937         }
5938
5939         if (connect_allow) {
5940                 *ch = cur_ch;
5941                 *bw = cur_bw;
5942                 *offset = cur_ch_offset;
5943         }
5944
5945         return connect_allow ? _SUCCESS : _FAIL;
5946 }
5947
5948 /* Find union about ch, bw, ch_offset of all linked/linking interfaces */
5949 int rtw_get_ch_setting_union(struct adapter *adapter, u8 *ch, u8 *bw, u8 *offset)
5950 {
5951         struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
5952         struct adapter *iface;
5953
5954         if (ch)
5955                 *ch = 0;
5956         if (bw)
5957                 *bw = CHANNEL_WIDTH_20;
5958         if (offset)
5959                 *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5960
5961         iface = dvobj->padapters;
5962
5963         if (!check_fwstate(&iface->mlmepriv, _FW_LINKED|_FW_UNDER_LINKING))
5964                 return 0;
5965
5966         return 1;
5967 }
5968
5969 u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf)
5970 {
5971         struct set_ch_parm *set_ch_parm;
5972         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5973
5974         if (!pbuf)
5975                 return H2C_PARAMETERS_ERROR;
5976
5977         set_ch_parm = (struct set_ch_parm *)pbuf;
5978
5979         pmlmeext->cur_channel = set_ch_parm->ch;
5980         pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
5981         pmlmeext->cur_bwmode = set_ch_parm->bw;
5982
5983         set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
5984
5985         return  H2C_SUCCESS;
5986 }
5987
5988 u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf)
5989 {
5990         struct SetChannelPlan_param *setChannelPlan_param;
5991         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5992
5993         if (!pbuf)
5994                 return H2C_PARAMETERS_ERROR;
5995
5996         setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
5997
5998         pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
5999         init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
6000
6001         if (padapter->rtw_wdev && padapter->rtw_wdev->wiphy) {
6002                 struct regulatory_request request;
6003
6004                 request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
6005                 rtw_reg_notifier(padapter->rtw_wdev->wiphy, &request);
6006         }
6007
6008         return  H2C_SUCCESS;
6009 }
6010
6011 u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf)
6012 {
6013         return  H2C_REJECTED;
6014 }
6015
6016 /*  TDLS_ESTABLISHED    : write RCR DATA BIT */
6017 /*  TDLS_CS_OFF         : go back to the channel linked with AP, terminating channel switch procedure */
6018 /*  TDLS_INIT_CH_SEN    : init channel sensing, receive all data and mgnt frame */
6019 /*  TDLS_DONE_CH_SEN: channel sensing and report candidate channel */
6020 /*  TDLS_OFF_CH         : first time set channel to off channel */
6021 /*  TDLS_BASE_CH                : go back tp the channel linked with AP when set base channel as target channel */
6022 /*  TDLS_P_OFF_CH       : periodically go to off channel */
6023 /*  TDLS_P_BASE_CH      : periodically go back to base channel */
6024 /*  TDLS_RS_RCR         : restore RCR */
6025 /*  TDLS_TEAR_STA       : free tdls sta */
6026 u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf)
6027 {
6028         return H2C_REJECTED;
6029 }
6030
6031 u8 run_in_thread_hdl(struct adapter *padapter, u8 *pbuf)
6032 {
6033         struct RunInThread_param *p;
6034
6035
6036         if (pbuf == NULL)
6037                 return H2C_PARAMETERS_ERROR;
6038         p = (struct RunInThread_param *)pbuf;
6039
6040         if (p->func)
6041                 p->func(p->context);
6042
6043         return H2C_SUCCESS;
6044 }