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