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) | |
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) | |
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 JS |
238 | if (!res) { |
239 | printk(KERN_ERR "%s: Call to queue_work() failed\n", __func__); | |
240 | res = _FAIL; | |
241 | } else | |
242 | res = _SUCCESS; | |
5e93f352 | 243 | exit: |
5e93f352 | 244 | |
d97e2d2b | 245 | return res; |
5e93f352 LF |
246 | } |
247 | ||
248 | void rtw_cmd_clr_isr23a(struct cmd_priv *pcmdpriv) | |
249 | { | |
250 | pcmdpriv->cmd_done_cnt++; | |
251 | } | |
252 | ||
253 | void rtw_free_cmd_obj23a(struct cmd_obj *pcmd) | |
254 | { | |
255 | ||
256 | if (pcmd->cmdcode != _JoinBss_CMD_ && | |
257 | pcmd->cmdcode != _CreateBss_CMD_) { | |
258 | /* free parmbuf in cmd_obj */ | |
259 | kfree(pcmd->parmbuf); | |
260 | } | |
261 | ||
262 | if (pcmd->rsp) { | |
263 | if (pcmd->rspsz != 0) { | |
264 | /* free rsp in cmd_obj */ | |
265 | kfree(pcmd->rsp); | |
266 | } | |
267 | } | |
268 | ||
269 | kfree(pcmd); | |
270 | } | |
271 | ||
d97e2d2b | 272 | static void rtw_cmd_work(struct work_struct *work) |
5e93f352 | 273 | { |
1ec8911b | 274 | int (*cmd_hdl)(struct rtw_adapter *padapter, const u8 *pbuf); |
5e93f352 | 275 | void (*pcmd_callback)(struct rtw_adapter *dev, struct cmd_obj *pcmd); |
d97e2d2b JS |
276 | struct cmd_priv *pcmdpriv; |
277 | struct cmd_obj *pcmd = container_of(work, struct cmd_obj, work); | |
5e93f352 | 278 | |
d97e2d2b | 279 | pcmdpriv = &pcmd->padapter->cmdpriv; |
5e93f352 | 280 | |
d97e2d2b JS |
281 | if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) { |
282 | pcmd->res = H2C_DROPPED; | |
283 | goto post_process; | |
284 | } | |
5e93f352 | 285 | |
d97e2d2b | 286 | pcmdpriv->cmd_issued_cnt++; |
5e93f352 | 287 | |
d97e2d2b | 288 | pcmd->cmdsz = ALIGN(pcmd->cmdsz, 4); |
5e93f352 | 289 | |
d97e2d2b JS |
290 | if (pcmd->cmdcode < (sizeof(wlancmds)/sizeof(struct cmd_hdl))) { |
291 | cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns; | |
5e93f352 | 292 | |
d97e2d2b | 293 | if (cmd_hdl) |
c347dc62 | 294 | pcmd->res = cmd_hdl(pcmd->padapter, pcmd->parmbuf); |
d97e2d2b JS |
295 | else |
296 | pcmd->res = H2C_DROPPED; | |
297 | } else | |
298 | pcmd->res = H2C_PARAMETERS_ERROR; | |
5e93f352 LF |
299 | |
300 | post_process: | |
d97e2d2b JS |
301 | /* call callback function for post-processed */ |
302 | if (pcmd->cmdcode < (sizeof(rtw_cmd_callback) / | |
303 | sizeof(struct _cmd_callback))) { | |
304 | pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback; | |
305 | if (!pcmd_callback) { | |
306 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, | |
307 | ("mlme_cmd_hdl(): pcmd_callback = 0x%p, " | |
308 | "cmdcode = 0x%x\n", | |
309 | pcmd_callback, pcmd->cmdcode)); | |
5e93f352 | 310 | rtw_free_cmd_obj23a(pcmd); |
d97e2d2b | 311 | } else { |
808bcb4e | 312 | /* need consider that free cmd_obj in |
d97e2d2b JS |
313 | rtw_cmd_callback */ |
314 | pcmd_callback(pcmd->padapter, pcmd); | |
5e93f352 | 315 | } |
d97e2d2b JS |
316 | } else { |
317 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
318 | ("%s: cmdcode = 0x%x callback not defined!\n", | |
319 | __func__, pcmd->cmdcode)); | |
5e93f352 | 320 | rtw_free_cmd_obj23a(pcmd); |
d97e2d2b | 321 | } |
5e93f352 LF |
322 | } |
323 | ||
d97e2d2b | 324 | |
1ec8911b JS |
325 | int rtw_sitesurvey_cmd23a(struct rtw_adapter *padapter, |
326 | struct cfg80211_ssid *ssid, int ssid_num, | |
327 | struct rtw_ieee80211_channel *ch, int ch_num) | |
5e93f352 | 328 | { |
1ec8911b | 329 | int res = _FAIL; |
5e93f352 LF |
330 | struct cmd_obj *ph2c; |
331 | struct sitesurvey_parm *psurveyPara; | |
332 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
333 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
334 | ||
f2f97035 | 335 | if (check_fwstate(pmlmepriv, _FW_LINKED)) |
5e93f352 LF |
336 | rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_SCAN, 1); |
337 | ||
5e93f352 LF |
338 | ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); |
339 | if (!ph2c) | |
340 | return _FAIL; | |
341 | ||
342 | psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC); | |
343 | if (!psurveyPara) { | |
344 | kfree(ph2c); | |
345 | return _FAIL; | |
346 | } | |
347 | ||
528e5c1d | 348 | rtw_free_network_queue23a(padapter); |
5e93f352 LF |
349 | |
350 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, | |
351 | ("%s: flush network queue\n", __func__)); | |
352 | ||
353 | init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, | |
354 | GEN_CMD_CODE(_SiteSurvey)); | |
355 | ||
356 | /* psurveyPara->bsslimit = 48; */ | |
357 | psurveyPara->scan_mode = pmlmepriv->scan_mode; | |
358 | ||
359 | /* prepare ssid list */ | |
360 | if (ssid) { | |
361 | int i; | |
fbc6d797 | 362 | |
5e93f352 LF |
363 | for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) { |
364 | if (ssid[i].ssid_len) { | |
365 | memcpy(&psurveyPara->ssid[i], &ssid[i], | |
366 | sizeof(struct cfg80211_ssid)); | |
367 | psurveyPara->ssid_num++; | |
5e93f352 LF |
368 | } |
369 | } | |
370 | } | |
371 | ||
372 | /* prepare channel list */ | |
373 | if (ch) { | |
374 | int i; | |
fbc6d797 | 375 | |
5e93f352 LF |
376 | for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) { |
377 | if (ch[i].hw_value && | |
378 | !(ch[i].flags & IEEE80211_CHAN_DISABLED)) { | |
379 | memcpy(&psurveyPara->ch[i], &ch[i], | |
380 | sizeof(struct rtw_ieee80211_channel)); | |
381 | psurveyPara->ch_num++; | |
5e93f352 LF |
382 | } |
383 | } | |
384 | } | |
385 | ||
386 | set_fwstate(pmlmepriv, _FW_UNDER_SURVEY); | |
387 | ||
388 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); | |
389 | ||
390 | if (res == _SUCCESS) { | |
391 | mod_timer(&pmlmepriv->scan_to_timer, jiffies + | |
392 | msecs_to_jiffies(SCANNING_TIMEOUT)); | |
393 | ||
394 | rtw_led_control(padapter, LED_CTL_SITE_SURVEY); | |
395 | ||
396 | pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */ | |
397 | } else | |
398 | _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); | |
399 | ||
400 | return res; | |
401 | } | |
402 | ||
403 | void rtw_getbbrfreg_cmdrsp_callback23a(struct rtw_adapter *padapter, | |
404 | struct cmd_obj *pcmd) | |
405 | { | |
406 | kfree(pcmd->parmbuf); | |
407 | kfree(pcmd); | |
408 | } | |
409 | ||
1ec8911b | 410 | int rtw_createbss_cmd23a(struct rtw_adapter *padapter) |
5e93f352 LF |
411 | { |
412 | struct cmd_obj *pcmd; | |
413 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
414 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
415 | struct wlan_bssid_ex *pdev_network; | |
416 | u8 res = _SUCCESS; | |
417 | ||
418 | pdev_network = &padapter->registrypriv.dev_network; | |
419 | ||
420 | rtw_led_control(padapter, LED_CTL_START_TO_LINK); | |
421 | ||
422 | if (pmlmepriv->assoc_ssid.ssid_len == 0) { | |
423 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, | |
424 | (" createbss for Any SSid:%s\n", | |
425 | pmlmepriv->assoc_ssid.ssid)); | |
426 | } else { | |
427 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, | |
428 | (" createbss for SSid:%s\n", | |
429 | pmlmepriv->assoc_ssid.ssid)); | |
430 | } | |
431 | ||
432 | pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); | |
433 | if (!pcmd) { | |
434 | res = _FAIL; | |
435 | goto exit; | |
436 | } | |
437 | ||
5e93f352 LF |
438 | pcmd->cmdcode = _CreateBss_CMD_; |
439 | pcmd->parmbuf = (unsigned char *)pdev_network; | |
aab26454 | 440 | pcmd->cmdsz = get_wlan_bssid_ex_sz(pdev_network); |
5e93f352 LF |
441 | pcmd->rsp = NULL; |
442 | pcmd->rspsz = 0; | |
443 | ||
444 | pdev_network->Length = pcmd->cmdsz; | |
445 | ||
446 | res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); | |
447 | ||
448 | exit: | |
449 | ||
450 | return res; | |
451 | } | |
452 | ||
1ec8911b JS |
453 | int rtw_joinbss_cmd23a(struct rtw_adapter *padapter, |
454 | struct wlan_network *pnetwork) | |
5e93f352 | 455 | { |
1ec8911b | 456 | int res = _SUCCESS; |
5e93f352 LF |
457 | struct wlan_bssid_ex *psecnetwork; |
458 | struct cmd_obj *pcmd; | |
459 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
460 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
5e93f352 LF |
461 | struct security_priv *psecuritypriv = &padapter->securitypriv; |
462 | struct registry_priv *pregistrypriv = &padapter->registrypriv; | |
463 | struct ht_priv *phtpriv = &pmlmepriv->htpriv; | |
efc7144f | 464 | enum nl80211_iftype ifmode; |
5e93f352 LF |
465 | struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; |
466 | struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; | |
467 | ||
efc7144f | 468 | ifmode = pnetwork->network.ifmode; |
5e93f352 LF |
469 | |
470 | rtw_led_control(padapter, LED_CTL_START_TO_LINK); | |
471 | ||
472 | if (pmlmepriv->assoc_ssid.ssid_len == 0) { | |
473 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, | |
474 | ("+Join cmd: Any SSid\n")); | |
475 | } else { | |
476 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, | |
477 | ("+Join cmd: SSid =[%s]\n", | |
478 | pmlmepriv->assoc_ssid.ssid)); | |
479 | } | |
480 | ||
481 | pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); | |
482 | if (!pcmd) { | |
483 | res = _FAIL; | |
484 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
485 | ("rtw_joinbss_cmd23a: memory allocate for cmd_obj " | |
486 | "fail!!!\n")); | |
487 | goto exit; | |
488 | } | |
5e93f352 LF |
489 | |
490 | /* for hidden ap to set fw_state here */ | |
491 | if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE)) { | |
efc7144f JS |
492 | switch (ifmode) { |
493 | case NL80211_IFTYPE_ADHOC: | |
5e93f352 LF |
494 | set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); |
495 | break; | |
efc7144f JS |
496 | case NL80211_IFTYPE_P2P_CLIENT: |
497 | case NL80211_IFTYPE_STATION: | |
5e93f352 LF |
498 | set_fwstate(pmlmepriv, WIFI_STATION_STATE); |
499 | break; | |
efc7144f | 500 | default: |
5e93f352 LF |
501 | break; |
502 | } | |
503 | } | |
504 | ||
ea4190b1 | 505 | psecnetwork = &psecuritypriv->sec_bss; |
5e93f352 | 506 | if (!psecnetwork) { |
352f145d | 507 | kfree(pcmd); |
5e93f352 LF |
508 | res = _FAIL; |
509 | ||
510 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
511 | ("rtw_joinbss_cmd23a :psecnetwork == NULL!!!\n")); | |
512 | ||
513 | goto exit; | |
514 | } | |
515 | ||
ea4190b1 | 516 | memset(psecnetwork, 0, sizeof(struct wlan_bssid_ex)); |
5e93f352 LF |
517 | |
518 | memcpy(psecnetwork, &pnetwork->network, | |
519 | get_wlan_bssid_ex_sz(&pnetwork->network)); | |
520 | ||
5e93f352 LF |
521 | psecnetwork->IELength = 0; |
522 | /* Added by Albert 2009/02/18 */ | |
523 | /* If the the driver wants to use the bssid to create the | |
524 | * connection. If not, we have to copy the connecting AP's | |
525 | * MAC address to it so that the driver just has the bssid | |
526 | * information for PMKIDList searching. */ | |
527 | ||
528 | if (pmlmepriv->assoc_by_bssid == false) | |
529 | ether_addr_copy(&pmlmepriv->assoc_bssid[0], | |
530 | &pnetwork->network.MacAddress[0]); | |
531 | ||
532 | psecnetwork->IELength = | |
533 | rtw_restruct_sec_ie23a(padapter, &pnetwork->network.IEs[0], | |
534 | &psecnetwork->IEs[0], | |
535 | pnetwork->network.IELength); | |
536 | ||
bd8ad4a5 | 537 | pmlmepriv->qos_option = 0; |
5e93f352 LF |
538 | |
539 | if (pregistrypriv->wmm_enable) { | |
540 | u32 tmp_len; | |
541 | ||
542 | tmp_len = rtw_restruct_wmm_ie23a(padapter, | |
543 | &pnetwork->network.IEs[0], | |
544 | &psecnetwork->IEs[0], | |
545 | pnetwork->network.IELength, | |
546 | psecnetwork->IELength); | |
547 | ||
548 | if (psecnetwork->IELength != tmp_len) { | |
549 | psecnetwork->IELength = tmp_len; | |
550 | /* There is WMM IE in this corresp. beacon */ | |
bd8ad4a5 | 551 | pmlmepriv->qos_option = 1; |
5e93f352 LF |
552 | } else { |
553 | /* There is no WMM IE in this corresp. beacon */ | |
bd8ad4a5 | 554 | pmlmepriv->qos_option = 0; |
5e93f352 LF |
555 | } |
556 | } | |
557 | ||
558 | phtpriv->ht_option = false; | |
559 | if (pregistrypriv->ht_enable) { | |
9e3d6df2 | 560 | u32 algo = padapter->securitypriv.dot11PrivacyAlgrthm; |
5e93f352 LF |
561 | /* Added by Albert 2010/06/23 */ |
562 | /* For the WEP mode, we will use the bg mode to do | |
563 | the connection to avoid some IOT issue. */ | |
564 | /* Especially for Realtek 8192u SoftAP. */ | |
9e3d6df2 JS |
565 | if (algo != WLAN_CIPHER_SUITE_WEP40 && |
566 | algo != WLAN_CIPHER_SUITE_WEP104 && | |
567 | algo != WLAN_CIPHER_SUITE_TKIP) { | |
5e93f352 LF |
568 | /* rtw_restructure_ht_ie23a */ |
569 | rtw_restructure_ht_ie23a(padapter, | |
570 | &pnetwork->network.IEs[0], | |
571 | &psecnetwork->IEs[0], | |
572 | pnetwork->network.IELength, | |
573 | &psecnetwork->IELength); | |
574 | } | |
575 | } | |
576 | ||
577 | pmlmeinfo->assoc_AP_vendor = | |
578 | check_assoc_AP23a(pnetwork->network.IEs, | |
579 | pnetwork->network.IELength); | |
580 | ||
581 | if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA) | |
582 | padapter->pwrctrlpriv.smart_ps = 0; | |
583 | else | |
584 | padapter->pwrctrlpriv.smart_ps = | |
585 | padapter->registrypriv.smart_ps; | |
586 | ||
587 | DBG_8723A("%s: smart_ps =%d\n", __func__, | |
588 | padapter->pwrctrlpriv.smart_ps); | |
589 | ||
590 | /* get cmdsz before endian conversion */ | |
591 | pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork); | |
592 | ||
5e93f352 LF |
593 | pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */ |
594 | pcmd->parmbuf = (unsigned char *)psecnetwork; | |
595 | pcmd->rsp = NULL; | |
596 | pcmd->rspsz = 0; | |
597 | ||
598 | res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); | |
599 | exit: | |
600 | ||
601 | return res; | |
602 | } | |
603 | ||
1ec8911b JS |
604 | int rtw_disassoc_cmd23a(struct rtw_adapter*padapter, u32 deauth_timeout_ms, |
605 | bool enqueue) | |
5e93f352 LF |
606 | { |
607 | struct cmd_obj *cmdobj = NULL; | |
608 | struct disconnect_parm *param = NULL; | |
609 | struct cmd_priv *cmdpriv = &padapter->cmdpriv; | |
1ec8911b | 610 | int res = _SUCCESS; |
5e93f352 LF |
611 | |
612 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, | |
613 | ("+rtw_disassoc_cmd23a\n")); | |
614 | ||
615 | /* prepare cmd parameter */ | |
616 | param = kzalloc(sizeof(*param), GFP_ATOMIC); | |
617 | if (param == NULL) { | |
618 | res = _FAIL; | |
619 | goto exit; | |
620 | } | |
621 | param->deauth_timeout_ms = deauth_timeout_ms; | |
622 | ||
623 | if (enqueue) { | |
624 | /* need enqueue, prepare cmd_obj and enqueue */ | |
625 | cmdobj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); | |
626 | if (!cmdobj) { | |
627 | res = _FAIL; | |
628 | kfree(param); | |
629 | goto exit; | |
630 | } | |
631 | init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_); | |
632 | res = rtw_enqueue_cmd23a(cmdpriv, cmdobj); | |
633 | } else { | |
634 | /* no need to enqueue, do the cmd hdl directly and | |
635 | free cmd parameter */ | |
636 | if (H2C_SUCCESS != disconnect_hdl23a(padapter, (u8 *)param)) | |
637 | res = _FAIL; | |
638 | kfree(param); | |
639 | } | |
640 | ||
641 | exit: | |
642 | return res; | |
643 | } | |
644 | ||
1ec8911b | 645 | int rtw_setopmode_cmd23a(struct rtw_adapter *padapter, |
efc7144f | 646 | enum nl80211_iftype ifmode) |
5e93f352 LF |
647 | { |
648 | struct cmd_obj *ph2c; | |
649 | struct setopmode_parm *psetop; | |
650 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
1ec8911b | 651 | int res = _SUCCESS; |
5e93f352 LF |
652 | |
653 | ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); | |
654 | if (!ph2c) { | |
655 | res = false; | |
656 | goto exit; | |
657 | } | |
658 | psetop = kzalloc(sizeof(struct setopmode_parm), GFP_KERNEL); | |
659 | ||
660 | if (!psetop) { | |
661 | kfree(ph2c); | |
662 | res = false; | |
663 | goto exit; | |
664 | } | |
665 | ||
666 | init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_); | |
efc7144f | 667 | psetop->mode = ifmode; |
5e93f352 LF |
668 | |
669 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); | |
670 | exit: | |
671 | return res; | |
672 | } | |
673 | ||
1ec8911b | 674 | int rtw_setstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 unicast_key) |
5e93f352 LF |
675 | { |
676 | struct cmd_obj *ph2c; | |
677 | struct set_stakey_parm *psetstakey_para; | |
678 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
679 | struct set_stakey_rsp *psetstakey_rsp = NULL; | |
680 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
681 | struct security_priv *psecuritypriv = &padapter->securitypriv; | |
7e6646d5 | 682 | struct sta_info *sta = (struct sta_info *)psta; |
1ec8911b | 683 | int res = _SUCCESS; |
5e93f352 LF |
684 | |
685 | ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); | |
686 | if (!ph2c) { | |
687 | res = _FAIL; | |
688 | goto exit; | |
689 | } | |
690 | ||
691 | psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL); | |
692 | if (!psetstakey_para) { | |
693 | kfree(ph2c); | |
694 | res = _FAIL; | |
695 | goto exit; | |
696 | } | |
697 | ||
698 | psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_KERNEL); | |
699 | if (!psetstakey_rsp) { | |
700 | kfree(ph2c); | |
701 | kfree(psetstakey_para); | |
702 | res = _FAIL; | |
703 | goto exit; | |
704 | } | |
705 | ||
706 | init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); | |
707 | ph2c->rsp = (u8 *) psetstakey_rsp; | |
708 | ph2c->rspsz = sizeof(struct set_stakey_rsp); | |
709 | ||
710 | ether_addr_copy(psetstakey_para->addr, sta->hwaddr); | |
711 | ||
712 | if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { | |
713 | psetstakey_para->algorithm = | |
714 | (unsigned char)psecuritypriv->dot11PrivacyAlgrthm; | |
715 | } else { | |
716 | GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, | |
717 | false); | |
718 | } | |
719 | ||
720 | if (unicast_key == true) { | |
721 | memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16); | |
a82b4b01 | 722 | } else { |
5e93f352 | 723 | int idx = psecuritypriv->dot118021XGrpKeyid; |
fbc6d797 | 724 | |
5e93f352 LF |
725 | memcpy(&psetstakey_para->key, |
726 | &psecuritypriv->dot118021XGrpKey[idx].skey, 16); | |
a82b4b01 | 727 | } |
5e93f352 | 728 | |
808bcb4e | 729 | /* jeff: set this because at least sw key is ready */ |
9216c517 | 730 | padapter->securitypriv.busetkipkey = 1; |
5e93f352 LF |
731 | |
732 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); | |
733 | ||
734 | exit: | |
735 | ||
736 | return res; | |
737 | } | |
738 | ||
1ec8911b JS |
739 | int rtw_clearstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 entry, |
740 | u8 enqueue) | |
5e93f352 LF |
741 | { |
742 | struct cmd_obj *ph2c; | |
743 | struct set_stakey_parm *psetstakey_para; | |
744 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
745 | struct set_stakey_rsp *psetstakey_rsp = NULL; | |
746 | struct sta_info *sta = (struct sta_info *)psta; | |
1ec8911b | 747 | int res = _SUCCESS; |
5e93f352 LF |
748 | |
749 | if (!enqueue) { | |
750 | clear_cam_entry23a(padapter, entry); | |
751 | } else { | |
752 | ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); | |
753 | if (!ph2c) { | |
754 | res = _FAIL; | |
755 | goto exit; | |
756 | } | |
757 | ||
758 | psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), | |
759 | GFP_KERNEL); | |
760 | if (!psetstakey_para) { | |
761 | kfree(ph2c); | |
762 | res = _FAIL; | |
763 | goto exit; | |
764 | } | |
765 | ||
766 | psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), | |
767 | GFP_KERNEL); | |
768 | if (!psetstakey_rsp) { | |
769 | kfree(ph2c); | |
770 | kfree(psetstakey_para); | |
771 | res = _FAIL; | |
772 | goto exit; | |
773 | } | |
774 | ||
775 | init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, | |
776 | _SetStaKey_CMD_); | |
777 | ph2c->rsp = (u8 *) psetstakey_rsp; | |
778 | ph2c->rspsz = sizeof(struct set_stakey_rsp); | |
779 | ||
780 | ether_addr_copy(psetstakey_para->addr, sta->hwaddr); | |
781 | ||
9e3d6df2 | 782 | psetstakey_para->algorithm = 0; |
5e93f352 LF |
783 | |
784 | psetstakey_para->id = entry; | |
785 | ||
786 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); | |
787 | } | |
788 | exit: | |
789 | return res; | |
790 | } | |
791 | ||
1ec8911b | 792 | int rtw_addbareq_cmd23a(struct rtw_adapter*padapter, u8 tid, u8 *addr) |
5e93f352 LF |
793 | { |
794 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
795 | struct cmd_obj *ph2c; | |
796 | struct addBaReq_parm *paddbareq_parm; | |
1ec8911b | 797 | int res = _SUCCESS; |
5e93f352 | 798 | |
d7f2c23a JS |
799 | if (tid >= MAXTID) { |
800 | res = _FAIL; | |
801 | goto exit; | |
802 | } | |
803 | ||
5e93f352 LF |
804 | ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); |
805 | if (!ph2c) { | |
806 | res = _FAIL; | |
807 | goto exit; | |
808 | } | |
809 | ||
810 | paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_ATOMIC); | |
811 | if (!paddbareq_parm) { | |
812 | kfree(ph2c); | |
813 | res = _FAIL; | |
814 | goto exit; | |
815 | } | |
816 | ||
817 | paddbareq_parm->tid = tid; | |
818 | ether_addr_copy(paddbareq_parm->addr, addr); | |
819 | ||
820 | init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, | |
821 | GEN_CMD_CODE(_AddBAReq)); | |
822 | ||
823 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); | |
824 | exit: | |
825 | return res; | |
826 | } | |
827 | ||
1ec8911b | 828 | int rtw_dynamic_chk_wk_cmd23a(struct rtw_adapter*padapter) |
5e93f352 LF |
829 | { |
830 | struct cmd_obj *ph2c; | |
831 | struct drvextra_cmd_parm *pdrvextra_cmd_parm; | |
832 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
1ec8911b | 833 | int res = _SUCCESS; |
5e93f352 LF |
834 | |
835 | ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); | |
836 | if (!ph2c) { | |
837 | res = _FAIL; | |
838 | goto exit; | |
839 | } | |
840 | ||
841 | pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC); | |
842 | if (!pdrvextra_cmd_parm) { | |
843 | kfree(ph2c); | |
844 | res = _FAIL; | |
845 | goto exit; | |
846 | } | |
847 | ||
848 | pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID; | |
849 | pdrvextra_cmd_parm->type_size = 0; | |
850 | pdrvextra_cmd_parm->pbuf = (u8 *)padapter; | |
851 | ||
852 | init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, | |
853 | GEN_CMD_CODE(_Set_Drv_Extra)); | |
854 | ||
855 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); | |
856 | exit: | |
857 | ||
858 | return res; | |
859 | } | |
860 | ||
861 | /* | |
862 | * This is only ever called from on_action_spct23a_ch_switch () which isn't | |
863 | * called from anywhere itself | |
864 | */ | |
1ec8911b JS |
865 | int rtw_set_ch_cmd23a(struct rtw_adapter*padapter, u8 ch, u8 bw, u8 ch_offset, |
866 | u8 enqueue) | |
5e93f352 LF |
867 | { |
868 | struct cmd_obj *pcmdobj; | |
869 | struct set_ch_parm *set_ch_parm; | |
870 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
1ec8911b | 871 | int res = _SUCCESS; |
5e93f352 | 872 | |
a790d58e JS |
873 | DBG_8723A("%s(%s): ch:%u, bw:%u, ch_offset:%u\n", __func__, |
874 | padapter->pnetdev->name, ch, bw, ch_offset); | |
5e93f352 LF |
875 | |
876 | /* check input parameter */ | |
877 | ||
878 | /* prepare cmd parameter */ | |
879 | set_ch_parm = kzalloc(sizeof(*set_ch_parm), GFP_KERNEL); | |
880 | if (!set_ch_parm) { | |
881 | res = _FAIL; | |
882 | goto exit; | |
883 | } | |
884 | set_ch_parm->ch = ch; | |
885 | set_ch_parm->bw = bw; | |
886 | set_ch_parm->ch_offset = ch_offset; | |
887 | ||
888 | if (enqueue) { | |
889 | /* need enqueue, prepare cmd_obj and enqueue */ | |
890 | pcmdobj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); | |
891 | if (!pcmdobj) { | |
892 | kfree(set_ch_parm); | |
893 | res = _FAIL; | |
894 | goto exit; | |
895 | } | |
896 | ||
897 | init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm, | |
898 | GEN_CMD_CODE(_SetChannel)); | |
899 | res = rtw_enqueue_cmd23a(pcmdpriv, pcmdobj); | |
900 | } else { | |
901 | /* no need to enqueue, do the cmd hdl directly and | |
902 | free cmd parameter */ | |
903 | if (H2C_SUCCESS != set_ch_hdl23a(padapter, (u8 *)set_ch_parm)) | |
904 | res = _FAIL; | |
905 | ||
906 | kfree(set_ch_parm); | |
907 | } | |
908 | ||
909 | /* do something based on res... */ | |
910 | exit: | |
911 | ||
a790d58e | 912 | DBG_8723A("%s(%s): res:%u\n", __func__, padapter->pnetdev->name, res); |
5e93f352 LF |
913 | |
914 | return res; | |
915 | } | |
916 | ||
917 | static void traffic_status_watchdog(struct rtw_adapter *padapter) | |
918 | { | |
919 | u8 bEnterPS; | |
920 | u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false; | |
921 | u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false; | |
922 | u8 bHigherBusyTxTraffic = false; | |
923 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
c17416ef | 924 | int BusyThreshold = 100; |
5e93f352 LF |
925 | /* */ |
926 | /* Determine if our traffic is busy now */ | |
927 | /* */ | |
928 | if (check_fwstate(pmlmepriv, _FW_LINKED)) { | |
09d88791 JS |
929 | if (rtl8723a_BT_coexist(padapter)) |
930 | BusyThreshold = 50; | |
931 | else if (pmlmepriv->LinkDetectInfo.bBusyTraffic) | |
932 | BusyThreshold = 75; | |
5e93f352 LF |
933 | /* if we raise bBusyTraffic in last watchdog, using |
934 | lower threshold. */ | |
5e93f352 | 935 | if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold || |
09d88791 | 936 | pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold) { |
5e93f352 LF |
937 | bBusyTraffic = true; |
938 | ||
939 | if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > | |
940 | pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) | |
941 | bRxBusyTraffic = true; | |
942 | else | |
943 | bTxBusyTraffic = true; | |
944 | } | |
945 | ||
946 | /* Higher Tx/Rx data. */ | |
947 | if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 || | |
948 | pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) { | |
949 | bHigherBusyTraffic = true; | |
950 | ||
951 | if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > | |
952 | pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) | |
953 | bHigherBusyRxTraffic = true; | |
954 | else | |
955 | bHigherBusyTxTraffic = true; | |
956 | } | |
957 | ||
ef95e276 JS |
958 | if (!rtl8723a_BT_coexist(padapter) || |
959 | !rtl8723a_BT_using_antenna_1(padapter)) { | |
5e93f352 | 960 | /* check traffic for powersaving. */ |
ef95e276 JS |
961 | if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + |
962 | pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) || | |
963 | pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod >2) | |
964 | bEnterPS = false; | |
965 | else | |
966 | bEnterPS = true; | |
5e93f352 | 967 | |
ef95e276 JS |
968 | /* LeisurePS only work in infra mode. */ |
969 | if (bEnterPS) | |
970 | LPS_Enter23a(padapter); | |
971 | else | |
972 | LPS_Leave23a(padapter); | |
5e93f352 LF |
973 | } |
974 | } else | |
975 | LPS_Leave23a(padapter); | |
976 | ||
977 | pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0; | |
978 | pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0; | |
979 | pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0; | |
980 | pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic; | |
981 | pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic; | |
982 | pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic; | |
983 | pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic; | |
984 | pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic; | |
985 | pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic; | |
986 | } | |
987 | ||
c0b99bed | 988 | static void dynamic_chk_wk_hdl(struct rtw_adapter *padapter, u8 *pbuf, int sz) |
5e93f352 LF |
989 | { |
990 | struct mlme_priv *pmlmepriv; | |
991 | ||
992 | padapter = (struct rtw_adapter *)pbuf; | |
993 | pmlmepriv = &padapter->mlmepriv; | |
994 | ||
995 | #ifdef CONFIG_8723AU_AP_MODE | |
f2f97035 | 996 | if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) |
5e93f352 LF |
997 | expire_timeout_chk23a(padapter); |
998 | #endif | |
999 | ||
b7c19c27 | 1000 | rtl8723a_sreset_xmit_status_check(padapter); |
5e93f352 LF |
1001 | |
1002 | linked_status_chk23a(padapter); | |
1003 | traffic_status_watchdog(padapter); | |
1004 | ||
8289d357 | 1005 | rtl8723a_HalDmWatchDog(padapter); |
5e93f352 | 1006 | |
5e93f352 LF |
1007 | /* */ |
1008 | /* BT-Coexist */ | |
1009 | /* */ | |
febf3087 | 1010 | rtl8723a_BT_do_coexist(padapter); |
5e93f352 LF |
1011 | } |
1012 | ||
c0b99bed | 1013 | static void lps_ctrl_wk_hdl(struct rtw_adapter *padapter, u8 lps_ctrl_type) |
5e93f352 LF |
1014 | { |
1015 | struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; | |
1016 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
1017 | u8 mstatus; | |
1018 | ||
f2f97035 JS |
1019 | if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || |
1020 | check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) | |
5e93f352 LF |
1021 | return; |
1022 | ||
f237216e | 1023 | switch (lps_ctrl_type) { |
5e93f352 | 1024 | case LPS_CTRL_SCAN: |
d952e4c4 JS |
1025 | rtl8723a_BT_wifiscan_notify(padapter, true); |
1026 | if (!rtl8723a_BT_using_antenna_1(padapter)) { | |
5e93f352 LF |
1027 | if (check_fwstate(pmlmepriv, _FW_LINKED)) |
1028 | LPS_Leave23a(padapter); | |
1029 | } | |
1030 | break; | |
1031 | case LPS_CTRL_JOINBSS: | |
1032 | LPS_Leave23a(padapter); | |
1033 | break; | |
1034 | case LPS_CTRL_CONNECT: | |
1035 | mstatus = 1;/* connect */ | |
1036 | /* Reset LPS Setting */ | |
1037 | padapter->pwrctrlpriv.LpsIdleCount = 0; | |
327c70c0 | 1038 | rtl8723a_set_FwJoinBssReport_cmd(padapter, 1); |
43de0304 | 1039 | rtl8723a_BT_mediastatus_notify(padapter, mstatus); |
5e93f352 LF |
1040 | break; |
1041 | case LPS_CTRL_DISCONNECT: | |
1042 | mstatus = 0;/* disconnect */ | |
43de0304 JS |
1043 | rtl8723a_BT_mediastatus_notify(padapter, mstatus); |
1044 | if (!rtl8723a_BT_using_antenna_1(padapter)) | |
5e93f352 | 1045 | LPS_Leave23a(padapter); |
327c70c0 | 1046 | rtl8723a_set_FwJoinBssReport_cmd(padapter, 0); |
5e93f352 LF |
1047 | break; |
1048 | case LPS_CTRL_SPECIAL_PACKET: | |
1049 | pwrpriv->DelayLPSLastTimeStamp = jiffies; | |
f83e9e2a JS |
1050 | rtl8723a_BT_specialpacket_notify(padapter); |
1051 | if (!rtl8723a_BT_using_antenna_1(padapter)) | |
5e93f352 | 1052 | LPS_Leave23a(padapter); |
5e93f352 LF |
1053 | break; |
1054 | case LPS_CTRL_LEAVE: | |
a862d5d3 JS |
1055 | rtl8723a_BT_lps_leave(padapter); |
1056 | if (!rtl8723a_BT_using_antenna_1(padapter)) | |
5e93f352 | 1057 | LPS_Leave23a(padapter); |
5e93f352 LF |
1058 | break; |
1059 | ||
1060 | default: | |
1061 | break; | |
1062 | } | |
1063 | } | |
1064 | ||
1ec8911b JS |
1065 | int rtw_lps_ctrl_wk_cmd23a(struct rtw_adapter *padapter, |
1066 | u8 lps_ctrl_type, u8 enqueue) | |
5e93f352 LF |
1067 | { |
1068 | struct cmd_obj *ph2c; | |
1069 | struct drvextra_cmd_parm *pdrvextra_cmd_parm; | |
1070 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
1ec8911b | 1071 | int res = _SUCCESS; |
5e93f352 LF |
1072 | |
1073 | if (enqueue) { | |
1074 | ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); | |
1075 | if (!ph2c) { | |
1076 | res = _FAIL; | |
1077 | goto exit; | |
1078 | } | |
1079 | ||
1080 | pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), | |
1081 | GFP_ATOMIC); | |
1082 | if (!pdrvextra_cmd_parm) { | |
1083 | kfree(ph2c); | |
1084 | res = _FAIL; | |
1085 | goto exit; | |
1086 | } | |
1087 | ||
1088 | pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID; | |
1089 | pdrvextra_cmd_parm->type_size = lps_ctrl_type; | |
1090 | pdrvextra_cmd_parm->pbuf = NULL; | |
1091 | ||
1092 | init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, | |
1093 | GEN_CMD_CODE(_Set_Drv_Extra)); | |
1094 | ||
1095 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); | |
1096 | } else | |
1097 | lps_ctrl_wk_hdl(padapter, lps_ctrl_type); | |
1098 | exit: | |
1099 | ||
1100 | return res; | |
1101 | } | |
1102 | ||
1ec8911b | 1103 | int rtw_ps_cmd23a(struct rtw_adapter*padapter) |
5e93f352 LF |
1104 | { |
1105 | struct cmd_obj *ppscmd; | |
1106 | struct drvextra_cmd_parm *pdrvextra_cmd_parm; | |
1107 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
1ec8911b | 1108 | int res = _SUCCESS; |
5e93f352 LF |
1109 | |
1110 | ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); | |
1111 | if (!ppscmd) { | |
1112 | res = _FAIL; | |
1113 | goto exit; | |
1114 | } | |
1115 | ||
1116 | pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), | |
1117 | GFP_ATOMIC); | |
1118 | if (!pdrvextra_cmd_parm) { | |
1119 | kfree(ppscmd); | |
1120 | res = _FAIL; | |
1121 | goto exit; | |
1122 | } | |
1123 | ||
1124 | pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID; | |
1125 | pdrvextra_cmd_parm->pbuf = NULL; | |
1126 | init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, | |
1127 | GEN_CMD_CODE(_Set_Drv_Extra)); | |
1128 | ||
1129 | res = rtw_enqueue_cmd23a(pcmdpriv, ppscmd); | |
1130 | exit: | |
1131 | ||
1132 | return res; | |
1133 | } | |
1134 | ||
1135 | #ifdef CONFIG_8723AU_AP_MODE | |
1136 | ||
1137 | static void rtw_chk_hi_queue_hdl(struct rtw_adapter *padapter) | |
1138 | { | |
1139 | int cnt = 0; | |
1140 | struct sta_info *psta_bmc; | |
1141 | struct sta_priv *pstapriv = &padapter->stapriv; | |
1142 | ||
1143 | psta_bmc = rtw_get_bcmc_stainfo23a(padapter); | |
1144 | if (!psta_bmc) | |
1145 | return; | |
1146 | ||
1147 | if (psta_bmc->sleepq_len == 0) { | |
8d3fd614 | 1148 | bool val; |
5e93f352 | 1149 | |
8d3fd614 | 1150 | val = rtl8723a_chk_hi_queue_empty(padapter); |
5e93f352 | 1151 | |
8d3fd614 | 1152 | while (val == false) { |
5e93f352 LF |
1153 | msleep(100); |
1154 | ||
1155 | cnt++; | |
1156 | ||
1157 | if (cnt>10) | |
1158 | break; | |
1159 | ||
8d3fd614 | 1160 | val = rtl8723a_chk_hi_queue_empty(padapter); |
5e93f352 LF |
1161 | } |
1162 | ||
1163 | if (cnt <= 10) { | |
1164 | pstapriv->tim_bitmap &= ~BIT(0); | |
1165 | pstapriv->sta_dz_bitmap &= ~BIT(0); | |
1166 | ||
3021bc42 | 1167 | update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); |
5e93f352 LF |
1168 | } else /* re check again */ |
1169 | rtw_chk_hi_queue_cmd23a(padapter); | |
1170 | } | |
1171 | } | |
1172 | ||
1ec8911b | 1173 | int rtw_chk_hi_queue_cmd23a(struct rtw_adapter*padapter) |
5e93f352 LF |
1174 | { |
1175 | struct cmd_obj *ph2c; | |
1176 | struct drvextra_cmd_parm *pdrvextra_cmd_parm; | |
1177 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
1ec8911b | 1178 | int res = _SUCCESS; |
5e93f352 LF |
1179 | |
1180 | ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); | |
1181 | if (!ph2c) { | |
1182 | res = _FAIL; | |
1183 | goto exit; | |
1184 | } | |
1185 | ||
1186 | pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), | |
1187 | GFP_ATOMIC); | |
1188 | if (!pdrvextra_cmd_parm) { | |
1189 | kfree(ph2c); | |
1190 | res = _FAIL; | |
1191 | goto exit; | |
1192 | } | |
1193 | ||
1194 | pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID; | |
1195 | pdrvextra_cmd_parm->type_size = 0; | |
1196 | pdrvextra_cmd_parm->pbuf = NULL; | |
1197 | ||
1198 | init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, | |
1199 | GEN_CMD_CODE(_Set_Drv_Extra)); | |
1200 | ||
1201 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); | |
1202 | exit: | |
1203 | ||
1204 | return res; | |
1205 | } | |
1206 | #endif | |
1207 | ||
1ec8911b | 1208 | int rtw_c2h_wk_cmd23a(struct rtw_adapter *padapter, u8 *c2h_evt) |
5e93f352 LF |
1209 | { |
1210 | struct cmd_obj *ph2c; | |
1211 | struct drvextra_cmd_parm *pdrvextra_cmd_parm; | |
1212 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; | |
1ec8911b | 1213 | int res = _SUCCESS; |
5e93f352 LF |
1214 | |
1215 | ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); | |
1216 | if (!ph2c) { | |
1217 | res = _FAIL; | |
1218 | goto exit; | |
1219 | } | |
1220 | ||
1221 | pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), | |
1222 | GFP_ATOMIC); | |
1223 | if (!pdrvextra_cmd_parm) { | |
1224 | kfree(ph2c); | |
1225 | res = _FAIL; | |
1226 | goto exit; | |
1227 | } | |
1228 | ||
1229 | pdrvextra_cmd_parm->ec_id = C2H_WK_CID; | |
1230 | pdrvextra_cmd_parm->type_size = c2h_evt?16:0; | |
1231 | pdrvextra_cmd_parm->pbuf = c2h_evt; | |
1232 | ||
1233 | init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, | |
1234 | GEN_CMD_CODE(_Set_Drv_Extra)); | |
1235 | ||
1236 | res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); | |
1237 | ||
1238 | exit: | |
1239 | ||
1240 | return res; | |
1241 | } | |
1242 | ||
849befad | 1243 | static int c2h_evt_hdl(struct rtw_adapter *adapter, struct c2h_evt_hdr *c2h_evt) |
5e93f352 | 1244 | { |
ab281e3b | 1245 | int ret = _FAIL; |
5e93f352 LF |
1246 | u8 buf[16]; |
1247 | ||
1248 | if (!c2h_evt) { | |
1249 | /* No c2h event in cmd_obj, read c2h event before handling*/ | |
1250 | if (c2h_evt_read23a(adapter, buf) == _SUCCESS) { | |
1251 | c2h_evt = (struct c2h_evt_hdr *)buf; | |
1252 | ||
00cf86c9 | 1253 | ret = c2h_handler_8723a(adapter, c2h_evt); |
5e93f352 | 1254 | } |
849befad | 1255 | } else |
00cf86c9 | 1256 | ret = c2h_handler_8723a(adapter, c2h_evt); |
849befad | 1257 | |
5e93f352 LF |
1258 | return ret; |
1259 | } | |
1260 | ||
980cf72a | 1261 | static void rtw_irq_work(struct work_struct *work) |
5e93f352 LF |
1262 | { |
1263 | struct evt_priv *evtpriv; | |
1264 | struct rtw_adapter *adapter; | |
5e93f352 | 1265 | |
980cf72a | 1266 | evtpriv = container_of(work, struct evt_priv, irq_wk); |
5e93f352 | 1267 | adapter = container_of(evtpriv, struct rtw_adapter, evtpriv); |
5e93f352 | 1268 | |
980cf72a JS |
1269 | c2h_evt_clear23a(adapter); |
1270 | } | |
5e93f352 | 1271 | |
980cf72a JS |
1272 | void rtw_evt_work(struct work_struct *work) |
1273 | { | |
1274 | struct evt_work *ework; | |
1275 | struct rtw_adapter *adapter; | |
5e93f352 | 1276 | |
980cf72a JS |
1277 | ework = container_of(work, struct evt_work, work); |
1278 | adapter = ework->adapter; | |
5e93f352 | 1279 | |
980cf72a JS |
1280 | c2h_evt_clear23a(adapter); |
1281 | ||
1282 | if (!c2h_evt_exist(&ework->u.c2h_evt)) { | |
1283 | kfree(ework); | |
1284 | return; | |
5e93f352 LF |
1285 | } |
1286 | ||
227ca8c4 | 1287 | if (c2h_id_filter_ccx_8723a(ework->u.c2h_evt.id) == true) { |
980cf72a | 1288 | /* Handle CCX report here */ |
00cf86c9 | 1289 | c2h_handler_8723a(adapter, &ework->u.c2h_evt); |
980cf72a JS |
1290 | kfree(ework); |
1291 | } else { | |
1292 | /* | |
1293 | * Enqueue into cmd_thread for others. | |
1294 | * ework will be turned into a c2h_evt and freed once it | |
1295 | * has been consumed. | |
1296 | */ | |
1297 | rtw_c2h_wk_cmd23a(adapter, (u8 *)&ework->u.c2h_evt); | |
1298 | } | |
5e93f352 LF |
1299 | } |
1300 | ||
1ec8911b | 1301 | int rtw_drvextra_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) |
5e93f352 | 1302 | { |
0348dc74 | 1303 | const struct drvextra_cmd_parm *pdrvextra_cmd; |
5e93f352 LF |
1304 | |
1305 | if (!pbuf) | |
1306 | return H2C_PARAMETERS_ERROR; | |
1307 | ||
1308 | pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf; | |
1309 | ||
f237216e | 1310 | switch (pdrvextra_cmd->ec_id) { |
5e93f352 LF |
1311 | case DYNAMIC_CHK_WK_CID: |
1312 | dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf, | |
1313 | pdrvextra_cmd->type_size); | |
1314 | break; | |
1315 | case POWER_SAVING_CTRL_WK_CID: | |
462eb49e | 1316 | rtw_ps_processor23a(padapter); |
5e93f352 LF |
1317 | break; |
1318 | case LPS_CTRL_WK_CID: | |
1319 | lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size); | |
1320 | break; | |
5e93f352 LF |
1321 | #ifdef CONFIG_8723AU_AP_MODE |
1322 | case CHECK_HIQ_WK_CID: | |
1323 | rtw_chk_hi_queue_hdl(padapter); | |
1324 | break; | |
1325 | #endif /* CONFIG_8723AU_AP_MODE */ | |
1326 | case C2H_WK_CID: | |
1327 | c2h_evt_hdl(padapter, | |
849befad | 1328 | (struct c2h_evt_hdr *)pdrvextra_cmd->pbuf); |
5e93f352 LF |
1329 | break; |
1330 | ||
1331 | default: | |
1332 | break; | |
1333 | } | |
1334 | ||
1335 | if (pdrvextra_cmd->pbuf && (pdrvextra_cmd->type_size > 0)) { | |
1336 | kfree(pdrvextra_cmd->pbuf); | |
0348dc74 JS |
1337 | /* |
1338 | * No need to set pdrvextra_cmd->pbuf = NULL as we were | |
1339 | * operating on a copy of the original pcmd->parmbuf | |
1340 | * created in rtw_cmd_work(). | |
1341 | */ | |
5e93f352 LF |
1342 | } |
1343 | ||
1344 | return H2C_SUCCESS; | |
1345 | } | |
1346 | ||
1347 | void rtw_survey_cmd_callback23a(struct rtw_adapter *padapter, | |
1ec8911b | 1348 | struct cmd_obj *pcmd) |
5e93f352 LF |
1349 | { |
1350 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
1351 | ||
1352 | if (pcmd->res == H2C_DROPPED) { | |
1353 | /* TODO: cancel timer and do timeout handler directly... */ | |
1354 | /* need to make timeout handlerOS independent */ | |
1355 | mod_timer(&pmlmepriv->scan_to_timer, | |
1356 | jiffies + msecs_to_jiffies(1)); | |
1357 | } else if (pcmd->res != H2C_SUCCESS) { | |
1358 | mod_timer(&pmlmepriv->scan_to_timer, | |
1359 | jiffies + msecs_to_jiffies(1)); | |
1360 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
1361 | ("\n ********Error: MgntActrtw_set_802_11_bssid23a_" | |
1362 | "LIST_SCAN Fail ************\n\n.")); | |
1363 | } | |
1364 | ||
1365 | /* free cmd */ | |
1366 | rtw_free_cmd_obj23a(pcmd); | |
1367 | } | |
1368 | ||
1369 | void rtw_disassoc_cmd23a_callback(struct rtw_adapter *padapter, | |
1370 | struct cmd_obj *pcmd) | |
1371 | { | |
1372 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
1373 | ||
1374 | if (pcmd->res != H2C_SUCCESS) { | |
1375 | spin_lock_bh(&pmlmepriv->lock); | |
1376 | set_fwstate(pmlmepriv, _FW_LINKED); | |
1377 | spin_unlock_bh(&pmlmepriv->lock); | |
1378 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
1379 | ("\n ***Error: disconnect_cmd_callback Fail ***\n.")); | |
1380 | return; | |
1381 | } | |
1382 | ||
1383 | /* free cmd */ | |
1384 | rtw_free_cmd_obj23a(pcmd); | |
1385 | } | |
1386 | ||
1387 | void rtw_joinbss_cmd23a_callback(struct rtw_adapter *padapter, | |
1388 | struct cmd_obj *pcmd) | |
1389 | { | |
1390 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
1391 | ||
1392 | if (pcmd->res == H2C_DROPPED) { | |
1393 | /* TODO: cancel timer and do timeout handler directly... */ | |
1394 | /* need to make timeout handlerOS independent */ | |
1395 | mod_timer(&pmlmepriv->assoc_timer, | |
1396 | jiffies + msecs_to_jiffies(1)); | |
1397 | } else if (pcmd->res != H2C_SUCCESS) { | |
1398 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
1399 | ("********Error:rtw_select_and_join_from_scanned_" | |
1400 | "queue Wait Sema Fail ************\n")); | |
1401 | mod_timer(&pmlmepriv->assoc_timer, | |
1402 | jiffies + msecs_to_jiffies(1)); | |
1403 | } | |
1404 | ||
1405 | rtw_free_cmd_obj23a(pcmd); | |
1406 | } | |
1407 | ||
1408 | void rtw_createbss_cmd23a_callback(struct rtw_adapter *padapter, | |
1409 | struct cmd_obj *pcmd) | |
1410 | { | |
1411 | struct sta_info *psta; | |
1412 | struct wlan_network *pwlan; | |
1413 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
1414 | struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf; | |
1415 | struct wlan_network *tgt_network = &pmlmepriv->cur_network; | |
1416 | ||
1417 | if (pcmd->res != H2C_SUCCESS) { | |
1418 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
1419 | ("\n ********Error: rtw_createbss_cmd23a_callback " | |
1420 | "Fail ************\n\n.")); | |
1421 | mod_timer(&pmlmepriv->assoc_timer, | |
1422 | jiffies + msecs_to_jiffies(1)); | |
1423 | } | |
1424 | ||
1425 | del_timer_sync(&pmlmepriv->assoc_timer); | |
1426 | ||
5e93f352 LF |
1427 | if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { |
1428 | psta = rtw_get_stainfo23a(&padapter->stapriv, | |
1429 | pnetwork->MacAddress); | |
1430 | if (!psta) { | |
1431 | psta = rtw_alloc_stainfo23a(&padapter->stapriv, | |
6e8bc71d JS |
1432 | pnetwork->MacAddress, |
1433 | GFP_KERNEL); | |
5e93f352 LF |
1434 | if (!psta) { |
1435 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
1436 | ("\nCan't alloc sta_info when " | |
1437 | "createbss_cmd_callback\n")); | |
1438 | goto createbss_cmd_fail ; | |
1439 | } | |
1440 | } | |
1441 | ||
5290cd68 | 1442 | spin_lock_bh(&pmlmepriv->lock); |
5e93f352 | 1443 | rtw_indicate_connect23a(padapter); |
5290cd68 | 1444 | spin_unlock_bh(&pmlmepriv->lock); |
5e93f352 | 1445 | } else { |
ec838b0b | 1446 | pwlan = rtw_alloc_network(pmlmepriv, GFP_KERNEL); |
5e93f352 LF |
1447 | spin_lock_bh(&pmlmepriv->scanned_queue.lock); |
1448 | if (!pwlan) { | |
1449 | pwlan = rtw_get_oldest_wlan_network23a(&pmlmepriv->scanned_queue); | |
1450 | if (!pwlan) { | |
1451 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
1452 | ("\n Error: can't get pwlan in " | |
1453 | "rtw23a_joinbss_event_cb\n")); | |
1454 | spin_unlock_bh(&pmlmepriv->scanned_queue.lock); | |
1455 | goto createbss_cmd_fail; | |
1456 | } | |
1457 | pwlan->last_scanned = jiffies; | |
1458 | } else { | |
1459 | list_add_tail(&pwlan->list, | |
1460 | &pmlmepriv->scanned_queue.queue); | |
1461 | } | |
1462 | ||
1463 | pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork); | |
1464 | memcpy(&pwlan->network, pnetwork, pnetwork->Length); | |
1465 | /* pwlan->fixed = true; */ | |
1466 | ||
1467 | /* list_add_tail(&pwlan->list, | |
1468 | &pmlmepriv->scanned_queue.queue); */ | |
1469 | ||
1470 | /* copy pdev_network information to | |
1471 | pmlmepriv->cur_network */ | |
1472 | memcpy(&tgt_network->network, pnetwork, | |
1473 | get_wlan_bssid_ex_sz(pnetwork)); | |
1474 | ||
1475 | /* reset DSConfig */ | |
1476 | ||
5290cd68 | 1477 | clr_fwstate(pmlmepriv, _FW_UNDER_LINKING); |
5e93f352 LF |
1478 | |
1479 | spin_unlock_bh(&pmlmepriv->scanned_queue.lock); | |
1480 | /* we will set _FW_LINKED when there is one more sat to | |
1481 | join us (rtw_stassoc_event_callback23a) */ | |
1482 | } | |
1483 | ||
1484 | createbss_cmd_fail: | |
1485 | ||
5e93f352 LF |
1486 | rtw_free_cmd_obj23a(pcmd); |
1487 | } | |
1488 | ||
1489 | void rtw_setstaKey_cmdrsp_callback23a(struct rtw_adapter *padapter, | |
1490 | struct cmd_obj *pcmd) | |
1491 | { | |
1492 | struct sta_priv *pstapriv; | |
1493 | struct set_stakey_rsp *psetstakey_rsp; | |
1494 | struct sta_info *psta; | |
1495 | ||
1496 | pstapriv = &padapter->stapriv; | |
7e6646d5 | 1497 | psetstakey_rsp = (struct set_stakey_rsp *) (pcmd->rsp); |
5e93f352 LF |
1498 | psta = rtw_get_stainfo23a(pstapriv, psetstakey_rsp->addr); |
1499 | ||
1500 | if (!psta) { | |
1501 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
1502 | ("\nERROR: rtw_setstaKey_cmdrsp_callback23a => " | |
1503 | "can't get sta_info\n\n")); | |
1504 | goto exit; | |
1505 | } | |
1506 | ||
1507 | exit: | |
1508 | ||
1509 | rtw_free_cmd_obj23a(pcmd); | |
1510 | } | |
1511 | ||
1512 | void rtw_setassocsta_cmdrsp_callback23a(struct rtw_adapter *padapter, | |
1513 | struct cmd_obj *pcmd) | |
1514 | { | |
1515 | struct sta_priv *pstapriv = &padapter->stapriv; | |
1516 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
4e66cf09 GD |
1517 | struct set_assocsta_parm *passocsta_parm; |
1518 | struct set_assocsta_rsp *passocsta_rsp; | |
5e93f352 LF |
1519 | struct sta_info *psta; |
1520 | ||
1521 | passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf); | |
7e6646d5 | 1522 | passocsta_rsp = (struct set_assocsta_rsp *) (pcmd->rsp); |
5e93f352 LF |
1523 | psta = rtw_get_stainfo23a(pstapriv, passocsta_parm->addr); |
1524 | ||
1525 | if (psta == NULL) { | |
1526 | RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, | |
1527 | ("\nERROR: setassocsta_cmdrsp_callbac => can't " | |
1528 | "get sta_info\n\n")); | |
1529 | goto exit; | |
1530 | } | |
1531 | ||
1532 | psta->aid = psta->mac_id = passocsta_rsp->cam_id; | |
1533 | ||
1534 | spin_lock_bh(&pmlmepriv->lock); | |
1535 | ||
f2f97035 JS |
1536 | if (check_fwstate(pmlmepriv, WIFI_MP_STATE) && |
1537 | check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) | |
5e93f352 LF |
1538 | _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); |
1539 | ||
1540 | set_fwstate(pmlmepriv, _FW_LINKED); | |
1541 | spin_unlock_bh(&pmlmepriv->lock); | |
1542 | ||
1543 | exit: | |
1544 | rtw_free_cmd_obj23a(pcmd); | |
1545 | } |