Commit | Line | Data |
---|---|---|
5e93f352 LF |
1 | /****************************************************************************** |
2 | * | |
3 | * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
12 | * more details. | |
13 | * | |
14 | ******************************************************************************/ | |
15 | #define _RTW_CMD_C_ | |
16 | ||
17 | #include <osdep_service.h> | |
18 | #include <drv_types.h> | |
19 | #include <recv_osdep.h> | |
5e93f352 | 20 | #include <mlme_osdep.h> |
88cdc943 | 21 | #include <rtl8723a_cmd.h> |
96808173 | 22 | #include <rtw_sreset.h> |
5e93f352 | 23 | |
5e93f352 LF |
24 | static struct cmd_hdl wlancmds[] = { |
25 | GEN_DRV_CMD_HANDLER(0, NULL) /*0*/ | |
26 | GEN_DRV_CMD_HANDLER(0, NULL) | |
27 | GEN_DRV_CMD_HANDLER(0, NULL) | |
28 | GEN_DRV_CMD_HANDLER(0, NULL) | |
29 | GEN_DRV_CMD_HANDLER(0, NULL) | |
30 | GEN_DRV_CMD_HANDLER(0, NULL) | |
31 | GEN_MLME_EXT_HANDLER(0, NULL) | |
32 | GEN_MLME_EXT_HANDLER(0, NULL) | |
33 | GEN_MLME_EXT_HANDLER(0, NULL) | |
34 | GEN_MLME_EXT_HANDLER(0, NULL) | |
35 | GEN_MLME_EXT_HANDLER(0, NULL) /*10*/ | |
36 | GEN_MLME_EXT_HANDLER(0, NULL) | |
37 | GEN_MLME_EXT_HANDLER(0, NULL) | |
38 | GEN_MLME_EXT_HANDLER(0, NULL) | |
ed09b447 | 39 | GEN_MLME_EXT_HANDLER(sizeof(struct wlan_bssid_ex), join_cmd_hdl23a) /*14*/ |
40 | GEN_MLME_EXT_HANDLER(sizeof(struct disconnect_parm), disconnect_hdl23a) | |
41 | GEN_MLME_EXT_HANDLER(sizeof(struct wlan_bssid_ex), createbss_hdl23a) | |
42 | GEN_MLME_EXT_HANDLER(sizeof(struct setopmode_parm), setopmode_hdl23a) | |
43 | GEN_MLME_EXT_HANDLER(sizeof(struct sitesurvey_parm), sitesurvey_cmd_hdl23a) /*18*/ | |
44 | GEN_MLME_EXT_HANDLER(sizeof(struct setauth_parm), setauth_hdl23a) | |
45 | GEN_MLME_EXT_HANDLER(sizeof(struct setkey_parm), setkey_hdl23a) /*20*/ | |
46 | GEN_MLME_EXT_HANDLER(sizeof(struct set_stakey_parm), set_stakey_hdl23a) | |
47 | GEN_MLME_EXT_HANDLER(sizeof(struct set_assocsta_parm), NULL) | |
48 | GEN_MLME_EXT_HANDLER(sizeof(struct del_assocsta_parm), NULL) | |
49 | GEN_MLME_EXT_HANDLER(sizeof(struct setstapwrstate_parm), NULL) | |
50 | GEN_MLME_EXT_HANDLER(sizeof(struct setbasicrate_parm), NULL) | |
51 | GEN_MLME_EXT_HANDLER(sizeof(struct getbasicrate_parm), NULL) | |
52 | GEN_MLME_EXT_HANDLER(sizeof(struct setdatarate_parm), NULL) | |
53 | GEN_MLME_EXT_HANDLER(sizeof(struct getdatarate_parm), NULL) | |
54 | GEN_MLME_EXT_HANDLER(sizeof(struct setphyinfo_parm), NULL) | |
55 | GEN_MLME_EXT_HANDLER(sizeof(struct getphyinfo_parm), NULL) /*30*/ | |
56 | GEN_MLME_EXT_HANDLER(sizeof(struct setphy_parm), NULL) | |
57 | GEN_MLME_EXT_HANDLER(sizeof(struct getphy_parm), NULL) | |
5e93f352 LF |
58 | GEN_MLME_EXT_HANDLER(0, NULL) |
59 | GEN_MLME_EXT_HANDLER(0, NULL) | |
60 | GEN_MLME_EXT_HANDLER(0, NULL) | |
61 | GEN_MLME_EXT_HANDLER(0, NULL) | |
62 | GEN_MLME_EXT_HANDLER(0, NULL) | |
63 | GEN_MLME_EXT_HANDLER(0, NULL) | |
64 | GEN_MLME_EXT_HANDLER(0, NULL) | |
65 | GEN_MLME_EXT_HANDLER(0, NULL) /*40*/ | |
66 | GEN_MLME_EXT_HANDLER(0, NULL) | |
67 | GEN_MLME_EXT_HANDLER(0, NULL) | |
68 | GEN_MLME_EXT_HANDLER(0, NULL) | |
69 | GEN_MLME_EXT_HANDLER(0, NULL) | |
70 | GEN_MLME_EXT_HANDLER(sizeof(struct addBaReq_parm), add_ba_hdl23a) | |
71 | GEN_MLME_EXT_HANDLER(sizeof(struct set_ch_parm), set_ch_hdl23a) /* 46 */ | |
72 | GEN_MLME_EXT_HANDLER(0, NULL) | |
73 | GEN_MLME_EXT_HANDLER(0, NULL) | |
74 | GEN_MLME_EXT_HANDLER(0, NULL) | |
75 | GEN_MLME_EXT_HANDLER(0, NULL) /*50*/ | |
76 | GEN_MLME_EXT_HANDLER(0, NULL) | |
77 | GEN_MLME_EXT_HANDLER(0, NULL) | |
78 | GEN_MLME_EXT_HANDLER(0, NULL) | |
79 | GEN_MLME_EXT_HANDLER(0, NULL) | |
80 | GEN_MLME_EXT_HANDLER(sizeof(struct Tx_Beacon_param), tx_beacon_hdl23a) /*55*/ | |
81 | ||
82 | GEN_MLME_EXT_HANDLER(0, mlme_evt_hdl23a) /*56*/ | |
83 | GEN_MLME_EXT_HANDLER(0, rtw_drvextra_cmd_hdl23a) /*57*/ | |
84 | ||
85 | GEN_MLME_EXT_HANDLER(0, h2c_msg_hdl23a) /*58*/ | |
86 | GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelPlan_param), set_chplan_hdl23a) /*59*/ | |
87 | GEN_MLME_EXT_HANDLER(sizeof(struct LedBlink_param), led_blink_hdl23a) /*60*/ | |
88 | ||
89 | GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelSwitch_param), set_csa_hdl23a) /*61*/ | |
90 | GEN_MLME_EXT_HANDLER(sizeof(struct TDLSoption_param), tdls_hdl23a) /*62*/ | |
91 | }; | |
92 | ||
93 | struct _cmd_callback rtw_cmd_callback[] = { | |
94 | {GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/ | |
95 | {GEN_CMD_CODE(_Write_MACREG), NULL}, | |
96 | {GEN_CMD_CODE(_Read_BBREG), &rtw_getbbrfreg_cmdrsp_callback23a}, | |
97 | {GEN_CMD_CODE(_Write_BBREG), NULL}, | |
98 | {GEN_CMD_CODE(_Read_RFREG), &rtw_getbbrfreg_cmdrsp_callback23a}, | |
99 | {GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/ | |
100 | {GEN_CMD_CODE(_Read_EEPROM), NULL}, | |
101 | {GEN_CMD_CODE(_Write_EEPROM), NULL}, | |
102 | {GEN_CMD_CODE(_Read_EFUSE), NULL}, | |
103 | {GEN_CMD_CODE(_Write_EFUSE), NULL}, | |
104 | ||
105 | {GEN_CMD_CODE(_Read_CAM), NULL}, /*10*/ | |
106 | {GEN_CMD_CODE(_Write_CAM), NULL}, | |
107 | {GEN_CMD_CODE(_setBCNITV), NULL}, | |
108 | {GEN_CMD_CODE(_setMBIDCFG), NULL}, | |
109 | {GEN_CMD_CODE(_JoinBss), &rtw_joinbss_cmd23a_callback}, /*14*/ | |
110 | {GEN_CMD_CODE(_DisConnect), &rtw_disassoc_cmd23a_callback}, /*15*/ | |
111 | {GEN_CMD_CODE(_CreateBss), &rtw_createbss_cmd23a_callback}, | |
112 | {GEN_CMD_CODE(_SetOpMode), NULL}, | |
113 | {GEN_CMD_CODE(_SiteSurvey), &rtw_survey_cmd_callback23a}, /*18*/ | |
114 | {GEN_CMD_CODE(_SetAuth), NULL}, | |
115 | ||
116 | {GEN_CMD_CODE(_SetKey), NULL}, /*20*/ | |
117 | {GEN_CMD_CODE(_SetStaKey), &rtw_setstaKey_cmdrsp_callback23a}, | |
118 | {GEN_CMD_CODE(_SetAssocSta), &rtw_setassocsta_cmdrsp_callback23a}, | |
119 | {GEN_CMD_CODE(_DelAssocSta), NULL}, | |
120 | {GEN_CMD_CODE(_SetStaPwrState), NULL}, | |
121 | {GEN_CMD_CODE(_SetBasicRate), NULL}, /*25*/ | |
122 | {GEN_CMD_CODE(_GetBasicRate), NULL}, | |
123 | {GEN_CMD_CODE(_SetDataRate), NULL}, | |
124 | {GEN_CMD_CODE(_GetDataRate), NULL}, | |
125 | {GEN_CMD_CODE(_SetPhyInfo), NULL}, | |
126 | ||
127 | {GEN_CMD_CODE(_GetPhyInfo), NULL}, /*30*/ | |
128 | {GEN_CMD_CODE(_SetPhy), NULL}, | |
129 | {GEN_CMD_CODE(_GetPhy), NULL}, | |
130 | {GEN_CMD_CODE(_readRssi), NULL}, | |
131 | {GEN_CMD_CODE(_readGain), NULL}, | |
132 | {GEN_CMD_CODE(_SetAtim), NULL}, /*35*/ | |
133 | {GEN_CMD_CODE(_SetPwrMode), NULL}, | |
134 | {GEN_CMD_CODE(_JoinbssRpt), NULL}, | |
135 | {GEN_CMD_CODE(_SetRaTable), NULL}, | |
136 | {GEN_CMD_CODE(_GetRaTable), NULL}, | |
137 | ||
138 | {GEN_CMD_CODE(_GetCCXReport), NULL}, /*40*/ | |
139 | {GEN_CMD_CODE(_GetDTMReport), NULL}, | |
140 | {GEN_CMD_CODE(_GetTXRateStatistics), NULL}, | |
141 | {GEN_CMD_CODE(_SetUsbSuspend), NULL}, | |
142 | {GEN_CMD_CODE(_SetH2cLbk), NULL}, | |
143 | {GEN_CMD_CODE(_AddBAReq), NULL}, /*45*/ | |
144 | {GEN_CMD_CODE(_SetChannel), NULL}, /*46*/ | |
145 | {GEN_CMD_CODE(_SetTxPower), NULL}, | |
146 | {GEN_CMD_CODE(_SwitchAntenna), NULL}, | |
147 | {GEN_CMD_CODE(_SetCrystalCap), NULL}, | |
148 | {GEN_CMD_CODE(_SetSingleCarrierTx), NULL}, /*50*/ | |
149 | ||
150 | {GEN_CMD_CODE(_SetSingleToneTx), NULL}, /*51*/ | |
151 | {GEN_CMD_CODE(_SetCarrierSuppressionTx), NULL}, | |
152 | {GEN_CMD_CODE(_SetContinuousTx), NULL}, | |
153 | {GEN_CMD_CODE(_SwitchBandwidth), NULL}, /*54*/ | |
154 | {GEN_CMD_CODE(_TX_Beacon), NULL},/*55*/ | |
155 | ||
156 | {GEN_CMD_CODE(_Set_MLME_EVT), NULL},/*56*/ | |
157 | {GEN_CMD_CODE(_Set_Drv_Extra), NULL},/*57*/ | |
158 | {GEN_CMD_CODE(_Set_H2C_MSG), NULL},/*58*/ | |
159 | {GEN_CMD_CODE(_SetChannelPlan), NULL},/*59*/ | |
160 | {GEN_CMD_CODE(_LedBlink), NULL},/*60*/ | |
161 | ||
162 | {GEN_CMD_CODE(_SetChannelSwitch), NULL},/*61*/ | |
163 | {GEN_CMD_CODE(_TDLS), NULL},/*62*/ | |
164 | }; | |
165 | ||
166 | /* | |
167 | Caller and the rtw_cmd_thread23a can protect cmd_q by spin_lock. | |
168 | No irqsave is necessary. | |
169 | */ | |
170 | ||
171 | int rtw_init_cmd_priv23a(struct cmd_priv *pcmdpriv) | |
172 | { | |
173 | int res = _SUCCESS; | |
174 | ||
5e93f352 LF |
175 | pcmdpriv->cmd_issued_cnt = 0; |
176 | pcmdpriv->cmd_done_cnt = 0; | |
177 | pcmdpriv->rsp_cnt = 0; | |
178 | ||
8df06a3b | 179 | pcmdpriv->wq = alloc_workqueue("rtl8723au_cmd", 0, 1); |
d97e2d2b JS |
180 | if (!pcmdpriv->wq) |
181 | res = _FAIL; | |
182 | ||
5e93f352 LF |
183 | return res; |
184 | } | |
185 | ||
186 | /* forward definition */ | |
187 | ||
980cf72a | 188 | static void rtw_irq_work(struct work_struct *work); |
5e93f352 | 189 | |
ab033fdb JS |
190 | u32 rtw_init_evt_priv23a(struct evt_priv *pevtpriv) |
191 | { | |
980cf72a JS |
192 | pevtpriv->wq = alloc_workqueue("rtl8723au_evt", 0, 1); |
193 | ||
194 | INIT_WORK(&pevtpriv->irq_wk, rtw_irq_work); | |
5e93f352 | 195 | |
ab033fdb | 196 | return _SUCCESS; |
5e93f352 LF |
197 | } |
198 | ||
199 | void rtw_free_evt_priv23a(struct evt_priv *pevtpriv) | |
200 | { | |
980cf72a | 201 | cancel_work_sync(&pevtpriv->irq_wk); |
5e93f352 LF |
202 | } |
203 | ||
5e93f352 LF |
204 | static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) |
205 | { | |
5e93f352 LF |
206 | /* set to true to allow enqueuing cmd when hw_init_completed is false */ |
207 | u8 bAllow = false; | |
208 | ||
5e93f352 LF |
209 | if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan)) |
210 | bAllow = true; | |
211 | ||
d97e2d2b | 212 | if (pcmdpriv->padapter->hw_init_completed == false && bAllow == false) |
5e93f352 LF |
213 | return _FAIL; |
214 | return _SUCCESS; | |
215 | } | |
216 | ||
d97e2d2b JS |
217 | static void rtw_cmd_work(struct work_struct *work); |
218 | ||
219 | int rtw_enqueue_cmd23a(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) | |
5e93f352 LF |
220 | { |
221 | int res = _FAIL; | |
5e93f352 LF |
222 | |
223 | if (!cmd_obj) | |
224 | goto exit; | |
225 | ||
d97e2d2b | 226 | cmd_obj->padapter = pcmdpriv->padapter; |
5e93f352 LF |
227 | |
228 | res = rtw_cmd_filter(pcmdpriv, cmd_obj); | |
229 | if (res == _FAIL) { | |
230 | rtw_free_cmd_obj23a(cmd_obj); | |
231 | goto exit; | |
232 | } | |
233 | ||
d97e2d2b | 234 | INIT_WORK(&cmd_obj->work, rtw_cmd_work); |
5e93f352 | 235 | |
d97e2d2b | 236 | res = queue_work(pcmdpriv->wq, &cmd_obj->work); |
5e93f352 | 237 | |
d97e2d2b | 238 | if (!res) { |
0d07fc1b AS |
239 | netdev_err(pcmdpriv->padapter->pnetdev, |
240 | "%s: Call to queue_work() failed\n", __func__); | |
d97e2d2b JS |
241 | res = _FAIL; |
242 | } else | |
243 | res = _SUCCESS; | |
5e93f352 | 244 | exit: |
5e93f352 | 245 | |
d97e2d2b | 246 | return res; |
5e93f352 LF |
247 | } |
248 | ||
5e93f352 LF |
249 | void rtw_free_cmd_obj23a(struct cmd_obj *pcmd) |
250 | { | |
251 | ||
252 | if (pcmd->cmdcode != _JoinBss_CMD_ && | |
253 | pcmd->cmdcode != _CreateBss_CMD_) { | |
254 | /* free parmbuf in cmd_obj */ | |
255 | kfree(pcmd->parmbuf); | |
256 | } | |
257 | ||
258 | if (pcmd->rsp) { | |
259 | if (pcmd->rspsz != 0) { | |
260 | /* free rsp in cmd_obj */ | |
261 | kfree(pcmd->rsp); | |
262 | } | |
263 | } | |
264 | ||
265 | kfree(pcmd); | |
266 | } | |
267 | ||
d97e2d2b | 268 | static void rtw_cmd_work(struct work_struct *work) |
5e93f352 | 269 | { |
1ec8911b | 270 | int (*cmd_hdl)(struct rtw_adapter *padapter, const u8 *pbuf); |
5e93f352 | 271 | void (*pcmd_callback)(struct rtw_adapter *dev, struct cmd_obj *pcmd); |
d97e2d2b JS |
272 | struct cmd_priv *pcmdpriv; |
273 | struct cmd_obj *pcmd = container_of(work, struct cmd_obj, work); | |
5e93f352 | 274 | |
d97e2d2b | 275 | pcmdpriv = &pcmd->padapter->cmdpriv; |
5e93f352 | 276 | |
d97e2d2b JS |
277 | if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) { |
278 | pcmd->res = H2C_DROPPED; | |
279 | goto post_process; | |
280 | } | |
5e93f352 | 281 | |
d97e2d2b | 282 | pcmdpriv->cmd_issued_cnt++; |
5e93f352 | 283 | |
d97e2d2b | 284 | pcmd->cmdsz = ALIGN(pcmd->cmdsz, 4); |
5e93f352 | 285 | |
d97e2d2b JS |
286 | if (pcmd->cmdcode < (sizeof(wlancmds)/sizeof(struct cmd_hdl))) { |
287 | cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns; | |
5e93f352 | 288 | |
d97e2d2b | 289 | if (cmd_hdl) |
c347dc62 | 290 | pcmd->res = cmd_hdl(pcmd->padapter, pcmd->parmbuf); |
d97e2d2b JS |
291 | else |
292 | pcmd->res = H2C_DROPPED; | |
293 | } else | |
294 | pcmd->res = H2C_PARAMETERS_ERROR; | |
5e93f352 LF |
295 | |
296 | post_process: | |
d97e2d2b | 297 | /* call callback function for post-processed */ |
993c0a0e | 298 | if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) { |
d97e2d2b JS |
299 | pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback; |
300 | if (!pcmd_callback) { | |
301 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, | |
90403aa1 JP |
302 | "mlme_cmd_hdl(): pcmd_callback = 0x%p, cmdcode = 0x%x\n", |
303 | pcmd_callback, pcmd->cmdcode); | |
5e93f352 | 304 | rtw_free_cmd_obj23a(pcmd); |
d97e2d2b | 305 | } else { |
808bcb4e | 306 | /* need consider that free cmd_obj in |
d97e2d2b JS |
307 | rtw_cmd_callback */ |
308 | pcmd_callback(pcmd->padapter, pcmd); | |
5e93f352 | 309 | } |
d97e2d2b JS |
310 | } else { |
311 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
90403aa1 JP |
312 | "%s: cmdcode = 0x%x callback not defined!\n", |
313 | __func__, pcmd->cmdcode); | |
5e93f352 | 314 | rtw_free_cmd_obj23a(pcmd); |
d97e2d2b | 315 | } |
5e93f352 LF |
316 | } |
317 | ||
d97e2d2b | 318 | |
1ec8911b JS |
319 | int rtw_sitesurvey_cmd23a(struct rtw_adapter *padapter, |
320 | struct cfg80211_ssid *ssid, int ssid_num, | |
321 | struct rtw_ieee80211_channel *ch, int ch_num) | |
5e93f352 | 322 | { |
1ec8911b | 323 | int res = _FAIL; |
5e93f352 LF |
324 | struct cmd_obj *ph2c; |
325 | struct sitesurvey_parm *psurveyPara; | |
326 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
327 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
328 | ||
f2f97035 | 329 | if (check_fwstate(pmlmepriv, _FW_LINKED)) |
5e93f352 LF |
330 | rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_SCAN, 1); |
331 | ||
5e93f352 LF |
332 | ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); |
333 | if (!ph2c) | |
334 | return _FAIL; | |
335 | ||
336 | psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC); | |
337 | if (!psurveyPara) { | |
338 | kfree(ph2c); | |
339 | return _FAIL; | |
340 | } | |
341 | ||
528e5c1d | 342 | rtw_free_network_queue23a(padapter); |
5e93f352 LF |
343 | |
344 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, | |
90403aa1 | 345 | "%s: flush network queue\n", __func__); |
5e93f352 LF |
346 | |
347 | init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, | |
348 | GEN_CMD_CODE(_SiteSurvey)); | |
349 | ||
350 | /* psurveyPara->bsslimit = 48; */ | |
351 | psurveyPara->scan_mode = pmlmepriv->scan_mode; | |
352 | ||
353 | /* prepare ssid list */ | |
354 | if (ssid) { | |
355 | int i; | |
fbc6d797 | 356 | |
5e93f352 LF |
357 | for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) { |
358 | if (ssid[i].ssid_len) { | |
359 | memcpy(&psurveyPara->ssid[i], &ssid[i], | |
360 | sizeof(struct cfg80211_ssid)); | |
361 | psurveyPara->ssid_num++; | |
5e93f352 LF |
362 | } |
363 | } | |
364 | } | |
365 | ||
366 | /* prepare channel list */ | |
367 | if (ch) { | |
368 | int i; | |
fbc6d797 | 369 | |
5e93f352 LF |
370 | for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) { |
371 | if (ch[i].hw_value && | |
372 | !(ch[i].flags & IEEE80211_CHAN_DISABLED)) { | |
373 | memcpy(&psurveyPara->ch[i], &ch[i], | |
374 | sizeof(struct rtw_ieee80211_channel)); | |
375 | psurveyPara->ch_num++; | |
5e93f352 LF |
376 | } |
377 | } | |
378 | } | |
379 | ||
380 | set_fwstate(pmlmepriv, _FW_UNDER_SURVEY); | |
381 | ||
382 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); | |
383 | ||
384 | if (res == _SUCCESS) { | |
385 | mod_timer(&pmlmepriv->scan_to_timer, jiffies + | |
386 | msecs_to_jiffies(SCANNING_TIMEOUT)); | |
387 | ||
5e93f352 LF |
388 | pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */ |
389 | } else | |
390 | _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); | |
391 | ||
392 | return res; | |
393 | } | |
394 | ||
395 | void rtw_getbbrfreg_cmdrsp_callback23a(struct rtw_adapter *padapter, | |
396 | struct cmd_obj *pcmd) | |
397 | { | |
398 | kfree(pcmd->parmbuf); | |
399 | kfree(pcmd); | |
400 | } | |
401 | ||
1ec8911b | 402 | int rtw_createbss_cmd23a(struct rtw_adapter *padapter) |
5e93f352 LF |
403 | { |
404 | struct cmd_obj *pcmd; | |
405 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
406 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
407 | struct wlan_bssid_ex *pdev_network; | |
408 | u8 res = _SUCCESS; | |
409 | ||
410 | pdev_network = &padapter->registrypriv.dev_network; | |
411 | ||
5e93f352 LF |
412 | if (pmlmepriv->assoc_ssid.ssid_len == 0) { |
413 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, | |
90403aa1 JP |
414 | "createbss for Any SSid:%s\n", |
415 | pmlmepriv->assoc_ssid.ssid); | |
5e93f352 LF |
416 | } else { |
417 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, | |
90403aa1 JP |
418 | "createbss for SSid:%s\n", |
419 | pmlmepriv->assoc_ssid.ssid); | |
5e93f352 LF |
420 | } |
421 | ||
422 | pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); | |
423 | if (!pcmd) { | |
424 | res = _FAIL; | |
425 | goto exit; | |
426 | } | |
427 | ||
5e93f352 LF |
428 | pcmd->cmdcode = _CreateBss_CMD_; |
429 | pcmd->parmbuf = (unsigned char *)pdev_network; | |
aab26454 | 430 | pcmd->cmdsz = get_wlan_bssid_ex_sz(pdev_network); |
5e93f352 LF |
431 | pcmd->rsp = NULL; |
432 | pcmd->rspsz = 0; | |
433 | ||
434 | pdev_network->Length = pcmd->cmdsz; | |
435 | ||
436 | res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); | |
437 | ||
438 | exit: | |
439 | ||
440 | return res; | |
441 | } | |
442 | ||
1ec8911b JS |
443 | int rtw_joinbss_cmd23a(struct rtw_adapter *padapter, |
444 | struct wlan_network *pnetwork) | |
5e93f352 | 445 | { |
1ec8911b | 446 | int res = _SUCCESS; |
5e93f352 LF |
447 | struct wlan_bssid_ex *psecnetwork; |
448 | struct cmd_obj *pcmd; | |
449 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
450 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
5e93f352 LF |
451 | struct security_priv *psecuritypriv = &padapter->securitypriv; |
452 | struct registry_priv *pregistrypriv = &padapter->registrypriv; | |
453 | struct ht_priv *phtpriv = &pmlmepriv->htpriv; | |
efc7144f | 454 | enum nl80211_iftype ifmode; |
5e93f352 LF |
455 | struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; |
456 | struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; | |
457 | ||
efc7144f | 458 | ifmode = pnetwork->network.ifmode; |
5e93f352 | 459 | |
5e93f352 LF |
460 | if (pmlmepriv->assoc_ssid.ssid_len == 0) { |
461 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, | |
90403aa1 | 462 | "+Join cmd: Any SSid\n"); |
5e93f352 LF |
463 | } else { |
464 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, | |
90403aa1 JP |
465 | "+Join cmd: SSid =[%s]\n", |
466 | pmlmepriv->assoc_ssid.ssid); | |
5e93f352 LF |
467 | } |
468 | ||
469 | pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); | |
470 | if (!pcmd) { | |
471 | res = _FAIL; | |
472 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
90403aa1 | 473 | "rtw_joinbss_cmd23a: memory allocate for cmd_obj fail!!!\n"); |
5e93f352 LF |
474 | goto exit; |
475 | } | |
5e93f352 LF |
476 | |
477 | /* for hidden ap to set fw_state here */ | |
478 | if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE)) { | |
efc7144f JS |
479 | switch (ifmode) { |
480 | case NL80211_IFTYPE_ADHOC: | |
5e93f352 LF |
481 | set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); |
482 | break; | |
efc7144f JS |
483 | case NL80211_IFTYPE_P2P_CLIENT: |
484 | case NL80211_IFTYPE_STATION: | |
5e93f352 LF |
485 | set_fwstate(pmlmepriv, WIFI_STATION_STATE); |
486 | break; | |
efc7144f | 487 | default: |
5e93f352 LF |
488 | break; |
489 | } | |
490 | } | |
491 | ||
ea4190b1 | 492 | psecnetwork = &psecuritypriv->sec_bss; |
5e93f352 | 493 | if (!psecnetwork) { |
352f145d | 494 | kfree(pcmd); |
5e93f352 LF |
495 | res = _FAIL; |
496 | ||
497 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
90403aa1 | 498 | "rtw_joinbss_cmd23a :psecnetwork == NULL!!!\n"); |
5e93f352 LF |
499 | |
500 | goto exit; | |
501 | } | |
502 | ||
ea4190b1 | 503 | memset(psecnetwork, 0, sizeof(struct wlan_bssid_ex)); |
5e93f352 LF |
504 | |
505 | memcpy(psecnetwork, &pnetwork->network, | |
506 | get_wlan_bssid_ex_sz(&pnetwork->network)); | |
507 | ||
5e93f352 LF |
508 | psecnetwork->IELength = 0; |
509 | /* Added by Albert 2009/02/18 */ | |
510 | /* If the the driver wants to use the bssid to create the | |
511 | * connection. If not, we have to copy the connecting AP's | |
512 | * MAC address to it so that the driver just has the bssid | |
513 | * information for PMKIDList searching. */ | |
514 | ||
515 | if (pmlmepriv->assoc_by_bssid == false) | |
516 | ether_addr_copy(&pmlmepriv->assoc_bssid[0], | |
517 | &pnetwork->network.MacAddress[0]); | |
518 | ||
519 | psecnetwork->IELength = | |
520 | rtw_restruct_sec_ie23a(padapter, &pnetwork->network.IEs[0], | |
521 | &psecnetwork->IEs[0], | |
522 | pnetwork->network.IELength); | |
523 | ||
bd8ad4a5 | 524 | pmlmepriv->qos_option = 0; |
5e93f352 LF |
525 | |
526 | if (pregistrypriv->wmm_enable) { | |
527 | u32 tmp_len; | |
528 | ||
529 | tmp_len = rtw_restruct_wmm_ie23a(padapter, | |
530 | &pnetwork->network.IEs[0], | |
531 | &psecnetwork->IEs[0], | |
532 | pnetwork->network.IELength, | |
533 | psecnetwork->IELength); | |
534 | ||
535 | if (psecnetwork->IELength != tmp_len) { | |
536 | psecnetwork->IELength = tmp_len; | |
537 | /* There is WMM IE in this corresp. beacon */ | |
bd8ad4a5 | 538 | pmlmepriv->qos_option = 1; |
5e93f352 LF |
539 | } else { |
540 | /* There is no WMM IE in this corresp. beacon */ | |
bd8ad4a5 | 541 | pmlmepriv->qos_option = 0; |
5e93f352 LF |
542 | } |
543 | } | |
544 | ||
545 | phtpriv->ht_option = false; | |
546 | if (pregistrypriv->ht_enable) { | |
9e3d6df2 | 547 | u32 algo = padapter->securitypriv.dot11PrivacyAlgrthm; |
5e93f352 LF |
548 | /* Added by Albert 2010/06/23 */ |
549 | /* For the WEP mode, we will use the bg mode to do | |
550 | the connection to avoid some IOT issue. */ | |
551 | /* Especially for Realtek 8192u SoftAP. */ | |
9e3d6df2 JS |
552 | if (algo != WLAN_CIPHER_SUITE_WEP40 && |
553 | algo != WLAN_CIPHER_SUITE_WEP104 && | |
554 | algo != WLAN_CIPHER_SUITE_TKIP) { | |
5e93f352 LF |
555 | /* rtw_restructure_ht_ie23a */ |
556 | rtw_restructure_ht_ie23a(padapter, | |
557 | &pnetwork->network.IEs[0], | |
558 | &psecnetwork->IEs[0], | |
559 | pnetwork->network.IELength, | |
560 | &psecnetwork->IELength); | |
561 | } | |
562 | } | |
563 | ||
564 | pmlmeinfo->assoc_AP_vendor = | |
565 | check_assoc_AP23a(pnetwork->network.IEs, | |
566 | pnetwork->network.IELength); | |
567 | ||
568 | if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA) | |
569 | padapter->pwrctrlpriv.smart_ps = 0; | |
570 | else | |
571 | padapter->pwrctrlpriv.smart_ps = | |
572 | padapter->registrypriv.smart_ps; | |
573 | ||
574 | DBG_8723A("%s: smart_ps =%d\n", __func__, | |
575 | padapter->pwrctrlpriv.smart_ps); | |
576 | ||
577 | /* get cmdsz before endian conversion */ | |
578 | pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork); | |
579 | ||
5e93f352 LF |
580 | pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */ |
581 | pcmd->parmbuf = (unsigned char *)psecnetwork; | |
582 | pcmd->rsp = NULL; | |
583 | pcmd->rspsz = 0; | |
584 | ||
585 | res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); | |
586 | exit: | |
587 | ||
588 | return res; | |
589 | } | |
590 | ||
a58af1e1 | 591 | int rtw_disassoc_cmd23a(struct rtw_adapter *padapter, u32 deauth_timeout_ms, |
1ec8911b | 592 | bool enqueue) |
5e93f352 LF |
593 | { |
594 | struct cmd_obj *cmdobj = NULL; | |
595 | struct disconnect_parm *param = NULL; | |
596 | struct cmd_priv *cmdpriv = &padapter->cmdpriv; | |
1ec8911b | 597 | int res = _SUCCESS; |
5e93f352 LF |
598 | |
599 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, | |
90403aa1 | 600 | "+rtw_disassoc_cmd23a\n"); |
5e93f352 LF |
601 | |
602 | /* prepare cmd parameter */ | |
603 | param = kzalloc(sizeof(*param), GFP_ATOMIC); | |
604 | if (param == NULL) { | |
605 | res = _FAIL; | |
606 | goto exit; | |
607 | } | |
608 | param->deauth_timeout_ms = deauth_timeout_ms; | |
609 | ||
610 | if (enqueue) { | |
611 | /* need enqueue, prepare cmd_obj and enqueue */ | |
612 | cmdobj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); | |
613 | if (!cmdobj) { | |
614 | res = _FAIL; | |
615 | kfree(param); | |
616 | goto exit; | |
617 | } | |
618 | init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_); | |
619 | res = rtw_enqueue_cmd23a(cmdpriv, cmdobj); | |
620 | } else { | |
621 | /* no need to enqueue, do the cmd hdl directly and | |
622 | free cmd parameter */ | |
c12e8dba | 623 | if (disconnect_hdl23a(padapter, (u8 *)param) != H2C_SUCCESS) |
5e93f352 LF |
624 | res = _FAIL; |
625 | kfree(param); | |
626 | } | |
627 | ||
628 | exit: | |
629 | return res; | |
630 | } | |
631 | ||
1ec8911b | 632 | int rtw_setopmode_cmd23a(struct rtw_adapter *padapter, |
efc7144f | 633 | enum nl80211_iftype ifmode) |
5e93f352 LF |
634 | { |
635 | struct cmd_obj *ph2c; | |
636 | struct setopmode_parm *psetop; | |
637 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
1ec8911b | 638 | int res = _SUCCESS; |
5e93f352 LF |
639 | |
640 | ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); | |
641 | if (!ph2c) { | |
642 | res = false; | |
643 | goto exit; | |
644 | } | |
645 | psetop = kzalloc(sizeof(struct setopmode_parm), GFP_KERNEL); | |
646 | ||
647 | if (!psetop) { | |
648 | kfree(ph2c); | |
649 | res = false; | |
650 | goto exit; | |
651 | } | |
652 | ||
653 | init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_); | |
efc7144f | 654 | psetop->mode = ifmode; |
5e93f352 LF |
655 | |
656 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); | |
657 | exit: | |
658 | return res; | |
659 | } | |
660 | ||
1ec8911b | 661 | int rtw_setstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 unicast_key) |
5e93f352 LF |
662 | { |
663 | struct cmd_obj *ph2c; | |
664 | struct set_stakey_parm *psetstakey_para; | |
665 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
666 | struct set_stakey_rsp *psetstakey_rsp = NULL; | |
667 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
668 | struct security_priv *psecuritypriv = &padapter->securitypriv; | |
7e6646d5 | 669 | struct sta_info *sta = (struct sta_info *)psta; |
1ec8911b | 670 | int res = _SUCCESS; |
5e93f352 LF |
671 | |
672 | ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); | |
673 | if (!ph2c) { | |
674 | res = _FAIL; | |
675 | goto exit; | |
676 | } | |
677 | ||
678 | psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL); | |
679 | if (!psetstakey_para) { | |
680 | kfree(ph2c); | |
681 | res = _FAIL; | |
682 | goto exit; | |
683 | } | |
684 | ||
685 | psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_KERNEL); | |
686 | if (!psetstakey_rsp) { | |
687 | kfree(ph2c); | |
688 | kfree(psetstakey_para); | |
689 | res = _FAIL; | |
690 | goto exit; | |
691 | } | |
692 | ||
693 | init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); | |
694 | ph2c->rsp = (u8 *) psetstakey_rsp; | |
695 | ph2c->rspsz = sizeof(struct set_stakey_rsp); | |
696 | ||
697 | ether_addr_copy(psetstakey_para->addr, sta->hwaddr); | |
698 | ||
699 | if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { | |
700 | psetstakey_para->algorithm = | |
701 | (unsigned char)psecuritypriv->dot11PrivacyAlgrthm; | |
702 | } else { | |
703 | GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, | |
704 | false); | |
705 | } | |
706 | ||
707 | if (unicast_key == true) { | |
708 | memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16); | |
a82b4b01 | 709 | } else { |
5e93f352 | 710 | int idx = psecuritypriv->dot118021XGrpKeyid; |
fbc6d797 | 711 | |
5e93f352 LF |
712 | memcpy(&psetstakey_para->key, |
713 | &psecuritypriv->dot118021XGrpKey[idx].skey, 16); | |
a82b4b01 | 714 | } |
5e93f352 | 715 | |
808bcb4e | 716 | /* jeff: set this because at least sw key is ready */ |
9216c517 | 717 | padapter->securitypriv.busetkipkey = 1; |
5e93f352 LF |
718 | |
719 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); | |
720 | ||
721 | exit: | |
722 | ||
723 | return res; | |
724 | } | |
725 | ||
1ec8911b JS |
726 | int rtw_clearstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 entry, |
727 | u8 enqueue) | |
5e93f352 LF |
728 | { |
729 | struct cmd_obj *ph2c; | |
730 | struct set_stakey_parm *psetstakey_para; | |
731 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
732 | struct set_stakey_rsp *psetstakey_rsp = NULL; | |
733 | struct sta_info *sta = (struct sta_info *)psta; | |
1ec8911b | 734 | int res = _SUCCESS; |
5e93f352 LF |
735 | |
736 | if (!enqueue) { | |
737 | clear_cam_entry23a(padapter, entry); | |
738 | } else { | |
739 | ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); | |
740 | if (!ph2c) { | |
741 | res = _FAIL; | |
742 | goto exit; | |
743 | } | |
744 | ||
745 | psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), | |
746 | GFP_KERNEL); | |
747 | if (!psetstakey_para) { | |
748 | kfree(ph2c); | |
749 | res = _FAIL; | |
750 | goto exit; | |
751 | } | |
752 | ||
753 | psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), | |
754 | GFP_KERNEL); | |
755 | if (!psetstakey_rsp) { | |
756 | kfree(ph2c); | |
757 | kfree(psetstakey_para); | |
758 | res = _FAIL; | |
759 | goto exit; | |
760 | } | |
761 | ||
762 | init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, | |
763 | _SetStaKey_CMD_); | |
764 | ph2c->rsp = (u8 *) psetstakey_rsp; | |
765 | ph2c->rspsz = sizeof(struct set_stakey_rsp); | |
766 | ||
767 | ether_addr_copy(psetstakey_para->addr, sta->hwaddr); | |
768 | ||
9e3d6df2 | 769 | psetstakey_para->algorithm = 0; |
5e93f352 LF |
770 | |
771 | psetstakey_para->id = entry; | |
772 | ||
773 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); | |
774 | } | |
775 | exit: | |
776 | return res; | |
777 | } | |
778 | ||
a58af1e1 | 779 | int rtw_addbareq_cmd23a(struct rtw_adapter *padapter, u8 tid, u8 *addr) |
5e93f352 LF |
780 | { |
781 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
782 | struct cmd_obj *ph2c; | |
783 | struct addBaReq_parm *paddbareq_parm; | |
1ec8911b | 784 | int res = _SUCCESS; |
5e93f352 | 785 | |
d7f2c23a JS |
786 | if (tid >= MAXTID) { |
787 | res = _FAIL; | |
788 | goto exit; | |
789 | } | |
790 | ||
5e93f352 LF |
791 | ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); |
792 | if (!ph2c) { | |
793 | res = _FAIL; | |
794 | goto exit; | |
795 | } | |
796 | ||
797 | paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_ATOMIC); | |
798 | if (!paddbareq_parm) { | |
799 | kfree(ph2c); | |
800 | res = _FAIL; | |
801 | goto exit; | |
802 | } | |
803 | ||
804 | paddbareq_parm->tid = tid; | |
805 | ether_addr_copy(paddbareq_parm->addr, addr); | |
806 | ||
807 | init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, | |
808 | GEN_CMD_CODE(_AddBAReq)); | |
809 | ||
810 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); | |
811 | exit: | |
812 | return res; | |
813 | } | |
814 | ||
a58af1e1 | 815 | int rtw_dynamic_chk_wk_cmd23a(struct rtw_adapter *padapter) |
5e93f352 LF |
816 | { |
817 | struct cmd_obj *ph2c; | |
818 | struct drvextra_cmd_parm *pdrvextra_cmd_parm; | |
819 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
1ec8911b | 820 | int res = _SUCCESS; |
5e93f352 LF |
821 | |
822 | ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); | |
823 | if (!ph2c) { | |
824 | res = _FAIL; | |
825 | goto exit; | |
826 | } | |
827 | ||
828 | pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC); | |
829 | if (!pdrvextra_cmd_parm) { | |
830 | kfree(ph2c); | |
831 | res = _FAIL; | |
832 | goto exit; | |
833 | } | |
834 | ||
835 | pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID; | |
836 | pdrvextra_cmd_parm->type_size = 0; | |
837 | pdrvextra_cmd_parm->pbuf = (u8 *)padapter; | |
838 | ||
839 | init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, | |
840 | GEN_CMD_CODE(_Set_Drv_Extra)); | |
841 | ||
842 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); | |
843 | exit: | |
844 | ||
845 | return res; | |
846 | } | |
847 | ||
5e93f352 LF |
848 | static void traffic_status_watchdog(struct rtw_adapter *padapter) |
849 | { | |
850 | u8 bEnterPS; | |
851 | u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false; | |
852 | u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false; | |
853 | u8 bHigherBusyTxTraffic = false; | |
854 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
c17416ef | 855 | int BusyThreshold = 100; |
6b1b4cad SS |
856 | struct rt_link_detect *ldi = &pmlmepriv->LinkDetectInfo; |
857 | ||
5e93f352 LF |
858 | /* */ |
859 | /* Determine if our traffic is busy now */ | |
860 | /* */ | |
861 | if (check_fwstate(pmlmepriv, _FW_LINKED)) { | |
09d88791 JS |
862 | if (rtl8723a_BT_coexist(padapter)) |
863 | BusyThreshold = 50; | |
6b1b4cad | 864 | else if (ldi->bBusyTraffic) |
09d88791 | 865 | BusyThreshold = 75; |
5e93f352 LF |
866 | /* if we raise bBusyTraffic in last watchdog, using |
867 | lower threshold. */ | |
6b1b4cad SS |
868 | if (ldi->NumRxOkInPeriod > BusyThreshold || |
869 | ldi->NumTxOkInPeriod > BusyThreshold) { | |
5e93f352 LF |
870 | bBusyTraffic = true; |
871 | ||
6b1b4cad | 872 | if (ldi->NumRxOkInPeriod > ldi->NumTxOkInPeriod) |
5e93f352 LF |
873 | bRxBusyTraffic = true; |
874 | else | |
875 | bTxBusyTraffic = true; | |
876 | } | |
877 | ||
878 | /* Higher Tx/Rx data. */ | |
6b1b4cad SS |
879 | if (ldi->NumRxOkInPeriod > 4000 || |
880 | ldi->NumTxOkInPeriod > 4000) { | |
5e93f352 LF |
881 | bHigherBusyTraffic = true; |
882 | ||
6b1b4cad | 883 | if (ldi->NumRxOkInPeriod > ldi->NumTxOkInPeriod) |
5e93f352 LF |
884 | bHigherBusyRxTraffic = true; |
885 | else | |
886 | bHigherBusyTxTraffic = true; | |
887 | } | |
888 | ||
ef95e276 JS |
889 | if (!rtl8723a_BT_coexist(padapter) || |
890 | !rtl8723a_BT_using_antenna_1(padapter)) { | |
5e93f352 | 891 | /* check traffic for powersaving. */ |
6b1b4cad SS |
892 | if (((ldi->NumRxUnicastOkInPeriod + |
893 | ldi->NumTxOkInPeriod) > 8) || | |
894 | ldi->NumRxUnicastOkInPeriod > 2) | |
ef95e276 JS |
895 | bEnterPS = false; |
896 | else | |
897 | bEnterPS = true; | |
5e93f352 | 898 | |
ef95e276 JS |
899 | /* LeisurePS only work in infra mode. */ |
900 | if (bEnterPS) | |
901 | LPS_Enter23a(padapter); | |
902 | else | |
903 | LPS_Leave23a(padapter); | |
5e93f352 LF |
904 | } |
905 | } else | |
906 | LPS_Leave23a(padapter); | |
907 | ||
6b1b4cad SS |
908 | ldi->NumRxOkInPeriod = 0; |
909 | ldi->NumTxOkInPeriod = 0; | |
910 | ldi->NumRxUnicastOkInPeriod = 0; | |
911 | ldi->bBusyTraffic = bBusyTraffic; | |
912 | ldi->bTxBusyTraffic = bTxBusyTraffic; | |
913 | ldi->bRxBusyTraffic = bRxBusyTraffic; | |
914 | ldi->bHigherBusyTraffic = bHigherBusyTraffic; | |
915 | ldi->bHigherBusyRxTraffic = bHigherBusyRxTraffic; | |
916 | ldi->bHigherBusyTxTraffic = bHigherBusyTxTraffic; | |
5e93f352 LF |
917 | } |
918 | ||
c0b99bed | 919 | static void dynamic_chk_wk_hdl(struct rtw_adapter *padapter, u8 *pbuf, int sz) |
5e93f352 LF |
920 | { |
921 | struct mlme_priv *pmlmepriv; | |
922 | ||
923 | padapter = (struct rtw_adapter *)pbuf; | |
924 | pmlmepriv = &padapter->mlmepriv; | |
925 | ||
926 | #ifdef CONFIG_8723AU_AP_MODE | |
f2f97035 | 927 | if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) |
5e93f352 LF |
928 | expire_timeout_chk23a(padapter); |
929 | #endif | |
930 | ||
b7c19c27 | 931 | rtl8723a_sreset_xmit_status_check(padapter); |
5e93f352 LF |
932 | |
933 | linked_status_chk23a(padapter); | |
934 | traffic_status_watchdog(padapter); | |
935 | ||
8289d357 | 936 | rtl8723a_HalDmWatchDog(padapter); |
5e93f352 | 937 | |
5e93f352 LF |
938 | /* */ |
939 | /* BT-Coexist */ | |
940 | /* */ | |
febf3087 | 941 | rtl8723a_BT_do_coexist(padapter); |
5e93f352 LF |
942 | } |
943 | ||
c0b99bed | 944 | static void lps_ctrl_wk_hdl(struct rtw_adapter *padapter, u8 lps_ctrl_type) |
5e93f352 LF |
945 | { |
946 | struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; | |
947 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
948 | u8 mstatus; | |
949 | ||
f2f97035 JS |
950 | if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || |
951 | check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) | |
5e93f352 LF |
952 | return; |
953 | ||
f237216e | 954 | switch (lps_ctrl_type) { |
3e3f878f TR |
955 | case LPS_CTRL_SCAN: |
956 | rtl8723a_BT_wifiscan_notify(padapter, true); | |
957 | if (!rtl8723a_BT_using_antenna_1(padapter)) { | |
958 | if (check_fwstate(pmlmepriv, _FW_LINKED)) | |
959 | LPS_Leave23a(padapter); | |
5e93f352 | 960 | } |
3e3f878f TR |
961 | break; |
962 | case LPS_CTRL_JOINBSS: | |
963 | LPS_Leave23a(padapter); | |
964 | break; | |
965 | case LPS_CTRL_CONNECT: | |
966 | mstatus = 1;/* connect */ | |
967 | /* Reset LPS Setting */ | |
968 | padapter->pwrctrlpriv.LpsIdleCount = 0; | |
969 | rtl8723a_set_FwJoinBssReport_cmd(padapter, 1); | |
970 | rtl8723a_BT_mediastatus_notify(padapter, mstatus); | |
971 | break; | |
972 | case LPS_CTRL_DISCONNECT: | |
973 | mstatus = 0;/* disconnect */ | |
974 | rtl8723a_BT_mediastatus_notify(padapter, mstatus); | |
975 | if (!rtl8723a_BT_using_antenna_1(padapter)) | |
5e93f352 | 976 | LPS_Leave23a(padapter); |
3e3f878f TR |
977 | rtl8723a_set_FwJoinBssReport_cmd(padapter, 0); |
978 | break; | |
979 | case LPS_CTRL_SPECIAL_PACKET: | |
980 | pwrpriv->DelayLPSLastTimeStamp = jiffies; | |
981 | rtl8723a_BT_specialpacket_notify(padapter); | |
982 | if (!rtl8723a_BT_using_antenna_1(padapter)) | |
983 | LPS_Leave23a(padapter); | |
984 | break; | |
985 | case LPS_CTRL_LEAVE: | |
986 | rtl8723a_BT_lps_leave(padapter); | |
987 | if (!rtl8723a_BT_using_antenna_1(padapter)) | |
988 | LPS_Leave23a(padapter); | |
989 | break; | |
5e93f352 | 990 | |
3e3f878f TR |
991 | default: |
992 | break; | |
5e93f352 LF |
993 | } |
994 | } | |
995 | ||
1ec8911b JS |
996 | int rtw_lps_ctrl_wk_cmd23a(struct rtw_adapter *padapter, |
997 | u8 lps_ctrl_type, u8 enqueue) | |
5e93f352 LF |
998 | { |
999 | struct cmd_obj *ph2c; | |
1000 | struct drvextra_cmd_parm *pdrvextra_cmd_parm; | |
1001 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
1ec8911b | 1002 | int res = _SUCCESS; |
5e93f352 LF |
1003 | |
1004 | if (enqueue) { | |
1005 | ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); | |
1006 | if (!ph2c) { | |
1007 | res = _FAIL; | |
1008 | goto exit; | |
1009 | } | |
1010 | ||
1011 | pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), | |
1012 | GFP_ATOMIC); | |
1013 | if (!pdrvextra_cmd_parm) { | |
1014 | kfree(ph2c); | |
1015 | res = _FAIL; | |
1016 | goto exit; | |
1017 | } | |
1018 | ||
1019 | pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID; | |
1020 | pdrvextra_cmd_parm->type_size = lps_ctrl_type; | |
1021 | pdrvextra_cmd_parm->pbuf = NULL; | |
1022 | ||
1023 | init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, | |
1024 | GEN_CMD_CODE(_Set_Drv_Extra)); | |
1025 | ||
1026 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); | |
1027 | } else | |
1028 | lps_ctrl_wk_hdl(padapter, lps_ctrl_type); | |
1029 | exit: | |
1030 | ||
1031 | return res; | |
1032 | } | |
1033 | ||
a58af1e1 | 1034 | int rtw_ps_cmd23a(struct rtw_adapter *padapter) |
5e93f352 LF |
1035 | { |
1036 | struct cmd_obj *ppscmd; | |
1037 | struct drvextra_cmd_parm *pdrvextra_cmd_parm; | |
1038 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
1ec8911b | 1039 | int res = _SUCCESS; |
5e93f352 LF |
1040 | |
1041 | ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); | |
1042 | if (!ppscmd) { | |
1043 | res = _FAIL; | |
1044 | goto exit; | |
1045 | } | |
1046 | ||
1047 | pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), | |
1048 | GFP_ATOMIC); | |
1049 | if (!pdrvextra_cmd_parm) { | |
1050 | kfree(ppscmd); | |
1051 | res = _FAIL; | |
1052 | goto exit; | |
1053 | } | |
1054 | ||
1055 | pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID; | |
1056 | pdrvextra_cmd_parm->pbuf = NULL; | |
1057 | init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, | |
1058 | GEN_CMD_CODE(_Set_Drv_Extra)); | |
1059 | ||
1060 | res = rtw_enqueue_cmd23a(pcmdpriv, ppscmd); | |
1061 | exit: | |
1062 | ||
1063 | return res; | |
1064 | } | |
1065 | ||
1066 | #ifdef CONFIG_8723AU_AP_MODE | |
1067 | ||
1068 | static void rtw_chk_hi_queue_hdl(struct rtw_adapter *padapter) | |
1069 | { | |
1070 | int cnt = 0; | |
1071 | struct sta_info *psta_bmc; | |
1072 | struct sta_priv *pstapriv = &padapter->stapriv; | |
1073 | ||
1074 | psta_bmc = rtw_get_bcmc_stainfo23a(padapter); | |
1075 | if (!psta_bmc) | |
1076 | return; | |
1077 | ||
1078 | if (psta_bmc->sleepq_len == 0) { | |
8d3fd614 | 1079 | bool val; |
5e93f352 | 1080 | |
8d3fd614 | 1081 | val = rtl8723a_chk_hi_queue_empty(padapter); |
5e93f352 | 1082 | |
08551cbb | 1083 | while (!val) { |
5e93f352 LF |
1084 | msleep(100); |
1085 | ||
1086 | cnt++; | |
1087 | ||
af13ccf7 | 1088 | if (cnt > 10) |
5e93f352 LF |
1089 | break; |
1090 | ||
8d3fd614 | 1091 | val = rtl8723a_chk_hi_queue_empty(padapter); |
5e93f352 LF |
1092 | } |
1093 | ||
1094 | if (cnt <= 10) { | |
1095 | pstapriv->tim_bitmap &= ~BIT(0); | |
1096 | pstapriv->sta_dz_bitmap &= ~BIT(0); | |
1097 | ||
3021bc42 | 1098 | update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); |
5e93f352 LF |
1099 | } else /* re check again */ |
1100 | rtw_chk_hi_queue_cmd23a(padapter); | |
1101 | } | |
1102 | } | |
1103 | ||
a58af1e1 | 1104 | int rtw_chk_hi_queue_cmd23a(struct rtw_adapter *padapter) |
5e93f352 LF |
1105 | { |
1106 | struct cmd_obj *ph2c; | |
1107 | struct drvextra_cmd_parm *pdrvextra_cmd_parm; | |
1108 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
1ec8911b | 1109 | int res = _SUCCESS; |
5e93f352 LF |
1110 | |
1111 | ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); | |
1112 | if (!ph2c) { | |
1113 | res = _FAIL; | |
1114 | goto exit; | |
1115 | } | |
1116 | ||
1117 | pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), | |
1118 | GFP_ATOMIC); | |
1119 | if (!pdrvextra_cmd_parm) { | |
1120 | kfree(ph2c); | |
1121 | res = _FAIL; | |
1122 | goto exit; | |
1123 | } | |
1124 | ||
1125 | pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID; | |
1126 | pdrvextra_cmd_parm->type_size = 0; | |
1127 | pdrvextra_cmd_parm->pbuf = NULL; | |
1128 | ||
1129 | init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, | |
1130 | GEN_CMD_CODE(_Set_Drv_Extra)); | |
1131 | ||
1132 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); | |
1133 | exit: | |
1134 | ||
1135 | return res; | |
1136 | } | |
1137 | #endif | |
1138 | ||
1ec8911b | 1139 | int rtw_c2h_wk_cmd23a(struct rtw_adapter *padapter, u8 *c2h_evt) |
5e93f352 LF |
1140 | { |
1141 | struct cmd_obj *ph2c; | |
1142 | struct drvextra_cmd_parm *pdrvextra_cmd_parm; | |
1143 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
1ec8911b | 1144 | int res = _SUCCESS; |
5e93f352 LF |
1145 | |
1146 | ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); | |
1147 | if (!ph2c) { | |
1148 | res = _FAIL; | |
1149 | goto exit; | |
1150 | } | |
1151 | ||
1152 | pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), | |
1153 | GFP_ATOMIC); | |
1154 | if (!pdrvextra_cmd_parm) { | |
1155 | kfree(ph2c); | |
1156 | res = _FAIL; | |
1157 | goto exit; | |
1158 | } | |
1159 | ||
1160 | pdrvextra_cmd_parm->ec_id = C2H_WK_CID; | |
1161 | pdrvextra_cmd_parm->type_size = c2h_evt?16:0; | |
1162 | pdrvextra_cmd_parm->pbuf = c2h_evt; | |
1163 | ||
1164 | init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, | |
1165 | GEN_CMD_CODE(_Set_Drv_Extra)); | |
1166 | ||
1167 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); | |
1168 | ||
1169 | exit: | |
1170 | ||
1171 | return res; | |
1172 | } | |
1173 | ||
849befad | 1174 | static int c2h_evt_hdl(struct rtw_adapter *adapter, struct c2h_evt_hdr *c2h_evt) |
5e93f352 | 1175 | { |
ab281e3b | 1176 | int ret = _FAIL; |
5e93f352 LF |
1177 | u8 buf[16]; |
1178 | ||
1179 | if (!c2h_evt) { | |
1180 | /* No c2h event in cmd_obj, read c2h event before handling*/ | |
1181 | if (c2h_evt_read23a(adapter, buf) == _SUCCESS) { | |
1182 | c2h_evt = (struct c2h_evt_hdr *)buf; | |
1183 | ||
00cf86c9 | 1184 | ret = c2h_handler_8723a(adapter, c2h_evt); |
5e93f352 | 1185 | } |
849befad | 1186 | } else |
00cf86c9 | 1187 | ret = c2h_handler_8723a(adapter, c2h_evt); |
849befad | 1188 | |
5e93f352 LF |
1189 | return ret; |
1190 | } | |
1191 | ||
980cf72a | 1192 | static void rtw_irq_work(struct work_struct *work) |
5e93f352 LF |
1193 | { |
1194 | struct evt_priv *evtpriv; | |
1195 | struct rtw_adapter *adapter; | |
5e93f352 | 1196 | |
980cf72a | 1197 | evtpriv = container_of(work, struct evt_priv, irq_wk); |
5e93f352 | 1198 | adapter = container_of(evtpriv, struct rtw_adapter, evtpriv); |
5e93f352 | 1199 | |
980cf72a JS |
1200 | c2h_evt_clear23a(adapter); |
1201 | } | |
5e93f352 | 1202 | |
980cf72a JS |
1203 | void rtw_evt_work(struct work_struct *work) |
1204 | { | |
1205 | struct evt_work *ework; | |
1206 | struct rtw_adapter *adapter; | |
5e93f352 | 1207 | |
980cf72a JS |
1208 | ework = container_of(work, struct evt_work, work); |
1209 | adapter = ework->adapter; | |
5e93f352 | 1210 | |
980cf72a JS |
1211 | c2h_evt_clear23a(adapter); |
1212 | ||
1213 | if (!c2h_evt_exist(&ework->u.c2h_evt)) { | |
1214 | kfree(ework); | |
1215 | return; | |
5e93f352 LF |
1216 | } |
1217 | ||
227ca8c4 | 1218 | if (c2h_id_filter_ccx_8723a(ework->u.c2h_evt.id) == true) { |
980cf72a | 1219 | /* Handle CCX report here */ |
00cf86c9 | 1220 | c2h_handler_8723a(adapter, &ework->u.c2h_evt); |
980cf72a JS |
1221 | kfree(ework); |
1222 | } else { | |
1223 | /* | |
1224 | * Enqueue into cmd_thread for others. | |
1225 | * ework will be turned into a c2h_evt and freed once it | |
1226 | * has been consumed. | |
1227 | */ | |
1228 | rtw_c2h_wk_cmd23a(adapter, (u8 *)&ework->u.c2h_evt); | |
1229 | } | |
5e93f352 LF |
1230 | } |
1231 | ||
1ec8911b | 1232 | int rtw_drvextra_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) |
5e93f352 | 1233 | { |
0348dc74 | 1234 | const struct drvextra_cmd_parm *pdrvextra_cmd; |
5e93f352 LF |
1235 | |
1236 | if (!pbuf) | |
1237 | return H2C_PARAMETERS_ERROR; | |
1238 | ||
1239 | pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf; | |
1240 | ||
f237216e | 1241 | switch (pdrvextra_cmd->ec_id) { |
5e93f352 LF |
1242 | case DYNAMIC_CHK_WK_CID: |
1243 | dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf, | |
1244 | pdrvextra_cmd->type_size); | |
1245 | break; | |
1246 | case POWER_SAVING_CTRL_WK_CID: | |
462eb49e | 1247 | rtw_ps_processor23a(padapter); |
5e93f352 LF |
1248 | break; |
1249 | case LPS_CTRL_WK_CID: | |
1250 | lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size); | |
1251 | break; | |
5e93f352 LF |
1252 | #ifdef CONFIG_8723AU_AP_MODE |
1253 | case CHECK_HIQ_WK_CID: | |
1254 | rtw_chk_hi_queue_hdl(padapter); | |
1255 | break; | |
1256 | #endif /* CONFIG_8723AU_AP_MODE */ | |
1257 | case C2H_WK_CID: | |
1258 | c2h_evt_hdl(padapter, | |
849befad | 1259 | (struct c2h_evt_hdr *)pdrvextra_cmd->pbuf); |
5e93f352 LF |
1260 | break; |
1261 | ||
1262 | default: | |
1263 | break; | |
1264 | } | |
1265 | ||
1266 | if (pdrvextra_cmd->pbuf && (pdrvextra_cmd->type_size > 0)) { | |
1267 | kfree(pdrvextra_cmd->pbuf); | |
0348dc74 JS |
1268 | /* |
1269 | * No need to set pdrvextra_cmd->pbuf = NULL as we were | |
1270 | * operating on a copy of the original pcmd->parmbuf | |
1271 | * created in rtw_cmd_work(). | |
1272 | */ | |
5e93f352 LF |
1273 | } |
1274 | ||
1275 | return H2C_SUCCESS; | |
1276 | } | |
1277 | ||
1278 | void rtw_survey_cmd_callback23a(struct rtw_adapter *padapter, | |
1ec8911b | 1279 | struct cmd_obj *pcmd) |
5e93f352 LF |
1280 | { |
1281 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
1282 | ||
1283 | if (pcmd->res == H2C_DROPPED) { | |
1284 | /* TODO: cancel timer and do timeout handler directly... */ | |
1285 | /* need to make timeout handlerOS independent */ | |
1286 | mod_timer(&pmlmepriv->scan_to_timer, | |
1287 | jiffies + msecs_to_jiffies(1)); | |
1288 | } else if (pcmd->res != H2C_SUCCESS) { | |
1289 | mod_timer(&pmlmepriv->scan_to_timer, | |
1290 | jiffies + msecs_to_jiffies(1)); | |
1291 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
90403aa1 | 1292 | "********Error: MgntActrtw_set_802_11_bssid23a_LIST_SCAN Fail ************\n"); |
5e93f352 LF |
1293 | } |
1294 | ||
1295 | /* free cmd */ | |
1296 | rtw_free_cmd_obj23a(pcmd); | |
1297 | } | |
1298 | ||
1299 | void rtw_disassoc_cmd23a_callback(struct rtw_adapter *padapter, | |
1300 | struct cmd_obj *pcmd) | |
1301 | { | |
1302 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
1303 | ||
1304 | if (pcmd->res != H2C_SUCCESS) { | |
1305 | spin_lock_bh(&pmlmepriv->lock); | |
1306 | set_fwstate(pmlmepriv, _FW_LINKED); | |
1307 | spin_unlock_bh(&pmlmepriv->lock); | |
1308 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
90403aa1 | 1309 | "***Error: disconnect_cmd_callback Fail ***\n"); |
5e93f352 LF |
1310 | return; |
1311 | } | |
1312 | ||
1313 | /* free cmd */ | |
1314 | rtw_free_cmd_obj23a(pcmd); | |
1315 | } | |
1316 | ||
1317 | void rtw_joinbss_cmd23a_callback(struct rtw_adapter *padapter, | |
1318 | struct cmd_obj *pcmd) | |
1319 | { | |
1320 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
1321 | ||
1322 | if (pcmd->res == H2C_DROPPED) { | |
1323 | /* TODO: cancel timer and do timeout handler directly... */ | |
1324 | /* need to make timeout handlerOS independent */ | |
1325 | mod_timer(&pmlmepriv->assoc_timer, | |
1326 | jiffies + msecs_to_jiffies(1)); | |
1327 | } else if (pcmd->res != H2C_SUCCESS) { | |
1328 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
90403aa1 | 1329 | "********Error:rtw_select_and_join_from_scanned_queue Wait Sema Fail ************\n"); |
5e93f352 LF |
1330 | mod_timer(&pmlmepriv->assoc_timer, |
1331 | jiffies + msecs_to_jiffies(1)); | |
1332 | } | |
1333 | ||
1334 | rtw_free_cmd_obj23a(pcmd); | |
1335 | } | |
1336 | ||
1337 | void rtw_createbss_cmd23a_callback(struct rtw_adapter *padapter, | |
1338 | struct cmd_obj *pcmd) | |
1339 | { | |
1340 | struct sta_info *psta; | |
1341 | struct wlan_network *pwlan; | |
1342 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
1343 | struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf; | |
1344 | struct wlan_network *tgt_network = &pmlmepriv->cur_network; | |
164e265b | 1345 | struct rtw_queue *scanned_queue = &pmlmepriv->scanned_queue; |
5e93f352 LF |
1346 | |
1347 | if (pcmd->res != H2C_SUCCESS) { | |
1348 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
90403aa1 | 1349 | "********Error: rtw_createbss_cmd23a_callback Fail ************\n"); |
5e93f352 LF |
1350 | mod_timer(&pmlmepriv->assoc_timer, |
1351 | jiffies + msecs_to_jiffies(1)); | |
1352 | } | |
1353 | ||
1354 | del_timer_sync(&pmlmepriv->assoc_timer); | |
1355 | ||
5e93f352 LF |
1356 | if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { |
1357 | psta = rtw_get_stainfo23a(&padapter->stapriv, | |
1358 | pnetwork->MacAddress); | |
1359 | if (!psta) { | |
1360 | psta = rtw_alloc_stainfo23a(&padapter->stapriv, | |
6e8bc71d JS |
1361 | pnetwork->MacAddress, |
1362 | GFP_KERNEL); | |
5e93f352 LF |
1363 | if (!psta) { |
1364 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
90403aa1 | 1365 | "Can't alloc sta_info when createbss_cmd_callback\n"); |
25d5546c | 1366 | goto createbss_cmd_fail; |
5e93f352 LF |
1367 | } |
1368 | } | |
1369 | ||
5290cd68 | 1370 | spin_lock_bh(&pmlmepriv->lock); |
5e93f352 | 1371 | rtw_indicate_connect23a(padapter); |
5290cd68 | 1372 | spin_unlock_bh(&pmlmepriv->lock); |
5e93f352 | 1373 | } else { |
ec838b0b | 1374 | pwlan = rtw_alloc_network(pmlmepriv, GFP_KERNEL); |
164e265b | 1375 | spin_lock_bh(&scanned_queue->lock); |
5e93f352 | 1376 | if (!pwlan) { |
164e265b | 1377 | pwlan = rtw_get_oldest_wlan_network23a(scanned_queue); |
5e93f352 LF |
1378 | if (!pwlan) { |
1379 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
90403aa1 | 1380 | "Error: can't get pwlan in rtw23a_joinbss_event_cb\n"); |
164e265b | 1381 | spin_unlock_bh(&scanned_queue->lock); |
5e93f352 LF |
1382 | goto createbss_cmd_fail; |
1383 | } | |
1384 | pwlan->last_scanned = jiffies; | |
1385 | } else { | |
1386 | list_add_tail(&pwlan->list, | |
164e265b | 1387 | &scanned_queue->queue); |
5e93f352 LF |
1388 | } |
1389 | ||
1390 | pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork); | |
1391 | memcpy(&pwlan->network, pnetwork, pnetwork->Length); | |
1392 | /* pwlan->fixed = true; */ | |
1393 | ||
1394 | /* list_add_tail(&pwlan->list, | |
1395 | &pmlmepriv->scanned_queue.queue); */ | |
1396 | ||
1397 | /* copy pdev_network information to | |
1398 | pmlmepriv->cur_network */ | |
1399 | memcpy(&tgt_network->network, pnetwork, | |
1400 | get_wlan_bssid_ex_sz(pnetwork)); | |
1401 | ||
1402 | /* reset DSConfig */ | |
1403 | ||
5290cd68 | 1404 | clr_fwstate(pmlmepriv, _FW_UNDER_LINKING); |
5e93f352 | 1405 | |
5e93f352 LF |
1406 | /* we will set _FW_LINKED when there is one more sat to |
1407 | join us (rtw_stassoc_event_callback23a) */ | |
164e265b | 1408 | spin_unlock_bh(&scanned_queue->lock); |
5e93f352 LF |
1409 | } |
1410 | ||
1411 | createbss_cmd_fail: | |
1412 | ||
5e93f352 LF |
1413 | rtw_free_cmd_obj23a(pcmd); |
1414 | } | |
1415 | ||
1416 | void rtw_setstaKey_cmdrsp_callback23a(struct rtw_adapter *padapter, | |
1417 | struct cmd_obj *pcmd) | |
1418 | { | |
1419 | struct sta_priv *pstapriv; | |
1420 | struct set_stakey_rsp *psetstakey_rsp; | |
1421 | struct sta_info *psta; | |
1422 | ||
1423 | pstapriv = &padapter->stapriv; | |
7e6646d5 | 1424 | psetstakey_rsp = (struct set_stakey_rsp *) (pcmd->rsp); |
5e93f352 LF |
1425 | psta = rtw_get_stainfo23a(pstapriv, psetstakey_rsp->addr); |
1426 | ||
1427 | if (!psta) { | |
1428 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
90403aa1 | 1429 | "ERROR: rtw_setstaKey_cmdrsp_callback23a => can't get sta_info\n"); |
5e93f352 LF |
1430 | goto exit; |
1431 | } | |
1432 | ||
1433 | exit: | |
1434 | ||
1435 | rtw_free_cmd_obj23a(pcmd); | |
1436 | } | |
1437 | ||
1438 | void rtw_setassocsta_cmdrsp_callback23a(struct rtw_adapter *padapter, | |
1439 | struct cmd_obj *pcmd) | |
1440 | { | |
1441 | struct sta_priv *pstapriv = &padapter->stapriv; | |
1442 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
4e66cf09 GD |
1443 | struct set_assocsta_parm *passocsta_parm; |
1444 | struct set_assocsta_rsp *passocsta_rsp; | |
5e93f352 LF |
1445 | struct sta_info *psta; |
1446 | ||
1447 | passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf); | |
7e6646d5 | 1448 | passocsta_rsp = (struct set_assocsta_rsp *) (pcmd->rsp); |
5e93f352 LF |
1449 | psta = rtw_get_stainfo23a(pstapriv, passocsta_parm->addr); |
1450 | ||
1451 | if (psta == NULL) { | |
1452 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
90403aa1 | 1453 | "ERROR: setassocsta_cmdrsp_callbac => can't get sta_info\n"); |
5e93f352 LF |
1454 | goto exit; |
1455 | } | |
1456 | ||
1457 | psta->aid = psta->mac_id = passocsta_rsp->cam_id; | |
1458 | ||
1459 | spin_lock_bh(&pmlmepriv->lock); | |
1460 | ||
f2f97035 JS |
1461 | if (check_fwstate(pmlmepriv, WIFI_MP_STATE) && |
1462 | check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) | |
5e93f352 LF |
1463 | _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); |
1464 | ||
1465 | set_fwstate(pmlmepriv, _FW_LINKED); | |
1466 | spin_unlock_bh(&pmlmepriv->lock); | |
1467 | ||
1468 | exit: | |
1469 | rtw_free_cmd_obj23a(pcmd); | |
1470 | } |