blob: 8996c1e24568c64464d4190acc65494c5b393357 [file] [log] [blame]
Larry Finger5e93f352014-03-28 21:37:38 -05001/******************************************************************************
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>
Larry Finger5e93f352014-03-28 21:37:38 -050024#include <linux/ieee80211.h>
Larry Finger5e93f352014-03-28 21:37:38 -050025#include <rtl8723a_hal.h>
Larry Finger5e93f352014-03-28 21:37:38 -050026
Jes Sorensene0facfa2014-04-15 19:43:53 +020027static int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
28static int OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
29static int OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
30static int OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
31static int DoReserved23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
32static int OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
33static int OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
34static int OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
Jes Sorensene0facfa2014-04-15 19:43:53 +020035static int OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
36static int OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
37static int OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
38
39static int on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
40static int OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
41static int OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
42static int OnAction23a_back23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
43static int on_action_public23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
44static int OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
45static int OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
46static int OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
47
Jes Sorensen0e176852014-05-21 09:38:20 +020048static void issue_assocreq(struct rtw_adapter *padapter);
Jes Sorensen0e176852014-05-21 09:38:20 +020049static void issue_probereq(struct rtw_adapter *padapter,
50 struct cfg80211_ssid *pssid, u8 *da);
51static int issue_probereq_ex(struct rtw_adapter *padapter,
52 struct cfg80211_ssid *pssid,
53 u8 *da, int try_cnt, int wait_ms);
54static void issue_probersp(struct rtw_adapter *padapter, unsigned char *da,
55 u8 is_valid_p2p_probereq);
56static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta,
57 unsigned short status);
58static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da,
59 unsigned short reason, int try_cnt, int wait_ms);
60static void start_clnt_assoc(struct rtw_adapter *padapter);
61static void start_clnt_auth(struct rtw_adapter *padapter);
62static void start_clnt_join(struct rtw_adapter *padapter);
63static void start_create_ibss(struct rtw_adapter *padapter);
Jes Sorensen1bebe752014-06-09 15:16:30 +020064static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter,
65 struct recv_frame *precv_frame);
Jes Sorensen0e176852014-05-21 09:38:20 +020066
Jes Sorensena402b802014-05-21 09:38:21 +020067#ifdef CONFIG_8723AU_AP_MODE
68static int OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
69static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status,
70 struct sta_info *pstat, u16 pkt_type);
71#endif
Jes Sorensen5986a3f2014-05-21 09:38:13 +020072
Larry Finger5e93f352014-03-28 21:37:38 -050073static 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
94static 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
106static u8 null_addr[ETH_ALEN]= {0, 0, 0, 0, 0, 0};
107
108/**************************************************
109OUI definitions for the vendor specific IE
110***************************************************/
Larry Finger5e93f352014-03-28 21:37:38 -0500111unsigned char WMM_OUI23A[] = {0x00, 0x50, 0xf2, 0x02};
Jes Sorensend54239a2014-05-31 18:05:08 +0200112unsigned char WPS_OUI23A[] = {0x00, 0x50, 0xf2, 0x04};
113unsigned char P2P_OUI23A[] = {0x50, 0x6F, 0x9A, 0x09};
114unsigned char WFD_OUI23A[] = {0x50, 0x6F, 0x9A, 0x0A};
Larry Finger5e93f352014-03-28 21:37:38 -0500115
Jes Sorensend54239a2014-05-31 18:05:08 +0200116unsigned char WMM_INFO_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
117unsigned char WMM_PARA_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
Larry Finger5e93f352014-03-28 21:37:38 -0500118
Jes Sorensenf85bd052014-05-09 15:04:06 +0200119static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
Larry Finger5e93f352014-03-28 21:37:38 -0500120
121/********************************************************
122MCS rate definitions
123*********************************************************/
124unsigned char MCS_rate_2R23A[16] = {
Jes Sorensend54239a2014-05-31 18:05:08 +0200125 0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0,
126 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
Larry Finger5e93f352014-03-28 21:37:38 -0500127unsigned char MCS_rate_1R23A[16] = {
Jes Sorensend54239a2014-05-31 18:05:08 +0200128 0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0,
129 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
Larry Finger5e93f352014-03-28 21:37:38 -0500130
131/********************************************************
132ChannelPlan definitions
133*********************************************************/
134
Jes Sorensend54239a2014-05-31 18:05:08 +0200135static 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},
Larry Finger5e93f352014-03-28 21:37:38 -0500148};
149
Jes Sorensend54239a2014-05-31 18:05:08 +0200150static 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},
Larry Finger5e93f352014-03-28 21:37:38 -0500193
Jes Sorensend54239a2014-05-31 18:05:08 +0200194 /* 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},
Larry Finger5e93f352014-03-28 21:37:38 -0500203};
204
Jes Sorensend54239a2014-05-31 18:05:08 +0200205static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
Larry Finger5e93f352014-03-28 21:37:38 -0500206 /* 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
Jes Sorensend54239a2014-05-31 18:05:08 +0200276static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE =
277{0x03, 0x02}; /* use the conbination for max channel numbers */
Larry Finger5e93f352014-03-28 21:37:38 -0500278
Jes Sorensencdaf6ef2014-05-21 09:38:25 +0200279static void dummy_event_callback(struct rtw_adapter *adapter, const u8 *pbuf)
280{
281}
282
Larry Finger5e93f352014-03-28 21:37:38 -0500283static struct fwevent wlanevents[] =
284{
Jes Sorensencdaf6ef2014-05-21 09:38:25 +0200285 {0, &dummy_event_callback}, /*0*/
Larry Finger5e93f352014-03-28 21:37:38 -0500286 {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*/
Jes Sorensend54239a2014-05-31 18:05:08 +0200294 {sizeof (struct surveydone_event), &rtw_surveydone_event_callback23a},
Larry Finger5e93f352014-03-28 21:37:38 -0500295 {0, &rtw23a_joinbss_event_cb}, /*10*/
296 {sizeof(struct stassoc_event), &rtw_stassoc_event_callback23a},
297 {sizeof(struct stadel_event), &rtw_stadel_event_callback23a},
Jes Sorensencdaf6ef2014-05-21 09:38:25 +0200298 {0, &dummy_event_callback},
299 {0, &dummy_event_callback},
Larry Finger5e93f352014-03-28 21:37:38 -0500300 {0, NULL}, /*15*/
301 {0, NULL},
302 {0, NULL},
303 {0, NULL},
Jes Sorensencdaf6ef2014-05-21 09:38:25 +0200304 {0, &dummy_event_callback},
Larry Finger5e93f352014-03-28 21:37:38 -0500305 {0, NULL}, /*20*/
306 {0, NULL},
307 {0, NULL},
Jes Sorensencdaf6ef2014-05-21 09:38:25 +0200308 {0, &dummy_event_callback},
Larry Finger5e93f352014-03-28 21:37:38 -0500309 {0, NULL},
310};
311
312
Jes Sorensen0e959692014-04-15 19:44:28 +0200313static void rtw_correct_TSF(struct rtw_adapter *padapter)
314{
315 hw_var_set_correct_tsf(padapter);
316}
317
Jes Sorensen04fad922014-04-15 19:44:27 +0200318static void
319rtw_update_TSF(struct mlme_ext_priv *pmlmeext, struct ieee80211_mgmt *mgmt)
320{
321 pmlmeext->TSFValue = get_unaligned_le64(&mgmt->u.beacon.timestamp);
322}
323
Larry Finger5e93f352014-03-28 21:37:38 -0500324/*
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 */
331int rtw_ch_set_search_ch23a(struct rt_channel_info *ch_set, const u32 ch)
332{
333 int i;
Yeliz Taneroglu2ce71bd2014-10-09 01:22:15 +0300334
Larry Finger5e93f352014-03-28 21:37:38 -0500335 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
347Following are the initialization functions for WiFi MLME
348
349*****************************************************************************/
350
351int init_hw_mlme_ext23a(struct rtw_adapter *padapter)
352{
Jes Sorensend54239a2014-05-31 18:05:08 +0200353 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -0500354
355 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
356 pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
357 return _SUCCESS;
358}
359
Greg Donald4e66cf02014-08-22 10:57:49 -0500360static void init_mlme_ext_priv23a_value(struct rtw_adapter *padapter)
Larry Finger5e93f352014-03-28 21:37:38 -0500361{
Jes Sorensend54239a2014-05-31 18:05:08 +0200362 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -0500363 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
Jes Sorensen6ec26272014-07-17 22:59:46 +0200397 pmlmeinfo->state = MSR_NOLINK;
Larry Finger5e93f352014-03-28 21:37:38 -0500398 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
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200406 pmlmeinfo->enc_algo = 0;
Larry Finger5e93f352014-03-28 21:37:38 -0500407 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
420static 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
432static void init_channel_list(struct rtw_adapter *padapter,
433 struct rt_channel_info *channel_set,
434 u8 chanset_size,
Jes Sorensend54239a2014-05-31 18:05:08 +0200435 struct p2p_channels *channel_list)
436{
Larry Finger5e93f352014-03-28 21:37:38 -0500437 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
Greg Donald4e66cf02014-08-22 10:57:49 -0500484static u8 init_channel_set(struct rtw_adapter *padapter, u8 cplan,
Jes Sorensen68e68312014-04-15 19:44:35 +0200485 struct rt_channel_info *c_set)
Larry Finger5e93f352014-03-28 21:37:38 -0500486{
Jes Sorensen68e68312014-04-15 19:44:35 +0200487 u8 i, ch_size = 0;
488 u8 b5GBand = false, b2_4GBand = false;
489 u8 Index2G = 0, Index5G = 0;
Larry Finger5e93f352014-03-28 21:37:38 -0500490
Jes Sorensen68e68312014-04-15 19:44:35 +0200491 memset(c_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM);
Larry Finger5e93f352014-03-28 21:37:38 -0500492
Jes Sorensen68e68312014-04-15 19:44:35 +0200493 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;
Larry Finger5e93f352014-03-28 21:37:38 -0500497 }
498
499 if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
500 b2_4GBand = true;
Jes Sorensen68e68312014-04-15 19:44:35 +0200501 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan)
Larry Finger5e93f352014-03-28 21:37:38 -0500502 Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
503 else
Jes Sorensen68e68312014-04-15 19:44:35 +0200504 Index2G = RTW_ChannelPlanMap[cplan].Index2G;
Larry Finger5e93f352014-03-28 21:37:38 -0500505 }
506
507 if (padapter->registrypriv.wireless_mode & WIRELESS_11A) {
508 b5GBand = true;
Jes Sorensen68e68312014-04-15 19:44:35 +0200509 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan)
Larry Finger5e93f352014-03-28 21:37:38 -0500510 Index5G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index5G;
511 else
Jes Sorensen68e68312014-04-15 19:44:35 +0200512 Index5G = RTW_ChannelPlanMap[cplan].Index5G;
Larry Finger5e93f352014-03-28 21:37:38 -0500513 }
514
515 if (b2_4GBand) {
Jes Sorensen68e68312014-04-15 19:44:35 +0200516 for (i = 0; i < RTW_ChannelPlan2G[Index2G].Len; i++) {
517 c_set[ch_size].ChannelNum =
518 RTW_ChannelPlan2G[Index2G].Channel[i];
Larry Finger5e93f352014-03-28 21:37:38 -0500519
Jes Sorensen68e68312014-04-15 19:44:35 +0200520 if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == cplan) ||
Larry Finger5e93f352014-03-28 21:37:38 -0500521 /* Channel 1~11 is active, and 12~14 is passive */
Jes Sorensen68e68312014-04-15 19:44:35 +0200522 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 ||
Larry Finger5e93f352014-03-28 21:37:38 -0500531 RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) {
532 /* channel 12~13, passive scan */
Jes Sorensen68e68312014-04-15 19:44:35 +0200533 if (c_set[ch_size].ChannelNum <= 11)
534 c_set[ch_size].ScanType = SCAN_ACTIVE;
Larry Finger5e93f352014-03-28 21:37:38 -0500535 else
Jes Sorensen68e68312014-04-15 19:44:35 +0200536 c_set[ch_size].ScanType = SCAN_PASSIVE;
Larry Finger5e93f352014-03-28 21:37:38 -0500537 } else
Jes Sorensen68e68312014-04-15 19:44:35 +0200538 c_set[ch_size].ScanType = SCAN_ACTIVE;
Larry Finger5e93f352014-03-28 21:37:38 -0500539
Jes Sorensen68e68312014-04-15 19:44:35 +0200540 ch_size++;
Larry Finger5e93f352014-03-28 21:37:38 -0500541 }
542 }
543
544 if (b5GBand) {
Jes Sorensen68e68312014-04-15 19:44:35 +0200545 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) {
Larry Finger5e93f352014-03-28 21:37:38 -0500551 /* passive scan for all 5G channels */
Jes Sorensen68e68312014-04-15 19:44:35 +0200552 c_set[ch_size].ScanType =
Larry Finger5e93f352014-03-28 21:37:38 -0500553 SCAN_PASSIVE;
554 } else
Jes Sorensen68e68312014-04-15 19:44:35 +0200555 c_set[ch_size].ScanType =
Larry Finger5e93f352014-03-28 21:37:38 -0500556 SCAN_ACTIVE;
557 DBG_8723A("%s(): channel_set[%d].ChannelNum = "
Jes Sorensen68e68312014-04-15 19:44:35 +0200558 "%d\n", __func__, ch_size,
559 c_set[ch_size].ChannelNum);
560 ch_size++;
Larry Finger5e93f352014-03-28 21:37:38 -0500561 }
562 }
563 }
564
Jes Sorensen68e68312014-04-15 19:44:35 +0200565 return ch_size;
Larry Finger5e93f352014-03-28 21:37:38 -0500566}
567
Greg Donald4e66cf02014-08-22 10:57:49 -0500568int init_mlme_ext_priv23a(struct rtw_adapter *padapter)
Larry Finger5e93f352014-03-28 21:37:38 -0500569{
Greg Donald4e66cf02014-08-22 10:57:49 -0500570 struct registry_priv *pregistrypriv = &padapter->registrypriv;
Larry Finger5e93f352014-03-28 21:37:38 -0500571 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;
Roberta Dobrescu038b7032014-10-26 23:30:09 +0200596 return _SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -0500597}
598
599void 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
613static void
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);
Greg Donalda82b4b02014-09-08 20:50:23 -0500628 }
Larry Finger5e93f352014-03-28 21:37:38 -0500629}
630
631void mgt_dispatcher23a(struct rtw_adapter *padapter,
632 struct recv_frame *precv_frame)
633{
Larry Finger5e93f352014-03-28 21:37:38 -0500634 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;
Jes Sorensen34df0dd2014-04-15 19:44:34 +0200639 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
Larry Finger5e93f352014-03-28 21:37:38 -0500640 struct sta_info *psta;
Jes Sorensen34df0dd2014-04-15 19:44:34 +0200641 u16 stype;
642 int index;
Larry Finger5e93f352014-03-28 21:37:38 -0500643
Jes Sorensen34df0dd2014-04-15 19:44:34 +0200644 if (!ieee80211_is_mgmt(mgmt->frame_control))
Larry Finger5e93f352014-03-28 21:37:38 -0500645 return;
646
647 /* receive the frames that ra(a1) is my address or ra(a1) is
648 bc address. */
Jes Sorensen34df0dd2014-04-15 19:44:34 +0200649 if (!ether_addr_equal(mgmt->da, myid(&padapter->eeprompriv)) &&
650 !is_broadcast_ether_addr(mgmt->da))
Larry Finger5e93f352014-03-28 21:37:38 -0500651 return;
652
653 ptable = mlme_sta_tbl;
654
Jes Sorensen34df0dd2014-04-15 19:44:34 +0200655 stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
Larry Finger5e93f352014-03-28 21:37:38 -0500656 index = stype >> 4;
657
658 if (index > 13) {
659 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
660 ("Currently we do not support reserved sub-fr-type ="
661 "%d\n", index));
662 return;
663 }
664 ptable += index;
665
Jes Sorensen34df0dd2014-04-15 19:44:34 +0200666 psta = rtw_get_stainfo23a(&padapter->stapriv, mgmt->sa);
Larry Finger5e93f352014-03-28 21:37:38 -0500667
668 if (psta) {
Jes Sorensen34df0dd2014-04-15 19:44:34 +0200669 if (ieee80211_has_retry(mgmt->frame_control)) {
Larry Finger5e93f352014-03-28 21:37:38 -0500670 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
Tina Ruchandani5db8bee2014-10-23 20:17:20 -0700683 switch (stype) {
Larry Finger5e93f352014-03-28 21:37:38 -0500684 case IEEE80211_STYPE_AUTH:
Jes Sorensenf2f97032014-05-25 22:43:04 +0200685 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
Larry Finger5e93f352014-03-28 21:37:38 -0500686 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:
Jes Sorensenf2f97032014-05-25 22:43:04 +0200695 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
Larry Finger5e93f352014-03-28 21:37:38 -0500696 _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:
Jes Sorensenf2f97032014-05-25 22:43:04 +0200704 /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) */
Larry Finger5e93f352014-03-28 21:37:38 -0500705 _mgt_dispatcher23a(padapter, ptable, precv_frame);
706 break;
707 default:
708 _mgt_dispatcher23a(padapter, ptable, precv_frame);
Larry Finger5e93f352014-03-28 21:37:38 -0500709 break;
710 }
711#else
712 _mgt_dispatcher23a(padapter, ptable, precv_frame);
713#endif
714}
715
Larry Finger5e93f352014-03-28 21:37:38 -0500716/****************************************************************************
717
718Following are the callback functions for each subtype of the management frames
719
720*****************************************************************************/
721
Jes Sorensene0facfa2014-04-15 19:43:53 +0200722static int
723OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -0500724{
Jes Sorensen9f0e5862014-04-15 19:43:39 +0200725 const u8 *ie;
Larry Finger5e93f352014-03-28 21:37:38 -0500726 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;
Jes Sorensend3c60942014-04-15 19:44:22 +0200731 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
732 int len = skb->len;
Larry Finger5e93f352014-03-28 21:37:38 -0500733
Jes Sorensen9f0e5862014-04-15 19:43:39 +0200734 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
Larry Finger5e93f352014-03-28 21:37:38 -0500735 return _SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -0500736
Jes Sorensen9f0e5862014-04-15 19:43:39 +0200737 if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
738 !check_fwstate(pmlmepriv,
739 WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
Larry Finger5e93f352014-03-28 21:37:38 -0500740 return _SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -0500741
Jes Sorensend3c60942014-04-15 19:44:22 +0200742 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 }
Jes Sorensen9f0e5862014-04-15 19:43:39 +0200747
Jes Sorensend3c60942014-04-15 19:44:22 +0200748 len -= offsetof(struct ieee80211_mgmt, u.probe_req.variable);
749
750 ie = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.probe_req.variable, len);
Larry Finger5e93f352014-03-28 21:37:38 -0500751
752 /* check (wildcard) SSID */
Jes Sorensen9f0e5862014-04-15 19:43:39 +0200753 if (!ie)
754 goto out;
Larry Finger5e93f352014-03-28 21:37:38 -0500755
Jes Sorensen8e64bc52014-04-15 19:44:23 +0200756 if ((ie[1] && memcmp(ie + 2, cur->Ssid.ssid, cur->Ssid.ssid_len)) ||
757 (ie[1] == 0 && pmlmeinfo->hidden_ssid_mode)) {
758 return _SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -0500759 }
760
Jes Sorensen9f0e5862014-04-15 19:43:39 +0200761 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
Jes Sorensend3c60942014-04-15 19:44:22 +0200762 pmlmepriv->cur_network.join_res)
Jes Sorensen0e176852014-05-21 09:38:20 +0200763 issue_probersp(padapter, mgmt->sa, false);
Jes Sorensen9f0e5862014-04-15 19:43:39 +0200764
765out:
Larry Finger5e93f352014-03-28 21:37:38 -0500766 return _SUCCESS;
767}
768
Jes Sorensene0facfa2014-04-15 19:43:53 +0200769static int
770OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -0500771{
772 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -0500773
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
Jes Sorensene0facfa2014-04-15 19:43:53 +0200782static int
783OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -0500784{
785 int cam_idx;
786 struct sta_info *psta;
Jes Sorensenf96355b2014-04-15 19:43:57 +0200787 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -0500788 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;
Jes Sorensenee79b562014-04-15 19:43:56 +0200792 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
Jes Sorensenf96355b2014-04-15 19:43:57 +0200793 int pkt_len = skb->len;
Larry Finger5e93f352014-03-28 21:37:38 -0500794 struct wlan_bssid_ex *pbss;
795 int ret = _SUCCESS;
Jes Sorensenf96355b2014-04-15 19:43:57 +0200796 u8 *p, *pie;
797 int pie_len;
Larry Finger5e93f352014-03-28 21:37:38 -0500798 u32 ielen = 0;
799
Jes Sorensenf96355b2014-04-15 19:43:57 +0200800 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);
Jes Sorensen9af36802014-04-15 19:44:26 +0200803 if (p && ielen > 0) {
804 if (p[1 + ielen] == 0x2D && p[2 + ielen] != 0x2D) {
Larry Finger5e93f352014-03-28 21:37:38 -0500805 /* 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",
Jes Sorensenee79b562014-04-15 19:43:56 +0200812 mgmt->bssid);
Jes Sorensen9af36802014-04-15 19:44:26 +0200813 p[1] = ielen - 1;
Larry Finger5e93f352014-03-28 21:37:38 -0500814 }
815 }
816
817 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
818 report_survey_event23a(padapter, precv_frame);
819 return _SUCCESS;
820 }
821
Jes Sorensen9af36802014-04-15 19:44:26 +0200822 if (!ether_addr_equal(mgmt->bssid,
823 get_my_bssid23a(&pmlmeinfo->network)))
824 goto out;
Larry Finger5e93f352014-03-28 21:37:38 -0500825
Jes Sorensen9af36802014-04-15 19:44:26 +0200826 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
827 /* we should update current network before auth,
828 or some IE is wrong */
Jes Sorensen1bebe752014-06-09 15:16:30 +0200829 pbss = collect_bss_info(padapter, precv_frame);
Jes Sorensen9af36802014-04-15 19:44:26 +0200830 if (pbss) {
Jes Sorensen1bebe752014-06-09 15:16:30 +0200831 update_network23a(&pmlmepriv->cur_network.network, pbss,
832 padapter, true);
833 rtw_get_bcn_info23a(&pmlmepriv->cur_network);
Jes Sorensen9af36802014-04-15 19:44:26 +0200834 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 */
Jes Sorensen04fad922014-04-15 19:44:27 +0200843 rtw_update_TSF(pmlmeext, mgmt);
Jes Sorensen9af36802014-04-15 19:44:26 +0200844
845 /* start auth */
Jes Sorensen0e176852014-05-21 09:38:20 +0200846 start_clnt_auth(padapter);
Jes Sorensen9af36802014-04-15 19:44:26 +0200847
848 return _SUCCESS;
849 }
850
Jes Sorensen6ec26272014-07-17 22:59:46 +0200851 if (((pmlmeinfo->state & 0x03) == MSR_AP) &&
Jes Sorensen9af36802014-04-15 19:44:26 +0200852 (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);
Jes Sorensen17b19392014-06-09 15:16:25 +0200856 if (ret != _SUCCESS) {
Jes Sorensen9af36802014-04-15 19:44:26 +0200857 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"); */
Jes Sorensen7882ef42014-05-31 18:05:17 +0200867 update_beacon23a_info(padapter, mgmt,
Jes Sorensen9af36802014-04-15 19:44:26 +0200868 pkt_len, psta);
869 }
870 }
Jes Sorensen6ec26272014-07-17 22:59:46 +0200871 } else if ((pmlmeinfo->state&0x03) == MSR_ADHOC) {
Jes Sorensen9af36802014-04-15 19:44:26 +0200872 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"); */
Jes Sorensen7882ef42014-05-31 18:05:17 +0200879 update_beacon23a_info(padapter, mgmt,
Jes Sorensen9af36802014-04-15 19:44:26 +0200880 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 }
Larry Finger5e93f352014-03-28 21:37:38 -0500894
895 /* update TSF Value */
Jes Sorensen04fad922014-04-15 19:44:27 +0200896 rtw_update_TSF(pmlmeext, mgmt);
Larry Finger5e93f352014-03-28 21:37:38 -0500897
Jes Sorensen9af36802014-04-15 19:44:26 +0200898 /* report sta add event */
899 report_add_sta_event23a(padapter, mgmt->sa,
900 cam_idx);
Larry Finger5e93f352014-03-28 21:37:38 -0500901 }
902 }
903
Jes Sorensen9af36802014-04-15 19:44:26 +0200904out:
Larry Finger5e93f352014-03-28 21:37:38 -0500905
906 return _SUCCESS;
907}
908
Jes Sorensena402b802014-05-21 09:38:21 +0200909#ifdef CONFIG_8723AU_AP_MODE
Jes Sorensene0facfa2014-04-15 19:43:53 +0200910static int
911OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -0500912{
Larry Finger5e93f352014-03-28 21:37:38 -0500913 static struct sta_info stat;
Jes Sorensenb1b2bbb2014-04-15 19:43:40 +0200914 struct sta_info *pstat = NULL;
915 struct sta_priv *pstapriv = &padapter->stapriv;
Larry Finger5e93f352014-03-28 21:37:38 -0500916 struct security_priv *psecuritypriv = &padapter->securitypriv;
Jes Sorensenb1b2bbb2014-04-15 19:43:40 +0200917 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -0500918 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
919 struct sk_buff *skb = precv_frame->pkt;
Jes Sorensen78d23502014-04-15 19:44:33 +0200920 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;
Larry Finger5e93f352014-03-28 21:37:38 -0500926
Jes Sorensen6ec26272014-07-17 22:59:46 +0200927 if ((pmlmeinfo->state & 0x03) != MSR_AP)
Larry Finger5e93f352014-03-28 21:37:38 -0500928 return _FAIL;
929
930 DBG_8723A("+OnAuth23a\n");
931
Jes Sorensen78d23502014-04-15 19:44:33 +0200932 sa = mgmt->sa;
Larry Finger5e93f352014-03-28 21:37:38 -0500933
934 auth_mode = psecuritypriv->dot11AuthAlgrthm;
Jes Sorensenb1b2bbb2014-04-15 19:43:40 +0200935
Jes Sorensen78d23502014-04-15 19:44:33 +0200936 pframe = mgmt->u.auth.variable;
937 len = skb->len - offsetof(struct ieee80211_mgmt, u.auth.variable);
Jes Sorensenb1b2bbb2014-04-15 19:43:40 +0200938
Jes Sorensen78d23502014-04-15 19:44:33 +0200939 seq = le16_to_cpu(mgmt->u.auth.auth_transaction);
940 algorithm = le16_to_cpu(mgmt->u.auth.auth_alg);
Larry Finger5e93f352014-03-28 21:37:38 -0500941
942 DBG_8723A("auth alg =%x, seq =%X\n", algorithm, seq);
943
944 if (auth_mode == 2 &&
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200945 psecuritypriv->dot11PrivacyAlgrthm != WLAN_CIPHER_SUITE_WEP40 &&
946 psecuritypriv->dot11PrivacyAlgrthm != WLAN_CIPHER_SUITE_WEP104)
Larry Finger5e93f352014-03-28 21:37:38 -0500947 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 */
Jes Sorensen78d23502014-04-15 19:44:33 +0200951 if ((algorithm != WLAN_AUTH_OPEN && auth_mode == 0) ||
952 (algorithm == WLAN_AUTH_OPEN && auth_mode == 1)) {
Larry Finger5e93f352014-03-28 21:37:38 -0500953 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 */
Joe Perchesea072782015-03-24 11:10:09 -0700971 DBG_8723A("going to alloc stainfo for sa =%pM\n", sa);
Jes Sorensen6e8bc712014-05-09 15:03:49 +0200972 pstat = rtw_alloc_stainfo23a(pstapriv, sa, GFP_ATOMIC);
Larry Finger5e93f352014-03-28 21:37:38 -0500973 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--;
Jes Sorensenb1b2bbb2014-04-15 19:43:40 +0200990 if (pstat->expire_to > 0) {
Larry Finger5e93f352014-03-28 21:37:38 -0500991 /* 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
Jes Sorensen78d23502014-04-15 19:44:33 +02001018 if (algorithm == WLAN_AUTH_OPEN && (auth_mode == 0 || auth_mode == 2)) {
Larry Finger5e93f352014-03-28 21:37:38 -05001019 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
Jes Sorensen78d23502014-04-15 19:44:33 +02001042 p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pframe, len);
Jes Sorensenb1b2bbb2014-04-15 19:43:40 +02001043 if (!p || p[1] <= 0) {
Larry Finger5e93f352014-03-28 21:37:38 -05001044 DBG_8723A("auth rejected because challenge "
1045 "failure!(1)\n");
1046 status = WLAN_STATUS_CHALLENGE_FAIL;
1047 goto auth_fail;
1048 }
1049
Jes Sorensenb1b2bbb2014-04-15 19:43:40 +02001050 if (!memcmp(p + 2, pstat->chg_txt, 128)) {
1051 pstat->state &= ~WIFI_FW_AUTH_STATE;
Larry Finger5e93f352014-03-28 21:37:38 -05001052 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
Jes Sorensen0e176852014-05-21 09:38:20 +02001070 /* Now, we are going to issue_auth... */
Larry Finger5e93f352014-03-28 21:37:38 -05001071 pstat->auth_seq = seq + 1;
1072
Jes Sorensen0e176852014-05-21 09:38:20 +02001073 issue_auth(padapter, pstat, WLAN_STATUS_SUCCESS);
Larry Finger5e93f352014-03-28 21:37:38 -05001074
1075 if (pstat->state & WIFI_FW_AUTH_SUCCESS)
1076 pstat->auth_seq = 0;
1077
1078 return _SUCCESS;
1079
1080auth_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;
Jes Sorensended7a202014-06-09 15:16:34 +02001088 ether_addr_copy(pstat->hwaddr, sa);
Larry Finger5e93f352014-03-28 21:37:38 -05001089
Jes Sorensen0e176852014-05-21 09:38:20 +02001090 issue_auth(padapter, pstat, (unsigned short)status);
Larry Finger5e93f352014-03-28 21:37:38 -05001091
Larry Finger5e93f352014-03-28 21:37:38 -05001092 return _FAIL;
1093}
Jes Sorensena402b802014-05-21 09:38:21 +02001094#endif
Larry Finger5e93f352014-03-28 21:37:38 -05001095
Jes Sorensene0facfa2014-04-15 19:43:53 +02001096static int
1097OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05001098{
Jes Sorensen580e7562014-04-15 19:44:32 +02001099 unsigned int seq, status, algthm;
Jes Sorensen781f65c2014-04-15 19:43:41 +02001100 unsigned int go2asoc = 0;
1101 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05001102 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1103 struct sk_buff *skb = precv_frame->pkt;
Jes Sorensen580e7562014-04-15 19:44:32 +02001104 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1105 const u8 *p;
1106 u8 *pie;
1107 int plen = skb->len;
Larry Finger5e93f352014-03-28 21:37:38 -05001108
1109 DBG_8723A("%s\n", __func__);
1110
1111 /* check A1 matches or not */
Jes Sorensen580e7562014-04-15 19:44:32 +02001112 if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da))
Larry Finger5e93f352014-03-28 21:37:38 -05001113 return _SUCCESS;
1114
1115 if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
1116 return _SUCCESS;
1117
Jes Sorensen580e7562014-04-15 19:44:32 +02001118 pie = mgmt->u.auth.variable;
1119 plen -= offsetof(struct ieee80211_mgmt, u.auth.variable);
Larry Finger5e93f352014-03-28 21:37:38 -05001120
Jes Sorensen580e7562014-04-15 19:44:32 +02001121 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);
Jes Sorensen781f65c2014-04-15 19:43:41 +02001124
1125 if (status) {
Larry Finger5e93f352014-03-28 21:37:38 -05001126 DBG_8723A("clnt auth fail, status: %d\n", status);
Jes Sorensen781f65c2014-04-15 19:43:41 +02001127 /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
Jes Sorensen580e7562014-04-15 19:44:32 +02001128 if (status == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
Larry Finger5e93f352014-03-28 21:37:38 -05001129 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
Jes Sorensen781f65c2014-04-15 19:43:41 +02001140 if (seq == 2) {
1141 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
1142 /* legendary shared system */
Jes Sorensen580e7562014-04-15 19:44:32 +02001143 p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pie, plen);
Larry Finger5e93f352014-03-28 21:37:38 -05001144
Jes Sorensen781f65c2014-04-15 19:43:41 +02001145 if (!p) {
Larry Finger5e93f352014-03-28 21:37:38 -05001146 /* DBG_8723A("marc: no challenge text?\n"); */
1147 goto authclnt_fail;
1148 }
1149
Jes Sorensen781f65c2014-04-15 19:43:41 +02001150 memcpy((void *)(pmlmeinfo->chg_txt), p + 2, p[1]);
Larry Finger5e93f352014-03-28 21:37:38 -05001151 pmlmeinfo->auth_seq = 3;
Jes Sorensen0e176852014-05-21 09:38:20 +02001152 issue_auth(padapter, NULL, 0);
Larry Finger5e93f352014-03-28 21:37:38 -05001153 set_link_timer(pmlmeext, REAUTH_TO);
1154
1155 return _SUCCESS;
Jes Sorensen781f65c2014-04-15 19:43:41 +02001156 } else {
Larry Finger5e93f352014-03-28 21:37:38 -05001157 /* open system */
1158 go2asoc = 1;
1159 }
Jes Sorensen781f65c2014-04-15 19:43:41 +02001160 } else if (seq == 4) {
Larry Finger5e93f352014-03-28 21:37:38 -05001161 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
Larry Finger5e93f352014-03-28 21:37:38 -05001162 go2asoc = 1;
Larry Finger5e93f352014-03-28 21:37:38 -05001163 else
Larry Finger5e93f352014-03-28 21:37:38 -05001164 goto authclnt_fail;
Jes Sorensen781f65c2014-04-15 19:43:41 +02001165 } else {
Larry Finger5e93f352014-03-28 21:37:38 -05001166 /* this is also illegal */
Jes Sorensen781f65c2014-04-15 19:43:41 +02001167 /* DBG_8723A("marc: clnt auth failed due to illegal seq =%x\n",
1168 seq); */
Larry Finger5e93f352014-03-28 21:37:38 -05001169 goto authclnt_fail;
1170 }
1171
Jes Sorensen781f65c2014-04-15 19:43:41 +02001172 if (go2asoc) {
Larry Finger5e93f352014-03-28 21:37:38 -05001173 DBG_8723A_LEVEL(_drv_always_, "auth success, start assoc\n");
Jes Sorensen0e176852014-05-21 09:38:20 +02001174 start_clnt_assoc(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05001175 return _SUCCESS;
1176 }
1177
1178authclnt_fail:
1179
1180 /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */
1181
1182 return _FAIL;
1183}
1184
Jes Sorensen7e075832014-04-15 19:44:16 +02001185#ifdef CONFIG_8723AU_AP_MODE
1186static 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]) {
Jes Sorensen42282f42014-06-24 15:03:57 +02001205 case WLAN_OUI_TYPE_MICROSOFT_WPA:
Jes Sorensen7e075832014-04-15 19:44:16 +02001206 /* Microsoft OUI (00:50:F2) with OUI Type 1:
1207 * real WPA information element */
1208 break;
Jes Sorensen42282f42014-06-24 15:03:57 +02001209 case WLAN_OUI_TYPE_MICROSOFT_WMM:
Jes Sorensen7e075832014-04-15 19:44:16 +02001210 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;
Jes Sorensen42282f42014-06-24 15:03:57 +02001228 case WLAN_OUI_TYPE_MICROSOFT_WPS:
Jes Sorensen7e075832014-04-15 19:44:16 +02001229 /* 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
1260static 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:
Jes Sorensen42282f42014-06-24 15:03:57 +02001290 break;
Jes Sorensen7e075832014-04-15 19:44:16 +02001291 case WLAN_EID_VENDOR_SPECIFIC:
Dan Carpenter1b3b9af2014-05-09 15:04:31 +02001292 if (rtw_validate_vendor_specific_ies(pos, elen))
1293 unknown++;
Jes Sorensen7e075832014-04-15 19:44:16 +02001294 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
Jes Sorensene0facfa2014-04-15 19:43:53 +02001321static int
1322OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05001323{
1324#ifdef CONFIG_8723AU_AP_MODE
1325 u16 capab_info, listen_interval;
Larry Finger5e93f352014-03-28 21:37:38 -05001326 struct sta_info *pstat;
Jes Sorensen7d692532014-04-15 19:44:13 +02001327 unsigned char reassoc;
Jes Sorensenda290c52014-04-15 19:43:52 +02001328 int i, wpa_ie_len, left;
1329 unsigned char supportRate[16];
1330 int supportRateNum;
1331 unsigned short status = WLAN_STATUS_SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -05001332 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;
Jes Sorensenda290c52014-04-15 19:43:52 +02001339 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
Jes Sorensen7e075832014-04-15 19:44:16 +02001340 const u8 *pos, *p, *wpa_ie, *wps_ie;
Larry Finger5e93f352014-03-28 21:37:38 -05001341 u8 *pframe = skb->data;
1342 uint pkt_len = skb->len;
Jes Sorensen7d692532014-04-15 19:44:13 +02001343 int r;
Larry Finger5e93f352014-03-28 21:37:38 -05001344
Jes Sorensen6ec26272014-07-17 22:59:46 +02001345 if ((pmlmeinfo->state & 0x03) != MSR_AP)
Larry Finger5e93f352014-03-28 21:37:38 -05001346 return _FAIL;
1347
Jes Sorensenda290c52014-04-15 19:43:52 +02001348 left = pkt_len - sizeof(struct ieee80211_hdr_3addr);
1349 if (ieee80211_is_assoc_req(mgmt->frame_control)) {
Larry Finger5e93f352014-03-28 21:37:38 -05001350 reassoc = 0;
Jes Sorensenda290c52014-04-15 19:43:52 +02001351 pos = mgmt->u.assoc_req.variable;
Jes Sorensen07d2c3b2014-04-15 19:44:21 +02001352 left -= offsetof(struct ieee80211_mgmt, u.assoc_req.variable);
Larry Finger5e93f352014-03-28 21:37:38 -05001353 } else { /* WIFI_REASSOCREQ */
1354 reassoc = 1;
Jes Sorensenda290c52014-04-15 19:43:52 +02001355 pos = mgmt->u.reassoc_req.variable;
Jes Sorensen07d2c3b2014-04-15 19:44:21 +02001356 left -= offsetof(struct ieee80211_mgmt, u.reassoc_req.variable);
Larry Finger5e93f352014-03-28 21:37:38 -05001357 }
1358
Jes Sorensenda290c52014-04-15 19:43:52 +02001359 if (left < 0) {
1360 DBG_8723A("handle_assoc(reassoc =%d) - too short payload "
1361 "(len =%lu)\n", reassoc, (unsigned long)pkt_len);
Larry Finger5e93f352014-03-28 21:37:38 -05001362 return _FAIL;
1363 }
1364
Jes Sorensenda290c52014-04-15 19:43:52 +02001365 pstat = rtw_get_stainfo23a(pstapriv, mgmt->sa);
Larry Finger5e93f352014-03-28 21:37:38 -05001366 if (!pstat) {
1367 status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
1368 goto asoc_class2_error;
1369 }
1370
Jes Sorensenda290c52014-04-15 19:43:52 +02001371 /* 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);
Larry Finger5e93f352014-03-28 21:37:38 -05001376
1377 DBG_8723A("%s\n", __func__);
1378
1379 /* check if this stat has been successfully authenticated/assocated */
Jes Sorensenda290c52014-04-15 19:43:52 +02001380 if (!(pstat->state & WIFI_FW_AUTH_SUCCESS)) {
1381 if (!(pstat->state & WIFI_FW_ASSOC_SUCCESS)) {
Larry Finger5e93f352014-03-28 21:37:38 -05001382 status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
1383 goto asoc_class2_error;
Jes Sorensenda290c52014-04-15 19:43:52 +02001384 } else {
Larry Finger5e93f352014-03-28 21:37:38 -05001385 pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
1386 pstat->state |= WIFI_FW_ASSOC_STATE;
1387 }
Jes Sorensenda290c52014-04-15 19:43:52 +02001388 } else {
Larry Finger5e93f352014-03-28 21:37:38 -05001389 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 */
Jes Sorensen7e075832014-04-15 19:44:16 +02001396
1397 if (rtw_validate_frame_ies(pos, left)) {
Joe Perchesea072782015-03-24 11:10:09 -07001398 DBG_8723A("STA %pM sent invalid association request\n",
1399 pstat->hwaddr);
Larry Finger5e93f352014-03-28 21:37:38 -05001400 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1401 goto OnAssocReq23aFail;
1402 }
1403
1404 /* now we should check all the fields... */
1405 /* checking SSID */
Jes Sorensenda290c52014-04-15 19:43:52 +02001406 p = cfg80211_find_ie(WLAN_EID_SSID, pos, left);
1407 if (!p || p[1] == 0) {
Jes Sorensen49ae9a52014-04-15 19:44:14 +02001408 /* broadcast ssid, however it is not allowed in assocreq */
Joe Perchesea072782015-03-24 11:10:09 -07001409 DBG_8723A("STA %pM sent invalid association request lacking an SSID\n",
1410 pstat->hwaddr);
Larry Finger5e93f352014-03-28 21:37:38 -05001411 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
Jes Sorensen49ae9a52014-04-15 19:44:14 +02001412 goto OnAssocReq23aFail;
Jes Sorensenda290c52014-04-15 19:43:52 +02001413 } else {
Larry Finger5e93f352014-03-28 21:37:38 -05001414 /* check if ssid match */
Jes Sorensenda290c52014-04-15 19:43:52 +02001415 if (memcmp(p + 2, cur->Ssid.ssid, cur->Ssid.ssid_len))
Larry Finger5e93f352014-03-28 21:37:38 -05001416 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1417
Jes Sorensenda290c52014-04-15 19:43:52 +02001418 if (p[1] != cur->Ssid.ssid_len)
Larry Finger5e93f352014-03-28 21:37:38 -05001419 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1420 }
1421
Jes Sorensenda290c52014-04-15 19:43:52 +02001422 if (status != WLAN_STATUS_SUCCESS)
Larry Finger5e93f352014-03-28 21:37:38 -05001423 goto OnAssocReq23aFail;
1424
1425 /* check if the supported rate is ok */
Jes Sorensenda290c52014-04-15 19:43:52 +02001426 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");
Larry Finger5e93f352014-03-28 21:37:38 -05001430 /* 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 {
Jes Sorensenda290c52014-04-15 19:43:52 +02001437 memcpy(supportRate, p + 2, p[1]);
1438 supportRateNum = p[1];
Larry Finger5e93f352014-03-28 21:37:38 -05001439
Jes Sorensenda290c52014-04-15 19:43:52 +02001440 p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, pos, left);
Jes Sorensen0b682c92014-04-26 18:54:50 +02001441 if (p) {
Jes Sorensenda290c52014-04-15 19:43:52 +02001442 if (supportRateNum <= sizeof(supportRate)) {
1443 memcpy(supportRate+supportRateNum, p + 2, p[1]);
1444 supportRateNum += p[1];
Larry Finger5e93f352014-03-28 21:37:38 -05001445 }
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));
Jes Sorensen7d692532014-04-15 19:44:13 +02001465
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) {
Larry Finger5e93f352014-03-28 21:37:38 -05001472 int group_cipher = 0, pairwise_cipher = 0;
1473
Jes Sorensen7d692532014-04-15 19:44:13 +02001474 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);
Larry Finger5e93f352014-03-28 21:37:38 -05001482
Jes Sorensen7d692532014-04-15 19:44:13 +02001483 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);
Larry Finger5e93f352014-03-28 21:37:38 -05001496
Jes Sorensen7d692532014-04-15 19:44:13 +02001497 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) {
Larry Finger5e93f352014-03-28 21:37:38 -05001508 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;
Jes Sorensen7d692532014-04-15 19:44:13 +02001513 }
Larry Finger5e93f352014-03-28 21:37:38 -05001514 }
1515
Jes Sorensen7d692532014-04-15 19:44:13 +02001516 if (status != WLAN_STATUS_SUCCESS)
Larry Finger5e93f352014-03-28 21:37:38 -05001517 goto OnAssocReq23aFail;
1518
1519 pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
Jes Sorensen7d692532014-04-15 19:44:13 +02001520
1521 wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1522 WLAN_OUI_TYPE_MICROSOFT_WPS,
1523 pos, left);
1524
Jes Sorensenda290c52014-04-15 19:43:52 +02001525 if (!wpa_ie) {
Jes Sorensen7d692532014-04-15 19:44:13 +02001526 if (wps_ie) {
Jes Sorensenda290c52014-04-15 19:43:52 +02001527 DBG_8723A("STA included WPS IE in (Re)Association "
1528 "Request - assume WPS is used\n");
Larry Finger5e93f352014-03-28 21:37:38 -05001529 pstat->flags |= WLAN_STA_WPS;
1530 } else {
Jes Sorensenda290c52014-04-15 19:43:52 +02001531 DBG_8723A("STA did not include WPA/RSN IE in (Re)"
1532 "Association Request - possible WPS use\n");
Larry Finger5e93f352014-03-28 21:37:38 -05001533 pstat->flags |= WLAN_STA_MAYBE_WPS;
1534 }
Larry Finger5e93f352014-03-28 21:37:38 -05001535 } else {
1536 int copy_len;
1537
1538 if (psecuritypriv->wpa_psk == 0) {
Joe Perchesea072782015-03-24 11:10:09 -07001539 DBG_8723A("STA %pM: WPA/RSN IE in association request, but AP don't support WPA/RSN\n",
1540 pstat->hwaddr);
Larry Finger5e93f352014-03-28 21:37:38 -05001541
1542 status = WLAN_STATUS_INVALID_IE;
1543
1544 goto OnAssocReq23aFail;
1545 }
1546
Jes Sorensen7d692532014-04-15 19:44:13 +02001547 if (wps_ie) {
1548 DBG_8723A("STA included WPS IE in (Re)Association "
1549 "Request - WPS is used\n");
Larry Finger5e93f352014-03-28 21:37:38 -05001550 pstat->flags |= WLAN_STA_WPS;
1551 copy_len = 0;
1552 } else {
Jes Sorensenda290c52014-04-15 19:43:52 +02001553 copy_len = ((wpa_ie_len + 2) > sizeof(pstat->wpa_ie)) ?
1554 sizeof(pstat->wpa_ie) : (wpa_ie_len + 2);
Larry Finger5e93f352014-03-28 21:37:38 -05001555 }
1556
Jes Sorensenda290c52014-04-15 19:43:52 +02001557 if (copy_len > 0)
1558 memcpy(pstat->wpa_ie, wpa_ie - 2, copy_len);
Larry Finger5e93f352014-03-28 21:37:38 -05001559 }
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;
Jes Sorensenbd8ad4a2014-05-09 15:03:21 +02001570 if (pmlmepriv->qos_option) {
Jes Sorensen7e075832014-04-15 19:44:16 +02001571 const u8 *end = pos + left;
Yeliz Taneroglu2ce71bd2014-10-09 01:22:15 +03001572
Jes Sorensenda290c52014-04-15 19:43:52 +02001573 p = pos;
Larry Finger5e93f352014-03-28 21:37:38 -05001574
Jes Sorensenda290c52014-04-15 19:43:52 +02001575 for (;;) {
1576 left = end - p;
Jes Sorensen7c3a8f22014-06-24 15:03:58 +02001577 p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1578 WLAN_OUI_TYPE_MICROSOFT_WMM,
1579 p, left);
Jes Sorensenda290c52014-04-15 19:43:52 +02001580 if (p) {
Jes Sorensen7c3a8f22014-06-24 15:03:58 +02001581 pstat->flags |= WLAN_STA_WME;
Larry Finger5e93f352014-03-28 21:37:38 -05001582
Jes Sorensen7c3a8f22014-06-24 15:03:58 +02001583 pstat->qos_option = 1;
1584 pstat->qos_info = *(p + 8);
Larry Finger5e93f352014-03-28 21:37:38 -05001585
Jes Sorensen7c3a8f22014-06-24 15:03:58 +02001586 pstat->max_sp_len =
1587 (pstat->qos_info >> 5) & 0x3;
Larry Finger5e93f352014-03-28 21:37:38 -05001588
Jes Sorensen7c3a8f22014-06-24 15:03:58 +02001589 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);
Larry Finger5e93f352014-03-28 21:37:38 -05001597 else
Jes Sorensen7c3a8f22014-06-24 15:03:58 +02001598 pstat->uapsd_vo = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05001599
Jes Sorensen7c3a8f22014-06-24 15:03:58 +02001600 if (pstat->qos_info & BIT(1))
1601 pstat->uapsd_vi = BIT(0)|BIT(1);
1602 else
1603 pstat->uapsd_vi = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05001604
Jes Sorensen7c3a8f22014-06-24 15:03:58 +02001605 if (pstat->qos_info & BIT(2))
1606 pstat->uapsd_bk = BIT(0)|BIT(1);
1607 else
1608 pstat->uapsd_bk = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05001609
Jes Sorensen7c3a8f22014-06-24 15:03:58 +02001610 if (pstat->qos_info & BIT(3))
1611 pstat->uapsd_be = BIT(0)|BIT(1);
1612 else
1613 pstat->uapsd_be = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05001614
Jes Sorensened2be122015-03-23 16:54:08 -04001615 break;
Larry Finger5e93f352014-03-28 21:37:38 -05001616 }
Jes Sorensenda290c52014-04-15 19:43:52 +02001617 } else {
Larry Finger5e93f352014-03-28 21:37:38 -05001618 break;
1619 }
Jes Sorensenda290c52014-04-15 19:43:52 +02001620 p = p + p[1] + 2;
Larry Finger5e93f352014-03-28 21:37:38 -05001621 }
1622 }
1623
1624 /* save HT capabilities in the sta object */
1625 memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap));
Jes Sorensen57ed7bb2014-04-15 19:44:15 +02001626 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pos, left);
1627
1628 if (p && p[1] >= sizeof(struct ieee80211_ht_cap)) {
Larry Finger5e93f352014-03-28 21:37:38 -05001629 pstat->flags |= WLAN_STA_HT;
1630
1631 pstat->flags |= WLAN_STA_WME;
1632
Jes Sorensen57ed7bb2014-04-15 19:44:15 +02001633 memcpy(&pstat->htpriv.ht_cap, p + 2,
Jes Sorensenda290c52014-04-15 19:43:52 +02001634 sizeof(struct ieee80211_ht_cap));
Larry Finger5e93f352014-03-28 21:37:38 -05001635 } else
1636 pstat->flags &= ~WLAN_STA_HT;
1637
Jes Sorensen6a5f6572014-06-09 15:16:07 +02001638 if (!pmlmepriv->htpriv.ht_option && pstat->flags & WLAN_STA_HT){
Larry Finger5e93f352014-03-28 21:37:38 -05001639 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1640 goto OnAssocReq23aFail;
1641 }
1642
Jes Sorensenda290c52014-04-15 19:43:52 +02001643 if (pstat->flags & WLAN_STA_HT &&
1644 (pstat->wpa2_pairwise_cipher & WPA_CIPHER_TKIP ||
1645 pstat->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) {
Joe Perchesea072782015-03-24 11:10:09 -07001646 DBG_8723A("HT: %pM tried to use TKIP with HT association\n",
1647 pstat->hwaddr);
Larry Finger5e93f352014-03-28 21:37:38 -05001648
1649 /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
1650 /* goto OnAssocReq23aFail; */
1651 }
1652
Larry Finger5e93f352014-03-28 21:37:38 -05001653 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
Larry Finger5e93f352014-03-28 21:37:38 -05001669 /* 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;
Larry Finger5e93f352014-03-28 21:37:38 -05001694 } else {
1695 pstapriv->sta_aid[pstat->aid - 1] = pstat;
1696 DBG_8723A("allocate new AID = (%d)\n", pstat->aid);
1697 }
1698 }
1699
Jes Sorensenda290c52014-04-15 19:43:52 +02001700 pstat->state &= ~WIFI_FW_ASSOC_STATE;
Larry Finger5e93f352014-03-28 21:37:38 -05001701 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... */
Jes Sorensenda290c52014-04-15 19:43:52 +02001719 if (pstat && pstat->state & WIFI_FW_ASSOC_SUCCESS &&
1720 status == WLAN_STATUS_SUCCESS) {
Larry Finger5e93f352014-03-28 21:37:38 -05001721#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. */
Jes Sorensenda290c52014-04-15 19:43:52 +02001727 if (ieee80211_is_assoc_req(mgmt->frame_control))
Jes Sorensen6ebd2942014-05-21 09:38:14 +02001728 issue_assocrsp(padapter, status, pstat,
1729 IEEE80211_STYPE_ASSOC_RESP);
Larry Finger5e93f352014-03-28 21:37:38 -05001730 else
Jes Sorensen6ebd2942014-05-21 09:38:14 +02001731 issue_assocrsp(padapter, status, pstat,
1732 IEEE80211_STYPE_REASSOC_RESP);
Larry Finger5e93f352014-03-28 21:37:38 -05001733
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
1745asoc_class2_error:
1746
1747#ifdef CONFIG_8723AU_AP_MODE
Jes Sorensenda290c52014-04-15 19:43:52 +02001748 issue_deauth23a(padapter, mgmt->sa, status);
Larry Finger5e93f352014-03-28 21:37:38 -05001749#endif
Larry Finger5e93f352014-03-28 21:37:38 -05001750 return _FAIL;
1751
1752OnAssocReq23aFail:
1753
1754#ifdef CONFIG_8723AU_AP_MODE
1755 pstat->aid = 0;
Jes Sorensenda290c52014-04-15 19:43:52 +02001756 if (ieee80211_is_assoc_req(mgmt->frame_control))
Jes Sorensen6ebd2942014-05-21 09:38:14 +02001757 issue_assocrsp(padapter, status, pstat,
1758 IEEE80211_STYPE_ASSOC_RESP);
Larry Finger5e93f352014-03-28 21:37:38 -05001759 else
Jes Sorensen6ebd2942014-05-21 09:38:14 +02001760 issue_assocrsp(padapter, status, pstat,
1761 IEEE80211_STYPE_REASSOC_RESP);
Larry Finger5e93f352014-03-28 21:37:38 -05001762#endif
1763
1764#endif /* CONFIG_8723AU_AP_MODE */
1765
1766 return _FAIL;
1767}
1768
Jes Sorensene0facfa2014-04-15 19:43:53 +02001769static int
1770OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05001771{
Larry Finger5e93f352014-03-28 21:37:38 -05001772 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;
Jes Sorensend7a15992014-04-15 19:43:42 +02001776 struct ieee80211_mgmt *pmgmt = (struct ieee80211_mgmt *) skb->data;
Jes Sorensene1d143b2014-06-09 15:16:04 +02001777 int res;
Jes Sorensend7a15992014-04-15 19:43:42 +02001778 unsigned short status;
Jes Sorensene1d143b2014-06-09 15:16:04 +02001779 const u8 *p, *pie;
Larry Finger5e93f352014-03-28 21:37:38 -05001780 u8 *pframe = skb->data;
Jes Sorensend7a15992014-04-15 19:43:42 +02001781 int pkt_len = skb->len;
Jes Sorensene1d143b2014-06-09 15:16:04 +02001782 int pielen;
Larry Finger5e93f352014-03-28 21:37:38 -05001783
1784 DBG_8723A("%s\n", __func__);
1785
1786 /* check A1 matches or not */
Jes Sorensen6c8207a2014-04-15 19:44:31 +02001787 if (!ether_addr_equal(myid(&padapter->eeprompriv), pmgmt->da))
Larry Finger5e93f352014-03-28 21:37:38 -05001788 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 */
Jes Sorensend7a15992014-04-15 19:43:42 +02001799 status = le16_to_cpu(pmgmt->u.assoc_resp.status_code);
1800 if (status > 0) {
Larry Finger5e93f352014-03-28 21:37:38 -05001801 DBG_8723A("assoc reject, status code: %d\n", status);
Jes Sorensen6ec26272014-07-17 22:59:46 +02001802 pmlmeinfo->state = MSR_NOLINK;
Larry Finger5e93f352014-03-28 21:37:38 -05001803 res = -4;
1804 goto report_assoc_result;
1805 }
1806
1807 /* get capabilities */
Jes Sorensend7a15992014-04-15 19:43:42 +02001808 pmlmeinfo->capability = le16_to_cpu(pmgmt->u.assoc_resp.capab_info);
Larry Finger5e93f352014-03-28 21:37:38 -05001809
1810 /* set slot time */
1811 pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10))? 9: 20;
1812
1813 /* AID */
Jes Sorensend7a15992014-04-15 19:43:42 +02001814 res = pmlmeinfo->aid = le16_to_cpu(pmgmt->u.assoc_resp.aid) & 0x3fff;
Larry Finger5e93f352014-03-28 21:37:38 -05001815
Jes Sorensene1d143b2014-06-09 15:16:04 +02001816 pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
1817 pielen = pkt_len -
1818 offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
Larry Finger5e93f352014-03-28 21:37:38 -05001819
Jes Sorensene1d143b2014-06-09 15:16:04 +02001820 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)
Larry Finger5e93f352014-03-28 21:37:38 -05001841 break;
1842
Jes Sorensene1d143b2014-06-09 15:16:04 +02001843 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)
Larry Finger5e93f352014-03-28 21:37:38 -05001849 break;
Larry Finger5e93f352014-03-28 21:37:38 -05001850 }
1851
Jes Sorensene1d143b2014-06-09 15:16:04 +02001852 if (p && p[1])
1853 WMM_param_handler23a(padapter, p);
1854
Jes Sorensend7a15992014-04-15 19:43:42 +02001855 pmlmeinfo->state &= ~WIFI_FW_ASSOC_STATE;
Larry Finger5e93f352014-03-28 21:37:38 -05001856 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
1861report_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
Jes Sorensene0facfa2014-04-15 19:43:53 +02001878static int
1879OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05001880{
Jes Sorensenbe47f782014-04-15 19:43:43 +02001881 unsigned short reason;
Larry Finger5e93f352014-03-28 21:37:38 -05001882 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Jes Sorensenbe47f782014-04-15 19:43:43 +02001883 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05001884 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1885 struct sk_buff *skb = precv_frame->pkt;
Jes Sorensenbe47f782014-04-15 19:43:43 +02001886 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
Larry Finger5e93f352014-03-28 21:37:38 -05001887
Jes Sorensenbe47f782014-04-15 19:43:43 +02001888 if (!ether_addr_equal(mgmt->bssid,
1889 get_my_bssid23a(&pmlmeinfo->network)))
Larry Finger5e93f352014-03-28 21:37:38 -05001890 return _SUCCESS;
1891
Jes Sorensenbe47f782014-04-15 19:43:43 +02001892 reason = le16_to_cpu(mgmt->u.deauth.reason_code);
Larry Finger5e93f352014-03-28 21:37:38 -05001893
1894 DBG_8723A("%s Reason code(%d)\n", __func__, reason);
1895
1896#ifdef CONFIG_8723AU_AP_MODE
Jes Sorensenf2f97032014-05-25 22:43:04 +02001897 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
Larry Finger5e93f352014-03-28 21:37:38 -05001898 struct sta_info *psta;
1899 struct sta_priv *pstapriv = &padapter->stapriv;
1900
1901 DBG_8723A_LEVEL(_drv_always_, "ap recv deauth reason code(%d) "
Jes Sorensenbe47f782014-04-15 19:43:43 +02001902 "sta:%pM\n", reason, mgmt->sa);
Larry Finger5e93f352014-03-28 21:37:38 -05001903
Jes Sorensenbe47f782014-04-15 19:43:43 +02001904 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
Larry Finger5e93f352014-03-28 21:37:38 -05001905 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;
Jes Sorensenbe47f782014-04-15 19:43:43 +02001921 } else
Larry Finger5e93f352014-03-28 21:37:38 -05001922#endif
1923 {
1924 DBG_8723A_LEVEL(_drv_always_, "sta recv deauth reason code(%d) "
Jes Sorensenbe47f782014-04-15 19:43:43 +02001925 "sta:%pM\n", reason, mgmt->bssid);
Larry Finger5e93f352014-03-28 21:37:38 -05001926
Jes Sorensenbe47f782014-04-15 19:43:43 +02001927 receive_disconnect23a(padapter, mgmt->bssid, reason);
Larry Finger5e93f352014-03-28 21:37:38 -05001928 }
1929 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
Jes Sorensenbe47f782014-04-15 19:43:43 +02001930
Larry Finger5e93f352014-03-28 21:37:38 -05001931 return _SUCCESS;
1932}
1933
Jes Sorensene0facfa2014-04-15 19:43:53 +02001934static int
1935OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05001936{
Jes Sorensend54239a2014-05-31 18:05:08 +02001937 unsigned short reason;
Larry Finger5e93f352014-03-28 21:37:38 -05001938 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Jes Sorensenc8f260e2014-04-15 19:43:44 +02001939 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05001940 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1941 struct sk_buff *skb = precv_frame->pkt;
Jes Sorensenc8f260e2014-04-15 19:43:44 +02001942 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
Larry Finger5e93f352014-03-28 21:37:38 -05001943
Jes Sorensenc8f260e2014-04-15 19:43:44 +02001944 if (!ether_addr_equal(mgmt->bssid,
1945 get_my_bssid23a(&pmlmeinfo->network)))
Larry Finger5e93f352014-03-28 21:37:38 -05001946 return _SUCCESS;
1947
Jes Sorensenc8f260e2014-04-15 19:43:44 +02001948 reason = le16_to_cpu(mgmt->u.disassoc.reason_code);
Larry Finger5e93f352014-03-28 21:37:38 -05001949
Greg Donalda82b4b02014-09-08 20:50:23 -05001950 DBG_8723A("%s Reason code(%d)\n", __func__, reason);
Larry Finger5e93f352014-03-28 21:37:38 -05001951
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)"
Jes Sorensenc8f260e2014-04-15 19:43:44 +02001958 " sta:%pM\n", reason, mgmt->sa);
Larry Finger5e93f352014-03-28 21:37:38 -05001959
Jes Sorensenc8f260e2014-04-15 19:43:44 +02001960 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
Larry Finger5e93f352014-03-28 21:37:38 -05001961 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,
Jes Sorensenc8f260e2014-04-15 19:43:44 +02001969 false, reason);
Larry Finger5e93f352014-03-28 21:37:38 -05001970 }
1971 spin_unlock_bh(&pstapriv->asoc_list_lock);
1972
1973 associated_clients_update23a(padapter, updated);
1974 }
1975
1976 return _SUCCESS;
Jes Sorensenc8f260e2014-04-15 19:43:44 +02001977 } else
Larry Finger5e93f352014-03-28 21:37:38 -05001978#endif
1979 {
1980 DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason "
Jes Sorensenc8f260e2014-04-15 19:43:44 +02001981 "code(%d) sta:%pM\n", reason, mgmt->bssid);
Larry Finger5e93f352014-03-28 21:37:38 -05001982
Jes Sorensenc8f260e2014-04-15 19:43:44 +02001983 receive_disconnect23a(padapter, mgmt->bssid, reason);
Larry Finger5e93f352014-03-28 21:37:38 -05001984 }
1985 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1986 return _SUCCESS;
1987}
1988
Jes Sorensene0facfa2014-04-15 19:43:53 +02001989static int
1990OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05001991{
1992 DBG_8723A("%s\n", __func__);
1993 return _SUCCESS;
1994}
1995
Jes Sorensene0facfa2014-04-15 19:43:53 +02001996static int
1997on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05001998{
1999 return _FAIL;
2000}
2001
Jes Sorensene0facfa2014-04-15 19:43:53 +02002002static int
2003OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05002004{
2005 return _SUCCESS;
2006}
2007
Jes Sorensene0facfa2014-04-15 19:43:53 +02002008static int
2009OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05002010{
2011 return _SUCCESS;
2012}
2013
Jes Sorensene0facfa2014-04-15 19:43:53 +02002014static int OnAction23a_back23a(struct rtw_adapter *padapter,
2015 struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05002016{
2017 u8 *addr;
2018 struct sta_info *psta = NULL;
2019 struct recv_reorder_ctrl *preorder_ctrl;
Jes Sorensen7ffdc3f2014-04-15 19:43:45 +02002020 unsigned char category, action;
2021 unsigned short tid, status, capab, params, reason_code = 0;
2022 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05002023 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2024 struct sk_buff *skb = precv_frame->pkt;
Jes Sorensen7ffdc3f2014-04-15 19:43:45 +02002025 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
Larry Finger5e93f352014-03-28 21:37:38 -05002026 struct sta_priv *pstapriv = &padapter->stapriv;
2027
2028 /* check RA matches or not */
Jes Sorensen7ffdc3f2014-04-15 19:43:45 +02002029 if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da))
Larry Finger5e93f352014-03-28 21:37:38 -05002030 return _SUCCESS;
2031
2032 DBG_8723A("%s\n", __func__);
2033
Jes Sorensen6ec26272014-07-17 22:59:46 +02002034 if ((pmlmeinfo->state&0x03) != MSR_AP)
Larry Finger5e93f352014-03-28 21:37:38 -05002035 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
2036 return _SUCCESS;
2037
Jes Sorensen7ffdc3f2014-04-15 19:43:45 +02002038 addr = mgmt->sa;
Larry Finger5e93f352014-03-28 21:37:38 -05002039 psta = rtw_get_stainfo23a(pstapriv, addr);
2040
2041 if (!psta)
2042 return _SUCCESS;
2043
Jes Sorensen7ffdc3f2014-04-15 19:43:45 +02002044 category = mgmt->u.action.category;
Larry Finger5e93f352014-03-28 21:37:38 -05002045 if (category == WLAN_CATEGORY_BACK) { /* representing Block Ack */
2046 if (!pmlmeinfo->HT_enable)
2047 return _SUCCESS;
Jes Sorensenb30f74e2014-04-15 19:44:30 +02002048 /* 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;
Larry Finger5e93f352014-03-28 21:37:38 -05002051 DBG_8723A("%s, action =%d\n", __func__, action);
2052 switch (action) {
2053 case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
Jes Sorensenb30f74e2014-04-15 19:44:30 +02002054 memcpy(&pmlmeinfo->ADDBA_req,
2055 &mgmt->u.action.u.addba_req.dialog_token,
Larry Finger5e93f352014-03-28 21:37:38 -05002056 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 */
Jes Sorensen7ffdc3f2014-04-15 19:43:45 +02002069 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;
Larry Finger5e93f352014-03-28 21:37:38 -05002074 if (status == 0) { /* successful */
2075 DBG_8723A("agg_enable for TID =%d\n", tid);
Jes Sorensen072fc842014-05-09 15:04:14 +02002076 psta->htpriv.agg_enable_bitmap |= BIT(tid);
2077 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
Larry Finger5e93f352014-03-28 21:37:38 -05002078 } else
Jes Sorensen072fc842014-05-09 15:04:14 +02002079 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
Larry Finger5e93f352014-03-28 21:37:38 -05002080 break;
2081
2082 case WLAN_ACTION_DELBA: /* DELBA */
Jes Sorensen7ffdc3f2014-04-15 19:43:45 +02002083 params = get_unaligned_le16(
2084 &mgmt->u.action.u.delba.params);
2085 tid = params >> 12;
Larry Finger5e93f352014-03-28 21:37:38 -05002086
Jes Sorensen7ffdc3f2014-04-15 19:43:45 +02002087 if (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) {
2088 preorder_ctrl = &psta->recvreorder_ctrl[tid];
Larry Finger5e93f352014-03-28 21:37:38 -05002089 preorder_ctrl->enable = false;
2090 preorder_ctrl->indicate_seq = 0xffff;
Jes Sorensen7ffdc3f2014-04-15 19:43:45 +02002091 } else {
Jes Sorensen072fc842014-05-09 15:04:14 +02002092 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
2093 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
Larry Finger5e93f352014-03-28 21:37:38 -05002094 }
Jes Sorensen7ffdc3f2014-04-15 19:43:45 +02002095 reason_code = get_unaligned_le16(
2096 &mgmt->u.action.u.delba.reason_code);
Larry Finger5e93f352014-03-28 21:37:38 -05002097 /* todo: how to notify the host while receiving
2098 DELETE BA */
2099 break;
2100 default:
2101 break;
2102 }
2103 }
2104 return _SUCCESS;
2105}
2106
Jes Sorensene0facfa2014-04-15 19:43:53 +02002107static int on_action_public23a(struct rtw_adapter *padapter,
2108 struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05002109{
Larry Finger5e93f352014-03-28 21:37:38 -05002110 struct sk_buff *skb = precv_frame->pkt;
2111 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2112 u8 *pframe = skb->data;
Jes Sorensen2e74d332014-06-09 15:16:17 +02002113 int freq, channel;
Larry Finger5e93f352014-03-28 21:37:38 -05002114
2115 /* check RA matches or not */
2116 if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
Jes Sorensen2e74d332014-06-09 15:16:17 +02002117 return _FAIL;
Larry Finger5e93f352014-03-28 21:37:38 -05002118
Jes Sorensen2e74d332014-06-09 15:16:17 +02002119 channel = rtw_get_oper_ch23a(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05002120
Jes Sorensen2e74d332014-06-09 15:16:17 +02002121 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);
Larry Finger5e93f352014-03-28 21:37:38 -05002127
Jes Sorensen2e74d332014-06-09 15:16:17 +02002128 if (cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pframe,
Vladimir Kondratiev970fdfa2014-08-11 03:29:57 -07002129 skb->len, 0))
Jes Sorensen2e74d332014-06-09 15:16:17 +02002130 return _SUCCESS;
2131
2132 return _FAIL;
Larry Finger5e93f352014-03-28 21:37:38 -05002133}
2134
Jes Sorensene0facfa2014-04-15 19:43:53 +02002135static int
2136OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05002137{
2138 return _SUCCESS;
2139}
2140
Jes Sorensene0facfa2014-04-15 19:43:53 +02002141static int
2142OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05002143{
2144 return _SUCCESS;
2145}
2146
Jes Sorensene0facfa2014-04-15 19:43:53 +02002147static int
2148OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05002149{
Larry Finger5e93f352014-03-28 21:37:38 -05002150 return _SUCCESS;
2151}
2152
Jes Sorensene0facfa2014-04-15 19:43:53 +02002153static int
2154OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05002155{
2156 int i;
Jes Sorensenf5f05712014-04-15 19:44:29 +02002157 u8 category;
Larry Finger5e93f352014-03-28 21:37:38 -05002158 struct action_handler *ptable;
Larry Finger5e93f352014-03-28 21:37:38 -05002159 struct sk_buff *skb = precv_frame->pkt;
Jes Sorensenf5f05712014-04-15 19:44:29 +02002160 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
Larry Finger5e93f352014-03-28 21:37:38 -05002161
Jes Sorensenf5f05712014-04-15 19:44:29 +02002162 category = mgmt->u.action.category;
Larry Finger5e93f352014-03-28 21:37:38 -05002163
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
Larry Fingerc0b99be2014-04-26 18:55:17 +02002175static int DoReserved23a(struct rtw_adapter *padapter,
2176 struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05002177{
2178 return _SUCCESS;
2179}
2180
2181struct 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) {
Jes Sorensen9cd613c2014-05-09 15:04:03 +02002189 DBG_8723A("%s(%s): alloc xmitframe fail\n", __func__,
2190 pxmitpriv->adapter->pnetdev->name);
Larry Finger5e93f352014-03-28 21:37:38 -05002191 goto exit;
2192 }
2193
2194 pxmitbuf = rtw_alloc_xmitbuf23a_ext(pxmitpriv);
2195 if (!pxmitbuf) {
Jes Sorensen9cd613c2014-05-09 15:04:03 +02002196 DBG_8723A("%s(%s): alloc xmitbuf fail\n", __func__,
2197 pxmitpriv->adapter->pnetdev->name);
Larry Finger5e93f352014-03-28 21:37:38 -05002198 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
2208exit:
2209 return pmgntframe;
2210}
2211
2212/****************************************************************************
2213
Masanari Iidafae062a2014-07-22 23:42:13 +09002214Following are some TX functions for WiFi MLME
Larry Finger5e93f352014-03-28 21:37:38 -05002215
2216*****************************************************************************/
2217
2218void 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
2226void 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
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02002246 pattrib->encrypt = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05002247 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
2260void dump_mgntframe23a(struct rtw_adapter *padapter,
2261 struct xmit_frame *pmgntframe)
2262{
2263 if (padapter->bSurpriseRemoved == true ||
2264 padapter->bDriverStopped == true)
2265 return;
2266
Jes Sorensen638443d2014-05-16 10:04:18 +02002267 rtl8723au_mgnt_xmit(padapter, pmgntframe);
Larry Finger5e93f352014-03-28 21:37:38 -05002268}
2269
Jes Sorensenf66e05d2014-05-16 10:04:34 +02002270int dump_mgntframe23a_and_wait(struct rtw_adapter *padapter,
Larry Finger5e93f352014-03-28 21:37:38 -05002271 struct xmit_frame *pmgntframe, int timeout_ms)
2272{
Jes Sorensenf66e05d2014-05-16 10:04:34 +02002273 int ret = _FAIL;
Larry Finger5e93f352014-03-28 21:37:38 -05002274 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
Jes Sorensen638443d2014-05-16 10:04:18 +02002286 ret = rtl8723au_mgnt_xmit(padapter, pmgntframe);
Larry Finger5e93f352014-03-28 21:37:38 -05002287
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
Jes Sorensenf66e05d2014-05-16 10:04:34 +02002298int dump_mgntframe23a_and_wait_ack23a(struct rtw_adapter *padapter,
Larry Finger5e93f352014-03-28 21:37:38 -05002299 struct xmit_frame *pmgntframe)
2300{
Jes Sorensenf66e05d2014-05-16 10:04:34 +02002301 int ret = _FAIL;
Larry Finger5e93f352014-03-28 21:37:38 -05002302 u32 timeout_ms = 500;/* 500ms */
2303 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2304
2305 if (padapter->bSurpriseRemoved == true ||
2306 padapter->bDriverStopped == true)
Jes Sorensenf66e05d2014-05-16 10:04:34 +02002307 return _FAIL;
Larry Finger5e93f352014-03-28 21:37:38 -05002308
2309 mutex_lock(&pxmitpriv->ack_tx_mutex);
2310 pxmitpriv->ack_tx = true;
2311
2312 pmgntframe->ack_report = 1;
Jes Sorensen638443d2014-05-16 10:04:18 +02002313 if (rtl8723au_mgnt_xmit(padapter, pmgntframe) == _SUCCESS)
Larry Finger5e93f352014-03-28 21:37:38 -05002314 ret = rtw_ack_tx_wait23a(pxmitpriv, timeout_ms);
Larry Finger5e93f352014-03-28 21:37:38 -05002315
2316 pxmitpriv->ack_tx = false;
2317 mutex_unlock(&pxmitpriv->ack_tx_mutex);
2318
2319 return ret;
2320}
2321
2322static 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) {
Tina Ruchandani5db8bee2014-10-23 20:17:20 -07002336 switch (hidden_ssid_mode) {
Larry Finger5e93f352014-03-28 21:37:38 -05002337 case 1:
2338 next_ie = ssid_ie + 2 + ssid_len_ori;
Larry Finger5e93f352014-03-28 21:37:38 -05002339 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
2357void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms)
2358{
2359 struct xmit_frame *pmgntframe;
2360 struct pkt_attrib *pattrib;
2361 unsigned char *pframe;
Jes Sorensen5d431822014-06-19 11:37:28 +02002362 struct ieee80211_mgmt *mgmt;
Larry Finger5e93f352014-03-28 21:37:38 -05002363 unsigned int rate_len;
2364 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05002365 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Larry Finger5e93f352014-03-28 21:37:38 -05002366 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};
Jes Sorensen6e5e4182014-06-09 15:15:54 +02002370 const u8 *wps_ie;
Larry Finger5e93f352014-03-28 21:37:38 -05002371 u8 sr = 0;
2372 int len_diff;
2373
2374 /* DBG_8723A("%s\n", __func__); */
2375
Jes Sorensend0fc1462014-05-25 22:43:36 +02002376 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2377 if (!pmgntframe) {
Larry Finger5e93f352014-03-28 21:37:38 -05002378 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;
Jes Sorensen5d431822014-06-19 11:37:28 +02002393 mgmt = (struct ieee80211_mgmt *)pframe;
Larry Finger5e93f352014-03-28 21:37:38 -05002394
Jes Sorensen5d431822014-06-19 11:37:28 +02002395 mgmt->frame_control =
2396 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
2397 mgmt->seq_ctrl = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05002398
Jes Sorensen5d431822014-06-19 11:37:28 +02002399 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));
Jes Sorensenb81d36c2014-06-19 11:37:27 +02002402
2403 /* timestamp will be inserted by hardware */
Jes Sorensenb81d36c2014-06-19 11:37:27 +02002404
Jes Sorensen5d431822014-06-19 11:37:28 +02002405 put_unaligned_le16(cur_network->beacon_interval,
2406 &mgmt->u.beacon.beacon_int);
Jes Sorensenb81d36c2014-06-19 11:37:27 +02002407
Jes Sorensen5d431822014-06-19 11:37:28 +02002408 put_unaligned_le16(cur_network->capability,
2409 &mgmt->u.beacon.capab_info);
Jes Sorensenb81d36c2014-06-19 11:37:27 +02002410
Jes Sorensen5d431822014-06-19 11:37:28 +02002411 pframe = mgmt->u.beacon.variable;
2412 pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
Jes Sorensenb81d36c2014-06-19 11:37:27 +02002413
Jes Sorensen6ec26272014-07-17 22:59:46 +02002414 if ((pmlmeinfo->state & 0x03) == MSR_AP) {
Jes Sorensen6e5e4182014-06-09 15:15:54 +02002415 u8 *iebuf;
2416 int buflen;
Larry Finger5e93f352014-03-28 21:37:38 -05002417 /* DBG_8723A("ie len =%d\n", cur_network->IELength); */
Jes Sorensen98fb8122014-04-15 19:43:35 +02002418 memcpy(pframe, cur_network->IEs, cur_network->IELength);
Jes Sorensen1de65cc2014-06-24 15:03:30 +02002419 len_diff = update_hidden_ssid(pframe, cur_network->IELength,
Larry Finger5e93f352014-03-28 21:37:38 -05002420 pmlmeinfo->hidden_ssid_mode);
2421 pframe += (cur_network->IELength+len_diff);
2422 pattrib->pktlen += (cur_network->IELength+len_diff);
2423
Jes Sorensen0f728f12014-06-24 15:03:27 +02002424 iebuf = mgmt->u.beacon.variable;
2425 buflen = pattrib->pktlen -
2426 offsetof(struct ieee80211_mgmt, u.beacon.variable);
Jes Sorensen6e5e4182014-06-09 15:15:54 +02002427 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],
Larry Finger5e93f352014-03-28 21:37:38 -05002433 WPS_ATTR_SELECTED_REGISTRAR,
Greg Donald7e6646d2014-09-06 19:42:03 -05002434 (u8 *)&sr);
Larry Finger5e93f352014-03-28 21:37:38 -05002435 }
2436 if (sr != 0)
2437 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
2438 else
2439 _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
2440
Larry Finger5e93f352014-03-28 21:37:38 -05002441 goto _issue_bcn;
2442 }
2443
Larry Finger5e93f352014-03-28 21:37:38 -05002444 /* SSID */
Jes Sorensen5afd3912014-04-15 19:43:24 +02002445 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
2446 cur_network->Ssid.ssid_len,
Larry Finger5e93f352014-03-28 21:37:38 -05002447 cur_network->Ssid.ssid, &pattrib->pktlen);
2448
2449 /* supported rates... */
2450 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
Jes Sorensen5afd3912014-04-15 19:43:24 +02002451 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
Larry Finger5e93f352014-03-28 21:37:38 -05002452 ((rate_len > 8)? 8: rate_len),
2453 cur_network->SupportedRates, &pattrib->pktlen);
2454
2455 /* DS parameter set */
Jes Sorensen5afd3912014-04-15 19:43:24 +02002456 pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)
Jes Sorensen37cb9822014-05-21 09:37:40 +02002457 &cur_network->DSConfig, &pattrib->pktlen);
Larry Finger5e93f352014-03-28 21:37:38 -05002458
Jes Sorensen6ec26272014-07-17 22:59:46 +02002459 /* if ((pmlmeinfo->state&0x03) == MSR_ADHOC) */
Larry Finger5e93f352014-03-28 21:37:38 -05002460 {
2461 u8 erpinfo = 0;
2462 u32 ATIMWindow;
2463 /* IBSS Parameter Set... */
Jes Sorensen37cb9822014-05-21 09:37:40 +02002464 /* ATIMWindow = cur->ATIMWindow; */
Larry Finger5e93f352014-03-28 21:37:38 -05002465 ATIMWindow = 0;
Jes Sorensen5afd3912014-04-15 19:43:24 +02002466 pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
Larry Finger5e93f352014-03-28 21:37:38 -05002467 (unsigned char *)&ATIMWindow,
2468 &pattrib->pktlen);
2469
2470 /* ERP IE */
Jes Sorensen5afd3912014-04-15 19:43:24 +02002471 pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1,
Larry Finger5e93f352014-03-28 21:37:38 -05002472 &erpinfo, &pattrib->pktlen);
2473 }
2474
2475 /* EXTERNDED SUPPORTED RATE */
2476 if (rate_len > 8)
Jes Sorensen5afd3912014-04-15 19:43:24 +02002477 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
Larry Finger5e93f352014-03-28 21:37:38 -05002478 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
Jes Sorensen0e176852014-05-21 09:38:20 +02002506static void issue_probersp(struct rtw_adapter *padapter, unsigned char *da,
2507 u8 is_valid_p2p_probereq)
Larry Finger5e93f352014-03-28 21:37:38 -05002508{
2509 struct xmit_frame *pmgntframe;
2510 struct pkt_attrib *pattrib;
2511 unsigned char *pframe;
Jes Sorensen08519032014-06-19 11:37:29 +02002512 struct ieee80211_mgmt *mgmt;
Larry Finger5e93f352014-03-28 21:37:38 -05002513 unsigned char *mac, *bssid;
2514 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2515#ifdef CONFIG_8723AU_AP_MODE
Jes Sorensen6e5e4182014-06-09 15:15:54 +02002516 const u8 *pwps_ie;
Larry Fingerc17416e2014-03-28 21:37:42 -05002517 u8 *ssid_ie;
2518 int ssid_ielen;
2519 int ssid_ielen_diff;
2520 u8 buf[MAX_IE_SZ];
Larry Finger5e93f352014-03-28 21:37:38 -05002521#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;
Larry Finger5e93f352014-03-28 21:37:38 -05002526
2527 /* DBG_8723A("%s\n", __func__); */
2528
Jes Sorensen08519032014-06-19 11:37:29 +02002529 if (cur_network->IELength > MAX_IE_SZ)
2530 return;
2531
Jes Sorensen858e6652014-04-15 19:43:51 +02002532 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2533 if (!pmgntframe) {
Larry Finger5e93f352014-03-28 21:37:38 -05002534 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
Jes Sorensen858e6652014-04-15 19:43:51 +02002544 pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
Jes Sorensen08519032014-06-19 11:37:29 +02002545 mgmt = (struct ieee80211_mgmt *)pframe;
Larry Finger5e93f352014-03-28 21:37:38 -05002546
2547 mac = myid(&padapter->eeprompriv);
2548 bssid = cur_network->MacAddress;
2549
Jes Sorensen08519032014-06-19 11:37:29 +02002550 mgmt->frame_control =
2551 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
Jes Sorensenaeda8252014-05-21 09:37:59 +02002552
Jes Sorensen08519032014-06-19 11:37:29 +02002553 ether_addr_copy(mgmt->da, da);
2554 ether_addr_copy(mgmt->sa, mac);
2555 ether_addr_copy(mgmt->bssid, bssid);
Larry Finger5e93f352014-03-28 21:37:38 -05002556
Jes Sorensen08519032014-06-19 11:37:29 +02002557 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
Larry Finger5e93f352014-03-28 21:37:38 -05002558 pmlmeext->mgnt_seq++;
Larry Finger5e93f352014-03-28 21:37:38 -05002559
2560 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
Larry Finger5e93f352014-03-28 21:37:38 -05002561
Jes Sorensen08519032014-06-19 11:37:29 +02002562 /* 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 */
Larry Finger5e93f352014-03-28 21:37:38 -05002574
2575#ifdef CONFIG_8723AU_AP_MODE
Jes Sorensen6ec26272014-07-17 22:59:46 +02002576 if ((pmlmeinfo->state & 0x03) == MSR_AP) {
Jes Sorensen6e5e4182014-06-09 15:15:54 +02002577 pwps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
2578 WLAN_OUI_TYPE_MICROSOFT_WPS,
Jes Sorensen1de65cc2014-06-24 15:03:30 +02002579 cur_network->IEs,
2580 cur_network->IELength);
Larry Finger5e93f352014-03-28 21:37:38 -05002581
Jes Sorensen1de65cc2014-06-24 15:03:30 +02002582 memcpy(pframe, cur_network->IEs, cur_network->IELength);
Jes Sorensen86bbac62014-06-21 16:50:11 +02002583 pframe += cur_network->IELength;
2584 pattrib->pktlen += cur_network->IELength;
Larry Finger5e93f352014-03-28 21:37:38 -05002585
2586 /* retrieve SSID IE from cur_network->Ssid */
Larry Finger5e93f352014-03-28 21:37:38 -05002587
Jes Sorensenad8686b2014-06-21 16:50:19 +02002588 ssid_ie = rtw_get_ie23a(mgmt->u.probe_resp.variable,
2589 WLAN_EID_SSID, &ssid_ielen,
2590 pframe - mgmt->u.probe_resp.variable);
Larry Finger5e93f352014-03-28 21:37:38 -05002591
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;
Yeliz Taneroglu2ce71bd2014-10-09 01:22:15 +03002597
Larry Finger5e93f352014-03-28 21:37:38 -05002598 remainder_ie = ssid_ie + 2;
Yeliz Taneroglu2ce71bd2014-10-09 01:22:15 +03002599
Jes Sorensen858e6652014-04-15 19:43:51 +02002600 remainder_ielen = pframe - remainder_ie;
Larry Finger5e93f352014-03-28 21:37:38 -05002601
Jes Sorensen9cd613c2014-05-09 15:04:03 +02002602 DBG_8723A_LEVEL(_drv_warning_, "%s(%s): "
2603 "remainder_ielen > MAX_IE_SZ\n",
2604 __func__, padapter->pnetdev->name);
Jes Sorensen858e6652014-04-15 19:43:51 +02002605 if (remainder_ielen > MAX_IE_SZ)
Larry Finger5e93f352014-03-28 21:37:38 -05002606 remainder_ielen = MAX_IE_SZ;
Larry Finger5e93f352014-03-28 21:37:38 -05002607
2608 memcpy(buf, remainder_ie, remainder_ielen);
Jes Sorensen858e6652014-04-15 19:43:51 +02002609 memcpy(remainder_ie + ssid_ielen_diff, buf,
Larry Finger5e93f352014-03-28 21:37:38 -05002610 remainder_ielen);
Jes Sorensen858e6652014-04-15 19:43:51 +02002611 *(ssid_ie + 1) = cur_network->Ssid.ssid_len;
2612 memcpy(ssid_ie + 2, cur_network->Ssid.ssid,
Larry Finger5e93f352014-03-28 21:37:38 -05002613 cur_network->Ssid.ssid_len);
2614
2615 pframe += ssid_ielen_diff;
2616 pattrib->pktlen += ssid_ielen_diff;
2617 }
2618 } else
2619#endif
2620 {
Larry Finger5e93f352014-03-28 21:37:38 -05002621 /* SSID */
Jes Sorensen5afd3912014-04-15 19:43:24 +02002622 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
Jes Sorensen858e6652014-04-15 19:43:51 +02002623 cur_network->Ssid.ssid_len,
2624 cur_network->Ssid.ssid,
2625 &pattrib->pktlen);
Larry Finger5e93f352014-03-28 21:37:38 -05002626
2627 /* supported rates... */
2628 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
Jes Sorensen5afd3912014-04-15 19:43:24 +02002629 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
Larry Finger5e93f352014-03-28 21:37:38 -05002630 ((rate_len > 8)? 8: rate_len),
2631 cur_network->SupportedRates,
2632 &pattrib->pktlen);
2633
2634 /* DS parameter set */
Jes Sorensen5afd3912014-04-15 19:43:24 +02002635 pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1,
Jes Sorensen37cb9822014-05-21 09:37:40 +02002636 (unsigned char *)&cur_network->DSConfig,
Larry Finger5e93f352014-03-28 21:37:38 -05002637 &pattrib->pktlen);
2638
Jes Sorensen6ec26272014-07-17 22:59:46 +02002639 if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) {
Larry Finger5e93f352014-03-28 21:37:38 -05002640 u8 erpinfo = 0;
2641 u32 ATIMWindow;
2642 /* IBSS Parameter Set... */
Jes Sorensen37cb9822014-05-21 09:37:40 +02002643 /* ATIMWindow = cur->ATIMWindow; */
Larry Finger5e93f352014-03-28 21:37:38 -05002644 ATIMWindow = 0;
Jes Sorensen5afd3912014-04-15 19:43:24 +02002645 pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
Larry Finger5e93f352014-03-28 21:37:38 -05002646 (unsigned char *)&ATIMWindow,
2647 &pattrib->pktlen);
2648
2649 /* ERP IE */
Jes Sorensen5afd3912014-04-15 19:43:24 +02002650 pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1,
Larry Finger5e93f352014-03-28 21:37:38 -05002651 &erpinfo, &pattrib->pktlen);
2652 }
2653
2654 /* EXTERNDED SUPPORTED RATE */
2655 if (rate_len > 8)
Jes Sorensen5afd3912014-04-15 19:43:24 +02002656 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
Larry Finger5e93f352014-03-28 21:37:38 -05002657 rate_len - 8,
2658 cur_network->SupportedRates + 8,
2659 &pattrib->pktlen);
2660
2661 /* todo:HT for adhoc */
2662 }
2663
Larry Finger5e93f352014-03-28 21:37:38 -05002664 pattrib->last_txcmdsz = pattrib->pktlen;
2665
2666 dump_mgntframe23a(padapter, pmgntframe);
2667
2668 return;
2669}
2670
Jes Sorensen0e176852014-05-21 09:38:20 +02002671static int _issue_probereq(struct rtw_adapter *padapter,
2672 struct cfg80211_ssid *pssid, u8 *da, int wait_ack)
Larry Finger5e93f352014-03-28 21:37:38 -05002673{
2674 int ret = _FAIL;
Jes Sorensend54239a2014-05-31 18:05:08 +02002675 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];
Larry Finger5e93f352014-03-28 21:37:38 -05002681 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2682 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2683 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Jes Sorensend54239a2014-05-31 18:05:08 +02002684 int bssrate_len = 0;
2685 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Larry Finger5e93f352014-03-28 21:37:38 -05002686
2687 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
Jes Sorensen0e176852014-05-21 09:38:20 +02002688 ("+%s\n", __func__));
Larry Finger5e93f352014-03-28 21:37:38 -05002689
Jes Sorensend0fc1462014-05-25 22:43:36 +02002690 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2691 if (!pmgntframe)
Larry Finger5e93f352014-03-28 21:37:38 -05002692 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
Jes Sorensenc2bfb142014-05-21 09:38:12 +02002705 pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
2706 IEEE80211_STYPE_PROBE_REQ);
Larry Finger5e93f352014-03-28 21:37:38 -05002707
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
Jes Sorensenaeda8252014-05-21 09:37:59 +02002720 pwlanhdr->seq_ctrl =
2721 cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2722
Larry Finger5e93f352014-03-28 21:37:38 -05002723 pmlmeext->mgnt_seq++;
Larry Finger5e93f352014-03-28 21:37:38 -05002724
2725 pframe += sizeof (struct ieee80211_hdr_3addr);
2726 pattrib->pktlen = sizeof (struct ieee80211_hdr_3addr);
2727
2728 if (pssid)
Jes Sorensen5afd3912014-04-15 19:43:24 +02002729 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, pssid->ssid_len,
Larry Finger5e93f352014-03-28 21:37:38 -05002730 pssid->ssid, &pattrib->pktlen);
2731 else
Jes Sorensen5afd3912014-04-15 19:43:24 +02002732 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, 0, NULL,
Larry Finger5e93f352014-03-28 21:37:38 -05002733 &pattrib->pktlen);
2734
2735 get_rate_set23a(padapter, bssrate, &bssrate_len);
2736
2737 if (bssrate_len > 8) {
Jes Sorensen5afd3912014-04-15 19:43:24 +02002738 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
Larry Finger5e93f352014-03-28 21:37:38 -05002739 bssrate, &pattrib->pktlen);
Jes Sorensen5afd3912014-04-15 19:43:24 +02002740 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
Larry Finger5e93f352014-03-28 21:37:38 -05002741 (bssrate_len - 8), (bssrate + 8),
2742 &pattrib->pktlen);
2743 } else {
Jes Sorensen5afd3912014-04-15 19:43:24 +02002744 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
Larry Finger5e93f352014-03-28 21:37:38 -05002745 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
2768exit:
2769 return ret;
2770}
2771
Jes Sorensen0e176852014-05-21 09:38:20 +02002772static inline void issue_probereq(struct rtw_adapter *padapter,
2773 struct cfg80211_ssid *pssid, u8 *da)
Larry Finger5e93f352014-03-28 21:37:38 -05002774{
Jes Sorensen0e176852014-05-21 09:38:20 +02002775 _issue_probereq(padapter, pssid, da, false);
Larry Finger5e93f352014-03-28 21:37:38 -05002776}
2777
Jes Sorensen0e176852014-05-21 09:38:20 +02002778static int issue_probereq_ex(struct rtw_adapter *padapter,
2779 struct cfg80211_ssid *pssid, u8 *da,
2780 int try_cnt, int wait_ms)
Larry Finger5e93f352014-03-28 21:37:38 -05002781{
2782 int ret;
2783 int i = 0;
2784 unsigned long start = jiffies;
2785
2786 do {
Jes Sorensen0e176852014-05-21 09:38:20 +02002787 ret = _issue_probereq(padapter, pssid, da,
2788 wait_ms > 0 ? true : false);
Larry Finger5e93f352014-03-28 21:37:38 -05002789
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)
Joe Perchesea072782015-03-24 11:10:09 -07002807 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,
Larry Finger5e93f352014-03-28 21:37:38 -05002811 jiffies_to_msecs(jiffies - start));
2812 else
Jes Sorensen9cd613c2014-05-09 15:04:03 +02002813 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
2814 __func__, padapter->pnetdev->name,
Larry Finger5e93f352014-03-28 21:37:38 -05002815 rtw_get_oper_ch23a(padapter),
Joe Perchesea072782015-03-24 11:10:09 -07002816 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
Larry Finger5e93f352014-03-28 21:37:38 -05002817 jiffies_to_msecs(jiffies - start));
2818 }
2819exit:
2820 return ret;
2821}
2822
2823/* if psta == NULL, indiate we are station(client) now... */
Jes Sorensen0e176852014-05-21 09:38:20 +02002824static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta,
2825 unsigned short status)
Larry Finger5e93f352014-03-28 21:37:38 -05002826{
2827 struct xmit_frame *pmgntframe;
2828 struct pkt_attrib *pattrib;
2829 unsigned char *pframe;
Jes Sorensen88e06f02014-06-09 15:16:09 +02002830 struct ieee80211_mgmt *mgmt;
Larry Finger5e93f352014-03-28 21:37:38 -05002831 unsigned int val32;
Jes Sorensen88e06f02014-06-09 15:16:09 +02002832 u16 auth_algo;
Larry Finger5e93f352014-03-28 21:37:38 -05002833 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
Jes Sorensend0fc1462014-05-25 22:43:36 +02002838 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2839 if (!pmgntframe)
Larry Finger5e93f352014-03-28 21:37:38 -05002840 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;
Jes Sorensen88e06f02014-06-09 15:16:09 +02002849 mgmt = (struct ieee80211_mgmt *)pframe;
Larry Finger5e93f352014-03-28 21:37:38 -05002850
Jes Sorensen88e06f02014-06-09 15:16:09 +02002851 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));
Larry Finger5e93f352014-03-28 21:37:38 -05002854 pmlmeext->mgnt_seq++;
Jes Sorensenaeda8252014-05-21 09:37:59 +02002855
Jes Sorensen88e06f02014-06-09 15:16:09 +02002856 pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.auth.variable);
Larry Finger5e93f352014-03-28 21:37:38 -05002857
2858 if (psta) { /* for AP mode */
2859#ifdef CONFIG_8723AU_AP_MODE
Jes Sorensenda237322014-06-09 15:17:06 +02002860 unsigned short val16;
Yeliz Taneroglu2ce71bd2014-10-09 01:22:15 +03002861
Jes Sorensen88e06f02014-06-09 15:16:09 +02002862 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));
Larry Finger5e93f352014-03-28 21:37:38 -05002865
2866 /* setting auth algo number */
2867 val16 = (u16)psta->authalg;
2868
2869 if (status != WLAN_STATUS_SUCCESS)
2870 val16 = 0;
2871
Jes Sorensen88e06f02014-06-09 15:16:09 +02002872 if (val16)
Larry Finger5e93f352014-03-28 21:37:38 -05002873 use_shared_key = 1;
Larry Finger5e93f352014-03-28 21:37:38 -05002874
Jes Sorensen88e06f02014-06-09 15:16:09 +02002875 mgmt->u.auth.auth_alg = cpu_to_le16(val16);
Larry Finger5e93f352014-03-28 21:37:38 -05002876
2877 /* setting auth seq number */
Jes Sorensen88e06f02014-06-09 15:16:09 +02002878 mgmt->u.auth.auth_transaction =
2879 cpu_to_le16((u16)psta->auth_seq);
Larry Finger5e93f352014-03-28 21:37:38 -05002880
2881 /* setting status code... */
Jes Sorensen88e06f02014-06-09 15:16:09 +02002882 mgmt->u.auth.status_code = cpu_to_le16(status);
Larry Finger5e93f352014-03-28 21:37:38 -05002883
Jes Sorensen88e06f02014-06-09 15:16:09 +02002884 pframe = mgmt->u.auth.variable;
Larry Finger5e93f352014-03-28 21:37:38 -05002885 /* added challenging text... */
2886 if ((psta->auth_seq == 2) &&
2887 (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
Jes Sorensen5afd3912014-04-15 19:43:24 +02002888 pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128,
Larry Finger5e93f352014-03-28 21:37:38 -05002889 psta->chg_txt, &pattrib->pktlen);
2890#endif
2891 } else {
Jes Sorensen88e06f02014-06-09 15:16:09 +02002892 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,
Larry Finger5e93f352014-03-28 21:37:38 -05002897 get_my_bssid23a(&pmlmeinfo->network));
2898
2899 /* setting auth algo number */
2900 /* 0:OPEN System, 1:Shared key */
Jes Sorensen88e06f02014-06-09 15:16:09 +02002901 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
Larry Finger5e93f352014-03-28 21:37:38 -05002902 use_shared_key = 1;
Jes Sorensen88e06f02014-06-09 15:16:09 +02002903 auth_algo = WLAN_AUTH_SHARED_KEY;
2904 } else
2905 auth_algo = WLAN_AUTH_OPEN;
2906
Larry Finger5e93f352014-03-28 21:37:38 -05002907 /* 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)) {
Jes Sorensen88e06f02014-06-09 15:16:09 +02002915 u32 *piv = (u32 *)&mgmt->u.auth;
2916
2917 iv_mgmt = (struct ieee80211_mgmt *)(pframe + 4);
Larry Finger5e93f352014-03-28 21:37:38 -05002918 /* DBG_8723A("==> iv(%d), key_index(%d)\n",
2919 pmlmeinfo->iv, pmlmeinfo->key_index); */
Jes Sorensen88e06f02014-06-09 15:16:09 +02002920 val32 = (pmlmeinfo->iv & 0x3fffffff) |
2921 (pmlmeinfo->key_index << 30);
2922 pmlmeinfo->iv++;
2923 put_unaligned_le32(val32, piv);
2924
2925 pattrib->pktlen += 4;
Larry Finger5e93f352014-03-28 21:37:38 -05002926
Jes Sorensen06e17e32014-05-25 22:43:02 +02002927 pattrib->iv_len = IEEE80211_WEP_IV_LEN;
Jes Sorensen88e06f02014-06-09 15:16:09 +02002928 } else
2929 iv_mgmt = mgmt;
Larry Finger5e93f352014-03-28 21:37:38 -05002930
Jes Sorensen88e06f02014-06-09 15:16:09 +02002931 iv_mgmt->u.auth.auth_alg = cpu_to_le16(auth_algo);
Larry Finger5e93f352014-03-28 21:37:38 -05002932
2933 /* setting auth seq number */
Jes Sorensen88e06f02014-06-09 15:16:09 +02002934 iv_mgmt->u.auth.auth_transaction =
2935 cpu_to_le16(pmlmeinfo->auth_seq);
Larry Finger5e93f352014-03-28 21:37:38 -05002936
2937 /* setting status code... */
Jes Sorensen88e06f02014-06-09 15:16:09 +02002938 iv_mgmt->u.auth.status_code = cpu_to_le16(status);
2939
2940 pframe = iv_mgmt->u.auth.variable;
Larry Finger5e93f352014-03-28 21:37:38 -05002941
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)) {
Jes Sorensen5afd3912014-04-15 19:43:24 +02002946 pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128,
Larry Finger5e93f352014-03-28 21:37:38 -05002947 pmlmeinfo->chg_txt,
2948 &pattrib->pktlen);
2949
Jes Sorensen88e06f02014-06-09 15:16:09 +02002950 mgmt->frame_control |=
Jes Sorensenc6716e12014-05-21 09:38:02 +02002951 cpu_to_le16(IEEE80211_FCTL_PROTECTED);
Larry Finger5e93f352014-03-28 21:37:38 -05002952
2953 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2954
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02002955 pattrib->encrypt = WLAN_CIPHER_SUITE_WEP40;
Larry Finger5e93f352014-03-28 21:37:38 -05002956
Jes Sorensen06e17e32014-05-25 22:43:02 +02002957 pattrib->icv_len = IEEE80211_WEP_ICV_LEN;
Larry Finger5e93f352014-03-28 21:37:38 -05002958
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
Jes Sorensena402b802014-05-21 09:38:21 +02002972#ifdef CONFIG_8723AU_AP_MODE
Jes Sorensen6ebd2942014-05-21 09:38:14 +02002973static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status,
2974 struct sta_info *pstat, u16 pkt_type)
Larry Finger5e93f352014-03-28 21:37:38 -05002975{
Larry Finger5e93f352014-03-28 21:37:38 -05002976 struct xmit_frame *pmgntframe;
Jes Sorensenc144c3b2014-06-09 15:16:10 +02002977 struct ieee80211_mgmt *mgmt;
Larry Finger5e93f352014-03-28 21:37:38 -05002978 struct pkt_attrib *pattrib;
Jes Sorensencfe4ecd2014-04-15 19:43:50 +02002979 unsigned char *pframe;
Larry Finger5e93f352014-03-28 21:37:38 -05002980 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;
Jes Sorensencfe4ecd2014-04-15 19:43:50 +02002985 const u8 *p;
Larry Finger5e93f352014-03-28 21:37:38 -05002986 u8 *ie = pnetwork->IEs;
Larry Finger5e93f352014-03-28 21:37:38 -05002987
2988 DBG_8723A("%s\n", __func__);
2989
Jes Sorensencfe4ecd2014-04-15 19:43:50 +02002990 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2991 if (!pmgntframe)
Larry Finger5e93f352014-03-28 21:37:38 -05002992 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;
Jes Sorensenc144c3b2014-06-09 15:16:10 +02003001 mgmt = (struct ieee80211_mgmt *)pframe;
Larry Finger5e93f352014-03-28 21:37:38 -05003002
Jes Sorensenc144c3b2014-06-09 15:16:10 +02003003 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | pkt_type);
Larry Finger5e93f352014-03-28 21:37:38 -05003004
Jes Sorensenc144c3b2014-06-09 15:16:10 +02003005 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));
Larry Finger5e93f352014-03-28 21:37:38 -05003008
Jes Sorensenc144c3b2014-06-09 15:16:10 +02003009 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
Jes Sorensenaeda8252014-05-21 09:37:59 +02003010
Larry Finger5e93f352014-03-28 21:37:38 -05003011 pmlmeext->mgnt_seq++;
Larry Finger5e93f352014-03-28 21:37:38 -05003012
3013 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
Jes Sorensenc144c3b2014-06-09 15:16:10 +02003014 pattrib->pktlen =
3015 offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
Larry Finger5e93f352014-03-28 21:37:38 -05003016
Jes Sorensen5376bad2014-06-19 11:37:30 +02003017 mgmt->u.assoc_resp.capab_info = cpu_to_le16(pnetwork->capability);
Jes Sorensenc144c3b2014-06-09 15:16:10 +02003018 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));
Larry Finger5e93f352014-03-28 21:37:38 -05003020
Jes Sorensenc144c3b2014-06-09 15:16:10 +02003021 pframe = mgmt->u.assoc_resp.variable;
Larry Finger5e93f352014-03-28 21:37:38 -05003022
3023 if (pstat->bssratelen <= 8) {
Jes Sorensen5afd3912014-04-15 19:43:24 +02003024 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
Larry Finger5e93f352014-03-28 21:37:38 -05003025 pstat->bssratelen, pstat->bssrateset,
3026 &pattrib->pktlen);
3027 } else {
Jes Sorensen5afd3912014-04-15 19:43:24 +02003028 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
Larry Finger5e93f352014-03-28 21:37:38 -05003029 pstat->bssrateset, &pattrib->pktlen);
Jes Sorensen5afd3912014-04-15 19:43:24 +02003030 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
Larry Finger5e93f352014-03-28 21:37:38 -05003031 pstat->bssratelen - 8,
3032 pstat->bssrateset + 8, &pattrib->pktlen);
3033 }
3034
Jes Sorensencfe4ecd2014-04-15 19:43:50 +02003035 if (pstat->flags & WLAN_STA_HT && pmlmepriv->htpriv.ht_option) {
Larry Finger5e93f352014-03-28 21:37:38 -05003036 /* FILL HT CAP INFO IE */
3037 /* p = hostapd_eid_ht_capabilities_info(hapd, p); */
Jes Sorensen1de65cc2014-06-24 15:03:30 +02003038 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ie,
3039 pnetwork->IELength);
Jes Sorensencfe4ecd2014-04-15 19:43:50 +02003040 if (p && p[1]) {
3041 memcpy(pframe, p, p[1] + 2);
3042 pframe += (p[1] + 2);
3043 pattrib->pktlen += (p[1] + 2);
Larry Finger5e93f352014-03-28 21:37:38 -05003044 }
3045
3046 /* FILL HT ADD INFO IE */
3047 /* p = hostapd_eid_ht_operation(hapd, p); */
Jes Sorensen1de65cc2014-06-24 15:03:30 +02003048 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie,
3049 pnetwork->IELength);
Jes Sorensencfe4ecd2014-04-15 19:43:50 +02003050 if (p && p[1] > 0) {
3051 memcpy(pframe, p, p[1] + 2);
3052 pframe += (p[1] + 2);
3053 pattrib->pktlen += (p[1] + 2);
Larry Finger5e93f352014-03-28 21:37:38 -05003054 }
3055 }
3056
3057 /* FILL WMM IE */
Jes Sorensenbd8ad4a2014-05-09 15:03:21 +02003058 if (pstat->flags & WLAN_STA_WME && pmlmepriv->qos_option) {
Larry Finger5e93f352014-03-28 21:37:38 -05003059 unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02,
3060 0x01, 0x01};
Jes Sorensencfe4ecd2014-04-15 19:43:50 +02003061 int ie_len = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05003062
Jes Sorensen1de65cc2014-06-24 15:03:30 +02003063 for (p = ie; ; p += (ie_len + 2)) {
Jes Sorensencfe4ecd2014-04-15 19:43:50 +02003064 p = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, p,
Jes Sorensen1de65cc2014-06-24 15:03:30 +02003065 pnetwork->IELength - (ie_len + 2));
Jes Sorensencfe4ecd2014-04-15 19:43:50 +02003066 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);
Larry Finger5e93f352014-03-28 21:37:38 -05003072 pframe += (ie_len + 2);
3073 pattrib->pktlen += (ie_len + 2);
3074
3075 break;
3076 }
3077
Jes Sorensencfe4ecd2014-04-15 19:43:50 +02003078 if (!p || ie_len == 0)
Larry Finger5e93f352014-03-28 21:37:38 -05003079 break;
3080 }
3081 }
3082
3083 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) {
Jes Sorensen9300c942014-04-15 19:43:21 +02003084 pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6,
Jes Sorensenf85bd052014-05-09 15:04:06 +02003085 REALTEK_96B_IE, &pattrib->pktlen);
Larry Finger5e93f352014-03-28 21:37:38 -05003086 }
3087
Larry Finger5e93f352014-03-28 21:37:38 -05003088 pattrib->last_txcmdsz = pattrib->pktlen;
3089
3090 dump_mgntframe23a(padapter, pmgntframe);
Larry Finger5e93f352014-03-28 21:37:38 -05003091}
Jes Sorensena402b802014-05-21 09:38:21 +02003092#endif
Larry Finger5e93f352014-03-28 21:37:38 -05003093
Jes Sorensen0e176852014-05-21 09:38:20 +02003094static void issue_assocreq(struct rtw_adapter *padapter)
Larry Finger5e93f352014-03-28 21:37:38 -05003095{
3096 int ret = _FAIL;
3097 struct xmit_frame *pmgntframe;
3098 struct pkt_attrib *pattrib;
Jes Sorensen0b2b6762014-04-15 19:43:49 +02003099 unsigned char *pframe;
3100 const u8 *p;
Jes Sorensen92af4492014-06-19 11:37:31 +02003101 struct ieee80211_mgmt *mgmt;
Jes Sorensen0b2b6762014-04-15 19:43:49 +02003102 unsigned int i, j, index = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05003103 unsigned char rf_type, bssrate[NumRates], sta_bssrate[NumRates];
Larry Finger5e93f352014-03-28 21:37:38 -05003104 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;
Jes Sorensen68e6c792014-06-24 15:03:29 +02003109 int bssrate_len = 0, sta_bssrate_len = 0, pie_len;
Jes Sorensenb171da32014-05-21 09:37:42 +02003110 u8 *pie;
Larry Finger5e93f352014-03-28 21:37:38 -05003111
Jes Sorensen0b2b6762014-04-15 19:43:49 +02003112 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3113 if (!pmgntframe)
Larry Finger5e93f352014-03-28 21:37:38 -05003114 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
Jes Sorensen0b2b6762014-04-15 19:43:49 +02003122 pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
Jes Sorensen92af4492014-06-19 11:37:31 +02003123 mgmt = (struct ieee80211_mgmt *)pframe;
Larry Finger5e93f352014-03-28 21:37:38 -05003124
Jes Sorensen92af4492014-06-19 11:37:31 +02003125 mgmt->frame_control =
3126 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ);
Jes Sorensenaeda8252014-05-21 09:37:59 +02003127
Jes Sorensen92af4492014-06-19 11:37:31 +02003128 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));
Larry Finger5e93f352014-03-28 21:37:38 -05003131
Jes Sorensen92af4492014-06-19 11:37:31 +02003132 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
Larry Finger5e93f352014-03-28 21:37:38 -05003133 pmlmeext->mgnt_seq++;
Larry Finger5e93f352014-03-28 21:37:38 -05003134
Larry Finger5e93f352014-03-28 21:37:38 -05003135 /* caps */
Jes Sorensen92af4492014-06-19 11:37:31 +02003136 put_unaligned_le16(pmlmeinfo->network.capability,
3137 &mgmt->u.assoc_req.capab_info);
Larry Finger5e93f352014-03-28 21:37:38 -05003138 /* todo: listen interval for power saving */
Jes Sorensen92af4492014-06-19 11:37:31 +02003139 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);
Larry Finger5e93f352014-03-28 21:37:38 -05003143
3144 /* SSID */
Jes Sorensen5afd3912014-04-15 19:43:24 +02003145 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
Larry Finger5e93f352014-03-28 21:37:38 -05003146 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) ==
Jes Sorensen0b2b6762014-04-15 19:43:49 +02003180 (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) {
Larry Finger5e93f352014-03-28 21:37:38 -05003181 /* 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) {
Jes Sorensen5afd3912014-04-15 19:43:24 +02003207 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
Larry Finger5e93f352014-03-28 21:37:38 -05003208 bssrate, &pattrib->pktlen);
Jes Sorensen5afd3912014-04-15 19:43:24 +02003209 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
Larry Finger5e93f352014-03-28 21:37:38 -05003210 (bssrate_len - 8), (bssrate + 8),
3211 &pattrib->pktlen);
3212 } else
Jes Sorensen5afd3912014-04-15 19:43:24 +02003213 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
Larry Finger5e93f352014-03-28 21:37:38 -05003214 bssrate_len, bssrate, &pattrib->pktlen);
3215
3216 /* RSN */
Jes Sorensenc164bcf2014-05-21 09:37:41 +02003217
Jes Sorensen68e6c792014-06-24 15:03:29 +02003218 pie = pmlmeinfo->network.IEs;
3219 pie_len = pmlmeinfo->network.IELength;
Jes Sorensen0b2b6762014-04-15 19:43:49 +02003220
3221 p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len);
Larry Finger5e93f352014-03-28 21:37:38 -05003222 if (p)
Jes Sorensen0b2b6762014-04-15 19:43:49 +02003223 pframe = rtw_set_ie23a(pframe, WLAN_EID_RSN, p[1], p + 2,
Larry Finger5e93f352014-03-28 21:37:38 -05003224 &pattrib->pktlen);
3225
3226 /* HT caps */
Jes Sorensen6a5f6572014-06-09 15:16:07 +02003227 if (padapter->mlmepriv.htpriv.ht_option) {
Jes Sorensen0b2b6762014-04-15 19:43:49 +02003228 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, pie_len);
3229
3230 if (p && !is_ap_in_tkip23a(padapter)) {
Jes Sorensen65be27d2014-05-31 18:05:11 +02003231 struct ieee80211_ht_cap *cap = &pmlmeinfo->ht_cap;
3232
3233 memcpy(cap, p + 2, sizeof(struct ieee80211_ht_cap));
Larry Finger5e93f352014-03-28 21:37:38 -05003234
3235 /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
3236 if (pregpriv->cbw40_enable == 0) {
Jes Sorensen65be27d2014-05-31 18:05:11 +02003237 cap->cap_info &= ~cpu_to_le16(
3238 IEEE80211_HT_CAP_SGI_40 |
3239 IEEE80211_HT_CAP_SUP_WIDTH_20_40);
Larry Finger5e93f352014-03-28 21:37:38 -05003240 } else {
Jes Sorensen65be27d2014-05-31 18:05:11 +02003241 cap->cap_info |= cpu_to_le16(
3242 IEEE80211_HT_CAP_SUP_WIDTH_20_40);
Larry Finger5e93f352014-03-28 21:37:38 -05003243 }
3244
3245 /* todo: disable SM power save mode */
Jes Sorensen65be27d2014-05-31 18:05:11 +02003246 cap->cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SM_PS);
Larry Finger5e93f352014-03-28 21:37:38 -05003247
Jes Sorensenc2370e82014-04-09 23:20:53 +02003248 rf_type = rtl8723a_get_rf_type(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05003249 /* switch (pregpriv->rf_config) */
Jes Sorensen0b2b6762014-04-15 19:43:49 +02003250 switch (rf_type) {
Larry Finger5e93f352014-03-28 21:37:38 -05003251 case RF_1T1R:
Jes Sorensen0b2b6762014-04-15 19:43:49 +02003252 /* RX STBC One spatial stream */
Larry Finger5e93f352014-03-28 21:37:38 -05003253 if (pregpriv->rx_stbc)
Jes Sorensen65be27d2014-05-31 18:05:11 +02003254 cap->cap_info |= cpu_to_le16(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
Larry Finger5e93f352014-03-28 21:37:38 -05003255
Jes Sorensen65be27d2014-05-31 18:05:11 +02003256 memcpy(&cap->mcs, MCS_rate_1R23A, 16);
Larry Finger5e93f352014-03-28 21:37:38 -05003257 break;
3258
3259 case RF_2T2R:
3260 case RF_1T2R:
3261 default:
Larry Finger5e93f352014-03-28 21:37:38 -05003262 /* enable for 2.4/5 GHz */
Jes Sorensen0b2b6762014-04-15 19:43:49 +02003263 if (pregpriv->rx_stbc == 0x3 ||
3264 (pmlmeext->cur_wireless_mode &
3265 WIRELESS_11_24N &&
Larry Finger5e93f352014-03-28 21:37:38 -05003266 /* enable for 2.4GHz */
Jes Sorensen0b2b6762014-04-15 19:43:49 +02003267 pregpriv->rx_stbc == 0x1) ||
3268 (pmlmeext->cur_wireless_mode &
3269 WIRELESS_11_5N &&
3270 pregpriv->rx_stbc == 0x2) ||
Larry Finger5e93f352014-03-28 21:37:38 -05003271 /* enable for 5GHz */
Jes Sorensen0b2b6762014-04-15 19:43:49 +02003272 pregpriv->wifi_spec == 1) {
Larry Finger5e93f352014-03-28 21:37:38 -05003273 DBG_8723A("declare supporting RX "
3274 "STBC\n");
Jes Sorensen65be27d2014-05-31 18:05:11 +02003275 /* RX STBC two spatial stream */
3276 cap->cap_info |= cpu_to_le16(2 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
Larry Finger5e93f352014-03-28 21:37:38 -05003277 }
Jes Sorensen65be27d2014-05-31 18:05:11 +02003278 memcpy(&cap->mcs, MCS_rate_2R23A, 16);
Larry Finger5e93f352014-03-28 21:37:38 -05003279 break;
3280 }
Larry Finger5e93f352014-03-28 21:37:38 -05003281
Jes Sorensen92825e62014-05-25 22:43:35 +02003282 if (rtl8723a_BT_coexist(padapter) &&
3283 rtl8723a_BT_using_antenna_1(padapter)) {
Larry Finger5e93f352014-03-28 21:37:38 -05003284 /* set to 8K */
Jes Sorensen65be27d2014-05-31 18:05:11 +02003285 cap->ampdu_params_info &=
3286 ~IEEE80211_HT_AMPDU_PARM_FACTOR;
3287/* cap->ampdu_params_info |= MAX_AMPDU_FACTOR_8K */
Larry Finger5e93f352014-03-28 21:37:38 -05003288 }
Larry Finger5e93f352014-03-28 21:37:38 -05003289
Jes Sorensen5afd3912014-04-15 19:43:24 +02003290 pframe = rtw_set_ie23a(pframe, WLAN_EID_HT_CAPABILITY,
Jes Sorensen65be27d2014-05-31 18:05:11 +02003291 p[1], (u8 *)&pmlmeinfo->ht_cap,
Larry Finger5e93f352014-03-28 21:37:38 -05003292 &pattrib->pktlen);
3293 }
3294 }
3295
3296 /* vendor specific IE, such as WPA, WMM, WPS */
Jes Sorensen68e6c792014-06-24 15:03:29 +02003297 for (i = 0; i < pmlmeinfo->network.IELength;) {
Jes Sorensenb171da32014-05-21 09:37:42 +02003298 p = pmlmeinfo->network.IEs + i;
Larry Finger5e93f352014-03-28 21:37:38 -05003299
Jes Sorensenb171da32014-05-21 09:37:42 +02003300 switch (p[0]) {
Jes Sorensen9300c942014-04-15 19:43:21 +02003301 case WLAN_EID_VENDOR_SPECIFIC:
Jes Sorensenb171da32014-05-21 09:37:42 +02003302 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];
Yeliz Taneroglu2ce71bd2014-10-09 01:22:15 +03003306
Larry Finger5e93f352014-03-28 21:37:38 -05003307 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 */
Jes Sorensenb171da32014-05-21 09:37:42 +02003312 if (!memcmp(p + 2, WPS_OUI23A, 4))
3313 plen = 14;
Larry Finger5e93f352014-03-28 21:37:38 -05003314 }
3315 pframe = rtw_set_ie23a(pframe,
Jes Sorensen9300c942014-04-15 19:43:21 +02003316 WLAN_EID_VENDOR_SPECIFIC,
Jes Sorensenb171da32014-05-21 09:37:42 +02003317 plen, p + 2,
Larry Finger5e93f352014-03-28 21:37:38 -05003318 &pattrib->pktlen);
3319 }
3320 break;
3321
3322 default:
3323 break;
3324 }
3325
Jes Sorensenb171da32014-05-21 09:37:42 +02003326 i += p[1] + 2;
Larry Finger5e93f352014-03-28 21:37:38 -05003327 }
3328
3329 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
Jes Sorensen9300c942014-04-15 19:43:21 +02003330 pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6,
Jes Sorensenf85bd052014-05-09 15:04:06 +02003331 REALTEK_96B_IE, &pattrib->pktlen);
Larry Finger5e93f352014-03-28 21:37:38 -05003332
Larry Finger5e93f352014-03-28 21:37:38 -05003333 pattrib->last_txcmdsz = pattrib->pktlen;
3334 dump_mgntframe23a(padapter, pmgntframe);
3335
3336 ret = _SUCCESS;
3337
3338exit:
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) {
Jes Sorensen92af4492014-06-19 11:37:31 +02003344 memcpy(pmlmepriv->assoc_req, mgmt, pattrib->pktlen);
Larry Finger5e93f352014-03-28 21:37:38 -05003345 pmlmepriv->assoc_req_len = pattrib->pktlen;
3346 }
3347 } else
3348 kfree(pmlmepriv->assoc_req);
3349
3350 return;
3351}
3352
Masanari Iidafae062a2014-07-22 23:42:13 +09003353/* when wait_ack is true, this function should be called at process context */
Larry Finger5e93f352014-03-28 21:37:38 -05003354static 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;
Larry Finger5e93f352014-03-28 21:37:38 -05003362 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
Jes Sorensend0fc1462014-05-25 22:43:36 +02003375 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3376 if (!pmgntframe)
Larry Finger5e93f352014-03-28 21:37:38 -05003377 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
Jes Sorensenc2bfb142014-05-21 09:38:12 +02003389 pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
3390 IEEE80211_STYPE_NULLFUNC);
Larry Finger5e93f352014-03-28 21:37:38 -05003391
Jes Sorensen6ec26272014-07-17 22:59:46 +02003392 if ((pmlmeinfo->state&0x03) == MSR_AP)
Jes Sorensen863b3142014-05-21 09:38:16 +02003393 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
Jes Sorensen6ec26272014-07-17 22:59:46 +02003394 else if ((pmlmeinfo->state&0x03) == MSR_INFRA)
Jes Sorensen863b3142014-05-21 09:38:16 +02003395 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
Larry Finger5e93f352014-03-28 21:37:38 -05003396
3397 if (power_mode)
Jes Sorensenc6716e12014-05-21 09:38:02 +02003398 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
Larry Finger5e93f352014-03-28 21:37:38 -05003399
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
Jes Sorensenaeda8252014-05-21 09:37:59 +02003404 pwlanhdr->seq_ctrl =
3405 cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
Larry Finger5e93f352014-03-28 21:37:38 -05003406 pmlmeext->mgnt_seq++;
Larry Finger5e93f352014-03-28 21:37:38 -05003407
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
3420exit:
3421 return ret;
3422}
3423
Masanari Iidafae062a2014-07-22 23:42:13 +09003424/* when wait_ms >0 , this function should be called at process context */
Larry Finger5e93f352014-03-28 21:37:38 -05003425/* da == NULL for station mode */
3426int 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
Masanari Iidafae062a2014-07-22 23:42:13 +09003435 /* da == NULL, assume it's null data for sta to ap*/
Larry Finger5e93f352014-03-28 21:37:38 -05003436 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)
Joe Perchesea072782015-03-24 11:10:09 -07003460 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,
Larry Finger5e93f352014-03-28 21:37:38 -05003464 jiffies_to_msecs(jiffies - start));
3465 else
Jes Sorensen9cd613c2014-05-09 15:04:03 +02003466 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3467 __func__, padapter->pnetdev->name,
Larry Finger5e93f352014-03-28 21:37:38 -05003468 rtw_get_oper_ch23a(padapter),
Joe Perchesea072782015-03-24 11:10:09 -07003469 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
Larry Finger5e93f352014-03-28 21:37:38 -05003470 jiffies_to_msecs(jiffies - start));
3471 }
3472exit:
3473 return ret;
3474}
3475
Masanari Iidafae062a2014-07-22 23:42:13 +09003476/* when wait_ack is true, this function should be called at process context */
Larry Finger5e93f352014-03-28 21:37:38 -05003477static 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;
Jes Sorensen24af77b2014-05-21 09:38:06 +02003484 struct ieee80211_qos_hdr *pwlanhdr;
Larry Finger5e93f352014-03-28 21:37:38 -05003485 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
Jes Sorensend0fc1462014-05-25 22:43:36 +02003491 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3492 if (!pmgntframe)
Larry Finger5e93f352014-03-28 21:37:38 -05003493 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;
Jes Sorensen24af77b2014-05-21 09:38:06 +02003508 pwlanhdr = (struct ieee80211_qos_hdr *)pframe;
Larry Finger5e93f352014-03-28 21:37:38 -05003509
Jes Sorensenc2bfb142014-05-21 09:38:12 +02003510 pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
3511 IEEE80211_STYPE_QOS_NULLFUNC);
Larry Finger5e93f352014-03-28 21:37:38 -05003512
Jes Sorensen6ec26272014-07-17 22:59:46 +02003513 if ((pmlmeinfo->state&0x03) == MSR_AP)
Jes Sorensen863b3142014-05-21 09:38:16 +02003514 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
Jes Sorensen6ec26272014-07-17 22:59:46 +02003515 else if ((pmlmeinfo->state&0x03) == MSR_INFRA)
Jes Sorensen863b3142014-05-21 09:38:16 +02003516 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
Larry Finger5e93f352014-03-28 21:37:38 -05003517
3518 if (pattrib->mdata)
Jes Sorensenc6716e12014-05-21 09:38:02 +02003519 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
Larry Finger5e93f352014-03-28 21:37:38 -05003520
Jes Sorensen24af77b2014-05-21 09:38:06 +02003521 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);
Larry Finger5e93f352014-03-28 21:37:38 -05003526
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
Jes Sorensenaeda8252014-05-21 09:37:59 +02003531 pwlanhdr->seq_ctrl =
3532 cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
Larry Finger5e93f352014-03-28 21:37:38 -05003533 pmlmeext->mgnt_seq++;
Larry Finger5e93f352014-03-28 21:37:38 -05003534
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
3547exit:
3548 return ret;
3549}
3550
Masanari Iidafae062a2014-07-22 23:42:13 +09003551/* when wait_ms >0 , this function should be called at process context */
Larry Finger5e93f352014-03-28 21:37:38 -05003552/* da == NULL for station mode */
3553int 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
Masanari Iidafae062a2014-07-22 23:42:13 +09003562 /* da == NULL, assume it's null data for sta to ap*/
Larry Finger5e93f352014-03-28 21:37:38 -05003563 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)
Joe Perchesea072782015-03-24 11:10:09 -07003586 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,
Larry Finger5e93f352014-03-28 21:37:38 -05003590 jiffies_to_msecs(jiffies - start));
3591 else
Jes Sorensen9cd613c2014-05-09 15:04:03 +02003592 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3593 __func__, padapter->pnetdev->name,
Larry Finger5e93f352014-03-28 21:37:38 -05003594 rtw_get_oper_ch23a(padapter),
Joe Perchesea072782015-03-24 11:10:09 -07003595 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
Larry Finger5e93f352014-03-28 21:37:38 -05003596 jiffies_to_msecs(jiffies - start));
3597 }
3598exit:
3599 return ret;
3600}
3601
Jes Sorensen0e176852014-05-21 09:38:20 +02003602static int _issue_deauth(struct rtw_adapter *padapter, unsigned char *da,
3603 unsigned short reason, u8 wait_ack)
Larry Finger5e93f352014-03-28 21:37:38 -05003604{
3605 struct xmit_frame *pmgntframe;
3606 struct pkt_attrib *pattrib;
Jes Sorensenf89547b2014-06-09 15:16:13 +02003607 struct ieee80211_mgmt *mgmt;
Larry Finger5e93f352014-03-28 21:37:38 -05003608 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;
Larry Finger5e93f352014-03-28 21:37:38 -05003612
Joe Perchesea072782015-03-24 11:10:09 -07003613 /* DBG_8723A("%s to %pM\n", __func__, da); */
Larry Finger5e93f352014-03-28 21:37:38 -05003614
Jes Sorensend0fc1462014-05-25 22:43:36 +02003615 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3616 if (!pmgntframe)
Larry Finger5e93f352014-03-28 21:37:38 -05003617 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
Jes Sorensenf89547b2014-06-09 15:16:13 +02003626 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
Larry Finger5e93f352014-03-28 21:37:38 -05003627
Jes Sorensenf89547b2014-06-09 15:16:13 +02003628 mgmt->frame_control =
3629 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
Larry Finger5e93f352014-03-28 21:37:38 -05003630
Jes Sorensenf89547b2014-06-09 15:16:13 +02003631 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));
Larry Finger5e93f352014-03-28 21:37:38 -05003634
Jes Sorensenf89547b2014-06-09 15:16:13 +02003635 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
Larry Finger5e93f352014-03-28 21:37:38 -05003636 pmlmeext->mgnt_seq++;
Larry Finger5e93f352014-03-28 21:37:38 -05003637
Jes Sorensenf89547b2014-06-09 15:16:13 +02003638 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 2;
Larry Finger5e93f352014-03-28 21:37:38 -05003639
Jes Sorensenf89547b2014-06-09 15:16:13 +02003640 mgmt->u.deauth.reason_code = cpu_to_le16(reason);
Larry Finger5e93f352014-03-28 21:37:38 -05003641
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
3651exit:
3652 return ret;
3653}
3654
3655int issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da,
3656 unsigned short reason)
3657{
Joe Perchesea072782015-03-24 11:10:09 -07003658 DBG_8723A("%s to %pM\n", __func__, da);
Jes Sorensen0e176852014-05-21 09:38:20 +02003659 return _issue_deauth(padapter, da, reason, false);
Larry Finger5e93f352014-03-28 21:37:38 -05003660}
3661
Jes Sorensen0e176852014-05-21 09:38:20 +02003662static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da,
3663 unsigned short reason, int try_cnt, int wait_ms)
Larry Finger5e93f352014-03-28 21:37:38 -05003664{
3665 int ret;
3666 int i = 0;
3667 unsigned long start = jiffies;
3668
3669 do {
Jes Sorensen0e176852014-05-21 09:38:20 +02003670 ret = _issue_deauth(padapter, da, reason,
3671 wait_ms >0 ? true : false);
Larry Finger5e93f352014-03-28 21:37:38 -05003672
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)
Joe Perchesea072782015-03-24 11:10:09 -07003690 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,
Larry Finger5e93f352014-03-28 21:37:38 -05003694 jiffies_to_msecs(jiffies - start));
3695 else
Jes Sorensen9cd613c2014-05-09 15:04:03 +02003696 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3697 __func__, padapter->pnetdev->name,
Larry Finger5e93f352014-03-28 21:37:38 -05003698 rtw_get_oper_ch23a(padapter),
Joe Perchesea072782015-03-24 11:10:09 -07003699 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
Larry Finger5e93f352014-03-28 21:37:38 -05003700 jiffies_to_msecs(jiffies - start));
3701 }
3702exit:
3703 return ret;
3704}
3705
3706void 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;
Jes Sorensen7ed61b52014-06-09 15:16:14 +02003712 struct ieee80211_mgmt *mgmt;
Larry Finger5e93f352014-03-28 21:37:38 -05003713 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3714 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05003715
Joe Perchesea072782015-03-24 11:10:09 -07003716 DBG_8723A("%s(%s): ra=%pM, ch:%u, offset:%u\n",
3717 __func__, padapter->pnetdev->name, ra, new_ch, ch_offset);
Larry Finger5e93f352014-03-28 21:37:38 -05003718
Jes Sorensend0fc1462014-05-25 22:43:36 +02003719 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3720 if (!pmgntframe)
Larry Finger5e93f352014-03-28 21:37:38 -05003721 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
Jes Sorensen7ed61b52014-06-09 15:16:14 +02003729 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
Larry Finger5e93f352014-03-28 21:37:38 -05003730
Jes Sorensen7ed61b52014-06-09 15:16:14 +02003731 mgmt->frame_control =
3732 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
Larry Finger5e93f352014-03-28 21:37:38 -05003733
Jes Sorensen7ed61b52014-06-09 15:16:14 +02003734 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 */
Larry Finger5e93f352014-03-28 21:37:38 -05003737
Jes Sorensen7ed61b52014-06-09 15:16:14 +02003738 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
Larry Finger5e93f352014-03-28 21:37:38 -05003739 pmlmeext->mgnt_seq++;
Larry Finger5e93f352014-03-28 21:37:38 -05003740
Jes Sorensen7ed61b52014-06-09 15:16:14 +02003741 mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT;
3742 mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH;
Larry Finger5e93f352014-03-28 21:37:38 -05003743
Jes Sorensen7ed61b52014-06-09 15:16:14 +02003744 pframe = mgmt->u.action.u.chan_switch.variable;
3745 pattrib->pktlen = offsetof(struct ieee80211_mgmt,
3746 u.action.u.chan_switch.variable);
Larry Finger5e93f352014-03-28 21:37:38 -05003747
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
Jes Sorensen0348dc742014-04-26 18:55:06 +02003758void issue_action_BA23a(struct rtw_adapter *padapter,
3759 const unsigned char *raddr,
Larry Finger5e93f352014-03-28 21:37:38 -05003760 unsigned char action, unsigned short status)
3761{
Larry Finger5e93f352014-03-28 21:37:38 -05003762 u16 start_seq;
3763 u16 BA_para_set;
Larry Finger5e93f352014-03-28 21:37:38 -05003764 u16 BA_starting_seqctrl;
Jes Sorensena4915482014-06-09 15:16:19 +02003765 u16 BA_para;
Larry Finger5e93f352014-03-28 21:37:38 -05003766 int max_rx_ampdu_factor;
3767 struct xmit_frame *pmgntframe;
3768 struct pkt_attrib *pattrib;
Jes Sorensena4915482014-06-09 15:16:19 +02003769 struct ieee80211_mgmt *mgmt;
Larry Finger5e93f352014-03-28 21:37:38 -05003770 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;
Larry Finger5e93f352014-03-28 21:37:38 -05003776 u8 tendaAPMac[] = {0xC8, 0x3A, 0x35};
Larry Finger5e93f352014-03-28 21:37:38 -05003777
Jes Sorensena4915482014-06-09 15:16:19 +02003778 DBG_8723A("%s, action =%d, status =%d\n", __func__, action, status);
Larry Finger5e93f352014-03-28 21:37:38 -05003779
Jes Sorensend0fc1462014-05-25 22:43:36 +02003780 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3781 if (!pmgntframe)
Larry Finger5e93f352014-03-28 21:37:38 -05003782 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
Jes Sorensena4915482014-06-09 15:16:19 +02003790 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
Larry Finger5e93f352014-03-28 21:37:38 -05003791
Jes Sorensena4915482014-06-09 15:16:19 +02003792 mgmt->frame_control =
3793 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
Larry Finger5e93f352014-03-28 21:37:38 -05003794
Jes Sorensena4915482014-06-09 15:16:19 +02003795 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));
Larry Finger5e93f352014-03-28 21:37:38 -05003798
Jes Sorensena4915482014-06-09 15:16:19 +02003799 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
Larry Finger5e93f352014-03-28 21:37:38 -05003800 pmlmeext->mgnt_seq++;
Larry Finger5e93f352014-03-28 21:37:38 -05003801
Jes Sorensena4915482014-06-09 15:16:19 +02003802 mgmt->u.action.category = WLAN_CATEGORY_BACK;
Larry Finger5e93f352014-03-28 21:37:38 -05003803
Jes Sorensena4915482014-06-09 15:16:19 +02003804 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 1;
Larry Finger5e93f352014-03-28 21:37:38 -05003805
3806 status = cpu_to_le16(status);
3807
Jes Sorensena4915482014-06-09 15:16:19 +02003808 switch (action) {
3809 case WLAN_ACTION_ADDBA_REQ:
3810 pattrib->pktlen += sizeof(mgmt->u.action.u.addba_req);
Larry Finger5e93f352014-03-28 21:37:38 -05003811
Jes Sorensena4915482014-06-09 15:16:19 +02003812 mgmt->u.action.u.addba_req.action_code = action;
3813
Larry Finger5e93f352014-03-28 21:37:38 -05003814 do {
3815 pmlmeinfo->dialogToken++;
3816 } while (pmlmeinfo->dialogToken == 0);
Jes Sorensena4915482014-06-09 15:16:19 +02003817
3818 mgmt->u.action.u.addba_req.dialog_token =
3819 pmlmeinfo->dialogToken;
Larry Finger5e93f352014-03-28 21:37:38 -05003820
Jes Sorensen92825e62014-05-25 22:43:35 +02003821 if (rtl8723a_BT_coexist(padapter) &&
3822 rtl8723a_BT_using_antenna_1(padapter) &&
3823 (pmlmeinfo->assoc_AP_vendor != broadcomAP ||
Larry Finger5e93f352014-03-28 21:37:38 -05003824 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;
Jes Sorensen92825e62014-05-25 22:43:35 +02003836 } else {
Larry Finger5e93f352014-03-28 21:37:38 -05003837 /* immediate ack & 64 buffer size */
Haneen Mohammedacc4b972015-03-13 20:45:25 +03003838 BA_para_set = 0x1002 | ((status & 0xf) << 2);
Larry Finger5e93f352014-03-28 21:37:38 -05003839 }
Jes Sorensena4915482014-06-09 15:16:19 +02003840
3841 put_unaligned_le16(BA_para_set,
3842 &mgmt->u.action.u.addba_req.capab);
Larry Finger5e93f352014-03-28 21:37:38 -05003843
Jes Sorensen5026df92015-03-22 19:09:44 -04003844 /* 5ms */
3845 put_unaligned_le16(5000, &mgmt->u.action.u.addba_req.timeout);
Larry Finger5e93f352014-03-28 21:37:38 -05003846
Jes Sorensena4915482014-06-09 15:16:19 +02003847 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;
Larry Finger5e93f352014-03-28 21:37:38 -05003854
3855 DBG_8723A("BA_starting_seqctrl = %d for TID =%d\n",
Jes Sorensena4915482014-06-09 15:16:19 +02003856 start_seq, idx);
Larry Finger5e93f352014-03-28 21:37:38 -05003857
Jes Sorensena4915482014-06-09 15:16:19 +02003858 psta->BA_starting_seqctrl[idx] = start_seq;
Larry Finger5e93f352014-03-28 21:37:38 -05003859
3860 BA_starting_seqctrl = start_seq << 4;
Jes Sorensena4915482014-06-09 15:16:19 +02003861 } else
3862 BA_starting_seqctrl = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05003863
Jes Sorensena4915482014-06-09 15:16:19 +02003864 put_unaligned_le16(BA_starting_seqctrl,
3865 &mgmt->u.action.u.addba_req.start_seq_num);
3866
Larry Finger5e93f352014-03-28 21:37:38 -05003867 break;
3868
Jes Sorensena4915482014-06-09 15:16:19 +02003869 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
Jes Sorensen39f1a8e2014-05-16 10:04:20 +02003878 GetHalDefVar8192CUsb(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
3879 &max_rx_ampdu_factor);
Jes Sorensena4915482014-06-09 15:16:19 +02003880
3881 BA_para = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f;
Larry Finger5e93f352014-03-28 21:37:38 -05003882 if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_64K)
Jes Sorensena4915482014-06-09 15:16:19 +02003883 BA_para_set = BA_para | 0x1000; /* 64 buffer size */
Larry Finger5e93f352014-03-28 21:37:38 -05003884 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_32K)
Jes Sorensena4915482014-06-09 15:16:19 +02003885 BA_para_set = BA_para | 0x0800; /* 32 buffer size */
Larry Finger5e93f352014-03-28 21:37:38 -05003886 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_16K)
Jes Sorensena4915482014-06-09 15:16:19 +02003887 BA_para_set = BA_para | 0x0400; /* 16 buffer size */
Larry Finger5e93f352014-03-28 21:37:38 -05003888 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_8K)
Jes Sorensena4915482014-06-09 15:16:19 +02003889 BA_para_set = BA_para | 0x0200; /* 8 buffer size */
Larry Finger5e93f352014-03-28 21:37:38 -05003890 else
Jes Sorensena4915482014-06-09 15:16:19 +02003891 BA_para_set = BA_para | 0x1000; /* 64 buffer size */
Larry Finger5e93f352014-03-28 21:37:38 -05003892
Jes Sorensen92825e62014-05-25 22:43:35 +02003893 if (rtl8723a_BT_coexist(padapter) &&
3894 rtl8723a_BT_using_antenna_1(padapter) &&
3895 (pmlmeinfo->assoc_AP_vendor != broadcomAP ||
Larry Finger5e93f352014-03-28 21:37:38 -05003896 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 }
Larry Finger5e93f352014-03-28 21:37:38 -05003902
3903 if (pregpriv->ampdu_amsdu == 0)/* disabled */
Jes Sorensena4915482014-06-09 15:16:19 +02003904 BA_para_set &= ~BIT(0);
Larry Finger5e93f352014-03-28 21:37:38 -05003905 else if (pregpriv->ampdu_amsdu == 1)/* enabled */
Jes Sorensena4915482014-06-09 15:16:19 +02003906 BA_para_set |= BIT(0);
Larry Finger5e93f352014-03-28 21:37:38 -05003907
Jes Sorensena4915482014-06-09 15:16:19 +02003908 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;
Larry Finger5e93f352014-03-28 21:37:38 -05003915 break;
Jes Sorensena4915482014-06-09 15:16:19 +02003916 case WLAN_ACTION_DELBA:
3917 pattrib->pktlen += sizeof(mgmt->u.action.u.delba);
Larry Finger5e93f352014-03-28 21:37:38 -05003918
Jes Sorensena4915482014-06-09 15:16:19 +02003919 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;
Larry Finger5e93f352014-03-28 21:37:38 -05003926 break;
3927 default:
3928 break;
3929 }
3930
Larry Finger5e93f352014-03-28 21:37:38 -05003931 pattrib->last_txcmdsz = pattrib->pktlen;
3932
3933 dump_mgntframe23a(padapter, pmgntframe);
3934}
3935
Jes Sorensenf66e05d2014-05-16 10:04:34 +02003936int send_delba23a(struct rtw_adapter *padapter, u8 initiator, u8 *addr)
Larry Finger5e93f352014-03-28 21:37:38 -05003937{
3938 struct sta_priv *pstapriv = &padapter->stapriv;
3939 struct sta_info *psta = NULL;
3940 /* struct recv_reorder_ctrl *preorder_ctrl; */
Jes Sorensend54239a2014-05-31 18:05:08 +02003941 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05003942 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3943 u16 tid;
3944
Jes Sorensen6ec26272014-07-17 22:59:46 +02003945 if ((pmlmeinfo->state&0x03) != MSR_AP)
Larry Finger5e93f352014-03-28 21:37:38 -05003946 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
Jes Sorensenf66e05d2014-05-16 10:04:34 +02003976int send_beacon23a(struct rtw_adapter *padapter)
Larry Finger5e93f352014-03-28 21:37:38 -05003977{
Jes Sorensend54239a2014-05-31 18:05:08 +02003978 bool bxmitok;
3979 int issue = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05003980 int poll = 0;
3981 unsigned long start = jiffies;
Larry Fingerc17416e2014-03-28 21:37:42 -05003982 unsigned int passing_time;
Larry Finger5e93f352014-03-28 21:37:38 -05003983
Jes Sorensen763b4242014-04-09 23:20:14 +02003984 rtl8723a_bcn_valid(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05003985 do {
3986 issue_beacon23a(padapter, 100);
3987 issue++;
3988 do {
3989 yield();
Jes Sorensenff5d82e2014-04-09 23:20:15 +02003990 bxmitok = rtl8723a_get_bcn_valid(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05003991 poll++;
Roberta Dobrescu08551cb2014-10-26 23:30:05 +02003992 } while ((poll % 10) != 0 && !bxmitok &&
Larry Finger5e93f352014-03-28 21:37:38 -05003993 !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
Larry Fingerc17416e2014-03-28 21:37:42 -05004002 passing_time = jiffies_to_msecs(jiffies - start);
4003
Larry Finger5e93f352014-03-28 21:37:38 -05004004 if (!bxmitok) {
Larry Fingerc17416e2014-03-28 21:37:42 -05004005 DBG_8723A("%s fail! %u ms\n", __func__, passing_time);
Larry Finger5e93f352014-03-28 21:37:38 -05004006 return _FAIL;
4007 } else {
Larry Finger5e93f352014-03-28 21:37:38 -05004008
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
Masanari Iidafae062a2014-07-22 23:42:13 +09004018Following are some utitity functions for WiFi MLME
Larry Finger5e93f352014-03-28 21:37:38 -05004019
4020*****************************************************************************/
4021
4022bool 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,
Jes Sorensend54239a2014-05-31 18:05:08 +02004027 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};
Larry Finger5e93f352014-03-28 21:37:38 -05004031 for (i = 0; i < sizeof(Channel_5G); i++)
4032 if (channel == Channel_5G[i])
4033 return true;
4034 return false;
4035}
4036
Jes Sorensen662c9bf2014-05-21 09:38:34 +02004037static void rtw_site_survey(struct rtw_adapter *padapter)
Larry Finger5e93f352014-03-28 21:37:38 -05004038{
Jes Sorensena0860232014-04-09 23:20:21 +02004039 unsigned char survey_channel = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05004040 enum rt_scan_type ScanType = SCAN_PASSIVE;
Jes Sorensend54239a2014-05-31 18:05:08 +02004041 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05004042 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
Jes Sorensen98fb8122014-04-15 19:43:35 +02004043 struct rtw_ieee80211_channel *ch;
Larry Finger5e93f352014-03-28 21:37:38 -05004044
Jes Sorensen98fb8122014-04-15 19:43:35 +02004045 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;
Larry Finger5e93f352014-03-28 21:37:38 -05004051 }
4052
4053 if (survey_channel != 0) {
Jes Sorensen662c9bf2014-05-21 09:38:34 +02004054 /* PAUSE 4-AC Queue when site_survey */
Larry Finger5e93f352014-03-28 21:37:38 -05004055 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 {
Jes Sorensen98fb8122014-04-15 19:43:35 +02004064 int i;
Yeliz Taneroglu2ce71bd2014-10-09 01:22:15 +03004065
Jes Sorensen98fb8122014-04-15 19:43:35 +02004066 for (i = 0;i<RTW_SSID_SCAN_AMOUNT;i++) {
4067 if (pmlmeext->sitesurvey_res.ssid[i].ssid_len) {
Larry Finger5e93f352014-03-28 21:37:38 -05004068 /* todo: to issue two probe req??? */
Jes Sorensen0e176852014-05-21 09:38:20 +02004069 issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
Larry Finger5e93f352014-03-28 21:37:38 -05004070 /* msleep(SURVEY_TO>>1); */
Jes Sorensen0e176852014-05-21 09:38:20 +02004071 issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
Larry Finger5e93f352014-03-28 21:37:38 -05004072 }
4073 }
Jes Sorensen98fb8122014-04-15 19:43:35 +02004074
4075 if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
4076 /* todo: to issue two probe req??? */
Jes Sorensen0e176852014-05-21 09:38:20 +02004077 issue_probereq(padapter, NULL, NULL);
Jes Sorensen98fb8122014-04-15 19:43:35 +02004078 /* msleep(SURVEY_TO>>1); */
Jes Sorensen0e176852014-05-21 09:38:20 +02004079 issue_probereq(padapter, NULL, NULL);
Jes Sorensen98fb8122014-04-15 19:43:35 +02004080 }
Larry Finger5e93f352014-03-28 21:37:38 -05004081 }
4082
4083 set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
4084 } else {
Larry Finger5e93f352014-03-28 21:37:38 -05004085 /* channel number is 0 or this channel is not valid. */
Jes Sorensen98fb8122014-04-15 19:43:35 +02004086 pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
Larry Finger5e93f352014-03-28 21:37:38 -05004087
Jes Sorensen98fb8122014-04-15 19:43:35 +02004088 /* switch back to the original channel */
Larry Finger5e93f352014-03-28 21:37:38 -05004089
Jes Sorensen98fb8122014-04-15 19:43:35 +02004090 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
4091 pmlmeext->cur_ch_offset,
4092 pmlmeext->cur_bwmode);
Larry Finger5e93f352014-03-28 21:37:38 -05004093
Jes Sorensen662c9bf2014-05-21 09:38:34 +02004094 /* flush 4-AC Queue after rtw_site_survey */
Jes Sorensen98fb8122014-04-15 19:43:35 +02004095 /* val8 = 0; */
Larry Finger5e93f352014-03-28 21:37:38 -05004096
Jes Sorensen98fb8122014-04-15 19:43:35 +02004097 /* config MSR */
Jes Sorensenee225f02014-07-17 22:59:45 +02004098 rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
Larry Finger5e93f352014-03-28 21:37:38 -05004099
Jes Sorensen98fb8122014-04-15 19:43:35 +02004100 /* restore RX GAIN */
4101 rtl8723a_set_initial_gain(padapter, 0xff);
4102 /* turn on dynamic functions */
4103 rtl8723a_odm_support_ability_restore(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05004104
Jes Sorensen98fb8122014-04-15 19:43:35 +02004105 if (is_client_associated_to_ap23a(padapter) == true)
4106 issue_nulldata23a(padapter, NULL, 0, 3, 500);
Larry Finger5e93f352014-03-28 21:37:38 -05004107
Jes Sorensen98fb8122014-04-15 19:43:35 +02004108 rtl8723a_mlme_sitesurvey(padapter, 0);
Larry Finger5e93f352014-03-28 21:37:38 -05004109
Jes Sorensen98fb8122014-04-15 19:43:35 +02004110 report_surveydone_event23a(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05004111
Jes Sorensen98fb8122014-04-15 19:43:35 +02004112 pmlmeext->chan_scan_time = SURVEY_TO;
4113 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
Larry Finger5e93f352014-03-28 21:37:38 -05004114 }
4115
4116 return;
4117}
4118
4119/* collect bss info from Beacon and Probe request/response frames. */
Jes Sorensen1bebe752014-06-09 15:16:30 +02004120static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter,
4121 struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05004122{
Larry Finger5e93f352014-03-28 21:37:38 -05004123 struct sk_buff *skb = precv_frame->pkt;
Jes Sorensend944b722014-04-15 19:44:49 +02004124 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
Jes Sorensenf73255d2014-04-15 19:43:47 +02004125 struct registry_priv *pregistrypriv = &padapter->registrypriv;
4126 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05004127 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
Jes Sorensen1bebe752014-06-09 15:16:30 +02004128 struct wlan_bssid_ex *bssid;
Jes Sorensen68e6c792014-06-24 15:03:29 +02004129 const u8 *p;
4130 u8 *pie;
4131 unsigned int length;
4132 int i;
Larry Finger5e93f352014-03-28 21:37:38 -05004133
Jes Sorensen68e6c792014-06-24 15:03:29 +02004134 length = skb->len;
Larry Finger5e93f352014-03-28 21:37:38 -05004135
Jes Sorensen1bebe752014-06-09 15:16:30 +02004136 bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
4137 if (!bssid)
4138 return NULL;
Larry Finger5e93f352014-03-28 21:37:38 -05004139
Jes Sorensend944b722014-04-15 19:44:49 +02004140 if (ieee80211_is_beacon(mgmt->frame_control)) {
Jes Sorensen68e6c792014-06-24 15:03:29 +02004141 length -= offsetof(struct ieee80211_mgmt, u.beacon.variable);
4142 pie = mgmt->u.beacon.variable;
Larry Finger5e93f352014-03-28 21:37:38 -05004143 bssid->reserved = 1;
Jes Sorensen53c66002014-06-19 11:37:20 +02004144 bssid->capability =
4145 get_unaligned_le16(&mgmt->u.beacon.capab_info);
Jes Sorensen143ced22014-06-19 11:37:22 +02004146 bssid->beacon_interval =
Jes Sorensen5b124b12014-05-31 18:05:18 +02004147 get_unaligned_le16(&mgmt->u.beacon.beacon_int);
Jes Sorensen993c52b2014-06-19 11:37:18 +02004148 bssid->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp);
Jes Sorensen68e6c792014-06-24 15:03:29 +02004149 } 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;
Jes Sorensend944b722014-04-15 19:44:49 +02004152 bssid->reserved = 2;
Jes Sorensen53c66002014-06-19 11:37:20 +02004153 bssid->capability = 0;
Jes Sorensen143ced22014-06-19 11:37:22 +02004154 bssid->beacon_interval =
4155 padapter->registrypriv.dev_network.beacon_interval;
Jes Sorensen993c52b2014-06-19 11:37:18 +02004156 bssid->tsf = 0;
Jes Sorensend944b722014-04-15 19:44:49 +02004157 } else if (ieee80211_is_probe_resp(mgmt->frame_control)) {
Jes Sorensen68e6c792014-06-24 15:03:29 +02004158 length -=
4159 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
4160 pie = mgmt->u.probe_resp.variable;
Jes Sorensend944b722014-04-15 19:44:49 +02004161 bssid->reserved = 3;
Jes Sorensen53c66002014-06-19 11:37:20 +02004162 bssid->capability =
4163 get_unaligned_le16(&mgmt->u.probe_resp.capab_info);
Jes Sorensen143ced22014-06-19 11:37:22 +02004164 bssid->beacon_interval =
Jes Sorensen5b124b12014-05-31 18:05:18 +02004165 get_unaligned_le16(&mgmt->u.probe_resp.beacon_int);
Jes Sorensen993c52b2014-06-19 11:37:18 +02004166 bssid->tsf = get_unaligned_le64(&mgmt->u.probe_resp.timestamp);
Larry Finger5e93f352014-03-28 21:37:38 -05004167 } else {
Jes Sorensen68e6c792014-06-24 15:03:29 +02004168 length -= offsetof(struct ieee80211_mgmt, u.beacon.variable);
4169 pie = mgmt->u.beacon.variable;
Jes Sorensend944b722014-04-15 19:44:49 +02004170 bssid->reserved = 0;
Jes Sorensen53c66002014-06-19 11:37:20 +02004171 bssid->capability =
4172 get_unaligned_le16(&mgmt->u.beacon.capab_info);
Jes Sorensen143ced22014-06-19 11:37:22 +02004173 bssid->beacon_interval =
4174 padapter->registrypriv.dev_network.beacon_interval;
Jes Sorensen993c52b2014-06-19 11:37:18 +02004175 bssid->tsf = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05004176 }
Jes Sorensen68e6c792014-06-24 15:03:29 +02004177
4178 if (length > MAX_IE_SZ) {
4179 /* DBG_8723A("IE too long for survey event\n"); */
4180 kfree(bssid);
4181 return NULL;
4182 }
Larry Finger5e93f352014-03-28 21:37:38 -05004183
Jes Sorensen5bd28bc2014-04-26 18:54:49 +02004184 bssid->Length = offsetof(struct wlan_bssid_ex, IEs) + length;
Larry Finger5e93f352014-03-28 21:37:38 -05004185
4186 /* below is to copy the information element */
Jes Sorensenf73255d2014-04-15 19:43:47 +02004187 bssid->IELength = length;
Jes Sorensen68e6c792014-06-24 15:03:29 +02004188 memcpy(bssid->IEs, pie, bssid->IELength);
Larry Finger5e93f352014-03-28 21:37:38 -05004189
4190 /* get the signal strength */
Jes Sorensenf73255d2014-04-15 19:43:47 +02004191 /* in dBM.raw data */
4192 bssid->Rssi = precv_frame->attrib.phy_info.RecvSignalPower;
Jes Sorensen60b152c2014-10-10 21:41:36 +02004193 bssid->SignalQuality =
Jes Sorensenf73255d2014-04-15 19:43:47 +02004194 precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
Jes Sorensen60b152c2014-10-10 21:41:36 +02004195 bssid->SignalStrength =
Jes Sorensenf73255d2014-04-15 19:43:47 +02004196 precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
Larry Finger5e93f352014-03-28 21:37:38 -05004197
4198 /* checking SSID */
Jes Sorensen68e6c792014-06-24 15:03:29 +02004199 p = cfg80211_find_ie(WLAN_EID_SSID, bssid->IEs, bssid->IELength);
Jes Sorensenf73255d2014-04-15 19:43:47 +02004200
4201 if (!p) {
Larry Finger5e93f352014-03-28 21:37:38 -05004202 DBG_8723A("marc: cannot find SSID for survey event\n");
Jes Sorensen1bebe752014-06-09 15:16:30 +02004203 goto fail;
Larry Finger5e93f352014-03-28 21:37:38 -05004204 }
4205
Jes Sorensenf73255d2014-04-15 19:43:47 +02004206 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]);
Jes Sorensen1bebe752014-06-09 15:16:30 +02004209 goto fail;
Larry Finger5e93f352014-03-28 21:37:38 -05004210 }
Jes Sorensenf73255d2014-04-15 19:43:47 +02004211 memcpy(bssid->Ssid.ssid, p + 2, p[1]);
4212 bssid->Ssid.ssid_len = p[1];
Larry Finger5e93f352014-03-28 21:37:38 -05004213
Larry Finger5e93f352014-03-28 21:37:38 -05004214 /* checking rate info... */
4215 i = 0;
Jes Sorensen68e6c792014-06-24 15:03:29 +02004216 p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, bssid->IEs, bssid->IELength);
Jes Sorensenf73255d2014-04-15 19:43:47 +02004217 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]);
Jes Sorensen1bebe752014-06-09 15:16:30 +02004221 goto fail;
Larry Finger5e93f352014-03-28 21:37:38 -05004222 }
Jes Sorensenf73255d2014-04-15 19:43:47 +02004223 memcpy(bssid->SupportedRates, p + 2, p[1]);
4224 i = p[1];
Larry Finger5e93f352014-03-28 21:37:38 -05004225 }
4226
Jes Sorensen68e6c792014-06-24 15:03:29 +02004227 p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, bssid->IEs,
4228 bssid->IELength);
Jes Sorensenf73255d2014-04-15 19:43:47 +02004229 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]);
Jes Sorensen1bebe752014-06-09 15:16:30 +02004233 goto fail;
Larry Finger5e93f352014-03-28 21:37:38 -05004234 }
Jes Sorensenf73255d2014-04-15 19:43:47 +02004235 memcpy(bssid->SupportedRates + i, p + 2, p[1]);
Larry Finger5e93f352014-03-28 21:37:38 -05004236 }
4237
Larry Finger5e93f352014-03-28 21:37:38 -05004238 /* Checking for DSConfig */
Jes Sorensen68e6c792014-06-24 15:03:29 +02004239 p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bssid->IEs, bssid->IELength);
Larry Finger5e93f352014-03-28 21:37:38 -05004240
Jes Sorensen37cb9822014-05-21 09:37:40 +02004241 bssid->DSConfig = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05004242
Jes Sorensenf73255d2014-04-15 19:43:47 +02004243 if (p) {
Jes Sorensen37cb9822014-05-21 09:37:40 +02004244 bssid->DSConfig = p[2];
Jes Sorensenf73255d2014-04-15 19:43:47 +02004245 } else {/* In 5G, some ap do not have DSSET IE */
Larry Finger5e93f352014-03-28 21:37:38 -05004246 /* checking HT info for channel */
Jes Sorensen68e6c792014-06-24 15:03:29 +02004247 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, bssid->IEs,
4248 bssid->IELength);
Jes Sorensenf73255d2014-04-15 19:43:47 +02004249 if (p) {
Jes Sorensen4dc5f8b2014-05-31 18:05:13 +02004250 struct ieee80211_ht_operation *HT_info =
4251 (struct ieee80211_ht_operation *)(p + 2);
4252 bssid->DSConfig = HT_info->primary_chan;
Jes Sorensen37cb9822014-05-21 09:37:40 +02004253 } else /* use current channel */
4254 bssid->DSConfig = rtw_get_oper_ch23a(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05004255 }
4256
Jes Sorensend944b722014-04-15 19:44:49 +02004257 if (ieee80211_is_probe_req(mgmt->frame_control)) {
Larry Finger5e93f352014-03-28 21:37:38 -05004258 /* FIXME */
Jes Sorensenefc71442014-05-21 09:37:26 +02004259 bssid->ifmode = NL80211_IFTYPE_STATION;
Jes Sorensend944b722014-04-15 19:44:49 +02004260 ether_addr_copy(bssid->MacAddress, mgmt->sa);
Larry Finger5e93f352014-03-28 21:37:38 -05004261 bssid->Privacy = 1;
Jes Sorensen1bebe752014-06-09 15:16:30 +02004262 return bssid;
Larry Finger5e93f352014-03-28 21:37:38 -05004263 }
4264
Jes Sorensen53c66002014-06-19 11:37:20 +02004265 if (bssid->capability & WLAN_CAPABILITY_ESS) {
Jes Sorensenefc71442014-05-21 09:37:26 +02004266 bssid->ifmode = NL80211_IFTYPE_STATION;
Jes Sorensend944b722014-04-15 19:44:49 +02004267 ether_addr_copy(bssid->MacAddress, mgmt->sa);
Larry Finger5e93f352014-03-28 21:37:38 -05004268 } else {
Jes Sorensenefc71442014-05-21 09:37:26 +02004269 bssid->ifmode = NL80211_IFTYPE_ADHOC;
Jes Sorensend944b722014-04-15 19:44:49 +02004270 ether_addr_copy(bssid->MacAddress, mgmt->bssid);
Larry Finger5e93f352014-03-28 21:37:38 -05004271 }
4272
Jes Sorensen53c66002014-06-19 11:37:20 +02004273 if (bssid->capability & WLAN_CAPABILITY_PRIVACY)
Larry Finger5e93f352014-03-28 21:37:38 -05004274 bssid->Privacy = 1;
4275 else
4276 bssid->Privacy = 0;
4277
Jes Sorensen37cb9822014-05-21 09:37:40 +02004278 bssid->ATIMWindow = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05004279
4280 /* 20/40 BSS Coexistence check */
Jes Sorensenf73255d2014-04-15 19:43:47 +02004281 if (pregistrypriv->wifi_spec == 1 &&
4282 pmlmeinfo->bwmode_updated == false) {
Larry Finger5e93f352014-03-28 21:37:38 -05004283 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4284
Jes Sorensen68e6c792014-06-24 15:03:29 +02004285 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, bssid->IEs,
4286 bssid->IELength);
Jes Sorensenf73255d2014-04-15 19:43:47 +02004287 if (p && p[1] > 0) {
Jes Sorensen65be27d2014-05-31 18:05:11 +02004288 struct ieee80211_ht_cap *pHT_caps;
Yeliz Taneroglu2ce71bd2014-10-09 01:22:15 +03004289
Jes Sorensen65be27d2014-05-31 18:05:11 +02004290 pHT_caps = (struct ieee80211_ht_cap *)(p + 2);
Larry Finger5e93f352014-03-28 21:37:38 -05004291
Jes Sorensen65be27d2014-05-31 18:05:11 +02004292 if (pHT_caps->cap_info &
4293 cpu_to_le16(IEEE80211_HT_CAP_40MHZ_INTOLERANT))
Larry Finger5e93f352014-03-28 21:37:38 -05004294 pmlmepriv->num_FortyMHzIntolerant++;
4295 } else
Larry Finger5e93f352014-03-28 21:37:38 -05004296 pmlmepriv->num_sta_no_ht++;
Larry Finger5e93f352014-03-28 21:37:38 -05004297 }
4298
4299
Masanari Iidafae062a2014-07-22 23:42:13 +09004300 /* mark bss info receiving from nearby channel as SignalQuality 101 */
Jes Sorensen37cb9822014-05-21 09:37:40 +02004301 if (bssid->DSConfig != rtw_get_oper_ch23a(padapter))
Jes Sorensen60b152c2014-10-10 21:41:36 +02004302 bssid->SignalQuality = 101;
Larry Finger5e93f352014-03-28 21:37:38 -05004303
Jes Sorensen1bebe752014-06-09 15:16:30 +02004304 return bssid;
4305fail:
4306 kfree (bssid);
4307 return NULL;
Larry Finger5e93f352014-03-28 21:37:38 -05004308}
4309
Greg Donald4e66cf02014-08-22 10:57:49 -05004310static void start_create_ibss(struct rtw_adapter *padapter)
Larry Finger5e93f352014-03-28 21:37:38 -05004311{
Jes Sorensend54239a2014-05-31 18:05:08 +02004312 unsigned short caps;
4313 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05004314 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4315 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
Yeliz Taneroglu2ce71bd2014-10-09 01:22:15 +03004316
Jes Sorensen37cb9822014-05-21 09:37:40 +02004317 pmlmeext->cur_channel = (u8)pnetwork->DSConfig;
Jes Sorensen0fd90b72014-06-19 11:37:35 +02004318 pmlmeinfo->bcn_interval = pnetwork->beacon_interval;
Larry Finger5e93f352014-03-28 21:37:38 -05004319
4320 /* update wireless mode */
4321 update_wireless_mode23a(padapter);
4322
Masanari Iidafae062a2014-07-22 23:42:13 +09004323 /* update capability */
Jes Sorensena94e12b2014-06-19 11:37:34 +02004324 caps = pnetwork->capability;
Larry Finger5e93f352014-03-28 21:37:38 -05004325 update_capinfo23a(padapter, caps);
Jes Sorensene1c04622014-05-21 09:37:46 +02004326 if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc master */
Jes Sorensenb8e99162014-04-09 23:20:27 +02004327 rtl8723a_set_sec_cfg(padapter, 0xcf);
Larry Finger5e93f352014-03-28 21:37:38 -05004328
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
Jes Sorensen88715bc2014-05-16 10:04:10 +02004333 rtl8723a_SetBeaconRelatedRegisters(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05004334
Jes Sorensen6ec26272014-07-17 22:59:46 +02004335 /* set msr to MSR_ADHOC */
4336 pmlmeinfo->state = MSR_ADHOC;
Jes Sorensenee225f02014-07-17 22:59:45 +02004337 rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
Larry Finger5e93f352014-03-28 21:37:38 -05004338
4339 /* issue beacon */
Jes Sorensen6ec26272014-07-17 22:59:46 +02004340 if (send_beacon23a(padapter) == _FAIL) {
Larry Finger5e93f352014-03-28 21:37:38 -05004341 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("issuing beacon frame fail....\n"));
4342
4343 report_join_res23a(padapter, -1);
Jes Sorensen6ec26272014-07-17 22:59:46 +02004344 pmlmeinfo->state = MSR_NOLINK;
4345 } else {
Jes Sorensen38dd10b2014-04-09 23:20:20 +02004346 hw_var_set_bssid(padapter, padapter->registrypriv.dev_network.MacAddress);
Jes Sorensenea0cd732014-04-09 23:20:22 +02004347 hw_var_set_mlme_join(padapter, 0);
Larry Finger5e93f352014-03-28 21:37:38 -05004348
4349 report_join_res23a(padapter, 1);
4350 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
4351 }
Tina Ruchandani5db8bee2014-10-23 20:17:20 -07004352 } else {
Jes Sorensen0e176852014-05-21 09:38:20 +02004353 DBG_8723A("%s: invalid cap:%x\n", __func__, caps);
Larry Finger5e93f352014-03-28 21:37:38 -05004354 return;
4355 }
4356}
4357
Greg Donald4e66cf02014-08-22 10:57:49 -05004358static void start_clnt_join(struct rtw_adapter *padapter)
Larry Finger5e93f352014-03-28 21:37:38 -05004359{
Jes Sorensend54239a2014-05-31 18:05:08 +02004360 unsigned short caps;
4361 u8 val8;
4362 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05004363 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4364 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
4365 int beacon_timeout;
4366
Jes Sorensen37cb9822014-05-21 09:37:40 +02004367 pmlmeext->cur_channel = (u8)pnetwork->DSConfig;
Jes Sorensen0fd90b72014-06-19 11:37:35 +02004368 pmlmeinfo->bcn_interval = pnetwork->beacon_interval;
Larry Finger5e93f352014-03-28 21:37:38 -05004369
4370 /* update wireless mode */
4371 update_wireless_mode23a(padapter);
4372
Masanari Iidafae062a2014-07-22 23:42:13 +09004373 /* update capability */
Jes Sorensena94e12b2014-06-19 11:37:34 +02004374 caps = pnetwork->capability;
Larry Finger5e93f352014-03-28 21:37:38 -05004375 update_capinfo23a(padapter, caps);
Jes Sorensene1c04622014-05-21 09:37:46 +02004376 if (caps & WLAN_CAPABILITY_ESS) {
Larry Finger5e93f352014-03-28 21:37:38 -05004377 /* switch channel */
4378 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4379
Jes Sorensen6ec26272014-07-17 22:59:46 +02004380 rtl8723a_set_media_status(padapter, MSR_INFRA);
Larry Finger5e93f352014-03-28 21:37:38 -05004381
Jes Sorensenb8e99162014-04-09 23:20:27 +02004382 val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ?
4383 0xcc: 0xcf;
Larry Finger5e93f352014-03-28 21:37:38 -05004384
Jes Sorensenb8e99162014-04-09 23:20:27 +02004385 rtl8723a_set_sec_cfg(padapter, val8);
Larry Finger5e93f352014-03-28 21:37:38 -05004386
4387 /* switch channel */
4388 /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
4389
4390 /* here wait for receiving the beacon to start auth */
4391 /* and enable a timer */
4392 beacon_timeout = decide_wait_for_beacon_timeout23a(pmlmeinfo->bcn_interval);
4393 set_link_timer(pmlmeext, beacon_timeout);
4394 mod_timer(&padapter->mlmepriv.assoc_timer, jiffies +
4395 msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout));
Jes Sorensen6ec26272014-07-17 22:59:46 +02004396 pmlmeinfo->state = WIFI_FW_AUTH_NULL | MSR_INFRA;
Jes Sorensene1c04622014-05-21 09:37:46 +02004397 } else if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc client */
Jes Sorensen6ec26272014-07-17 22:59:46 +02004398 rtl8723a_set_media_status(padapter, MSR_ADHOC);
Larry Finger5e93f352014-03-28 21:37:38 -05004399
Jes Sorensenb8e99162014-04-09 23:20:27 +02004400 rtl8723a_set_sec_cfg(padapter, 0xcf);
Larry Finger5e93f352014-03-28 21:37:38 -05004401
4402 /* switch channel */
4403 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4404
Jes Sorensen88715bc2014-05-16 10:04:10 +02004405 rtl8723a_SetBeaconRelatedRegisters(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05004406
Jes Sorensen6ec26272014-07-17 22:59:46 +02004407 pmlmeinfo->state = MSR_ADHOC;
Larry Finger5e93f352014-03-28 21:37:38 -05004408
4409 report_join_res23a(padapter, 1);
Tina Ruchandani5db8bee2014-10-23 20:17:20 -07004410 } else {
Larry Finger5e93f352014-03-28 21:37:38 -05004411 /* DBG_8723A("marc: invalid cap:%x\n", caps); */
4412 return;
4413 }
4414}
4415
Greg Donald4e66cf02014-08-22 10:57:49 -05004416static void start_clnt_auth(struct rtw_adapter *padapter)
Larry Finger5e93f352014-03-28 21:37:38 -05004417{
Jes Sorensend54239a2014-05-31 18:05:08 +02004418 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05004419 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4420
4421 del_timer_sync(&pmlmeext->link_timer);
4422
4423 pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
4424 pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
4425
4426 pmlmeinfo->auth_seq = 1;
4427 pmlmeinfo->reauth_count = 0;
4428 pmlmeinfo->reassoc_count = 0;
4429 pmlmeinfo->link_count = 0;
4430 pmlmeext->retry = 0;
4431
4432 /* Because of AP's not receiving deauth before */
4433 /* AP may: 1)not response auth or 2)deauth us after link is complete */
4434 /* issue deauth before issuing auth to deal with the situation */
4435 /* Commented by Albert 2012/07/21 */
Jes Sorensend54239a2014-05-31 18:05:08 +02004436 /* For the Win8 P2P connection, it will be hard to have a
4437 successful connection if this Wi-Fi doesn't connect to it. */
4438 issue_deauth23a(padapter, (&pmlmeinfo->network)->MacAddress,
4439 WLAN_REASON_DEAUTH_LEAVING);
Larry Finger5e93f352014-03-28 21:37:38 -05004440
4441 DBG_8723A_LEVEL(_drv_always_, "start auth\n");
Jes Sorensen0e176852014-05-21 09:38:20 +02004442 issue_auth(padapter, NULL, 0);
Larry Finger5e93f352014-03-28 21:37:38 -05004443
4444 set_link_timer(pmlmeext, REAUTH_TO);
4445}
4446
Greg Donald4e66cf02014-08-22 10:57:49 -05004447static void start_clnt_assoc(struct rtw_adapter *padapter)
Larry Finger5e93f352014-03-28 21:37:38 -05004448{
Jes Sorensend54239a2014-05-31 18:05:08 +02004449 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05004450 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4451
4452 del_timer_sync(&pmlmeext->link_timer);
4453
4454 pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
4455 pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
4456
Jes Sorensen0e176852014-05-21 09:38:20 +02004457 issue_assocreq(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05004458
4459 set_link_timer(pmlmeext, REASSOC_TO);
4460}
4461
Jes Sorensenf66e05d2014-05-16 10:04:34 +02004462int receive_disconnect23a(struct rtw_adapter *padapter,
4463 unsigned char *MacAddr, unsigned short reason)
Larry Finger5e93f352014-03-28 21:37:38 -05004464{
Jes Sorensend54239a2014-05-31 18:05:08 +02004465 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05004466 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4467
4468 /* check A3 */
4469 if (!ether_addr_equal(MacAddr, get_my_bssid23a(&pmlmeinfo->network)))
4470 return _SUCCESS;
4471
4472 DBG_8723A("%s\n", __func__);
4473
Tina Ruchandani5db8bee2014-10-23 20:17:20 -07004474 if ((pmlmeinfo->state&0x03) == MSR_INFRA) {
4475 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
Jes Sorensen6ec26272014-07-17 22:59:46 +02004476 pmlmeinfo->state = MSR_NOLINK;
Larry Finger5e93f352014-03-28 21:37:38 -05004477 report_del_sta_event23a(padapter, MacAddr, reason);
4478
Tina Ruchandani5db8bee2014-10-23 20:17:20 -07004479 } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
Jes Sorensen6ec26272014-07-17 22:59:46 +02004480 pmlmeinfo->state = MSR_NOLINK;
Larry Finger5e93f352014-03-28 21:37:38 -05004481 report_join_res23a(padapter, -2);
4482 }
4483 }
4484
4485 return _SUCCESS;
4486}
4487
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004488static void process_80211d(struct rtw_adapter *padapter,
4489 struct wlan_bssid_ex *bssid)
Larry Finger5e93f352014-03-28 21:37:38 -05004490{
4491 struct registry_priv *pregistrypriv;
4492 struct mlme_ext_priv *pmlmeext;
4493 struct rt_channel_info *chplan_new;
4494 u8 channel;
4495 u8 i;
4496
4497 pregistrypriv = &padapter->registrypriv;
4498 pmlmeext = &padapter->mlmeextpriv;
4499
4500 /* Adjust channel plan by AP Country IE */
4501 if (pregistrypriv->enable80211d &&
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004502 !pmlmeext->update_channel_plan_by_ap_done) {
4503 const u8 *ie, *p;
Larry Finger5e93f352014-03-28 21:37:38 -05004504 struct rt_channel_plan chplan_ap;
4505 struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
4506 u8 country[4];
4507 u8 fcn; /* first channel number */
4508 u8 noc; /* number of channel */
4509 u8 j, k;
4510
Jes Sorensen1de65cc2014-06-24 15:03:30 +02004511 ie = cfg80211_find_ie(WLAN_EID_COUNTRY, bssid->IEs,
4512 bssid->IELength);
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004513 if (!ie || ie[1] < IEEE80211_COUNTRY_IE_MIN_LEN)
4514 return;
Larry Finger5e93f352014-03-28 21:37:38 -05004515
Jes Sorensen17979952014-04-26 18:54:52 +02004516 p = ie + 2;
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004517 ie += ie[1];
Jes Sorensen17979952014-04-26 18:54:52 +02004518 ie += 2;
Larry Finger5e93f352014-03-28 21:37:38 -05004519
Larry Finger5e93f352014-03-28 21:37:38 -05004520 memcpy(country, p, 3);
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004521 country[3] = '\0';
4522
Larry Finger5e93f352014-03-28 21:37:38 -05004523 p += 3;
4524 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004525 ("%s: 802.11d country =%s\n", __func__, country));
Larry Finger5e93f352014-03-28 21:37:38 -05004526
4527 i = 0;
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004528 while ((ie - p) >= 3) {
Larry Finger5e93f352014-03-28 21:37:38 -05004529 fcn = *(p++);
4530 noc = *(p++);
4531 p++;
4532
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004533 for (j = 0; j < noc; j++) {
4534 if (fcn <= 14)
4535 channel = fcn + j; /* 2.4 GHz */
4536 else
4537 channel = fcn + j * 4; /* 5 GHz */
Larry Finger5e93f352014-03-28 21:37:38 -05004538
4539 chplan_ap.Channel[i++] = channel;
4540 }
4541 }
4542 chplan_ap.Len = i;
4543
4544 memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
4545 memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
4546 chplan_new = pmlmeext->channel_set;
4547
4548 i = j = k = 0;
4549 if (pregistrypriv->wireless_mode & WIRELESS_11G) {
4550 do {
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004551 if (i == MAX_CHANNEL_NUM ||
4552 chplan_sta[i].ChannelNum == 0 ||
4553 chplan_sta[i].ChannelNum > 14)
Larry Finger5e93f352014-03-28 21:37:38 -05004554 break;
4555
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004556 if (j == chplan_ap.Len ||
4557 chplan_ap.Channel[j] > 14)
Larry Finger5e93f352014-03-28 21:37:38 -05004558 break;
4559
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004560 if (chplan_sta[i].ChannelNum ==
4561 chplan_ap.Channel[j]) {
4562 chplan_new[k].ChannelNum =
4563 chplan_ap.Channel[j];
Larry Finger5e93f352014-03-28 21:37:38 -05004564 chplan_new[k].ScanType = SCAN_ACTIVE;
4565 i++;
4566 j++;
4567 k++;
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004568 } else if (chplan_sta[i].ChannelNum <
4569 chplan_ap.Channel[j]) {
4570 chplan_new[k].ChannelNum =
4571 chplan_sta[i].ChannelNum;
4572 chplan_new[k].ScanType =
4573 SCAN_PASSIVE;
Larry Finger5e93f352014-03-28 21:37:38 -05004574 i++;
4575 k++;
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004576 } else if (chplan_sta[i].ChannelNum >
4577 chplan_ap.Channel[j]) {
4578 chplan_new[k].ChannelNum =
4579 chplan_ap.Channel[j];
4580 chplan_new[k].ScanType =
4581 SCAN_ACTIVE;
Larry Finger5e93f352014-03-28 21:37:38 -05004582 j++;
4583 k++;
4584 }
4585 } while (1);
4586
4587 /* change AP not support channel to Passive scan */
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004588 while (i < MAX_CHANNEL_NUM &&
4589 chplan_sta[i].ChannelNum != 0 &&
4590 chplan_sta[i].ChannelNum <= 14) {
4591 chplan_new[k].ChannelNum =
4592 chplan_sta[i].ChannelNum;
Larry Finger5e93f352014-03-28 21:37:38 -05004593 chplan_new[k].ScanType = SCAN_PASSIVE;
4594 i++;
4595 k++;
4596 }
4597
4598 /* add channel AP supported */
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004599 while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14){
Larry Finger5e93f352014-03-28 21:37:38 -05004600 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4601 chplan_new[k].ScanType = SCAN_ACTIVE;
4602 j++;
4603 k++;
4604 }
4605 } else {
4606 /* keep original STA 2.4G channel plan */
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004607 while (i < MAX_CHANNEL_NUM &&
4608 chplan_sta[i].ChannelNum != 0 &&
4609 chplan_sta[i].ChannelNum <= 14) {
4610 chplan_new[k].ChannelNum =
4611 chplan_sta[i].ChannelNum;
Larry Finger5e93f352014-03-28 21:37:38 -05004612 chplan_new[k].ScanType = chplan_sta[i].ScanType;
4613 i++;
4614 k++;
4615 }
4616
4617 /* skip AP 2.4G channel plan */
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004618 while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14)
Larry Finger5e93f352014-03-28 21:37:38 -05004619 j++;
Larry Finger5e93f352014-03-28 21:37:38 -05004620 }
4621
4622 if (pregistrypriv->wireless_mode & WIRELESS_11A) {
4623 do {
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004624 if (i == MAX_CHANNEL_NUM ||
4625 chplan_sta[i].ChannelNum == 0)
Larry Finger5e93f352014-03-28 21:37:38 -05004626 break;
4627
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004628 if (j == chplan_ap.Len ||
4629 chplan_ap.Channel[j] == 0)
Larry Finger5e93f352014-03-28 21:37:38 -05004630 break;
4631
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004632 if (chplan_sta[i].ChannelNum ==
4633 chplan_ap.Channel[j]) {
4634 chplan_new[k].ChannelNum =
4635 chplan_ap.Channel[j];
Larry Finger5e93f352014-03-28 21:37:38 -05004636 chplan_new[k].ScanType = SCAN_ACTIVE;
4637 i++;
4638 j++;
4639 k++;
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004640 } else if (chplan_sta[i].ChannelNum <
4641 chplan_ap.Channel[j]) {
4642 chplan_new[k].ChannelNum =
4643 chplan_sta[i].ChannelNum;
Larry Finger5e93f352014-03-28 21:37:38 -05004644 chplan_new[k].ScanType = SCAN_PASSIVE;
4645 i++;
4646 k++;
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004647 } else if (chplan_sta[i].ChannelNum >
4648 chplan_ap.Channel[j]) {
4649 chplan_new[k].ChannelNum =
4650 chplan_ap.Channel[j];
Larry Finger5e93f352014-03-28 21:37:38 -05004651 chplan_new[k].ScanType = SCAN_ACTIVE;
4652 j++;
4653 k++;
4654 }
4655 } while (1);
4656
4657 /* change AP not support channel to Passive scan */
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004658 while (i < MAX_CHANNEL_NUM &&
4659 chplan_sta[i].ChannelNum != 0) {
4660 chplan_new[k].ChannelNum =
4661 chplan_sta[i].ChannelNum;
Larry Finger5e93f352014-03-28 21:37:38 -05004662 chplan_new[k].ScanType = SCAN_PASSIVE;
4663 i++;
4664 k++;
4665 }
4666
4667 /* add channel AP supported */
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004668 while (j < chplan_ap.Len && chplan_ap.Channel[j] != 0) {
Larry Finger5e93f352014-03-28 21:37:38 -05004669 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4670 chplan_new[k].ScanType = SCAN_ACTIVE;
4671 j++;
4672 k++;
4673 }
4674 } else {
4675 /* keep original STA 5G channel plan */
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004676 while (i < MAX_CHANNEL_NUM &&
4677 chplan_sta[i].ChannelNum != 0) {
4678 chplan_new[k].ChannelNum =
4679 chplan_sta[i].ChannelNum;
Larry Finger5e93f352014-03-28 21:37:38 -05004680 chplan_new[k].ScanType = chplan_sta[i].ScanType;
4681 i++;
4682 k++;
4683 }
4684 }
4685 pmlmeext->update_channel_plan_by_ap_done = 1;
4686 }
4687
4688 /* If channel is used by AP, set channel scan type to active */
Jes Sorensen37cb9822014-05-21 09:37:40 +02004689 channel = bssid->DSConfig;
Larry Finger5e93f352014-03-28 21:37:38 -05004690 chplan_new = pmlmeext->channel_set;
4691 i = 0;
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004692 while (i < MAX_CHANNEL_NUM && chplan_new[i].ChannelNum != 0) {
4693 if (chplan_new[i].ChannelNum == channel) {
Larry Finger5e93f352014-03-28 21:37:38 -05004694 if (chplan_new[i].ScanType == SCAN_PASSIVE) {
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004695 /* 5G Bnad 2, 3 (DFS) doesn't change
4696 to active scan */
Larry Finger5e93f352014-03-28 21:37:38 -05004697 if (channel >= 52 && channel <= 144)
4698 break;
4699
4700 chplan_new[i].ScanType = SCAN_ACTIVE;
4701 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
Jes Sorensenf9df1ea2014-04-15 19:43:46 +02004702 ("%s: change channel %d scan type "
4703 "from passive to active\n",
4704 __func__, channel));
Larry Finger5e93f352014-03-28 21:37:38 -05004705 }
4706 break;
4707 }
4708 i++;
4709 }
4710}
4711
4712/****************************************************************************
4713
4714Following are the functions to report events
4715
4716*****************************************************************************/
4717
Jes Sorensend54239a2014-05-31 18:05:08 +02004718void report_survey_event23a(struct rtw_adapter *padapter,
4719 struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05004720{
4721 struct cmd_obj *pcmd_obj;
Jes Sorensend54239a2014-05-31 18:05:08 +02004722 u8 *pevtcmd;
Larry Finger5e93f352014-03-28 21:37:38 -05004723 u32 cmdsz;
Jes Sorensend54239a2014-05-31 18:05:08 +02004724 struct survey_event *psurvey_evt;
Larry Finger5e93f352014-03-28 21:37:38 -05004725 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
Sachin Kamat248c9592014-05-29 17:05:18 +05304735 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
Larry Finger5e93f352014-03-28 21:37:38 -05004736 if (!pcmd_obj)
4737 return;
4738
Haneen Mohammedacc4b972015-03-13 20:45:25 +03004739 cmdsz = sizeof(struct survey_event) + sizeof(struct C2HEvent_Header);
Larry Finger5e93f352014-03-28 21:37:38 -05004740 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4741 if (!pevtcmd) {
4742 kfree(pcmd_obj);
4743 return;
4744 }
4745
Larry Finger5e93f352014-03-28 21:37:38 -05004746 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
Greg Donald7e6646d2014-09-06 19:42:03 -05004753 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
Larry Finger5e93f352014-03-28 21:37:38 -05004754 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
Jes Sorensen1bebe752014-06-09 15:16:30 +02004760 psurvey_evt->bss = collect_bss_info(padapter, precv_frame);
4761 if (!psurvey_evt->bss) {
Larry Finger5e93f352014-03-28 21:37:38 -05004762 kfree(pcmd_obj);
4763 kfree(pevtcmd);
4764 return;
4765 }
4766
Jes Sorensen24687962014-06-09 15:16:29 +02004767 process_80211d(padapter, psurvey_evt->bss);
Larry Finger5e93f352014-03-28 21:37:38 -05004768
4769 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4770
4771 pmlmeext->sitesurvey_res.bss_cnt++;
4772
4773 return;
4774}
4775
4776void report_surveydone_event23a(struct rtw_adapter *padapter)
4777{
4778 struct cmd_obj *pcmd_obj;
Jes Sorensend54239a2014-05-31 18:05:08 +02004779 u8 *pevtcmd;
Larry Finger5e93f352014-03-28 21:37:38 -05004780 u32 cmdsz;
4781 struct surveydone_event *psurveydone_evt;
Jes Sorensend54239a2014-05-31 18:05:08 +02004782 struct C2HEvent_Header *pc2h_evt_hdr;
4783 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05004784 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4785
Sachin Kamat248c9592014-05-29 17:05:18 +05304786 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
Larry Finger5e93f352014-03-28 21:37:38 -05004787 if (!pcmd_obj)
4788 return;
4789
Haneen Mohammedacc4b972015-03-13 20:45:25 +03004790 cmdsz = sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header);
Larry Finger5e93f352014-03-28 21:37:38 -05004791 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4792 if (!pevtcmd) {
4793 kfree(pcmd_obj);
4794 return;
4795 }
4796
Larry Finger5e93f352014-03-28 21:37:38 -05004797 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
Greg Donald7e6646d2014-09-06 19:42:03 -05004804 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
Larry Finger5e93f352014-03-28 21:37:38 -05004805 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
4819void report_join_res23a(struct rtw_adapter *padapter, int res)
4820{
4821 struct cmd_obj *pcmd_obj;
Jes Sorensend54239a2014-05-31 18:05:08 +02004822 u8 *pevtcmd;
Larry Finger5e93f352014-03-28 21:37:38 -05004823 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
Sachin Kamat248c9592014-05-29 17:05:18 +05304830 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
Larry Finger5e93f352014-03-28 21:37:38 -05004831 if (!pcmd_obj)
4832 return;
4833
Haneen Mohammedacc4b972015-03-13 20:45:25 +03004834 cmdsz = sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header);
Larry Finger5e93f352014-03-28 21:37:38 -05004835 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4836 if (!pevtcmd) {
4837 kfree(pcmd_obj);
4838 return;
4839 }
4840
Larry Finger5e93f352014-03-28 21:37:38 -05004841 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
Greg Donald7e6646d2014-09-06 19:42:03 -05004848 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
Larry Finger5e93f352014-03-28 21:37:38 -05004849 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));
Jes Sorenseneb18cf62014-10-10 21:41:38 +02004856 pjoinbss_evt->network.join_res = res;
Larry Finger5e93f352014-03-28 21:37:38 -05004857
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
Jes Sorensend54239a2014-05-31 18:05:08 +02004867void report_del_sta_event23a(struct rtw_adapter *padapter,
Greg Donald4e66cf02014-08-22 10:57:49 -05004868 unsigned char *MacAddr, unsigned short reason)
Larry Finger5e93f352014-03-28 21:37:38 -05004869{
4870 struct cmd_obj *pcmd_obj;
Jes Sorensend54239a2014-05-31 18:05:08 +02004871 u8 *pevtcmd;
Larry Finger5e93f352014-03-28 21:37:38 -05004872 u32 cmdsz;
4873 struct sta_info *psta;
Jes Sorensend54239a2014-05-31 18:05:08 +02004874 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;
Larry Finger5e93f352014-03-28 21:37:38 -05004878 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4879
Sachin Kamat248c9592014-05-29 17:05:18 +05304880 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
Larry Finger5e93f352014-03-28 21:37:38 -05004881 if (!pcmd_obj)
4882 return;
4883
Haneen Mohammedacc4b972015-03-13 20:45:25 +03004884 cmdsz = sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header);
Larry Finger5e93f352014-03-28 21:37:38 -05004885 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4886 if (!pevtcmd) {
4887 kfree(pcmd_obj);
4888 return;
4889 }
4890
Larry Finger5e93f352014-03-28 21:37:38 -05004891 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
Greg Donald7e6646d2014-09-06 19:42:03 -05004898 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
Larry Finger5e93f352014-03-28 21:37:38 -05004899 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
Haneen Mohammedacc4b972015-03-13 20:45:25 +03004912 mac_id = -1;
Larry Finger5e93f352014-03-28 21:37:38 -05004913
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
Jes Sorensend54239a2014-05-31 18:05:08 +02004923void report_add_sta_event23a(struct rtw_adapter *padapter,
Greg Donald4e66cf02014-08-22 10:57:49 -05004924 unsigned char *MacAddr, int cam_idx)
Larry Finger5e93f352014-03-28 21:37:38 -05004925{
4926 struct cmd_obj *pcmd_obj;
Jes Sorensend54239a2014-05-31 18:05:08 +02004927 u8 *pevtcmd;
Larry Finger5e93f352014-03-28 21:37:38 -05004928 u32 cmdsz;
Jes Sorensend54239a2014-05-31 18:05:08 +02004929 struct stassoc_event *padd_sta_evt;
4930 struct C2HEvent_Header *pc2h_evt_hdr;
4931 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05004932 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4933
Sachin Kamat248c9592014-05-29 17:05:18 +05304934 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
Larry Finger5e93f352014-03-28 21:37:38 -05004935 if (!pcmd_obj)
4936 return;
4937
Haneen Mohammedacc4b972015-03-13 20:45:25 +03004938 cmdsz = sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header);
Larry Finger5e93f352014-03-28 21:37:38 -05004939 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4940 if (!pevtcmd) {
4941 kfree(pcmd_obj);
4942 return;
4943 }
4944
Larry Finger5e93f352014-03-28 21:37:38 -05004945 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
Greg Donald7e6646d2014-09-06 19:42:03 -05004952 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
Larry Finger5e93f352014-03-28 21:37:38 -05004953 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
4970Following are the event callback functions
4971
4972*****************************************************************************/
4973
4974/* for sta/adhoc mode */
4975void update_sta_info23a(struct rtw_adapter *padapter, struct sta_info *psta)
4976{
4977 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Jes Sorensend54239a2014-05-31 18:05:08 +02004978 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4979 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
Larry Finger5e93f352014-03-28 21:37:38 -05004980
4981 /* ERP */
4982 VCS_update23a(padapter, psta);
4983
4984 /* HT */
Tina Ruchandani5db8bee2014-10-23 20:17:20 -07004985 if (pmlmepriv->htpriv.ht_option) {
Larry Finger5e93f352014-03-28 21:37:38 -05004986 psta->htpriv.ht_option = true;
4987
4988 psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
4989
Jes Sorensen65be27d2014-05-31 18:05:11 +02004990 if (support_short_GI23a(padapter, &pmlmeinfo->ht_cap))
Larry Finger5e93f352014-03-28 21:37:38 -05004991 psta->htpriv.sgi = true;
4992
4993 psta->qos_option = true;
4994
Tina Ruchandani5db8bee2014-10-23 20:17:20 -07004995 } else {
Larry Finger5e93f352014-03-28 21:37:38 -05004996 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 */
Jes Sorensenbd8ad4a2014-05-09 15:03:21 +02005011 if (pmlmepriv->qos_option)
Larry Finger5e93f352014-03-28 21:37:38 -05005012 psta->qos_option = true;
5013
5014 psta->state = _FW_LINKED;
5015}
5016
Jes Sorensend54239a2014-05-31 18:05:08 +02005017void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter,
5018 int join_res)
Larry Finger5e93f352014-03-28 21:37:38 -05005019{
Jes Sorensend54239a2014-05-31 18:05:08 +02005020 struct sta_info *psta, *psta_bmc;
5021 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05005022 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5023 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
Jes Sorensend54239a2014-05-31 18:05:08 +02005024 struct sta_priv *pstapriv = &padapter->stapriv;
Larry Finger5e93f352014-03-28 21:37:38 -05005025
Jes Sorensenea0cd732014-04-09 23:20:22 +02005026 if (join_res < 0) {
5027 hw_var_set_mlme_join(padapter, 1);
Jes Sorensen38dd10b2014-04-09 23:20:20 +02005028 hw_var_set_bssid(padapter, null_addr);
Larry Finger5e93f352014-03-28 21:37:38 -05005029
5030 /* restore to initial setting. */
Jes Sorensenea0cd732014-04-09 23:20:22 +02005031 update_tx_basic_rate23a(padapter,
5032 padapter->registrypriv.wireless_mode);
Larry Finger5e93f352014-03-28 21:37:38 -05005033
5034 goto exit_mlmeext_joinbss_event_callback23a;
5035 }
5036
Tina Ruchandani5db8bee2014-10-23 20:17:20 -07005037 if ((pmlmeinfo->state&0x03) == MSR_ADHOC) {
Larry Finger5e93f352014-03-28 21:37:38 -05005038 /* for bc/mc */
5039 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
Tina Ruchandani5db8bee2014-10-23 20:17:20 -07005040 if (psta_bmc) {
Larry Finger5e93f352014-03-28 21:37:38 -05005041 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 */
Jes Sorensen585eefb2014-04-09 23:20:43 +02005048 rtl8723a_odm_support_ability_set(padapter, DYNAMIC_ALL_FUNC_ENABLE);
Larry Finger5e93f352014-03-28 21:37:38 -05005049
5050 /* update IOT-releated issue */
5051 update_IOT_info23a(padapter);
5052
Jes Sorensenfa2e5202014-04-09 23:20:18 +02005053 HalSetBrateCfg23a(padapter, cur_network->SupportedRates);
Larry Finger5e93f352014-03-28 21:37:38 -05005054
5055 /* BCN interval */
Jes Sorensen477f0082014-04-09 23:20:23 +02005056 rtl8723a_set_beacon_interval(padapter, pmlmeinfo->bcn_interval);
Larry Finger5e93f352014-03-28 21:37:38 -05005057
Masanari Iidafae062a2014-07-22 23:42:13 +09005058 /* update capability */
Larry Finger5e93f352014-03-28 21:37:38 -05005059 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);
Tina Ruchandani5db8bee2014-10-23 20:17:20 -07005071 if (psta) { /* only for infra. mode */
Larry Finger5e93f352014-03-28 21:37:38 -05005072 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);
Larry Finger5e93f352014-03-28 21:37:38 -05005080 }
5081
Jes Sorensenea0cd732014-04-09 23:20:22 +02005082 hw_var_set_mlme_join(padapter, 2);
Larry Finger5e93f352014-03-28 21:37:38 -05005083
Jes Sorensen6ec26272014-07-17 22:59:46 +02005084 if ((pmlmeinfo->state&0x03) == MSR_INFRA) {
Larry Finger5e93f352014-03-28 21:37:38 -05005085 /* correcting TSF */
Jes Sorensen0e959692014-04-15 19:44:28 +02005086 rtw_correct_TSF(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05005087
5088 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
5089 }
5090
5091 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_CONNECT, 0);
5092
5093exit_mlmeext_joinbss_event_callback23a:
5094 DBG_8723A("=>%s\n", __func__);
5095}
5096
Jes Sorensend54239a2014-05-31 18:05:08 +02005097void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter,
5098 struct sta_info *psta)
Larry Finger5e93f352014-03-28 21:37:38 -05005099{
5100 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5101 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
Larry Finger5e93f352014-03-28 21:37:38 -05005102
5103 DBG_8723A("%s\n", __func__);
5104
Jes Sorensen6ec26272014-07-17 22:59:46 +02005105 if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) {
Jes Sorensend5bacb12014-05-21 09:38:36 +02005106 /* adhoc master or sta_count>1 */
Tina Ruchandani5db8bee2014-10-23 20:17:20 -07005107 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
Larry Finger5e93f352014-03-28 21:37:38 -05005108 /* nothing to do */
Jes Sorensend5bacb12014-05-21 09:38:36 +02005109 } else { /* adhoc client */
Larry Finger5e93f352014-03-28 21:37:38 -05005110 /* correcting TSF */
Jes Sorensen0e959692014-04-15 19:44:28 +02005111 rtw_correct_TSF(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05005112
5113 /* start beacon */
Jes Sorensend5bacb12014-05-21 09:38:36 +02005114 if (send_beacon23a(padapter) != _SUCCESS) {
Larry Finger5e93f352014-03-28 21:37:38 -05005115 pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
5116
Jes Sorensen6ec26272014-07-17 22:59:46 +02005117 pmlmeinfo->state ^= MSR_ADHOC;
Larry Finger5e93f352014-03-28 21:37:38 -05005118
5119 return;
5120 }
5121
5122 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -05005123 }
Jes Sorensenea0cd732014-04-09 23:20:22 +02005124 hw_var_set_mlme_join(padapter, 2);
Larry Finger5e93f352014-03-28 21:37:38 -05005125 }
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
5136void mlmeext_sta_del_event_callback23a(struct rtw_adapter *padapter)
5137{
Jes Sorensend5bacb12014-05-21 09:38:36 +02005138 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05005139 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5140
Jes Sorensend5bacb12014-05-21 09:38:36 +02005141 if (is_client_associated_to_ap23a(padapter) ||
5142 is_IBSS_empty23a(padapter)) {
Larry Finger5e93f352014-03-28 21:37:38 -05005143 /* set_opmode_cmd(padapter, infra_client_with_mlme); */
5144
Jes Sorensen763b4242014-04-09 23:20:14 +02005145 hw_var_set_mlme_disconnect(padapter);
Jes Sorensen38dd10b2014-04-09 23:20:20 +02005146 hw_var_set_bssid(padapter, null_addr);
Larry Finger5e93f352014-03-28 21:37:38 -05005147
5148 /* restore to initial setting. */
Jes Sorensend5bacb12014-05-21 09:38:36 +02005149 update_tx_basic_rate23a(padapter,
5150 padapter->registrypriv.wireless_mode);
Larry Finger5e93f352014-03-28 21:37:38 -05005151
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
Jes Sorensend5bacb12014-05-21 09:38:36 +02005156 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
5157 pmlmeext->cur_ch_offset,
5158 pmlmeext->cur_bwmode);
Larry Finger5e93f352014-03-28 21:37:38 -05005159
5160 flush_all_cam_entry23a(padapter);
5161
Jes Sorensen6ec26272014-07-17 22:59:46 +02005162 pmlmeinfo->state = MSR_NOLINK;
Larry Finger5e93f352014-03-28 21:37:38 -05005163
5164 /* set MSR to no link state -> infra. mode */
Jes Sorensen6ec26272014-07-17 22:59:46 +02005165 rtl8723a_set_media_status(padapter, MSR_INFRA);
Larry Finger5e93f352014-03-28 21:37:38 -05005166
5167 del_timer_sync(&pmlmeext->link_timer);
5168 }
5169}
5170
Larry Finger5e93f352014-03-28 21:37:38 -05005171static u8 chk_ap_is_alive(struct rtw_adapter *padapter, struct sta_info *psta)
5172{
5173 u8 ret = false;
5174
Jes Sorensend5bacb12014-05-21 09:38:36 +02005175 if (sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta) &&
Larry Finger5e93f352014-03-28 21:37:38 -05005176 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
5186void linked_status_chk23a(struct rtw_adapter *padapter)
5187{
Jes Sorensend5bacb12014-05-21 09:38:36 +02005188 u32 i;
5189 struct sta_info *psta;
Larry Finger5e93f352014-03-28 21:37:38 -05005190 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
Jes Sorensend5bacb12014-05-21 09:38:36 +02005191 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05005192 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
Jes Sorensend5bacb12014-05-21 09:38:36 +02005193 struct sta_priv *pstapriv = &padapter->stapriv;
Larry Finger5e93f352014-03-28 21:37:38 -05005194
Jes Sorensenb7c19c22014-05-16 10:04:00 +02005195 if (is_client_associated_to_ap23a(padapter)) {
Larry Finger5e93f352014-03-28 21:37:38 -05005196 /* 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
Jes Sorensend5bacb12014-05-21 09:38:36 +02005203 psta = rtw_get_stainfo23a(pstapriv,
5204 pmlmeinfo->network.MacAddress);
5205 if (psta) {
Larry Finger5e93f352014-03-28 21:37:38 -05005206 bool is_p2p_enable = false;
Larry Finger5e93f352014-03-28 21:37:38 -05005207
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
Jes Sorensend5bacb12014-05-21 09:38:36 +02005214 if (pmlmeext->active_keep_alive_check &&
5215 (rx_chk == _FAIL || tx_chk == _FAIL)) {
Larry Finger5e93f352014-03-28 21:37:38 -05005216 u8 backup_oper_channel = 0;
5217
Jes Sorensend5bacb12014-05-21 09:38:36 +02005218 /* 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);
Larry Finger5e93f352014-03-28 21:37:38 -05005226 }
5227
5228 if (rx_chk != _SUCCESS)
Jes Sorensen0e176852014-05-21 09:38:20 +02005229 issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
Larry Finger5e93f352014-03-28 21:37:38 -05005230
Jes Sorensend5bacb12014-05-21 09:38:36 +02005231 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)
Larry Finger5e93f352014-03-28 21:37:38 -05005242 rx_chk = _SUCCESS;
5243 }
5244
5245 /* back to the original operation channel */
5246 if (backup_oper_channel>0)
Jes Sorensend5bacb12014-05-21 09:38:36 +02005247 SelectChannel23a(padapter,
5248 backup_oper_channel);
Larry Finger5e93f352014-03-28 21:37:38 -05005249 } else {
5250 if (rx_chk != _SUCCESS) {
5251 if (pmlmeext->retry == 0) {
Jes Sorensen0e176852014-05-21 09:38:20 +02005252 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);
Larry Finger5e93f352014-03-28 21:37:38 -05005255 }
5256 }
5257
Jes Sorensend5bacb12014-05-21 09:38:36 +02005258 if (tx_chk != _SUCCESS &&
5259 pmlmeinfo->link_count++ == 0xf)
5260 tx_chk = issue_nulldata23a(padapter,
5261 NULL, 0, 1,
5262 0);
Larry Finger5e93f352014-03-28 21:37:38 -05005263 }
5264
5265 if (rx_chk == _FAIL) {
5266 pmlmeext->retry++;
5267 if (pmlmeext->retry > rx_chk_limit) {
Jes Sorensen9cd613c2014-05-09 15:04:03 +02005268 DBG_8723A_LEVEL(_drv_always_,
5269 "%s(%s): disconnect or "
5270 "roaming\n", __func__,
5271 padapter->pnetdev->name);
Larry Finger5e93f352014-03-28 21:37:38 -05005272 receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress,
5273 WLAN_REASON_EXPIRATION_CHK);
5274 return;
5275 }
Jes Sorensend5bacb12014-05-21 09:38:36 +02005276 } else
Larry Finger5e93f352014-03-28 21:37:38 -05005277 pmlmeext->retry = 0;
Larry Finger5e93f352014-03-28 21:37:38 -05005278
Jes Sorensend5bacb12014-05-21 09:38:36 +02005279 if (tx_chk == _FAIL)
Larry Finger5e93f352014-03-28 21:37:38 -05005280 pmlmeinfo->link_count &= 0xf;
Jes Sorensend5bacb12014-05-21 09:38:36 +02005281 else {
Larry Finger5e93f352014-03-28 21:37:38 -05005282 pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
5283 pmlmeinfo->link_count = 0;
5284 }
5285
Jes Sorensend5bacb12014-05-21 09:38:36 +02005286 }
5287 } else if (is_client_associated_to_ibss23a(padapter)) {
Larry Finger5e93f352014-03-28 21:37:38 -05005288 /* linked IBSS mode */
5289 /* for each assoc list entry to check the rx pkt counter */
Jes Sorensend5bacb12014-05-21 09:38:36 +02005290 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
5291 if (pmlmeinfo->FW_sta_info[i].status == 1) {
Larry Finger5e93f352014-03-28 21:37:38 -05005292 psta = pmlmeinfo->FW_sta_info[i].psta;
5293
Jes Sorensend5bacb12014-05-21 09:38:36 +02005294 if (!psta)
5295 continue;
Larry Finger5e93f352014-03-28 21:37:38 -05005296
Jes Sorensend5bacb12014-05-21 09:38:36 +02005297 if (pmlmeinfo->FW_sta_info[i].rx_pkt ==
5298 sta_rx_pkts(psta)) {
Larry Finger5e93f352014-03-28 21:37:38 -05005299
Jes Sorensend5bacb12014-05-21 09:38:36 +02005300 if (pmlmeinfo->FW_sta_info[i].retry<3) {
Larry Finger5e93f352014-03-28 21:37:38 -05005301 pmlmeinfo->FW_sta_info[i].retry++;
Jes Sorensend5bacb12014-05-21 09:38:36 +02005302 } else {
Larry Finger5e93f352014-03-28 21:37:38 -05005303 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 }
Jes Sorensend5bacb12014-05-21 09:38:36 +02005309 } else {
Larry Finger5e93f352014-03-28 21:37:38 -05005310 pmlmeinfo->FW_sta_info[i].retry = 0;
5311 pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
5312 }
5313 }
5314 }
Larry Finger5e93f352014-03-28 21:37:38 -05005315 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
Larry Finger5e93f352014-03-28 21:37:38 -05005316 }
5317}
5318
5319static 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;
Larry Finger5e93f352014-03-28 21:37:38 -05005326
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
Jes Sorensen98fb8122014-04-15 19:43:35 +02005332 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);
Larry Finger5e93f352014-03-28 21:37:38 -05005337
5338 pmlmeext->scan_abort = false;/* reset */
5339 }
5340
Sachin Kamat248c9592014-05-29 17:05:18 +05305341 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
Larry Finger5e93f352014-03-28 21:37:38 -05005342 if (!ph2c)
5343 goto exit_survey_timer_hdl;
5344
Sachin Kamat248c9592014-05-29 17:05:18 +05305345 psurveyPara = kzalloc(sizeof(struct sitesurvey_parm),
5346 GFP_ATOMIC);
Larry Finger5e93f352014-03-28 21:37:38 -05005347 if (!psurveyPara) {
5348 kfree(ph2c);
5349 goto exit_survey_timer_hdl;
5350 }
5351
Jes Sorensend5bacb12014-05-21 09:38:36 +02005352 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara,
5353 GEN_CMD_CODE(_SiteSurvey));
Larry Finger5e93f352014-03-28 21:37:38 -05005354 rtw_enqueue_cmd23a(pcmdpriv, ph2c);
5355 }
5356
5357exit_survey_timer_hdl:
5358 return;
5359}
5360
5361static 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; */
Jes Sorensend54239a2014-05-31 18:05:08 +02005367 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05005368 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5369 /* struct sta_priv *pstapriv = &padapter->stapriv; */
5370
Jes Sorensend5bacb12014-05-21 09:38:36 +02005371 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
Larry Finger5e93f352014-03-28 21:37:38 -05005372 DBG_8723A("link_timer_hdl:no beacon while connecting\n");
Jes Sorensen6ec26272014-07-17 22:59:46 +02005373 pmlmeinfo->state = MSR_NOLINK;
Larry Finger5e93f352014-03-28 21:37:38 -05005374 report_join_res23a(padapter, -3);
Jes Sorensend5bacb12014-05-21 09:38:36 +02005375 } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
Larry Finger5e93f352014-03-28 21:37:38 -05005376 /* re-auth timer */
Jes Sorensend5bacb12014-05-21 09:38:36 +02005377 if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
Larry Finger5e93f352014-03-28 21:37:38 -05005378 /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */
5379 /* */
5380 pmlmeinfo->state = 0;
5381 report_join_res23a(padapter, -1);
5382 return;
5383 /* */
5384 /* else */
5385 /* */
Jes Sorensend5bacb12014-05-21 09:38:36 +02005386 /* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */
5387 /* pmlmeinfo->reauth_count = 0; */
Larry Finger5e93f352014-03-28 21:37:38 -05005388 /* */
5389 }
5390
5391 DBG_8723A("link_timer_hdl: auth timeout and try again\n");
5392 pmlmeinfo->auth_seq = 1;
Jes Sorensen0e176852014-05-21 09:38:20 +02005393 issue_auth(padapter, NULL, 0);
Larry Finger5e93f352014-03-28 21:37:38 -05005394 set_link_timer(pmlmeext, REAUTH_TO);
Jes Sorensend5bacb12014-05-21 09:38:36 +02005395 } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
Larry Finger5e93f352014-03-28 21:37:38 -05005396 /* re-assoc timer */
Jes Sorensend5bacb12014-05-21 09:38:36 +02005397 if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
Jes Sorensen6ec26272014-07-17 22:59:46 +02005398 pmlmeinfo->state = MSR_NOLINK;
Larry Finger5e93f352014-03-28 21:37:38 -05005399 report_join_res23a(padapter, -2);
5400 return;
5401 }
5402
5403 DBG_8723A("link_timer_hdl: assoc timeout and try again\n");
Jes Sorensen0e176852014-05-21 09:38:20 +02005404 issue_assocreq(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05005405 set_link_timer(pmlmeext, REASSOC_TO);
5406 }
5407
5408 return;
5409}
5410
5411static void addba_timer_hdl(unsigned long data)
5412{
5413 struct sta_info *psta = (struct sta_info *)data;
Jes Sorensend54239a2014-05-31 18:05:08 +02005414 struct ht_priv *phtpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05005415
5416 if (!psta)
5417 return;
5418
5419 phtpriv = &psta->htpriv;
5420
Jes Sorensen47e5d2f2014-06-09 15:16:08 +02005421 if (phtpriv->ht_option && phtpriv->ampdu_enable) {
Larry Finger5e93f352014-03-28 21:37:38 -05005422 if (phtpriv->candidate_tid_bitmap)
5423 phtpriv->candidate_tid_bitmap = 0x0;
Larry Finger5e93f352014-03-28 21:37:38 -05005424 }
5425}
5426
5427void 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
5433void init_mlme_ext_timer23a(struct rtw_adapter *padapter)
5434{
Jes Sorensend54239a2014-05-31 18:05:08 +02005435 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05005436
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
Jes Sorensen1ec89112014-05-16 10:04:28 +02005444int NULL_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05005445{
5446 return H2C_SUCCESS;
5447}
5448
Jes Sorensen1ec89112014-05-16 10:04:28 +02005449int setopmode_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05005450{
Jes Sorensenefc71442014-05-21 09:37:26 +02005451 enum nl80211_iftype type;
5452 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05005453 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
Jes Sorensen0348dc742014-04-26 18:55:06 +02005454 const struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
Larry Finger5e93f352014-03-28 21:37:38 -05005455
Jes Sorensenefc71442014-05-21 09:37:26 +02005456 switch (psetop->mode) {
5457 case NL80211_IFTYPE_P2P_GO:
5458 case NL80211_IFTYPE_AP:
Jes Sorensen6ec26272014-07-17 22:59:46 +02005459 pmlmeinfo->state = MSR_AP;
5460 type = MSR_AP;
Jes Sorensenefc71442014-05-21 09:37:26 +02005461 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 */
Jes Sorensen6ec26272014-07-17 22:59:46 +02005467 pmlmeinfo->state |= MSR_INFRA;
5468 type = MSR_INFRA;
Jes Sorensenefc71442014-05-21 09:37:26 +02005469 break;
5470 case NL80211_IFTYPE_ADHOC:
Jes Sorensen6ec26272014-07-17 22:59:46 +02005471 type = MSR_ADHOC;
Jes Sorensenefc71442014-05-21 09:37:26 +02005472 break;
5473 default:
Jes Sorensen6ec26272014-07-17 22:59:46 +02005474 type = MSR_NOLINK;
Jes Sorensenefc71442014-05-21 09:37:26 +02005475 break;
5476 }
Larry Finger5e93f352014-03-28 21:37:38 -05005477
Jes Sorensendbdcd362014-04-09 23:20:17 +02005478 hw_var_set_opmode(padapter, type);
Larry Finger5e93f352014-03-28 21:37:38 -05005479 /* Set_NETYPE0_MSR(padapter, type); */
5480
5481 return H2C_SUCCESS;
5482}
5483
Jes Sorensen1ec89112014-05-16 10:04:28 +02005484int createbss_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05005485{
Jes Sorensend54239a2014-05-31 18:05:08 +02005486 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05005487 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5488 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
Jes Sorensen0348dc742014-04-26 18:55:06 +02005489 const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
Larry Finger5e93f352014-03-28 21:37:38 -05005490 /* u32 initialgain; */
5491
Jes Sorensenefc71442014-05-21 09:37:26 +02005492 if (pparm->ifmode == NL80211_IFTYPE_AP ||
5493 pparm->ifmode == NL80211_IFTYPE_P2P_GO) {
Larry Finger5e93f352014-03-28 21:37:38 -05005494#ifdef CONFIG_8723AU_AP_MODE
Jes Sorensen6ec26272014-07-17 22:59:46 +02005495 if (pmlmeinfo->state == MSR_AP) {
Larry Finger5e93f352014-03-28 21:37:38 -05005496 /* todo: */
5497 return H2C_SUCCESS;
5498 }
5499#endif
5500 }
5501
5502 /* below is for ad-hoc master */
Jes Sorensenefc71442014-05-21 09:37:26 +02005503 if (pparm->ifmode == NL80211_IFTYPE_ADHOC) {
Larry Finger5e93f352014-03-28 21:37:38 -05005504 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;
Larry Finger5e93f352014-03-28 21:37:38 -05005513
5514 /* disable dynamic functions, such as high power, DIG */
Jes Sorensena945bf32014-04-09 23:20:42 +02005515 rtl8723a_odm_support_ability_backup(padapter);
5516
Jes Sorensen585eefb2014-04-09 23:20:43 +02005517 rtl8723a_odm_support_ability_clr(padapter,
5518 DYNAMIC_FUNC_DISABLE);
Larry Finger5e93f352014-03-28 21:37:38 -05005519
Larry Finger5e93f352014-03-28 21:37:38 -05005520 /* 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
Jes Sorensen0e176852014-05-21 09:38:20 +02005531 start_create_ibss(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05005532 }
5533
5534 return H2C_SUCCESS;
5535}
5536
Jes Sorensen1ec89112014-05-16 10:04:28 +02005537int join_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05005538{
Jes Sorensend5bacb12014-05-21 09:38:36 +02005539 struct registry_priv *pregpriv = &padapter->registrypriv;
5540 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05005541 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5542 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
Jes Sorensen0348dc742014-04-26 18:55:06 +02005543 const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
Jes Sorensen4dc5f8b2014-05-31 18:05:13 +02005544 struct ieee80211_ht_operation *pht_info;
Larry Finger5e93f352014-03-28 21:37:38 -05005545 u32 i;
Jes Sorensenb171da32014-05-21 09:37:42 +02005546 u8 *p;
Greg Donalda82b4b02014-09-08 20:50:23 -05005547 /* u32 initialgain; */
Larry Finger5e93f352014-03-28 21:37:38 -05005548 /* u32 acparm; */
5549
5550 /* check already connecting to AP or not */
Jes Sorensend5bacb12014-05-21 09:38:36 +02005551 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
Jes Sorensen6ec26272014-07-17 22:59:46 +02005552 if (pmlmeinfo->state & MSR_INFRA)
Jes Sorensen0e176852014-05-21 09:38:20 +02005553 issue_deauth_ex(padapter, pnetwork->MacAddress,
Larry Finger5e93f352014-03-28 21:37:38 -05005554 WLAN_REASON_DEAUTH_LEAVING, 5, 100);
5555
Jes Sorensen6ec26272014-07-17 22:59:46 +02005556 pmlmeinfo->state = MSR_NOLINK;
Larry Finger5e93f352014-03-28 21:37:38 -05005557
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 */
Jes Sorensen6ec26272014-07-17 22:59:46 +02005564 rtl8723a_set_media_status(padapter, MSR_INFRA);
Larry Finger5e93f352014-03-28 21:37:38 -05005565
Jes Sorensen763b4242014-04-09 23:20:14 +02005566 hw_var_set_mlme_disconnect(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05005567 }
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;
Larry Finger5e93f352014-03-28 21:37:38 -05005578 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
Jes Sorensen68e6c792014-06-24 15:03:29 +02005590 for (i = 0; i < pnetwork->IELength;) {
Jes Sorensenb171da32014-05-21 09:37:42 +02005591 p = pnetwork->IEs + i;
Larry Finger5e93f352014-03-28 21:37:38 -05005592
Jes Sorensenb171da32014-05-21 09:37:42 +02005593 switch (p[0]) {
Jes Sorensen9300c942014-04-15 19:43:21 +02005594 case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */
Jes Sorensenb171da32014-05-21 09:37:42 +02005595 if (!memcmp(p + 2, WMM_OUI23A, 4))
Larry Finger5e93f352014-03-28 21:37:38 -05005596 pmlmeinfo->WMM_enable = 1;
5597 break;
5598
Jes Sorensen5afd3912014-04-15 19:43:24 +02005599 case WLAN_EID_HT_CAPABILITY: /* Get HT Cap IE. */
Larry Finger5e93f352014-03-28 21:37:38 -05005600 pmlmeinfo->HT_caps_enable = 1;
5601 break;
5602
Jes Sorensen5afd3912014-04-15 19:43:24 +02005603 case WLAN_EID_HT_OPERATION: /* Get HT Info IE. */
Larry Finger5e93f352014-03-28 21:37:38 -05005604 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 */
Jes Sorensen4dc5f8b2014-05-31 18:05:13 +02005608 pht_info = (struct ieee80211_ht_operation *)(p + 2);
Larry Finger5e93f352014-03-28 21:37:38 -05005609
Jes Sorensen4dc5f8b2014-05-31 18:05:13 +02005610 if (pregpriv->cbw40_enable &&
5611 (pht_info->ht_param &
5612 IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
Larry Finger5e93f352014-03-28 21:37:38 -05005613 /* switch to the 40M Hz mode according to AP */
5614 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
Jes Sorensen4dc5f8b2014-05-31 18:05:13 +02005615 switch (pht_info->ht_param &
5616 IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
5617 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
Larry Finger5e93f352014-03-28 21:37:38 -05005618 pmlmeext->cur_ch_offset =
5619 HAL_PRIME_CHNL_OFFSET_LOWER;
5620 break;
5621
Jes Sorensen4dc5f8b2014-05-31 18:05:13 +02005622 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
Larry Finger5e93f352014-03-28 21:37:38 -05005623 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
Jes Sorensenb171da32014-05-21 09:37:42 +02005641 i += (p[1] + 2);
Larry Finger5e93f352014-03-28 21:37:38 -05005642 }
Larry Finger5e93f352014-03-28 21:37:38 -05005643
Jes Sorensen38dd10b2014-04-09 23:20:20 +02005644 hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress);
Jes Sorensenea0cd732014-04-09 23:20:22 +02005645 hw_var_set_mlme_join(padapter, 0);
Larry Finger5e93f352014-03-28 21:37:38 -05005646
5647 /* cancel link timer */
5648 del_timer_sync(&pmlmeext->link_timer);
5649
Jes Sorensen0e176852014-05-21 09:38:20 +02005650 start_clnt_join(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05005651
5652 return H2C_SUCCESS;
5653}
5654
Jes Sorensen1ec89112014-05-16 10:04:28 +02005655int disconnect_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05005656{
Jes Sorensen0348dc742014-04-26 18:55:06 +02005657 const struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
Jes Sorensend5bacb12014-05-21 09:38:36 +02005658 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05005659 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5660 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
Larry Finger5e93f352014-03-28 21:37:38 -05005661
Jes Sorensend5bacb12014-05-21 09:38:36 +02005662 if (is_client_associated_to_ap23a(padapter)) {
Jes Sorensen0e176852014-05-21 09:38:20 +02005663 issue_deauth_ex(padapter, pnetwork->MacAddress,
5664 WLAN_REASON_DEAUTH_LEAVING,
5665 param->deauth_timeout_ms/100, 100);
Larry Finger5e93f352014-03-28 21:37:38 -05005666 }
5667
5668 /* set_opmode_cmd(padapter, infra_client_with_mlme); */
5669
Jes Sorensen6ec26272014-07-17 22:59:46 +02005670 /* pmlmeinfo->state = MSR_NOLINK; */
Larry Finger5e93f352014-03-28 21:37:38 -05005671
Jes Sorensen763b4242014-04-09 23:20:14 +02005672 hw_var_set_mlme_disconnect(padapter);
Jes Sorensen38dd10b2014-04-09 23:20:20 +02005673 hw_var_set_bssid(padapter, null_addr);
Larry Finger5e93f352014-03-28 21:37:38 -05005674
5675 /* restore to initial setting. */
5676 update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
5677
Jes Sorensen6ec26272014-07-17 22:59:46 +02005678 if ((pmlmeinfo->state & 0x03) == MSR_ADHOC ||
5679 (pmlmeinfo->state & 0x03) == MSR_AP)
Jes Sorensendc451602014-04-09 23:20:34 +02005680 rtl8723a_set_bcn_func(padapter, 0); /* Stop BCN */
Larry Finger5e93f352014-03-28 21:37:38 -05005681
5682 /* set MSR to no link state -> infra. mode */
Jes Sorensen6ec26272014-07-17 22:59:46 +02005683 rtl8723a_set_media_status(padapter, MSR_INFRA);
Larry Finger5e93f352014-03-28 21:37:38 -05005684
Jes Sorensen6ec26272014-07-17 22:59:46 +02005685 pmlmeinfo->state = MSR_NOLINK;
Larry Finger5e93f352014-03-28 21:37:38 -05005686
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
Jes Sorensend5bacb12014-05-21 09:38:36 +02005691 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
5692 pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
Larry Finger5e93f352014-03-28 21:37:38 -05005693
5694 flush_all_cam_entry23a(padapter);
5695
5696 del_timer_sync(&pmlmeext->link_timer);
5697
5698 rtw_free_uc_swdec_pending_queue23a(padapter);
5699
Jes Sorensend54239a2014-05-31 18:05:08 +02005700 return H2C_SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -05005701}
5702
Jes Sorensen0348dc742014-04-26 18:55:06 +02005703static int
5704rtw_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)
Larry Finger5e93f352014-03-28 21:37:38 -05005707{
5708 int i, j;
5709 int scan_ch_num = 0;
5710 int set_idx;
Jes Sorensend54239a2014-05-31 18:05:08 +02005711 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05005712
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++) {
Jes Sorensend5bacb12014-05-21 09:38:36 +02005719 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));
Larry Finger5e93f352014-03-28 21:37:38 -05005725
Jes Sorensend5bacb12014-05-21 09:38:36 +02005726 if (pmlmeext->channel_set[set_idx].ScanType ==
5727 SCAN_PASSIVE)
Larry Finger5e93f352014-03-28 21:37:38 -05005728 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
Jes Sorensend5bacb12014-05-21 09:38:36 +02005748 if (padapter->setband == GHZ_24) { /* 2.4G */
Larry Finger5e93f352014-03-28 21:37:38 -05005749 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;
Jes Sorensend5bacb12014-05-21 09:38:36 +02005757 } else if (padapter->setband == GHZ_50) { /* 5G */
Larry Finger5e93f352014-03-28 21:37:38 -05005758 for (i = 0; i < j ; i++) {
5759 if (out[i].hw_value > 35) {
Jes Sorensend5bacb12014-05-21 09:38:36 +02005760 memcpy(&out[scan_ch_num++], &out[i],
5761 sizeof(struct rtw_ieee80211_channel));
Larry Finger5e93f352014-03-28 21:37:38 -05005762 }
5763 }
5764 j = scan_ch_num;
5765 } else
5766 {}
5767
5768 return j;
5769}
5770
Jes Sorensen1ec89112014-05-16 10:04:28 +02005771int sitesurvey_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05005772{
5773 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Jes Sorensen0348dc742014-04-26 18:55:06 +02005774 const struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;
Larry Finger5e93f352014-03-28 21:37:38 -05005775 u8 bdelayscan = false;
Larry Finger5e93f352014-03-28 21:37:38 -05005776 u32 initialgain;
5777 u32 i;
5778
5779 if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
Larry Finger5e93f352014-03-28 21:37:38 -05005780 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,
Jes Sorensen7b2e06a2014-06-09 15:16:35 +02005787 pparm->ssid[i].ssid,
5788 IEEE80211_MAX_SSID_LEN);
Larry Finger5e93f352014-03-28 21:37:38 -05005789 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 */
Jes Sorensend5bacb12014-05-21 09:38:36 +02005810 if (rtw_get_oper_ch23a(padapter) !=
5811 pmlmeext->cur_channel)
5812 SelectChannel23a(padapter,
5813 pmlmeext->cur_channel);
Larry Finger5e93f352014-03-28 21:37:38 -05005814
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
Jes Sorensend5bacb12014-05-21 09:38:36 +02005827 if (pmlmeext->sitesurvey_res.state == SCAN_START ||
5828 pmlmeext->sitesurvey_res.state == SCAN_TXNULL) {
Larry Finger5e93f352014-03-28 21:37:38 -05005829 /* disable dynamic functions, such as high power, DIG */
Jes Sorensena945bf32014-04-09 23:20:42 +02005830 rtl8723a_odm_support_ability_backup(padapter);
Jes Sorensen585eefb2014-04-09 23:20:43 +02005831 rtl8723a_odm_support_ability_clr(padapter,
5832 DYNAMIC_FUNC_DISABLE);
Larry Finger5e93f352014-03-28 21:37:38 -05005833
Masanari Iidafae062a2014-07-22 23:42:13 +09005834 /* config the initial gain under scanning, need to
Larry Finger5e93f352014-03-28 21:37:38 -05005835 write the BB registers */
Jes Sorensen7c82a2b2014-04-09 23:20:33 +02005836 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == true)
Larry Finger5e93f352014-03-28 21:37:38 -05005837 initialgain = 0x30;
Jes Sorensen7c82a2b2014-04-09 23:20:33 +02005838 else
Larry Finger5e93f352014-03-28 21:37:38 -05005839 initialgain = 0x1E;
5840
Jes Sorensen7c82a2b2014-04-09 23:20:33 +02005841 rtl8723a_set_initial_gain(padapter, initialgain);
Larry Finger5e93f352014-03-28 21:37:38 -05005842
5843 /* set MSR to no link state */
Jes Sorensen6ec26272014-07-17 22:59:46 +02005844 rtl8723a_set_media_status(padapter, MSR_NOLINK);
Larry Finger5e93f352014-03-28 21:37:38 -05005845
Jes Sorensena0860232014-04-09 23:20:21 +02005846 rtl8723a_mlme_sitesurvey(padapter, 1);
Larry Finger5e93f352014-03-28 21:37:38 -05005847
5848 pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
5849 }
5850
Jes Sorensen662c9bf2014-05-21 09:38:34 +02005851 rtw_site_survey(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05005852
5853 return H2C_SUCCESS;
5854}
5855
Jes Sorensen1ec89112014-05-16 10:04:28 +02005856int setauth_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05005857{
Jes Sorensen0348dc742014-04-26 18:55:06 +02005858 const struct setauth_parm *pparm = (struct setauth_parm *)pbuf;
Jes Sorensend5bacb12014-05-21 09:38:36 +02005859 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05005860 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5861
5862 if (pparm->mode < 4)
Larry Finger5e93f352014-03-28 21:37:38 -05005863 pmlmeinfo->auth_algo = pparm->mode;
Larry Finger5e93f352014-03-28 21:37:38 -05005864
Jes Sorensend54239a2014-05-31 18:05:08 +02005865 return H2C_SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -05005866}
5867
Jes Sorensen1ec89112014-05-16 10:04:28 +02005868int setkey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05005869{
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005870 unsigned short ctrl;
Jes Sorensen0348dc742014-04-26 18:55:06 +02005871 const struct setkey_parm *pparm = (struct setkey_parm *)pbuf;
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005872 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05005873 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005874 unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Larry Finger5e93f352014-03-28 21:37:38 -05005875
5876 /* main tx key for wep. */
5877 if (pparm->set_tx)
5878 pmlmeinfo->key_index = pparm->keyid;
5879
5880 /* write cam */
Jes Sorensend5bacb12014-05-21 09:38:36 +02005881 ctrl = BIT(15) | (pparm->algorithm) << 2 | pparm->keyid;
Larry Finger5e93f352014-03-28 21:37:38 -05005882
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005883 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);
Jes Sorensendc0d16a2014-04-09 23:20:29 +02005886 rtl8723a_cam_write(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
Larry Finger5e93f352014-03-28 21:37:38 -05005887
5888 /* allow multicast packets to driver */
Jes Sorensen763b4242014-04-09 23:20:14 +02005889 rtl8723a_on_rcr_am(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -05005890
5891 return H2C_SUCCESS;
5892}
5893
Jes Sorensen1ec89112014-05-16 10:04:28 +02005894int set_stakey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05005895{
5896 u16 ctrl = 0;
5897 u8 cam_id;/* cam_entry */
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005898 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05005899 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
Jes Sorensen0348dc742014-04-26 18:55:06 +02005900 const struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf;
Larry Finger5e93f352014-03-28 21:37:38 -05005901
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
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005917 DBG_8723A_LEVEL(_drv_always_, "set pairwise key to hw: alg:%d(WEP40-1 "
5918 "WEP104-5 TKIP-2 AES-4) camid:%d\n",
Larry Finger5e93f352014-03-28 21:37:38 -05005919 pparm->algorithm, cam_id);
Jes Sorensen6ec26272014-07-17 22:59:46 +02005920 if ((pmlmeinfo->state & 0x03) == MSR_AP) {
Larry Finger5e93f352014-03-28 21:37:38 -05005921 struct sta_info *psta;
5922 struct sta_priv *pstapriv = &padapter->stapriv;
5923
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005924 if (pparm->algorithm == 0) { /* clear cam entry */
Larry Finger5e93f352014-03-28 21:37:38 -05005925 clear_cam_entry23a(padapter, pparm->id);
5926 return H2C_SUCCESS_RSP;
5927 }
5928
5929 psta = rtw_get_stainfo23a(pstapriv, pparm->addr);
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005930 if (psta) {
5931 ctrl = BIT(15) | (pparm->algorithm << 2);
Larry Finger5e93f352014-03-28 21:37:38 -05005932
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005933 DBG_8723A("r871x_set_stakey_hdl23a(): enc_algorithm "
5934 "=%d\n", pparm->algorithm);
Larry Finger5e93f352014-03-28 21:37:38 -05005935
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005936 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);
Larry Finger5e93f352014-03-28 21:37:38 -05005940 return H2C_REJECTED;
5941 }
5942
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005943 /* 0~3 for default key, cmd_id = macid + 3,
5944 macid = aid+1; */
Haneen Mohammedacc4b972015-03-13 20:45:25 +03005945 cam_id = psta->mac_id + 3;
Larry Finger5e93f352014-03-28 21:37:38 -05005946
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005947 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);
Larry Finger5e93f352014-03-28 21:37:38 -05005952
Jes Sorensendc0d16a2014-04-09 23:20:29 +02005953 rtl8723a_cam_write(padapter, cam_id, ctrl,
5954 pparm->addr, pparm->key);
Larry Finger5e93f352014-03-28 21:37:38 -05005955
5956 return H2C_SUCCESS_RSP;
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005957 } else {
5958 DBG_8723A("r871x_set_stakey_hdl23a(): sta has been "
5959 "free\n");
Larry Finger5e93f352014-03-28 21:37:38 -05005960 return H2C_REJECTED;
5961 }
Larry Finger5e93f352014-03-28 21:37:38 -05005962 }
5963
5964 /* below for sta mode */
5965
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02005966 if (pparm->algorithm == 0) { /* clear cam entry */
Larry Finger5e93f352014-03-28 21:37:38 -05005967 clear_cam_entry23a(padapter, pparm->id);
5968 return H2C_SUCCESS;
5969 }
5970
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005971 ctrl = BIT(15) | (pparm->algorithm << 2);
Larry Finger5e93f352014-03-28 21:37:38 -05005972
Jes Sorensendc0d16a2014-04-09 23:20:29 +02005973 rtl8723a_cam_write(padapter, cam_id, ctrl, pparm->addr, pparm->key);
Larry Finger5e93f352014-03-28 21:37:38 -05005974
5975 pmlmeinfo->enc_algo = pparm->algorithm;
5976
5977 return H2C_SUCCESS;
5978}
5979
Jes Sorensen1ec89112014-05-16 10:04:28 +02005980int add_ba_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05005981{
Jes Sorensen0348dc742014-04-26 18:55:06 +02005982 const struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf;
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005983 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05005984 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005985 struct sta_info *psta;
Larry Finger5e93f352014-03-28 21:37:38 -05005986
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005987 psta = rtw_get_stainfo23a(&padapter->stapriv, pparm->addr);
Larry Finger5e93f352014-03-28 21:37:38 -05005988
5989 if (!psta)
Jes Sorensend54239a2014-05-31 18:05:08 +02005990 return H2C_SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -05005991
5992 if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005993 pmlmeinfo->HT_enable) ||
Jes Sorensen6ec26272014-07-17 22:59:46 +02005994 (pmlmeinfo->state & 0x03) == MSR_AP) {
Larry Finger5e93f352014-03-28 21:37:38 -05005995 issue_action_BA23a(padapter, pparm->addr,
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005996 WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
Larry Finger5e93f352014-03-28 21:37:38 -05005997 mod_timer(&psta->addba_retry_timer,
5998 jiffies + msecs_to_jiffies(ADDBA_TO));
Jes Sorensen1feec0d2014-05-21 09:38:35 +02005999 } else
Jes Sorensend7f2c232014-05-09 15:04:17 +02006000 psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
Jes Sorensen1feec0d2014-05-21 09:38:35 +02006001
Jes Sorensend54239a2014-05-31 18:05:08 +02006002 return H2C_SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -05006003}
6004
Greg Donald4e66cf02014-08-22 10:57:49 -05006005int set_tx_beacon_cmd23a(struct rtw_adapter *padapter)
Larry Finger5e93f352014-03-28 21:37:38 -05006006{
Jes Sorensen1feec0d2014-05-21 09:38:35 +02006007 struct cmd_obj *ph2c;
Jes Sorensend54239a2014-05-31 18:05:08 +02006008 struct Tx_Beacon_param *ptxBeacon_parm;
Larry Finger5e93f352014-03-28 21:37:38 -05006009 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
Jes Sorensend54239a2014-05-31 18:05:08 +02006010 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05006011 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
Jes Sorensen1feec0d2014-05-21 09:38:35 +02006012 u8 res = _SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -05006013 int len_diff = 0;
6014
Sachin Kamat248c9592014-05-29 17:05:18 +05306015 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
Larry Finger5e93f352014-03-28 21:37:38 -05006016 if (!ph2c) {
6017 res = _FAIL;
6018 goto exit;
6019 }
6020
Sachin Kamat248c9592014-05-29 17:05:18 +05306021 ptxBeacon_parm = kzalloc(sizeof(struct Tx_Beacon_param), GFP_ATOMIC);
Larry Finger5e93f352014-03-28 21:37:38 -05006022 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
Jes Sorensen1de65cc2014-06-24 15:03:30 +02006031 len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs,
6032 ptxBeacon_parm->network.IELength,
6033 pmlmeinfo->hidden_ssid_mode);
Larry Finger5e93f352014-03-28 21:37:38 -05006034 ptxBeacon_parm->network.IELength += len_diff;
6035
Jes Sorensen1feec0d2014-05-21 09:38:35 +02006036 init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm,
6037 GEN_CMD_CODE(_TX_Beacon));
Larry Finger5e93f352014-03-28 21:37:38 -05006038
6039 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
6040
6041exit:
Larry Finger5e93f352014-03-28 21:37:38 -05006042 return res;
6043}
6044
Jes Sorensen1ec89112014-05-16 10:04:28 +02006045int mlme_evt_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05006046{
6047 u8 evt_code, evt_seq;
6048 u16 evt_sz;
Jes Sorensen0f6df022014-05-09 15:03:18 +02006049 const struct C2HEvent_Header *c2h;
Jes Sorensene2601962014-05-09 15:03:19 +02006050 void (*event_callback)(struct rtw_adapter *dev, const u8 *pbuf);
Larry Finger5e93f352014-03-28 21:37:38 -05006051
Jes Sorensen0f6df022014-05-09 15:03:18 +02006052 c2h = (struct C2HEvent_Header *)pbuf;
6053 evt_sz = c2h->len;
6054 evt_seq = c2h->seq;
6055 evt_code = c2h->ID;
Larry Finger5e93f352014-03-28 21:37:38 -05006056
6057 /* checking if event code is valid */
6058 if (evt_code >= MAX_C2HEVT) {
Jes Sorensen1feec0d2014-05-21 09:38:35 +02006059 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
6060 ("\nEvent Code(%d) mismatch!\n", evt_code));
Larry Finger5e93f352014-03-28 21:37:38 -05006061 goto _abort_event_;
6062 }
6063
6064 /* checking if event size match the event parm size */
Jes Sorensen1feec0d2014-05-21 09:38:35 +02006065 if (wlanevents[evt_code].parmsize != 0 &&
6066 wlanevents[evt_code].parmsize != evt_sz) {
6067 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
6068 ("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n",
6069 evt_code, wlanevents[evt_code].parmsize, evt_sz));
Larry Finger5e93f352014-03-28 21:37:38 -05006070 goto _abort_event_;
6071 }
6072
Jes Sorensen0f6df022014-05-09 15:03:18 +02006073 event_callback = wlanevents[evt_code].event_callback;
Jes Sorensene2601962014-05-09 15:03:19 +02006074 event_callback(padapter, pbuf + sizeof(struct C2HEvent_Header));
Larry Finger5e93f352014-03-28 21:37:38 -05006075
6076_abort_event_:
6077
6078 return H2C_SUCCESS;
6079}
6080
Jes Sorensen1ec89112014-05-16 10:04:28 +02006081int h2c_msg_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05006082{
6083 if (!pbuf)
6084 return H2C_PARAMETERS_ERROR;
6085
6086 return H2C_SUCCESS;
6087}
6088
Jes Sorensen1ec89112014-05-16 10:04:28 +02006089int tx_beacon_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05006090{
Jes Sorensen1feec0d2014-05-21 09:38:35 +02006091 if (send_beacon23a(padapter) == _FAIL) {
Larry Finger5e93f352014-03-28 21:37:38 -05006092 DBG_8723A("issue_beacon23a, fail!\n");
6093 return H2C_PARAMETERS_ERROR;
6094 }
6095#ifdef CONFIG_8723AU_AP_MODE
Jes Sorensen1feec0d2014-05-21 09:38:35 +02006096 else { /* tx bc/mc frames after update TIM */
Larry Finger5e93f352014-03-28 21:37:38 -05006097 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
Jes Sorensen1feec0d2014-05-21 09:38:35 +02006108 if (pstapriv->tim_bitmap & BIT(0) && psta_bmc->sleepq_len > 0) {
Larry Finger5e93f352014-03-28 21:37:38 -05006109 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
Jes Sorensen638443d2014-05-16 10:04:18 +02006132 rtl8723au_hal_xmitframe_enqueue(padapter,
6133 pxmitframe);
Larry Finger5e93f352014-03-28 21:37:38 -05006134 }
6135
6136 /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
6137 spin_unlock_bh(&pxmitpriv->lock);
6138 }
Larry Finger5e93f352014-03-28 21:37:38 -05006139 }
6140#endif
6141
6142 return H2C_SUCCESS;
6143}
6144
Jes Sorensen1ec89112014-05-16 10:04:28 +02006145int set_ch_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05006146{
Jes Sorensen0348dc742014-04-26 18:55:06 +02006147 const struct set_ch_parm *set_ch_parm;
Jes Sorensend54239a2014-05-31 18:05:08 +02006148 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05006149
6150 if (!pbuf)
6151 return H2C_PARAMETERS_ERROR;
6152
6153 set_ch_parm = (struct set_ch_parm *)pbuf;
6154
Jes Sorensena790d582014-05-09 15:04:04 +02006155 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);
Larry Finger5e93f352014-03-28 21:37:38 -05006158
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
Jes Sorensen1feec0d2014-05-21 09:38:35 +02006163 set_channel_bwmode23a(padapter, set_ch_parm->ch,
6164 set_ch_parm->ch_offset, set_ch_parm->bw);
Larry Finger5e93f352014-03-28 21:37:38 -05006165
Jes Sorensend54239a2014-05-31 18:05:08 +02006166 return H2C_SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -05006167}
6168
Jes Sorensen1ec89112014-05-16 10:04:28 +02006169int set_chplan_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05006170{
Jes Sorensen0348dc742014-04-26 18:55:06 +02006171 const struct SetChannelPlan_param *setChannelPlan_param;
Jes Sorensend54239a2014-05-31 18:05:08 +02006172 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05006173
6174 if (!pbuf)
6175 return H2C_PARAMETERS_ERROR;
6176
6177 setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
6178
Jes Sorensen1feec0d2014-05-21 09:38:35 +02006179 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);
Larry Finger5e93f352014-03-28 21:37:38 -05006184
Jes Sorensend54239a2014-05-31 18:05:08 +02006185 return H2C_SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -05006186}
6187
Jes Sorensen1ec89112014-05-16 10:04:28 +02006188int led_blink_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05006189{
6190 struct LedBlink_param *ledBlink_param;
6191
6192 if (!pbuf)
6193 return H2C_PARAMETERS_ERROR;
6194
6195 ledBlink_param = (struct LedBlink_param *)pbuf;
6196
Jes Sorensend54239a2014-05-31 18:05:08 +02006197 return H2C_SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -05006198}
6199
Jes Sorensen1ec89112014-05-16 10:04:28 +02006200int set_csa_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05006201{
Jes Sorensend54239a2014-05-31 18:05:08 +02006202 return H2C_REJECTED;
Larry Finger5e93f352014-03-28 21:37:38 -05006203}
6204
6205/* TDLS_WRCR : write RCR DATA BIT */
6206/* TDLS_SD_PTI : issue peer traffic indication */
Jes Sorensen1feec0d2014-05-21 09:38:35 +02006207/* 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 */
Larry Finger5e93f352014-03-28 21:37:38 -05006212/* TDLS_OFF_CH : first time set channel to off channel */
Jes Sorensen1feec0d2014-05-21 09:38:35 +02006213/* TDLS_BASE_CH : go back tp the channel linked with AP when set
6214 base channel as target channel */
Larry Finger5e93f352014-03-28 21:37:38 -05006215/* 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 */
Jes Sorensen1ec89112014-05-16 10:04:28 +02006221int tdls_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05006222{
6223 return H2C_REJECTED;
6224}