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