GNU Linux-libre 4.19.304-gnu1
[releases.git] / drivers / staging / rtl8723bs / core / rtw_cmd.c
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 #define _RTW_CMD_C_
8
9 #include <drv_types.h>
10 #include <rtw_debug.h>
11 #include <linux/jiffies.h>
12
13 static struct _cmd_callback rtw_cmd_callback[] = {
14         {GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/
15         {GEN_CMD_CODE(_Write_MACREG), NULL},
16         {GEN_CMD_CODE(_Read_BBREG), &rtw_getbbrfreg_cmdrsp_callback},
17         {GEN_CMD_CODE(_Write_BBREG), NULL},
18         {GEN_CMD_CODE(_Read_RFREG), &rtw_getbbrfreg_cmdrsp_callback},
19         {GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/
20         {GEN_CMD_CODE(_Read_EEPROM), NULL},
21         {GEN_CMD_CODE(_Write_EEPROM), NULL},
22         {GEN_CMD_CODE(_Read_EFUSE), NULL},
23         {GEN_CMD_CODE(_Write_EFUSE), NULL},
24
25         {GEN_CMD_CODE(_Read_CAM),       NULL},  /*10*/
26         {GEN_CMD_CODE(_Write_CAM),       NULL},
27         {GEN_CMD_CODE(_setBCNITV), NULL},
28         {GEN_CMD_CODE(_setMBIDCFG), NULL},
29         {GEN_CMD_CODE(_JoinBss), &rtw_joinbss_cmd_callback},  /*14*/
30         {GEN_CMD_CODE(_DisConnect), &rtw_disassoc_cmd_callback}, /*15*/
31         {GEN_CMD_CODE(_CreateBss), &rtw_createbss_cmd_callback},
32         {GEN_CMD_CODE(_SetOpMode), NULL},
33         {GEN_CMD_CODE(_SiteSurvey), &rtw_survey_cmd_callback}, /*18*/
34         {GEN_CMD_CODE(_SetAuth), NULL},
35
36         {GEN_CMD_CODE(_SetKey), NULL},  /*20*/
37         {GEN_CMD_CODE(_SetStaKey), &rtw_setstaKey_cmdrsp_callback},
38         {GEN_CMD_CODE(_SetAssocSta), &rtw_setassocsta_cmdrsp_callback},
39         {GEN_CMD_CODE(_DelAssocSta), NULL},
40         {GEN_CMD_CODE(_SetStaPwrState), NULL},
41         {GEN_CMD_CODE(_SetBasicRate), NULL}, /*25*/
42         {GEN_CMD_CODE(_GetBasicRate), NULL},
43         {GEN_CMD_CODE(_SetDataRate), NULL},
44         {GEN_CMD_CODE(_GetDataRate), NULL},
45         {GEN_CMD_CODE(_SetPhyInfo), NULL},
46
47         {GEN_CMD_CODE(_GetPhyInfo), NULL}, /*30*/
48         {GEN_CMD_CODE(_SetPhy), NULL},
49         {GEN_CMD_CODE(_GetPhy), NULL},
50         {GEN_CMD_CODE(_readRssi), NULL},
51         {GEN_CMD_CODE(_readGain), NULL},
52         {GEN_CMD_CODE(_SetAtim), NULL}, /*35*/
53         {GEN_CMD_CODE(_SetPwrMode), NULL},
54         {GEN_CMD_CODE(_JoinbssRpt), NULL},
55         {GEN_CMD_CODE(_SetRaTable), NULL},
56         {GEN_CMD_CODE(_GetRaTable), NULL},
57
58         {GEN_CMD_CODE(_GetCCXReport), NULL}, /*40*/
59         {GEN_CMD_CODE(_GetDTMReport),   NULL},
60         {GEN_CMD_CODE(_GetTXRateStatistics), NULL},
61         {GEN_CMD_CODE(_SetUsbSuspend), NULL},
62         {GEN_CMD_CODE(_SetH2cLbk), NULL},
63         {GEN_CMD_CODE(_AddBAReq), NULL}, /*45*/
64         {GEN_CMD_CODE(_SetChannel), NULL},              /*46*/
65         {GEN_CMD_CODE(_SetTxPower), NULL},
66         {GEN_CMD_CODE(_SwitchAntenna), NULL},
67         {GEN_CMD_CODE(_SetCrystalCap), NULL},
68         {GEN_CMD_CODE(_SetSingleCarrierTx), NULL},      /*50*/
69
70         {GEN_CMD_CODE(_SetSingleToneTx), NULL}, /*51*/
71         {GEN_CMD_CODE(_SetCarrierSuppressionTx), NULL},
72         {GEN_CMD_CODE(_SetContinuousTx), NULL},
73         {GEN_CMD_CODE(_SwitchBandwidth), NULL},         /*54*/
74         {GEN_CMD_CODE(_TX_Beacon), NULL},/*55*/
75
76         {GEN_CMD_CODE(_Set_MLME_EVT), NULL},/*56*/
77         {GEN_CMD_CODE(_Set_Drv_Extra), NULL},/*57*/
78         {GEN_CMD_CODE(_Set_H2C_MSG), NULL},/*58*/
79         {GEN_CMD_CODE(_SetChannelPlan), NULL},/*59*/
80         {GEN_CMD_CODE(_LedBlink), NULL},/*60*/
81
82         {GEN_CMD_CODE(_SetChannelSwitch), NULL},/*61*/
83         {GEN_CMD_CODE(_TDLS), NULL},/*62*/
84         {GEN_CMD_CODE(_ChkBMCSleepq), NULL}, /*63*/
85
86         {GEN_CMD_CODE(_RunInThreadCMD), NULL},/*64*/
87 };
88
89 static struct cmd_hdl wlancmds[] = {
90         GEN_DRV_CMD_HANDLER(0, NULL) /*0*/
91         GEN_DRV_CMD_HANDLER(0, NULL)
92         GEN_DRV_CMD_HANDLER(0, NULL)
93         GEN_DRV_CMD_HANDLER(0, NULL)
94         GEN_DRV_CMD_HANDLER(0, NULL)
95         GEN_DRV_CMD_HANDLER(0, NULL)
96         GEN_MLME_EXT_HANDLER(0, NULL)
97         GEN_MLME_EXT_HANDLER(0, NULL)
98         GEN_MLME_EXT_HANDLER(0, NULL)
99         GEN_MLME_EXT_HANDLER(0, NULL)
100         GEN_MLME_EXT_HANDLER(0, NULL) /*10*/
101         GEN_MLME_EXT_HANDLER(0, NULL)
102         GEN_MLME_EXT_HANDLER(0, NULL)
103         GEN_MLME_EXT_HANDLER(0, NULL)
104         GEN_MLME_EXT_HANDLER(sizeof(struct joinbss_parm), join_cmd_hdl) /*14*/
105         GEN_MLME_EXT_HANDLER(sizeof(struct disconnect_parm), disconnect_hdl)
106         GEN_MLME_EXT_HANDLER(sizeof(struct createbss_parm), createbss_hdl)
107         GEN_MLME_EXT_HANDLER(sizeof(struct setopmode_parm), setopmode_hdl)
108         GEN_MLME_EXT_HANDLER(sizeof(struct sitesurvey_parm), sitesurvey_cmd_hdl) /*18*/
109         GEN_MLME_EXT_HANDLER(sizeof(struct setauth_parm), setauth_hdl)
110         GEN_MLME_EXT_HANDLER(sizeof(struct setkey_parm), setkey_hdl) /*20*/
111         GEN_MLME_EXT_HANDLER(sizeof(struct set_stakey_parm), set_stakey_hdl)
112         GEN_MLME_EXT_HANDLER(sizeof(struct set_assocsta_parm), NULL)
113         GEN_MLME_EXT_HANDLER(sizeof(struct del_assocsta_parm), NULL)
114         GEN_MLME_EXT_HANDLER(sizeof(struct setstapwrstate_parm), NULL)
115         GEN_MLME_EXT_HANDLER(sizeof(struct setbasicrate_parm), NULL)
116         GEN_MLME_EXT_HANDLER(sizeof(struct getbasicrate_parm), NULL)
117         GEN_MLME_EXT_HANDLER(sizeof(struct setdatarate_parm), NULL)
118         GEN_MLME_EXT_HANDLER(sizeof(struct getdatarate_parm), NULL)
119         GEN_MLME_EXT_HANDLER(sizeof(struct setphyinfo_parm), NULL)
120         GEN_MLME_EXT_HANDLER(sizeof(struct getphyinfo_parm), NULL)  /*30*/
121         GEN_MLME_EXT_HANDLER(sizeof(struct setphy_parm), NULL)
122         GEN_MLME_EXT_HANDLER(sizeof(struct getphy_parm), NULL)
123         GEN_MLME_EXT_HANDLER(0, NULL)
124         GEN_MLME_EXT_HANDLER(0, NULL)
125         GEN_MLME_EXT_HANDLER(0, NULL)
126         GEN_MLME_EXT_HANDLER(0, NULL)
127         GEN_MLME_EXT_HANDLER(0, NULL)
128         GEN_MLME_EXT_HANDLER(0, NULL)
129         GEN_MLME_EXT_HANDLER(0, NULL)
130         GEN_MLME_EXT_HANDLER(0, NULL)   /*40*/
131         GEN_MLME_EXT_HANDLER(0, NULL)
132         GEN_MLME_EXT_HANDLER(0, NULL)
133         GEN_MLME_EXT_HANDLER(0, NULL)
134         GEN_MLME_EXT_HANDLER(0, NULL)
135         GEN_MLME_EXT_HANDLER(sizeof(struct addBaReq_parm), add_ba_hdl)
136         GEN_MLME_EXT_HANDLER(sizeof(struct set_ch_parm), set_ch_hdl) /* 46 */
137         GEN_MLME_EXT_HANDLER(0, NULL)
138         GEN_MLME_EXT_HANDLER(0, NULL)
139         GEN_MLME_EXT_HANDLER(0, NULL)
140         GEN_MLME_EXT_HANDLER(0, NULL) /*50*/
141         GEN_MLME_EXT_HANDLER(0, NULL)
142         GEN_MLME_EXT_HANDLER(0, NULL)
143         GEN_MLME_EXT_HANDLER(0, NULL)
144         GEN_MLME_EXT_HANDLER(0, NULL)
145         GEN_MLME_EXT_HANDLER(sizeof(struct Tx_Beacon_param), tx_beacon_hdl) /*55*/
146
147         GEN_MLME_EXT_HANDLER(0, mlme_evt_hdl) /*56*/
148         GEN_MLME_EXT_HANDLER(0, rtw_drvextra_cmd_hdl) /*57*/
149
150         GEN_MLME_EXT_HANDLER(0, h2c_msg_hdl) /*58*/
151         GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelPlan_param), set_chplan_hdl) /*59*/
152         GEN_MLME_EXT_HANDLER(sizeof(struct LedBlink_param), led_blink_hdl) /*60*/
153
154         GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelSwitch_param), set_csa_hdl) /*61*/
155         GEN_MLME_EXT_HANDLER(sizeof(struct TDLSoption_param), tdls_hdl) /*62*/
156         GEN_MLME_EXT_HANDLER(0, chk_bmc_sleepq_hdl) /*63*/
157         GEN_MLME_EXT_HANDLER(sizeof(struct RunInThread_param), run_in_thread_hdl) /*63*/
158 };
159
160 /*
161 Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.
162 No irqsave is necessary.
163 */
164
165 sint    _rtw_init_cmd_priv(struct       cmd_priv *pcmdpriv)
166 {
167         sint res = _SUCCESS;
168
169         sema_init(&(pcmdpriv->cmd_queue_sema), 0);
170         /* sema_init(&(pcmdpriv->cmd_done_sema), 0); */
171         sema_init(&(pcmdpriv->terminate_cmdthread_sema), 0);
172
173
174         _rtw_init_queue(&(pcmdpriv->cmd_queue));
175
176         /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
177
178         pcmdpriv->cmd_seq = 1;
179
180         pcmdpriv->cmd_allocated_buf = rtw_zmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ);
181
182         if (pcmdpriv->cmd_allocated_buf == NULL) {
183                 res = _FAIL;
184                 goto exit;
185         }
186
187         pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf  +  CMDBUFF_ALIGN_SZ - ((SIZE_PTR)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ-1));
188
189         pcmdpriv->rsp_allocated_buf = rtw_zmalloc(MAX_RSPSZ + 4);
190
191         if (pcmdpriv->rsp_allocated_buf == NULL) {
192                 res = _FAIL;
193                 goto exit;
194         }
195
196         pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf  +  4 - ((SIZE_PTR)(pcmdpriv->rsp_allocated_buf) & 3);
197
198         pcmdpriv->cmd_issued_cnt = pcmdpriv->cmd_done_cnt = pcmdpriv->rsp_cnt = 0;
199
200         mutex_init(&pcmdpriv->sctx_mutex);
201 exit:
202         return res;
203 }
204
205 static void c2h_wk_callback(_workitem *work);
206 sint _rtw_init_evt_priv(struct evt_priv *pevtpriv)
207 {
208         sint res = _SUCCESS;
209
210         /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
211         atomic_set(&pevtpriv->event_seq, 0);
212         pevtpriv->evt_done_cnt = 0;
213
214         _init_workitem(&pevtpriv->c2h_wk, c2h_wk_callback, NULL);
215         pevtpriv->c2h_wk_alive = false;
216         pevtpriv->c2h_queue = rtw_cbuf_alloc(C2H_QUEUE_MAX_LEN+1);
217
218         return res;
219 }
220
221 void _rtw_free_evt_priv(struct  evt_priv *pevtpriv)
222 {
223         RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+_rtw_free_evt_priv\n"));
224
225         _cancel_workitem_sync(&pevtpriv->c2h_wk);
226         while (pevtpriv->c2h_wk_alive)
227                 msleep(10);
228
229         while (!rtw_cbuf_empty(pevtpriv->c2h_queue)) {
230                 void *c2h = rtw_cbuf_pop(pevtpriv->c2h_queue);
231                 if (c2h != NULL && c2h != (void *)pevtpriv) {
232                         kfree(c2h);
233                 }
234         }
235         kfree(pevtpriv->c2h_queue);
236
237         RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("-_rtw_free_evt_priv\n"));
238 }
239
240 void _rtw_free_cmd_priv(struct  cmd_priv *pcmdpriv)
241 {
242         if (pcmdpriv) {
243                 kfree(pcmdpriv->cmd_allocated_buf);
244
245                 kfree(pcmdpriv->rsp_allocated_buf);
246
247                 mutex_destroy(&pcmdpriv->sctx_mutex);
248         }
249 }
250
251 /*
252 Calling Context:
253
254 rtw_enqueue_cmd can only be called between kernel thread,
255 since only spin_lock is used.
256
257 ISR/Call-Back functions can't call this sub-function.
258
259 */
260
261 sint    _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
262 {
263         _irqL irqL;
264
265         if (obj == NULL)
266                 goto exit;
267
268         /* spin_lock_bh(&queue->lock); */
269         spin_lock_irqsave(&queue->lock, irqL);
270
271         list_add_tail(&obj->list, &queue->queue);
272
273         /* spin_unlock_bh(&queue->lock); */
274         spin_unlock_irqrestore(&queue->lock, irqL);
275
276 exit:
277         return _SUCCESS;
278 }
279
280 struct  cmd_obj *_rtw_dequeue_cmd(struct __queue *queue)
281 {
282         _irqL irqL;
283         struct cmd_obj *obj;
284
285         /* spin_lock_bh(&(queue->lock)); */
286         spin_lock_irqsave(&queue->lock, irqL);
287         if (list_empty(&(queue->queue)))
288                 obj = NULL;
289         else{
290                 obj = LIST_CONTAINOR(get_next(&(queue->queue)), struct cmd_obj, list);
291                 list_del_init(&obj->list);
292         }
293
294         /* spin_unlock_bh(&(queue->lock)); */
295         spin_unlock_irqrestore(&queue->lock, irqL);
296
297         return obj;
298 }
299
300 u32 rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
301 {
302         u32 res;
303
304         res = _rtw_init_cmd_priv(pcmdpriv);
305         return res;
306 }
307
308 u32 rtw_init_evt_priv(struct    evt_priv *pevtpriv)
309 {
310         int     res;
311
312         res = _rtw_init_evt_priv(pevtpriv);
313         return res;
314 }
315
316 void rtw_free_evt_priv(struct   evt_priv *pevtpriv)
317 {
318         RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("rtw_free_evt_priv\n"));
319         _rtw_free_evt_priv(pevtpriv);
320 }
321
322 void rtw_free_cmd_priv(struct   cmd_priv *pcmdpriv)
323 {
324         RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("rtw_free_cmd_priv\n"));
325         _rtw_free_cmd_priv(pcmdpriv);
326 }
327
328 int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj);
329 int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
330 {
331         u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */
332
333         if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan))
334                 bAllow = true;
335
336         if ((pcmdpriv->padapter->hw_init_completed == false && bAllow == false)
337                 || atomic_read(&(pcmdpriv->cmdthd_running)) == false    /* com_thread not running */
338         ) {
339                 /* DBG_871X("%s:%s: drop cmdcode:%u, hw_init_completed:%u, cmdthd_running:%u\n", caller_func, __func__, */
340                 /*      cmd_obj->cmdcode, */
341                 /*      pcmdpriv->padapter->hw_init_completed, */
342                 /*      pcmdpriv->cmdthd_running */
343                 /*  */
344
345                 return _FAIL;
346         }
347         return _SUCCESS;
348 }
349
350
351
352 u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
353 {
354         int res = _FAIL;
355         struct adapter *padapter = pcmdpriv->padapter;
356
357         if (cmd_obj == NULL) {
358                 goto exit;
359         }
360
361         cmd_obj->padapter = padapter;
362
363         res = rtw_cmd_filter(pcmdpriv, cmd_obj);
364         if (_FAIL == res) {
365                 rtw_free_cmd_obj(cmd_obj);
366                 goto exit;
367         }
368
369         res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj);
370
371         if (res == _SUCCESS)
372                 up(&pcmdpriv->cmd_queue_sema);
373
374 exit:
375         return res;
376 }
377
378 struct  cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv)
379 {
380         struct cmd_obj *cmd_obj;
381
382         cmd_obj = _rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
383
384         return cmd_obj;
385 }
386
387 void rtw_free_cmd_obj(struct cmd_obj *pcmd)
388 {
389         if ((pcmd->cmdcode != _JoinBss_CMD_) &&
390             (pcmd->cmdcode != _CreateBss_CMD_)) {
391                 /* free parmbuf in cmd_obj */
392                 kfree((unsigned char *)pcmd->parmbuf);
393         }
394
395         if (pcmd->rsp != NULL) {
396                 if (pcmd->rspsz != 0) {
397                         /* free rsp in cmd_obj */
398                         kfree((unsigned char *)pcmd->rsp);
399                 }
400         }
401
402         /* free cmd_obj */
403         kfree(pcmd);
404 }
405
406
407 void rtw_stop_cmd_thread(struct adapter *adapter)
408 {
409         if (adapter->cmdThread &&
410                 atomic_read(&(adapter->cmdpriv.cmdthd_running)) == true &&
411                 adapter->cmdpriv.stop_req == 0) {
412                 adapter->cmdpriv.stop_req = 1;
413                 up(&adapter->cmdpriv.cmd_queue_sema);
414                 down(&adapter->cmdpriv.terminate_cmdthread_sema);
415         }
416 }
417
418 int rtw_cmd_thread(void *context)
419 {
420         u8 ret;
421         struct cmd_obj *pcmd;
422         u8 *pcmdbuf, *prspbuf;
423         unsigned long cmd_start_time;
424         unsigned long cmd_process_time;
425         u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf);
426         void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd);
427         struct adapter *padapter = context;
428         struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
429         struct drvextra_cmd_parm *extra_parm = NULL;
430
431         thread_enter("RTW_CMD_THREAD");
432
433         pcmdbuf = pcmdpriv->cmd_buf;
434         prspbuf = pcmdpriv->rsp_buf;
435
436         pcmdpriv->stop_req = 0;
437         atomic_set(&(pcmdpriv->cmdthd_running), true);
438         up(&pcmdpriv->terminate_cmdthread_sema);
439
440         RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("start r871x rtw_cmd_thread !!!!\n"));
441
442         while (1) {
443                 if (down_interruptible(&pcmdpriv->cmd_queue_sema)) {
444                         DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" down_interruptible(&pcmdpriv->cmd_queue_sema) return != 0, break\n", FUNC_ADPT_ARG(padapter));
445                         break;
446                 }
447
448                 if ((padapter->bDriverStopped == true) || (padapter->bSurpriseRemoved == true)) {
449                         DBG_871X_LEVEL(_drv_always_, "%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n",
450                                 __func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__);
451                         break;
452                 }
453
454                 if (pcmdpriv->stop_req) {
455                         DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" stop_req:%u, break\n", FUNC_ADPT_ARG(padapter), pcmdpriv->stop_req);
456                         break;
457                 }
458
459                 if (list_empty(&(pcmdpriv->cmd_queue.queue))) {
460                         /* DBG_871X("%s: cmd queue is empty!\n", __func__); */
461                         continue;
462                 }
463
464                 if (rtw_register_cmd_alive(padapter) != _SUCCESS) {
465                         RT_TRACE(_module_hal_xmit_c_, _drv_notice_,
466                                          ("%s: wait to leave LPS_LCLK\n", __func__));
467                         continue;
468                 }
469
470 _next:
471                 if ((padapter->bDriverStopped == true) || (padapter->bSurpriseRemoved == true)) {
472                         DBG_871X_LEVEL(_drv_always_, "%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n",
473                                 __func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__);
474                         break;
475                 }
476
477                 pcmd = rtw_dequeue_cmd(pcmdpriv);
478                 if (!pcmd) {
479                         rtw_unregister_cmd_alive(padapter);
480                         continue;
481                 }
482
483                 cmd_start_time = jiffies;
484
485                 if (_FAIL == rtw_cmd_filter(pcmdpriv, pcmd)) {
486                         pcmd->res = H2C_DROPPED;
487                         goto post_process;
488                 }
489
490                 pcmdpriv->cmd_issued_cnt++;
491
492                 pcmd->cmdsz = _RND4((pcmd->cmdsz));/* _RND4 */
493
494                 memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
495
496                 if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) {
497                         cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
498
499                         if (cmd_hdl) {
500                                 ret = cmd_hdl(pcmd->padapter, pcmdbuf);
501                                 pcmd->res = ret;
502                         }
503
504                         pcmdpriv->cmd_seq++;
505                 } else{
506                         pcmd->res = H2C_PARAMETERS_ERROR;
507                 }
508
509                 cmd_hdl = NULL;
510
511 post_process:
512
513                 if (mutex_lock_interruptible(&(pcmd->padapter->cmdpriv.sctx_mutex)) == 0) {
514                         if (pcmd->sctx) {
515                                 DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" pcmd->sctx\n",
516                                                FUNC_ADPT_ARG(pcmd->padapter));
517
518                                 if (pcmd->res == H2C_SUCCESS)
519                                         rtw_sctx_done(&pcmd->sctx);
520                                 else
521                                         rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_ERROR);
522                         }
523                         mutex_unlock(&(pcmd->padapter->cmdpriv.sctx_mutex));
524                 }
525
526                 cmd_process_time = jiffies_to_msecs(jiffies - cmd_start_time);
527                 if (cmd_process_time > 1000) {
528                         if (pcmd->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
529                                 DBG_871X(ADPT_FMT" cmd =%d process_time =%lu > 1 sec\n",
530                                         ADPT_ARG(pcmd->padapter), pcmd->cmdcode, cmd_process_time);
531                                 /* rtw_warn_on(1); */
532                         } else if (pcmd->cmdcode == GEN_CMD_CODE(_Set_MLME_EVT)) {
533                                 DBG_871X(ADPT_FMT" cmd =%d, process_time =%lu > 1 sec\n",
534                                         ADPT_ARG(pcmd->padapter), pcmd->cmdcode, cmd_process_time);
535                                 /* rtw_warn_on(1); */
536                         } else {
537                                 DBG_871X(ADPT_FMT" cmd =%d, process_time =%lu > 1 sec\n",
538                                         ADPT_ARG(pcmd->padapter), pcmd->cmdcode, cmd_process_time);
539                                 /* rtw_warn_on(1); */
540                         }
541                 }
542
543                 /* call callback function for post-processed */
544                 if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) {
545                         pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
546                         if (pcmd_callback == NULL) {
547                                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("mlme_cmd_hdl(): pcmd_callback = 0x%p, cmdcode = 0x%x\n", pcmd_callback, pcmd->cmdcode));
548                                 rtw_free_cmd_obj(pcmd);
549                         } else{
550                                 /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */
551                                 pcmd_callback(pcmd->padapter, pcmd);/* need conider that free cmd_obj in rtw_cmd_callback */
552                         }
553                 } else{
554                         RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("%s: cmdcode = 0x%x callback not defined!\n", __func__, pcmd->cmdcode));
555                         rtw_free_cmd_obj(pcmd);
556                 }
557
558                 flush_signals_thread();
559
560                 goto _next;
561
562         }
563
564         /*  free all cmd_obj resources */
565         do {
566                 pcmd = rtw_dequeue_cmd(pcmdpriv);
567                 if (pcmd == NULL) {
568                         rtw_unregister_cmd_alive(padapter);
569                         break;
570                 }
571
572                 /* DBG_871X("%s: leaving... drop cmdcode:%u size:%d\n", __func__, pcmd->cmdcode, pcmd->cmdsz); */
573
574                 if (pcmd->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
575                         extra_parm = (struct drvextra_cmd_parm *)pcmd->parmbuf;
576                         if (extra_parm->pbuf && extra_parm->size > 0) {
577                                 kfree(extra_parm->pbuf);
578                         }
579                 }
580
581                 rtw_free_cmd_obj(pcmd);
582         } while (1);
583
584         up(&pcmdpriv->terminate_cmdthread_sema);
585         atomic_set(&(pcmdpriv->cmdthd_running), false);
586
587         thread_exit();
588 }
589
590 /*
591 rtw_sitesurvey_cmd(~)
592         ### NOTE:#### (!!!!)
593         MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock
594 */
595 u8 rtw_sitesurvey_cmd(struct adapter  *padapter, struct ndis_802_11_ssid *ssid, int ssid_num,
596         struct rtw_ieee80211_channel *ch, int ch_num)
597 {
598         u8 res = _FAIL;
599         struct cmd_obj          *ph2c;
600         struct sitesurvey_parm  *psurveyPara;
601         struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
602         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
603
604         if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
605                 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1);
606         }
607
608         ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
609         if (ph2c == NULL)
610                 return _FAIL;
611
612         psurveyPara = rtw_zmalloc(sizeof(struct sitesurvey_parm));
613         if (psurveyPara == NULL) {
614                 kfree(ph2c);
615                 return _FAIL;
616         }
617
618         rtw_free_network_queue(padapter, false);
619
620         RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("%s: flush network queue\n", __func__));
621
622         init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
623
624         /* psurveyPara->bsslimit = 48; */
625         psurveyPara->scan_mode = pmlmepriv->scan_mode;
626
627         /* prepare ssid list */
628         if (ssid) {
629                 int i;
630                 for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {
631                         if (ssid[i].SsidLength) {
632                                 memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid));
633                                 psurveyPara->ssid_num++;
634
635                                 DBG_871X(FUNC_ADPT_FMT" ssid:(%s, %d)\n", FUNC_ADPT_ARG(padapter),
636                                         psurveyPara->ssid[i].Ssid, psurveyPara->ssid[i].SsidLength);
637                         }
638                 }
639         }
640
641         /* prepare channel list */
642         if (ch) {
643                 int i;
644                 for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
645                         if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) {
646                                 memcpy(&psurveyPara->ch[i], &ch[i], sizeof(struct rtw_ieee80211_channel));
647                                 psurveyPara->ch_num++;
648
649                                 DBG_871X(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter),
650                                         psurveyPara->ch[i].hw_value);
651                         }
652                 }
653         }
654
655         set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
656
657         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
658
659         if (res == _SUCCESS) {
660
661                 pmlmepriv->scan_start_time = jiffies;
662                 _set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT);
663         } else {
664                 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
665         }
666         return res;
667 }
668
669 u8 rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset)
670 {
671         struct cmd_obj *ph2c;
672         struct setdatarate_parm *pbsetdataratepara;
673         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
674         u8 res = _SUCCESS;
675
676         ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
677         if (ph2c == NULL) {
678                 res = _FAIL;
679                 goto exit;
680         }
681
682         pbsetdataratepara = rtw_zmalloc(sizeof(struct setdatarate_parm));
683         if (pbsetdataratepara == NULL) {
684                 kfree(ph2c);
685                 res = _FAIL;
686                 goto exit;
687         }
688
689         init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, GEN_CMD_CODE(_SetDataRate));
690         pbsetdataratepara->mac_id = 5;
691         memcpy(pbsetdataratepara->datarates, rateset, NumRates);
692
693         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
694 exit:
695         return res;
696 }
697
698 void rtw_getbbrfreg_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
699 {
700         /* rtw_free_cmd_obj(pcmd); */
701         kfree(pcmd->parmbuf);
702         kfree(pcmd);
703 }
704
705 u8 rtw_createbss_cmd(struct adapter  *padapter)
706 {
707         struct cmd_obj *pcmd;
708         struct cmd_priv                         *pcmdpriv = &padapter->cmdpriv;
709         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
710         struct wlan_bssid_ex            *pdev_network = &padapter->registrypriv.dev_network;
711         u8 res = _SUCCESS;
712
713         if (pmlmepriv->assoc_ssid.SsidLength == 0) {
714                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for Any SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
715         } else {
716                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
717         }
718
719         pcmd = rtw_zmalloc(sizeof(struct cmd_obj));
720         if (pcmd == NULL) {
721                 res = _FAIL;
722                 goto exit;
723         }
724
725         INIT_LIST_HEAD(&pcmd->list);
726         pcmd->cmdcode = _CreateBss_CMD_;
727         pcmd->parmbuf = (unsigned char *)pdev_network;
728         pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
729         pcmd->rsp = NULL;
730         pcmd->rspsz = 0;
731
732         pdev_network->Length = pcmd->cmdsz;
733
734         res = rtw_enqueue_cmd(pcmdpriv, pcmd);
735
736 exit:
737         return res;
738 }
739
740 u8 rtw_startbss_cmd(struct adapter  *padapter, int flags)
741 {
742         struct cmd_obj *pcmd;
743         struct cmd_priv  *pcmdpriv = &padapter->cmdpriv;
744         struct submit_ctx sctx;
745         u8 res = _SUCCESS;
746
747         if (flags & RTW_CMDF_DIRECTLY) {
748                 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
749                 start_bss_network(padapter, (u8 *)&(padapter->mlmepriv.cur_network.network));
750         } else {
751                 /* need enqueue, prepare cmd_obj and enqueue */
752                 pcmd = rtw_zmalloc(sizeof(struct cmd_obj));
753                 if (pcmd == NULL) {
754                         res = _FAIL;
755                         goto exit;
756                 }
757
758                 INIT_LIST_HEAD(&pcmd->list);
759                 pcmd->cmdcode = GEN_CMD_CODE(_CreateBss);
760                 pcmd->parmbuf = NULL;
761                 pcmd->cmdsz =  0;
762                 pcmd->rsp = NULL;
763                 pcmd->rspsz = 0;
764
765                 if (flags & RTW_CMDF_WAIT_ACK) {
766                         pcmd->sctx = &sctx;
767                         rtw_sctx_init(&sctx, 2000);
768                 }
769
770                 res = rtw_enqueue_cmd(pcmdpriv, pcmd);
771
772                 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
773                         rtw_sctx_wait(&sctx, __func__);
774                         if (mutex_lock_interruptible(&pcmdpriv->sctx_mutex) == 0) {
775                                 if (sctx.status == RTW_SCTX_SUBMITTED)
776                                         pcmd->sctx = NULL;
777                                 mutex_unlock(&pcmdpriv->sctx_mutex);
778                         }
779                 }
780         }
781
782 exit:
783         return res;
784 }
785
786 u8 rtw_joinbss_cmd(struct adapter  *padapter, struct wlan_network *pnetwork)
787 {
788         u8 *auth, res = _SUCCESS;
789         uint    t_len = 0;
790         struct wlan_bssid_ex            *psecnetwork;
791         struct cmd_obj          *pcmd;
792         struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
793         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
794         struct qos_priv         *pqospriv = &pmlmepriv->qospriv;
795         struct security_priv *psecuritypriv = &padapter->securitypriv;
796         struct registry_priv *pregistrypriv = &padapter->registrypriv;
797         struct ht_priv          *phtpriv = &pmlmepriv->htpriv;
798         enum NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = pnetwork->network.InfrastructureMode;
799         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
800         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
801         u32 tmp_len;
802         u8 *ptmp = NULL;
803
804         if (pmlmepriv->assoc_ssid.SsidLength == 0) {
805                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+Join cmd: Any SSid\n"));
806         } else {
807                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+Join cmd: SSid =[%s]\n", pmlmepriv->assoc_ssid.Ssid));
808         }
809
810         pcmd = rtw_zmalloc(sizeof(struct cmd_obj));
811         if (pcmd == NULL) {
812                 res = _FAIL;
813                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd: memory allocate for cmd_obj fail!!!\n"));
814                 goto exit;
815         }
816         /* for IEs is fix buf size */
817         t_len = sizeof(struct wlan_bssid_ex);
818
819
820         /* for hidden ap to set fw_state here */
821         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) != true) {
822                 switch (ndis_network_mode) {
823                 case Ndis802_11IBSS:
824                         set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
825                         break;
826
827                 case Ndis802_11Infrastructure:
828                         set_fwstate(pmlmepriv, WIFI_STATION_STATE);
829                         break;
830
831                 case Ndis802_11APMode:
832                 case Ndis802_11AutoUnknown:
833                 case Ndis802_11InfrastructureMax:
834                         break;
835
836                 }
837         }
838
839         psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss;
840         if (psecnetwork == NULL) {
841                 kfree(pcmd);
842                 res = _FAIL;
843
844                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd :psecnetwork == NULL!!!\n"));
845
846                 goto exit;
847         }
848
849         memset(psecnetwork, 0, t_len);
850
851         memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network));
852
853         auth = &psecuritypriv->authenticator_ie[0];
854         psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength;
855
856         if ((psecnetwork->IELength-12) < (256-1)) {
857                 memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength-12);
858         } else {
859                 memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256-1));
860         }
861
862         psecnetwork->IELength = 0;
863         /*  Added by Albert 2009/02/18 */
864         /*  If the the driver wants to use the bssid to create the connection. */
865         /*  If not,  we have to copy the connecting AP's MAC address to it so that */
866         /*  the driver just has the bssid information for PMKIDList searching. */
867
868         if (pmlmepriv->assoc_by_bssid == false) {
869                 memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
870         }
871
872         psecnetwork->IELength = rtw_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength);
873
874
875         pqospriv->qos_option = 0;
876
877         if (pregistrypriv->wmm_enable) {
878                 tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength);
879
880                 if (psecnetwork->IELength != tmp_len) {
881                         psecnetwork->IELength = tmp_len;
882                         pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
883                 } else{
884                         pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
885                 }
886         }
887
888         phtpriv->ht_option = false;
889         ptmp = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &tmp_len, pnetwork->network.IELength-12);
890         if (pregistrypriv->ht_enable && ptmp && tmp_len > 0) {
891                 /*      Added by Albert 2010/06/23 */
892                 /*      For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */
893                 /*      Especially for Realtek 8192u SoftAP. */
894                 if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
895                         (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
896                         (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
897                         rtw_ht_use_default_setting(padapter);
898
899                         rtw_build_wmm_ie_ht(padapter, &psecnetwork->IEs[12], &psecnetwork->IELength);
900
901                         /* rtw_restructure_ht_ie */
902                         rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[12], &psecnetwork->IEs[0],
903                                                                         pnetwork->network.IELength-12, &psecnetwork->IELength,
904                                                                         pnetwork->network.Configuration.DSConfig);
905                 }
906         }
907
908         rtw_append_exented_cap(padapter, &psecnetwork->IEs[0], &psecnetwork->IELength);
909
910         pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength);
911
912         pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */
913
914         INIT_LIST_HEAD(&pcmd->list);
915         pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */
916         pcmd->parmbuf = (unsigned char *)psecnetwork;
917         pcmd->rsp = NULL;
918         pcmd->rspsz = 0;
919
920         res = rtw_enqueue_cmd(pcmdpriv, pcmd);
921
922 exit:
923         return res;
924 }
925
926 u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */
927 {
928         struct cmd_obj *cmdobj = NULL;
929         struct disconnect_parm *param = NULL;
930         struct cmd_priv *cmdpriv = &padapter->cmdpriv;
931         u8 res = _SUCCESS;
932
933         RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_disassoc_cmd\n"));
934
935         /* prepare cmd parameter */
936         param = rtw_zmalloc(sizeof(*param));
937         if (param == NULL) {
938                 res = _FAIL;
939                 goto exit;
940         }
941         param->deauth_timeout_ms = deauth_timeout_ms;
942
943         if (enqueue) {
944                 /* need enqueue, prepare cmd_obj and enqueue */
945                 cmdobj = rtw_zmalloc(sizeof(*cmdobj));
946                 if (cmdobj == NULL) {
947                         res = _FAIL;
948                         kfree(param);
949                         goto exit;
950                 }
951                 init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
952                 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
953         } else {
954                 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
955                 if (H2C_SUCCESS != disconnect_hdl(padapter, (u8 *)param))
956                         res = _FAIL;
957                 kfree(param);
958         }
959
960 exit:
961         return res;
962 }
963
964 u8 rtw_setopmode_cmd(struct adapter  *padapter, enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype, bool enqueue)
965 {
966         struct  cmd_obj *ph2c;
967         struct  setopmode_parm *psetop;
968
969         struct  cmd_priv   *pcmdpriv = &padapter->cmdpriv;
970         u8 res = _SUCCESS;
971
972         psetop = rtw_zmalloc(sizeof(struct setopmode_parm));
973
974         if (psetop == NULL) {
975                 res = _FAIL;
976                 goto exit;
977         }
978         psetop->mode = (u8)networktype;
979
980         if (enqueue) {
981                 ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
982                 if (ph2c == NULL) {
983                         kfree(psetop);
984                         res = _FAIL;
985                         goto exit;
986                 }
987
988                 init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
989                 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
990         } else{
991                 setopmode_hdl(padapter, (u8 *)psetop);
992                 kfree(psetop);
993         }
994 exit:
995         return res;
996 }
997
998 u8 rtw_setstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 unicast_key, bool enqueue)
999 {
1000         struct cmd_obj *ph2c;
1001         struct set_stakey_parm  *psetstakey_para;
1002         struct cmd_priv                         *pcmdpriv = &padapter->cmdpriv;
1003         struct set_stakey_rsp           *psetstakey_rsp = NULL;
1004
1005         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
1006         struct security_priv    *psecuritypriv = &padapter->securitypriv;
1007         u8 res = _SUCCESS;
1008
1009         psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm));
1010         if (psetstakey_para == NULL) {
1011                 res = _FAIL;
1012                 goto exit;
1013         }
1014
1015         memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN);
1016
1017         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
1018                 psetstakey_para->algorithm = (unsigned char) psecuritypriv->dot11PrivacyAlgrthm;
1019         } else {
1020                 GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false);
1021         }
1022
1023         if (unicast_key == true) {
1024                 memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);
1025         } else{
1026                 memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16);
1027         }
1028
1029         /* jeff: set this becasue at least sw key is ready */
1030         padapter->securitypriv.busetkipkey = true;
1031
1032         if (enqueue) {
1033                 ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
1034                 if (ph2c == NULL) {
1035                         kfree(psetstakey_para);
1036                         res = _FAIL;
1037                         goto exit;
1038                 }
1039
1040                 psetstakey_rsp = rtw_zmalloc(sizeof(struct set_stakey_rsp));
1041                 if (psetstakey_rsp == NULL) {
1042                         kfree(ph2c);
1043                         kfree(psetstakey_para);
1044                         res = _FAIL;
1045                         goto exit;
1046                 }
1047
1048                 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
1049                 ph2c->rsp = (u8 *) psetstakey_rsp;
1050                 ph2c->rspsz = sizeof(struct set_stakey_rsp);
1051                 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1052         } else{
1053                 set_stakey_hdl(padapter, (u8 *)psetstakey_para);
1054                 kfree(psetstakey_para);
1055         }
1056 exit:
1057         return res;
1058 }
1059
1060 u8 rtw_clearstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 enqueue)
1061 {
1062         struct cmd_obj *ph2c;
1063         struct set_stakey_parm  *psetstakey_para;
1064         struct cmd_priv                         *pcmdpriv = &padapter->cmdpriv;
1065         struct set_stakey_rsp           *psetstakey_rsp = NULL;
1066         s16 cam_id = 0;
1067         u8 res = _SUCCESS;
1068
1069         if (!enqueue) {
1070                 while ((cam_id = rtw_camid_search(padapter, sta->hwaddr, -1)) >= 0) {
1071                         DBG_871X_LEVEL(_drv_always_, "clear key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(sta->hwaddr), cam_id);
1072                         clear_cam_entry(padapter, cam_id);
1073                         rtw_camid_free(padapter, cam_id);
1074                 }
1075         } else{
1076                 ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
1077                 if (ph2c == NULL) {
1078                         res = _FAIL;
1079                         goto exit;
1080                 }
1081
1082                 psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm));
1083                 if (psetstakey_para == NULL) {
1084                         kfree(ph2c);
1085                         res = _FAIL;
1086                         goto exit;
1087                 }
1088
1089                 psetstakey_rsp = rtw_zmalloc(sizeof(struct set_stakey_rsp));
1090                 if (psetstakey_rsp == NULL) {
1091                         kfree(ph2c);
1092                         kfree(psetstakey_para);
1093                         res = _FAIL;
1094                         goto exit;
1095                 }
1096
1097                 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
1098                 ph2c->rsp = (u8 *) psetstakey_rsp;
1099                 ph2c->rspsz = sizeof(struct set_stakey_rsp);
1100
1101                 memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN);
1102
1103                 psetstakey_para->algorithm = _NO_PRIVACY_;
1104
1105                 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1106
1107         }
1108
1109 exit:
1110         return res;
1111 }
1112
1113 u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr)
1114 {
1115         struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
1116         struct cmd_obj *ph2c;
1117         struct addBaReq_parm    *paddbareq_parm;
1118
1119         u8 res = _SUCCESS;
1120
1121         ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
1122         if (ph2c == NULL) {
1123                 res = _FAIL;
1124                 goto exit;
1125         }
1126
1127         paddbareq_parm = rtw_zmalloc(sizeof(struct addBaReq_parm));
1128         if (paddbareq_parm == NULL) {
1129                 kfree(ph2c);
1130                 res = _FAIL;
1131                 goto exit;
1132         }
1133
1134         paddbareq_parm->tid = tid;
1135         memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
1136
1137         init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq));
1138
1139         /* DBG_871X("rtw_addbareq_cmd, tid =%d\n", tid); */
1140
1141         /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1142         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1143
1144 exit:
1145         return res;
1146 }
1147 /* add for CONFIG_IEEE80211W, none 11w can use it */
1148 u8 rtw_reset_securitypriv_cmd(struct adapter *padapter)
1149 {
1150         struct cmd_obj *ph2c;
1151         struct drvextra_cmd_parm  *pdrvextra_cmd_parm;
1152         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1153         u8 res = _SUCCESS;
1154
1155         ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
1156         if (ph2c == NULL) {
1157                 res = _FAIL;
1158                 goto exit;
1159         }
1160
1161         pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1162         if (pdrvextra_cmd_parm == NULL) {
1163                 kfree(ph2c);
1164                 res = _FAIL;
1165                 goto exit;
1166         }
1167
1168         pdrvextra_cmd_parm->ec_id = RESET_SECURITYPRIV;
1169         pdrvextra_cmd_parm->type = 0;
1170         pdrvextra_cmd_parm->size = 0;
1171         pdrvextra_cmd_parm->pbuf = NULL;
1172
1173         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1174
1175
1176         /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1177         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1178
1179 exit:
1180         return res;
1181 }
1182
1183 u8 rtw_free_assoc_resources_cmd(struct adapter *padapter)
1184 {
1185         struct cmd_obj *ph2c;
1186         struct drvextra_cmd_parm  *pdrvextra_cmd_parm;
1187         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1188         u8 res = _SUCCESS;
1189
1190         ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
1191         if (ph2c == NULL) {
1192                 res = _FAIL;
1193                 goto exit;
1194         }
1195
1196         pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1197         if (pdrvextra_cmd_parm == NULL) {
1198                 kfree(ph2c);
1199                 res = _FAIL;
1200                 goto exit;
1201         }
1202
1203         pdrvextra_cmd_parm->ec_id = FREE_ASSOC_RESOURCES;
1204         pdrvextra_cmd_parm->type = 0;
1205         pdrvextra_cmd_parm->size = 0;
1206         pdrvextra_cmd_parm->pbuf = NULL;
1207
1208         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1209
1210
1211         /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1212         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1213
1214 exit:
1215         return res;
1216 }
1217
1218 u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter)
1219 {
1220         struct cmd_obj *ph2c;
1221         struct drvextra_cmd_parm  *pdrvextra_cmd_parm;
1222         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1223         u8 res = _SUCCESS;
1224
1225         /* only  primary padapter does this cmd */
1226         ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
1227         if (ph2c == NULL) {
1228                 res = _FAIL;
1229                 goto exit;
1230         }
1231
1232         pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1233         if (pdrvextra_cmd_parm == NULL) {
1234                 kfree(ph2c);
1235                 res = _FAIL;
1236                 goto exit;
1237         }
1238
1239         pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
1240         pdrvextra_cmd_parm->type = 0;
1241         pdrvextra_cmd_parm->size = 0;
1242         pdrvextra_cmd_parm->pbuf = NULL;
1243         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1244
1245
1246         /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
1247         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1248
1249 exit:
1250         return res;
1251 }
1252
1253 u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue, u8 swconfig)
1254 {
1255         struct  cmd_obj *pcmdobj;
1256         struct  SetChannelPlan_param *setChannelPlan_param;
1257         struct  cmd_priv   *pcmdpriv = &padapter->cmdpriv;
1258
1259         u8 res = _SUCCESS;
1260
1261         RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_chplan_cmd\n"));
1262
1263         /*  check if allow software config */
1264         if (swconfig && rtw_hal_is_disable_sw_channel_plan(padapter) == true) {
1265                 res = _FAIL;
1266                 goto exit;
1267         }
1268
1269         /* check input parameter */
1270         if (!rtw_is_channel_plan_valid(chplan)) {
1271                 res = _FAIL;
1272                 goto exit;
1273         }
1274
1275         /* prepare cmd parameter */
1276         setChannelPlan_param = rtw_zmalloc(sizeof(struct SetChannelPlan_param));
1277         if (setChannelPlan_param == NULL) {
1278                 res = _FAIL;
1279                 goto exit;
1280         }
1281         setChannelPlan_param->channel_plan = chplan;
1282
1283         if (enqueue) {
1284                 /* need enqueue, prepare cmd_obj and enqueue */
1285                 pcmdobj = rtw_zmalloc(sizeof(struct cmd_obj));
1286                 if (pcmdobj == NULL) {
1287                         kfree(setChannelPlan_param);
1288                         res = _FAIL;
1289                         goto exit;
1290                 }
1291
1292                 init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, GEN_CMD_CODE(_SetChannelPlan));
1293                 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
1294         } else{
1295                 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1296                 if (H2C_SUCCESS != set_chplan_hdl(padapter, (unsigned char *)setChannelPlan_param))
1297                         res = _FAIL;
1298
1299                 kfree(setChannelPlan_param);
1300         }
1301
1302         /* do something based on res... */
1303         if (res == _SUCCESS)
1304                 padapter->mlmepriv.ChannelPlan = chplan;
1305
1306 exit:
1307         return res;
1308 }
1309
1310 static void collect_traffic_statistics(struct adapter *padapter)
1311 {
1312         struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
1313
1314         /*  Tx */
1315         pdvobjpriv->traffic_stat.tx_bytes = padapter->xmitpriv.tx_bytes;
1316         pdvobjpriv->traffic_stat.tx_pkts = padapter->xmitpriv.tx_pkts;
1317         pdvobjpriv->traffic_stat.tx_drop = padapter->xmitpriv.tx_drop;
1318
1319         /*  Rx */
1320         pdvobjpriv->traffic_stat.rx_bytes = padapter->recvpriv.rx_bytes;
1321         pdvobjpriv->traffic_stat.rx_pkts = padapter->recvpriv.rx_pkts;
1322         pdvobjpriv->traffic_stat.rx_drop = padapter->recvpriv.rx_drop;
1323
1324         /*  Calculate throughput in last interval */
1325         pdvobjpriv->traffic_stat.cur_tx_bytes = pdvobjpriv->traffic_stat.tx_bytes - pdvobjpriv->traffic_stat.last_tx_bytes;
1326         pdvobjpriv->traffic_stat.cur_rx_bytes = pdvobjpriv->traffic_stat.rx_bytes - pdvobjpriv->traffic_stat.last_rx_bytes;
1327         pdvobjpriv->traffic_stat.last_tx_bytes = pdvobjpriv->traffic_stat.tx_bytes;
1328         pdvobjpriv->traffic_stat.last_rx_bytes = pdvobjpriv->traffic_stat.rx_bytes;
1329
1330         pdvobjpriv->traffic_stat.cur_tx_tp = (u32)(pdvobjpriv->traffic_stat.cur_tx_bytes * 8/2/1024/1024);
1331         pdvobjpriv->traffic_stat.cur_rx_tp = (u32)(pdvobjpriv->traffic_stat.cur_rx_bytes * 8/2/1024/1024);
1332 }
1333
1334 u8 traffic_status_watchdog(struct adapter *padapter, u8 from_timer)
1335 {
1336         u8 bEnterPS = false;
1337         u16 BusyThresholdHigh = 25;
1338         u16 BusyThresholdLow = 10;
1339         u16 BusyThreshold = BusyThresholdHigh;
1340         u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false;
1341         u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false;
1342
1343         struct mlme_priv        *pmlmepriv = &(padapter->mlmepriv);
1344
1345         collect_traffic_statistics(padapter);
1346
1347         /*  */
1348         /*  Determine if our traffic is busy now */
1349         /*  */
1350         if ((check_fwstate(pmlmepriv, _FW_LINKED) == true)
1351                 /*&& !MgntInitAdapterInProgress(pMgntInfo)*/) {
1352                 /*  if we raise bBusyTraffic in last watchdog, using lower threshold. */
1353                 if (pmlmepriv->LinkDetectInfo.bBusyTraffic)
1354                                 BusyThreshold = BusyThresholdLow;
1355
1356                 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold ||
1357                         pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold) {
1358                         bBusyTraffic = true;
1359
1360                         if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
1361                                 bRxBusyTraffic = true;
1362                         else
1363                                 bTxBusyTraffic = true;
1364                 }
1365
1366                 /*  Higher Tx/Rx data. */
1367                 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
1368                         pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
1369                         bHigherBusyTraffic = true;
1370
1371                         if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
1372                                 bHigherBusyRxTraffic = true;
1373                         else
1374                                 bHigherBusyTxTraffic = true;
1375                 }
1376
1377                 /*  check traffic for  powersaving. */
1378                 if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
1379                         (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2)) {
1380                         /* DBG_871X("(-)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); */
1381                         bEnterPS = false;
1382
1383                         if (bBusyTraffic == true) {
1384                                 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount <= 4)
1385                                         pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 4;
1386
1387                                 pmlmepriv->LinkDetectInfo.TrafficTransitionCount++;
1388
1389                                 /* DBG_871X("Set TrafficTransitionCount to %d\n", pmlmepriv->LinkDetectInfo.TrafficTransitionCount); */
1390
1391                                 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount > 30/*TrafficTransitionLevel*/) {
1392                                         pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 30;
1393                                 }
1394                         }
1395                 } else{
1396                         /* DBG_871X("(+)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); */
1397
1398                         if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount >= 2)
1399                                 pmlmepriv->LinkDetectInfo.TrafficTransitionCount -= 2;
1400                         else
1401                                 pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
1402
1403                         if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount == 0)
1404                                 bEnterPS = true;
1405                 }
1406
1407                 /*  LeisurePS only work in infra mode. */
1408                 if (bEnterPS) {
1409                         if (!from_timer)
1410                                 LPS_Enter(padapter, "TRAFFIC_IDLE");
1411                 } else {
1412                         if (!from_timer)
1413                                 LPS_Leave(padapter, "TRAFFIC_BUSY");
1414                         else
1415                                 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_TRAFFIC_BUSY, 1);
1416                 }
1417         } else{
1418                 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1419                 int n_assoc_iface = 0;
1420
1421                 if (check_fwstate(&(dvobj->padapters->mlmepriv), WIFI_ASOC_STATE))
1422                         n_assoc_iface++;
1423
1424                 if (!from_timer && n_assoc_iface == 0)
1425                         LPS_Leave(padapter, "NON_LINKED");
1426         }
1427
1428         pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
1429         pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
1430         pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
1431         pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
1432         pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
1433         pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
1434         pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
1435         pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
1436         pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
1437
1438         return bEnterPS;
1439
1440 }
1441
1442 static void dynamic_chk_wk_hdl(struct adapter *padapter)
1443 {
1444         struct mlme_priv *pmlmepriv;
1445         pmlmepriv = &(padapter->mlmepriv);
1446
1447         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
1448                 expire_timeout_chk(padapter);
1449         }
1450
1451         /* for debug purpose */
1452         _linked_info_dump(padapter);
1453
1454
1455         /* if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING|_FW_UNDER_SURVEY) ==false) */
1456         {
1457                 linked_status_chk(padapter);
1458                 traffic_status_watchdog(padapter, 0);
1459         }
1460
1461         rtw_hal_dm_watchdog(padapter);
1462
1463         /* check_hw_pbc(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type); */
1464
1465         /*  */
1466         /*  BT-Coexist */
1467         /*  */
1468         rtw_btcoex_Handler(padapter);
1469
1470
1471         /* always call rtw_ps_processor() at last one. */
1472         if (is_primary_adapter(padapter))
1473                 rtw_ps_processor(padapter);
1474 }
1475
1476 void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type);
1477 void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type)
1478 {
1479         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
1480         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1481         u8 mstatus;
1482
1483         if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)
1484                 || (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
1485                 return;
1486         }
1487
1488         switch (lps_ctrl_type) {
1489         case LPS_CTRL_SCAN:
1490                 /* DBG_871X("LPS_CTRL_SCAN\n"); */
1491                 rtw_btcoex_ScanNotify(padapter, true);
1492
1493                 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
1494                         /*  connect */
1495                         LPS_Leave(padapter, "LPS_CTRL_SCAN");
1496                 }
1497                 break;
1498         case LPS_CTRL_JOINBSS:
1499                 /* DBG_871X("LPS_CTRL_JOINBSS\n"); */
1500                 LPS_Leave(padapter, "LPS_CTRL_JOINBSS");
1501                 break;
1502         case LPS_CTRL_CONNECT:
1503                 /* DBG_871X("LPS_CTRL_CONNECT\n"); */
1504                 mstatus = 1;/* connect */
1505                 /*  Reset LPS Setting */
1506                 pwrpriv->LpsIdleCount = 0;
1507                 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
1508                 rtw_btcoex_MediaStatusNotify(padapter, mstatus);
1509                 break;
1510         case LPS_CTRL_DISCONNECT:
1511                 /* DBG_871X("LPS_CTRL_DISCONNECT\n"); */
1512                 mstatus = 0;/* disconnect */
1513                 rtw_btcoex_MediaStatusNotify(padapter, mstatus);
1514                 LPS_Leave(padapter, "LPS_CTRL_DISCONNECT");
1515                 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
1516                 break;
1517         case LPS_CTRL_SPECIAL_PACKET:
1518                 /* DBG_871X("LPS_CTRL_SPECIAL_PACKET\n"); */
1519                 pwrpriv->DelayLPSLastTimeStamp = jiffies;
1520                 rtw_btcoex_SpecialPacketNotify(padapter, PACKET_DHCP);
1521                 LPS_Leave(padapter, "LPS_CTRL_SPECIAL_PACKET");
1522                 break;
1523         case LPS_CTRL_LEAVE:
1524                 /* DBG_871X("LPS_CTRL_LEAVE\n"); */
1525                 LPS_Leave(padapter, "LPS_CTRL_LEAVE");
1526                 break;
1527         case LPS_CTRL_TRAFFIC_BUSY:
1528                 LPS_Leave(padapter, "LPS_CTRL_TRAFFIC_BUSY");
1529         default:
1530                 break;
1531         }
1532 }
1533
1534 u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
1535 {
1536         struct cmd_obj  *ph2c;
1537         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
1538         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1539         /* struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); */
1540         u8 res = _SUCCESS;
1541
1542         /* if (!pwrctrlpriv->bLeisurePs) */
1543         /*      return res; */
1544
1545         if (enqueue) {
1546                 ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
1547                 if (ph2c == NULL) {
1548                         res = _FAIL;
1549                         goto exit;
1550                 }
1551
1552                 pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1553                 if (pdrvextra_cmd_parm == NULL) {
1554                         kfree(ph2c);
1555                         res = _FAIL;
1556                         goto exit;
1557                 }
1558
1559                 pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
1560                 pdrvextra_cmd_parm->type = lps_ctrl_type;
1561                 pdrvextra_cmd_parm->size = 0;
1562                 pdrvextra_cmd_parm->pbuf = NULL;
1563
1564                 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1565
1566                 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1567         } else{
1568                 lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
1569         }
1570
1571 exit:
1572         return res;
1573 }
1574
1575 static void rtw_dm_in_lps_hdl(struct adapter *padapter)
1576 {
1577         rtw_hal_set_hwreg(padapter, HW_VAR_DM_IN_LPS, NULL);
1578 }
1579
1580 u8 rtw_dm_in_lps_wk_cmd(struct adapter *padapter)
1581 {
1582         struct cmd_obj  *ph2c;
1583         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
1584         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1585         u8 res = _SUCCESS;
1586
1587
1588         ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
1589         if (ph2c == NULL) {
1590                 res = _FAIL;
1591                 goto exit;
1592         }
1593
1594         pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1595         if (pdrvextra_cmd_parm == NULL) {
1596                 kfree(ph2c);
1597                 res = _FAIL;
1598                 goto exit;
1599         }
1600
1601         pdrvextra_cmd_parm->ec_id = DM_IN_LPS_WK_CID;
1602         pdrvextra_cmd_parm->type = 0;
1603         pdrvextra_cmd_parm->size = 0;
1604         pdrvextra_cmd_parm->pbuf = NULL;
1605
1606         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1607
1608         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1609
1610 exit:
1611
1612         return res;
1613
1614 }
1615
1616 static void rtw_lps_change_dtim_hdl(struct adapter *padapter, u8 dtim)
1617 {
1618         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
1619
1620         if (dtim <= 0 || dtim > 16)
1621                 return;
1622
1623         if (rtw_btcoex_IsBtControlLps(padapter) == true)
1624                 return;
1625
1626         down(&pwrpriv->lock);
1627
1628         if (pwrpriv->dtim != dtim) {
1629                 DBG_871X("change DTIM from %d to %d, bFwCurrentInPSMode =%d, ps_mode =%d\n", pwrpriv->dtim, dtim,
1630                         pwrpriv->bFwCurrentInPSMode, pwrpriv->pwr_mode);
1631
1632                 pwrpriv->dtim = dtim;
1633         }
1634
1635         if ((pwrpriv->bFwCurrentInPSMode == true) && (pwrpriv->pwr_mode > PS_MODE_ACTIVE)) {
1636                 u8 ps_mode = pwrpriv->pwr_mode;
1637
1638                 /* DBG_871X("change DTIM from %d to %d, ps_mode =%d\n", pwrpriv->dtim, dtim, ps_mode); */
1639
1640                 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
1641         }
1642
1643         up(&pwrpriv->lock);
1644 }
1645
1646 static void rtw_dm_ra_mask_hdl(struct adapter *padapter, struct sta_info *psta)
1647 {
1648         if (psta) {
1649                 set_sta_rate(padapter, psta);
1650         }
1651 }
1652
1653 u8 rtw_dm_ra_mask_wk_cmd(struct adapter *padapter, u8 *psta)
1654 {
1655         struct cmd_obj  *ph2c;
1656         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
1657         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1658         u8 res = _SUCCESS;
1659
1660
1661         ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
1662         if (ph2c == NULL) {
1663                 res = _FAIL;
1664                 goto exit;
1665         }
1666
1667         pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1668         if (pdrvextra_cmd_parm == NULL) {
1669                 kfree(ph2c);
1670                 res = _FAIL;
1671                 goto exit;
1672         }
1673
1674         pdrvextra_cmd_parm->ec_id = DM_RA_MSK_WK_CID;
1675         pdrvextra_cmd_parm->type = 0;
1676         pdrvextra_cmd_parm->size = 0;
1677         pdrvextra_cmd_parm->pbuf = psta;
1678
1679         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1680
1681         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1682
1683 exit:
1684
1685         return res;
1686
1687 }
1688
1689 static void power_saving_wk_hdl(struct adapter *padapter)
1690 {
1691          rtw_ps_processor(padapter);
1692 }
1693
1694 /* add for CONFIG_IEEE80211W, none 11w can use it */
1695 static void reset_securitypriv_hdl(struct adapter *padapter)
1696 {
1697          rtw_reset_securitypriv(padapter);
1698 }
1699
1700 static void free_assoc_resources_hdl(struct adapter *padapter)
1701 {
1702          rtw_free_assoc_resources(padapter, 1);
1703 }
1704
1705 u8 rtw_ps_cmd(struct adapter *padapter)
1706 {
1707         struct cmd_obj          *ppscmd;
1708         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
1709         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1710         u8 res = _SUCCESS;
1711
1712         ppscmd = rtw_zmalloc(sizeof(struct cmd_obj));
1713         if (ppscmd == NULL) {
1714                 res = _FAIL;
1715                 goto exit;
1716         }
1717
1718         pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1719         if (pdrvextra_cmd_parm == NULL) {
1720                 kfree(ppscmd);
1721                 res = _FAIL;
1722                 goto exit;
1723         }
1724
1725         pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
1726         pdrvextra_cmd_parm->type = 0;
1727         pdrvextra_cmd_parm->size = 0;
1728         pdrvextra_cmd_parm->pbuf = NULL;
1729         init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1730
1731         res = rtw_enqueue_cmd(pcmdpriv, ppscmd);
1732
1733 exit:
1734         return res;
1735 }
1736
1737 u32 g_wait_hiq_empty;
1738
1739 static void rtw_chk_hi_queue_hdl(struct adapter *padapter)
1740 {
1741         struct sta_info *psta_bmc;
1742         struct sta_priv *pstapriv = &padapter->stapriv;
1743         unsigned long start = jiffies;
1744         u8 empty = false;
1745
1746         psta_bmc = rtw_get_bcmc_stainfo(padapter);
1747         if (!psta_bmc)
1748                 return;
1749
1750         rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
1751
1752         while (false == empty && jiffies_to_msecs(jiffies - start) < g_wait_hiq_empty) {
1753                 msleep(100);
1754                 rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
1755         }
1756
1757         if (psta_bmc->sleepq_len == 0) {
1758                 if (empty == _SUCCESS) {
1759                         bool update_tim = false;
1760
1761                         if (pstapriv->tim_bitmap & BIT(0))
1762                                 update_tim = true;
1763
1764                         pstapriv->tim_bitmap &= ~BIT(0);
1765                         pstapriv->sta_dz_bitmap &= ~BIT(0);
1766
1767                         if (update_tim == true)
1768                                 update_beacon(padapter, _TIM_IE_, NULL, true);
1769                 } else{/* re check again */
1770                         rtw_chk_hi_queue_cmd(padapter);
1771                 }
1772
1773         }
1774
1775 }
1776
1777 u8 rtw_chk_hi_queue_cmd(struct adapter *padapter)
1778 {
1779         struct cmd_obj  *ph2c;
1780         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
1781         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1782         u8 res = _SUCCESS;
1783
1784         ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
1785         if (ph2c == NULL) {
1786                 res = _FAIL;
1787                 goto exit;
1788         }
1789
1790         pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1791         if (pdrvextra_cmd_parm == NULL) {
1792                 kfree(ph2c);
1793                 res = _FAIL;
1794                 goto exit;
1795         }
1796
1797         pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
1798         pdrvextra_cmd_parm->type = 0;
1799         pdrvextra_cmd_parm->size = 0;
1800         pdrvextra_cmd_parm->pbuf = NULL;
1801
1802         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1803
1804         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1805
1806 exit:
1807
1808         return res;
1809
1810 }
1811
1812 struct btinfo {
1813         u8 cid;
1814         u8 len;
1815
1816         u8 bConnection:1;
1817         u8 bSCOeSCO:1;
1818         u8 bInQPage:1;
1819         u8 bACLBusy:1;
1820         u8 bSCOBusy:1;
1821         u8 bHID:1;
1822         u8 bA2DP:1;
1823         u8 bFTP:1;
1824
1825         u8 retry_cnt:4;
1826         u8 rsvd_34:1;
1827         u8 rsvd_35:1;
1828         u8 rsvd_36:1;
1829         u8 rsvd_37:1;
1830
1831         u8 rssi;
1832
1833         u8 rsvd_50:1;
1834         u8 rsvd_51:1;
1835         u8 rsvd_52:1;
1836         u8 rsvd_53:1;
1837         u8 rsvd_54:1;
1838         u8 rsvd_55:1;
1839         u8 eSCO_SCO:1;
1840         u8 Master_Slave:1;
1841
1842         u8 rsvd_6;
1843         u8 rsvd_7;
1844 };
1845
1846 static void rtw_btinfo_hdl(struct adapter *adapter, u8 *buf, u16 buf_len)
1847 {
1848         #define BTINFO_WIFI_FETCH 0x23
1849         #define BTINFO_BT_AUTO_RPT 0x27
1850         struct btinfo *info = (struct btinfo *)buf;
1851         u8 cmd_idx;
1852         u8 len;
1853
1854         cmd_idx = info->cid;
1855
1856         if (info->len > buf_len-2) {
1857                 rtw_warn_on(1);
1858                 len = buf_len-2;
1859         } else {
1860                 len = info->len;
1861         }
1862
1863 /* define DBG_PROC_SET_BTINFO_EVT */
1864 #ifdef DBG_PROC_SET_BTINFO_EVT
1865         btinfo_evt_dump(RTW_DBGDUMP, info);
1866 #endif
1867
1868         /* transform BT-FW btinfo to WiFI-FW C2H format and notify */
1869         if (cmd_idx == BTINFO_WIFI_FETCH)
1870                 buf[1] = 0;
1871         else if (cmd_idx == BTINFO_BT_AUTO_RPT)
1872                 buf[1] = 2;
1873         rtw_btcoex_BtInfoNotify(adapter, len+1, &buf[1]);
1874 }
1875
1876 u8 rtw_c2h_packet_wk_cmd(struct adapter *padapter, u8 *pbuf, u16 length)
1877 {
1878         struct cmd_obj *ph2c;
1879         struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1880         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1881         u8 res = _SUCCESS;
1882
1883         ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
1884         if (ph2c == NULL) {
1885                 res = _FAIL;
1886                 goto exit;
1887         }
1888
1889         pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1890         if (pdrvextra_cmd_parm == NULL) {
1891                 kfree(ph2c);
1892                 res = _FAIL;
1893                 goto exit;
1894         }
1895
1896         pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
1897         pdrvextra_cmd_parm->type = 0;
1898         pdrvextra_cmd_parm->size = length;
1899         pdrvextra_cmd_parm->pbuf = pbuf;
1900
1901         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1902
1903         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1904
1905 exit:
1906         return res;
1907 }
1908
1909 /* dont call R/W in this function, beucase SDIO interrupt have claim host */
1910 /* or deadlock will happen and cause special-systemserver-died in android */
1911 u8 rtw_c2h_wk_cmd(struct adapter *padapter, u8 *c2h_evt)
1912 {
1913         struct cmd_obj *ph2c;
1914         struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1915         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1916         u8 res = _SUCCESS;
1917
1918         ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
1919         if (ph2c == NULL) {
1920                 res = _FAIL;
1921                 goto exit;
1922         }
1923
1924         pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1925         if (pdrvextra_cmd_parm == NULL) {
1926                 kfree(ph2c);
1927                 res = _FAIL;
1928                 goto exit;
1929         }
1930
1931         pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
1932         pdrvextra_cmd_parm->type = 0;
1933         pdrvextra_cmd_parm->size =  c2h_evt?16:0;
1934         pdrvextra_cmd_parm->pbuf = c2h_evt;
1935
1936         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1937
1938         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1939
1940 exit:
1941
1942         return res;
1943 }
1944
1945 static void c2h_wk_callback(_workitem *work)
1946 {
1947         struct evt_priv *evtpriv = container_of(work, struct evt_priv, c2h_wk);
1948         struct adapter *adapter = container_of(evtpriv, struct adapter, evtpriv);
1949         u8 *c2h_evt;
1950         c2h_id_filter ccx_id_filter = rtw_hal_c2h_id_filter_ccx(adapter);
1951
1952         evtpriv->c2h_wk_alive = true;
1953
1954         while (!rtw_cbuf_empty(evtpriv->c2h_queue)) {
1955                 c2h_evt = (u8 *)rtw_cbuf_pop(evtpriv->c2h_queue);
1956                 if (c2h_evt != NULL) {
1957                         /* This C2H event is read, clear it */
1958                         c2h_evt_clear(adapter);
1959                 } else{
1960                         c2h_evt = rtw_malloc(16);
1961                         if (c2h_evt != NULL) {
1962                                 /* This C2H event is not read, read & clear now */
1963                                 if (rtw_hal_c2h_evt_read(adapter, c2h_evt) != _SUCCESS) {
1964                                         kfree(c2h_evt);
1965                                         continue;
1966                                 }
1967                         }
1968                 }
1969
1970                 /* Special pointer to trigger c2h_evt_clear only */
1971                 if ((void *)c2h_evt == (void *)evtpriv)
1972                         continue;
1973
1974                 if (!rtw_hal_c2h_valid(adapter, c2h_evt)) {
1975                         kfree(c2h_evt);
1976                         continue;
1977                 }
1978
1979                 if (ccx_id_filter(c2h_evt) == true) {
1980                         /* Handle CCX report here */
1981                         rtw_hal_c2h_handler(adapter, c2h_evt);
1982                         kfree(c2h_evt);
1983                 } else{
1984                         /* Enqueue into cmd_thread for others */
1985                         rtw_c2h_wk_cmd(adapter, c2h_evt);
1986                 }
1987         }
1988
1989         evtpriv->c2h_wk_alive = false;
1990 }
1991
1992 u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf)
1993 {
1994         struct drvextra_cmd_parm *pdrvextra_cmd;
1995
1996         if (!pbuf)
1997                 return H2C_PARAMETERS_ERROR;
1998
1999         pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
2000
2001         switch (pdrvextra_cmd->ec_id) {
2002         case DYNAMIC_CHK_WK_CID:/* only  primary padapter go to this cmd, but execute dynamic_chk_wk_hdl() for two interfaces */
2003                 dynamic_chk_wk_hdl(padapter);
2004                 break;
2005         case POWER_SAVING_CTRL_WK_CID:
2006                 power_saving_wk_hdl(padapter);
2007                 break;
2008         case LPS_CTRL_WK_CID:
2009                 lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type);
2010                 break;
2011         case DM_IN_LPS_WK_CID:
2012                 rtw_dm_in_lps_hdl(padapter);
2013                 break;
2014         case LPS_CHANGE_DTIM_CID:
2015                 rtw_lps_change_dtim_hdl(padapter, (u8)pdrvextra_cmd->type);
2016                 break;
2017         case CHECK_HIQ_WK_CID:
2018                 rtw_chk_hi_queue_hdl(padapter);
2019                 break;
2020 #ifdef CONFIG_INTEL_WIDI
2021         case INTEl_WIDI_WK_CID:
2022                 intel_widi_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
2023                 break;
2024 #endif /* CONFIG_INTEL_WIDI */
2025         /* add for CONFIG_IEEE80211W, none 11w can use it */
2026         case RESET_SECURITYPRIV:
2027                 reset_securitypriv_hdl(padapter);
2028                 break;
2029         case FREE_ASSOC_RESOURCES:
2030                 free_assoc_resources_hdl(padapter);
2031                 break;
2032         case C2H_WK_CID:
2033                 rtw_hal_set_hwreg_with_buf(padapter, HW_VAR_C2H_HANDLE, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
2034                 break;
2035         case DM_RA_MSK_WK_CID:
2036                 rtw_dm_ra_mask_hdl(padapter, (struct sta_info *)pdrvextra_cmd->pbuf);
2037                 break;
2038         case BTINFO_WK_CID:
2039                 rtw_btinfo_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
2040                 break;
2041         default:
2042                 break;
2043         }
2044
2045         if (pdrvextra_cmd->pbuf && pdrvextra_cmd->size > 0) {
2046                 kfree(pdrvextra_cmd->pbuf);
2047         }
2048
2049         return H2C_SUCCESS;
2050 }
2051
2052 void rtw_survey_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
2053 {
2054         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
2055
2056         if (pcmd->res == H2C_DROPPED) {
2057                 /* TODO: cancel timer and do timeout handler directly... */
2058                 /* need to make timeout handlerOS independent */
2059                 _set_timer(&pmlmepriv->scan_to_timer, 1);
2060         } else if (pcmd->res != H2C_SUCCESS) {
2061                 _set_timer(&pmlmepriv->scan_to_timer, 1);
2062                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: MgntActrtw_set_802_11_bssid_LIST_SCAN Fail ************\n\n."));
2063         }
2064
2065         /*  free cmd */
2066         rtw_free_cmd_obj(pcmd);
2067 }
2068
2069 void rtw_disassoc_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
2070 {
2071         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
2072
2073         if (pcmd->res != H2C_SUCCESS) {
2074                 spin_lock_bh(&pmlmepriv->lock);
2075                 set_fwstate(pmlmepriv, _FW_LINKED);
2076                 spin_unlock_bh(&pmlmepriv->lock);
2077
2078                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ***Error: disconnect_cmd_callback Fail ***\n."));
2079                 return;
2080         }
2081         /*  free cmd */
2082         rtw_free_cmd_obj(pcmd);
2083 }
2084
2085 void rtw_joinbss_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
2086 {
2087         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
2088
2089         if (pcmd->res == H2C_DROPPED) {
2090                 /* TODO: cancel timer and do timeout handler directly... */
2091                 /* need to make timeout handlerOS independent */
2092                 _set_timer(&pmlmepriv->assoc_timer, 1);
2093         } else if (pcmd->res != H2C_SUCCESS) {
2094                 _set_timer(&pmlmepriv->assoc_timer, 1);
2095         }
2096
2097         rtw_free_cmd_obj(pcmd);
2098 }
2099
2100 void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
2101 {
2102         u8 timer_cancelled;
2103         struct sta_info *psta = NULL;
2104         struct wlan_network *pwlan = NULL;
2105         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
2106         struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
2107         struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
2108
2109         if (pcmd->parmbuf == NULL)
2110                 goto exit;
2111
2112         if ((pcmd->res != H2C_SUCCESS)) {
2113                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: rtw_createbss_cmd_callback  Fail ************\n\n."));
2114                 _set_timer(&pmlmepriv->assoc_timer, 1);
2115         }
2116
2117         _cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
2118
2119         spin_lock_bh(&pmlmepriv->lock);
2120
2121
2122         if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
2123                 psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress);
2124                 if (!psta) {
2125                         psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress);
2126                         if (psta == NULL) {
2127                                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nCan't alloc sta_info when createbss_cmd_callback\n"));
2128                                 goto createbss_cmd_fail;
2129                         }
2130                 }
2131
2132                 rtw_indicate_connect(padapter);
2133         } else{
2134                 pwlan = _rtw_alloc_network(pmlmepriv);
2135                 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
2136                 if (pwlan == NULL) {
2137                         pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
2138                         if (pwlan == NULL) {
2139                                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n Error:  can't get pwlan in rtw_joinbss_event_callback\n"));
2140                                 spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
2141                                 goto createbss_cmd_fail;
2142                         }
2143                         pwlan->last_scanned = jiffies;
2144                 } else{
2145                         list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
2146                 }
2147
2148                 pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
2149                 memcpy(&(pwlan->network), pnetwork, pnetwork->Length);
2150                 /* pwlan->fixed = true; */
2151
2152                 /* list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue); */
2153
2154                 /*  copy pdev_network information to    pmlmepriv->cur_network */
2155                 memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork)));
2156
2157                 /*  reset DSConfig */
2158                 /* tgt_network->network.Configuration.DSConfig = (u32)rtw_ch2freq(pnetwork->Configuration.DSConfig); */
2159
2160                 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
2161
2162                 spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
2163                 /*  we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */
2164
2165         }
2166
2167 createbss_cmd_fail:
2168
2169         spin_unlock_bh(&pmlmepriv->lock);
2170 exit:
2171         rtw_free_cmd_obj(pcmd);
2172 }
2173
2174
2175
2176 void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
2177 {
2178
2179         struct sta_priv *pstapriv = &padapter->stapriv;
2180         struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *) (pcmd->rsp);
2181         struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
2182
2183         if (psta == NULL) {
2184                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: rtw_setstaKey_cmdrsp_callback => can't get sta_info\n\n"));
2185                 goto exit;
2186         }
2187 exit:
2188         rtw_free_cmd_obj(pcmd);
2189 }
2190
2191 void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
2192 {
2193         struct sta_priv *pstapriv = &padapter->stapriv;
2194         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2195         struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
2196         struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *) (pcmd->rsp);
2197         struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr);
2198
2199         if (psta == NULL) {
2200                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: setassocsta_cmdrsp_callbac => can't get sta_info\n\n"));
2201                 goto exit;
2202         }
2203
2204         psta->aid = psta->mac_id = passocsta_rsp->cam_id;
2205
2206         spin_lock_bh(&pmlmepriv->lock);
2207
2208         if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) && (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true))
2209                 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
2210
2211         set_fwstate(pmlmepriv, _FW_LINKED);
2212         spin_unlock_bh(&pmlmepriv->lock);
2213
2214 exit:
2215         rtw_free_cmd_obj(pcmd);
2216 }