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