net: wireless: rockchip_wlan: add rtl8723cs support
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723cs / core / rtw_cmd.c
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  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _RTW_CMD_C_
21
22 #include <drv_types.h>
23 #include <hal_data.h>
24
25 #ifndef DBG_CMD_EXECUTE
26         #define DBG_CMD_EXECUTE 0
27 #endif
28
29 /*
30 Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.
31 No irqsave is necessary.
32 */
33
34 sint    _rtw_init_cmd_priv(struct       cmd_priv *pcmdpriv)
35 {
36         sint res = _SUCCESS;
37
38
39         _rtw_init_sema(&(pcmdpriv->cmd_queue_sema), 0);
40         /* _rtw_init_sema(&(pcmdpriv->cmd_done_sema), 0); */
41         _rtw_init_sema(&(pcmdpriv->terminate_cmdthread_sema), 0);
42
43
44         _rtw_init_queue(&(pcmdpriv->cmd_queue));
45
46         /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
47
48         pcmdpriv->cmd_seq = 1;
49
50         pcmdpriv->cmd_allocated_buf = rtw_zmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ);
51
52         if (pcmdpriv->cmd_allocated_buf == NULL) {
53                 res = _FAIL;
54                 goto exit;
55         }
56
57         pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf  +  CMDBUFF_ALIGN_SZ - ((SIZE_PTR)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ - 1));
58
59         pcmdpriv->rsp_allocated_buf = rtw_zmalloc(MAX_RSPSZ + 4);
60
61         if (pcmdpriv->rsp_allocated_buf == NULL) {
62                 res = _FAIL;
63                 goto exit;
64         }
65
66         pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf  +  4 - ((SIZE_PTR)(pcmdpriv->rsp_allocated_buf) & 3);
67
68         pcmdpriv->cmd_issued_cnt = pcmdpriv->cmd_done_cnt = pcmdpriv->rsp_cnt = 0;
69
70         _rtw_mutex_init(&pcmdpriv->sctx_mutex);
71 exit:
72
73
74         return res;
75
76 }
77
78 #ifdef CONFIG_C2H_WK
79 static void c2h_wk_callback(_workitem *work)
80 {
81         struct evt_priv *evtpriv = container_of(work, struct evt_priv, c2h_wk);
82         _adapter *adapter = container_of(evtpriv, _adapter, evtpriv);
83         u8 *c2h_evt;
84         c2h_id_filter direct_hdl_filter = rtw_hal_c2h_id_handle_directly;
85         u8 id, seq, plen;
86         u8 *payload;
87
88         evtpriv->c2h_wk_alive = _TRUE;
89
90         while (!rtw_cbuf_empty(evtpriv->c2h_queue)) {
91                 c2h_evt = (u8 *)rtw_cbuf_pop(evtpriv->c2h_queue);
92                 if (c2h_evt != NULL) {
93                         /* This C2H event is read, clear it */
94                         c2h_evt_clear(adapter);
95                 } else {
96                         c2h_evt = (u8 *)rtw_malloc(C2H_REG_LEN);
97                         if (c2h_evt == NULL) {
98                                 rtw_warn_on(1);
99                                 continue;
100                         }
101
102                         /* This C2H event is not read, read & clear now */
103                         if (rtw_hal_c2h_evt_read(adapter, c2h_evt) != _SUCCESS) {
104                                 rtw_mfree(c2h_evt, C2H_REG_LEN);
105                                 continue;
106                         }
107                 }
108
109                 /* Special pointer to trigger c2h_evt_clear only */
110                 if ((void *)c2h_evt == (void *)evtpriv)
111                         continue;
112
113                 if (!rtw_hal_c2h_valid(adapter, c2h_evt)
114                         || rtw_hal_c2h_reg_hdr_parse(adapter, c2h_evt, &id, &seq, &plen, &payload) != _SUCCESS
115                 ) {
116                         rtw_mfree(c2h_evt, C2H_REG_LEN);
117                         continue;
118                 }
119
120                 if (direct_hdl_filter(adapter, id, seq, plen, payload) == _TRUE) {
121                         /* Handle directly */
122                         rtw_hal_c2h_handler(adapter, id, seq, plen, payload);
123                         rtw_mfree(c2h_evt, C2H_REG_LEN);
124                 } else {
125                         /* Enqueue into cmd_thread for others */
126                         rtw_c2h_reg_wk_cmd(adapter, c2h_evt);
127                         rtw_mfree(c2h_evt, C2H_REG_LEN);
128                 }
129         }
130
131         evtpriv->c2h_wk_alive = _FALSE;
132 }
133 #endif /* CONFIG_C2H_WK */
134
135 sint _rtw_init_evt_priv(struct evt_priv *pevtpriv)
136 {
137         sint res = _SUCCESS;
138
139
140 #ifdef CONFIG_H2CLBK
141         _rtw_init_sema(&(pevtpriv->lbkevt_done), 0);
142         pevtpriv->lbkevt_limit = 0;
143         pevtpriv->lbkevt_num = 0;
144         pevtpriv->cmdevt_parm = NULL;
145 #endif
146
147         /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
148         ATOMIC_SET(&pevtpriv->event_seq, 0);
149         pevtpriv->evt_done_cnt = 0;
150
151 #ifdef CONFIG_EVENT_THREAD_MODE
152
153         _rtw_init_sema(&(pevtpriv->evt_notify), 0);
154         _rtw_init_sema(&(pevtpriv->terminate_evtthread_sema), 0);
155
156         pevtpriv->evt_allocated_buf = rtw_zmalloc(MAX_EVTSZ + 4);
157         if (pevtpriv->evt_allocated_buf == NULL) {
158                 res = _FAIL;
159                 goto exit;
160         }
161         pevtpriv->evt_buf = pevtpriv->evt_allocated_buf  +  4 - ((unsigned int)(pevtpriv->evt_allocated_buf) & 3);
162
163
164 #if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
165         pevtpriv->allocated_c2h_mem = rtw_zmalloc(C2H_MEM_SZ + 4);
166
167         if (pevtpriv->allocated_c2h_mem == NULL) {
168                 res = _FAIL;
169                 goto exit;
170         }
171
172         pevtpriv->c2h_mem = pevtpriv->allocated_c2h_mem +  4\
173                             - ((u32)(pevtpriv->allocated_c2h_mem) & 3);
174 #ifdef PLATFORM_OS_XP
175         pevtpriv->pc2h_mdl = IoAllocateMdl((u8 *)pevtpriv->c2h_mem, C2H_MEM_SZ , FALSE, FALSE, NULL);
176
177         if (pevtpriv->pc2h_mdl == NULL) {
178                 res = _FAIL;
179                 goto exit;
180         }
181         MmBuildMdlForNonPagedPool(pevtpriv->pc2h_mdl);
182 #endif
183 #endif /* end of CONFIG_SDIO_HCI */
184
185         _rtw_init_queue(&(pevtpriv->evt_queue));
186
187 exit:
188
189 #endif /* end of CONFIG_EVENT_THREAD_MODE */
190
191 #ifdef CONFIG_C2H_WK
192         _init_workitem(&pevtpriv->c2h_wk, c2h_wk_callback, NULL);
193         pevtpriv->c2h_wk_alive = _FALSE;
194         pevtpriv->c2h_queue = rtw_cbuf_alloc(C2H_QUEUE_MAX_LEN + 1);
195 #endif
196
197
198         return res;
199 }
200
201 void _rtw_free_evt_priv(struct  evt_priv *pevtpriv)
202 {
203
204
205 #ifdef CONFIG_EVENT_THREAD_MODE
206         _rtw_free_sema(&(pevtpriv->evt_notify));
207         _rtw_free_sema(&(pevtpriv->terminate_evtthread_sema));
208
209
210         if (pevtpriv->evt_allocated_buf)
211                 rtw_mfree(pevtpriv->evt_allocated_buf, MAX_EVTSZ + 4);
212 #endif
213
214 #ifdef CONFIG_C2H_WK
215         _cancel_workitem_sync(&pevtpriv->c2h_wk);
216         while (pevtpriv->c2h_wk_alive)
217                 rtw_msleep_os(10);
218
219         while (!rtw_cbuf_empty(pevtpriv->c2h_queue)) {
220                 void *c2h;
221                 c2h = rtw_cbuf_pop(pevtpriv->c2h_queue);
222                 if (c2h != NULL && c2h != (void *)pevtpriv)
223                         rtw_mfree(c2h, 16);
224         }
225         rtw_cbuf_free(pevtpriv->c2h_queue);
226 #endif
227
228
229
230 }
231
232 void _rtw_free_cmd_priv(struct  cmd_priv *pcmdpriv)
233 {
234
235         if (pcmdpriv) {
236                 _rtw_spinlock_free(&(pcmdpriv->cmd_queue.lock));
237                 _rtw_free_sema(&(pcmdpriv->cmd_queue_sema));
238                 /* _rtw_free_sema(&(pcmdpriv->cmd_done_sema)); */
239                 _rtw_free_sema(&(pcmdpriv->terminate_cmdthread_sema));
240
241                 if (pcmdpriv->cmd_allocated_buf)
242                         rtw_mfree(pcmdpriv->cmd_allocated_buf, MAX_CMDSZ + CMDBUFF_ALIGN_SZ);
243
244                 if (pcmdpriv->rsp_allocated_buf)
245                         rtw_mfree(pcmdpriv->rsp_allocated_buf, MAX_RSPSZ + 4);
246
247                 _rtw_mutex_free(&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 #ifdef DBG_CMD_QUEUE
261 extern u8 dump_cmd_id;
262 #endif
263
264 sint _rtw_enqueue_cmd(_queue *queue, struct cmd_obj *obj, bool to_head)
265 {
266         _irqL irqL;
267
268
269         if (obj == NULL)
270                 goto exit;
271
272         /* _enter_critical_bh(&queue->lock, &irqL); */
273         _enter_critical(&queue->lock, &irqL);
274
275         if (to_head)
276                 rtw_list_insert_head(&obj->list, &queue->queue);
277         else
278                 rtw_list_insert_tail(&obj->list, &queue->queue);
279
280 #ifdef DBG_CMD_QUEUE
281         if (dump_cmd_id) {
282                 printk("%s===> cmdcode:0x%02x\n", __FUNCTION__, obj->cmdcode);
283                 if (obj->cmdcode == GEN_CMD_CODE(_Set_MLME_EVT)) {
284                         if (obj->parmbuf) {
285                                 struct C2HEvent_Header *pc2h_evt_hdr = (struct C2HEvent_Header *)(obj->parmbuf);
286                                 printk("pc2h_evt_hdr->ID:0x%02x(%d)\n", pc2h_evt_hdr->ID, pc2h_evt_hdr->ID);
287                         }
288                 }
289                 if (obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
290                         if (obj->parmbuf) {
291                                 struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)(obj->parmbuf);
292                                 printk("pdrvextra_cmd_parm->ec_id:0x%02x\n", pdrvextra_cmd_parm->ec_id);
293                         }
294                 }
295         }
296
297         if (queue->queue.prev->next != &queue->queue) {
298                 RTW_INFO("[%d] head %p, tail %p, tail->prev->next %p[tail], tail->next %p[head]\n", __LINE__,
299                         &queue->queue, queue->queue.prev, queue->queue.prev->prev->next, queue->queue.prev->next);
300
301                 RTW_INFO("==========%s============\n", __FUNCTION__);
302                 RTW_INFO("head:%p,obj_addr:%p\n", &queue->queue, obj);
303                 RTW_INFO("padapter: %p\n", obj->padapter);
304                 RTW_INFO("cmdcode: 0x%02x\n", obj->cmdcode);
305                 RTW_INFO("res: %d\n", obj->res);
306                 RTW_INFO("parmbuf: %p\n", obj->parmbuf);
307                 RTW_INFO("cmdsz: %d\n", obj->cmdsz);
308                 RTW_INFO("rsp: %p\n", obj->rsp);
309                 RTW_INFO("rspsz: %d\n", obj->rspsz);
310                 RTW_INFO("sctx: %p\n", obj->sctx);
311                 RTW_INFO("list->next: %p\n", obj->list.next);
312                 RTW_INFO("list->prev: %p\n", obj->list.prev);
313         }
314 #endif /* DBG_CMD_QUEUE */
315
316         /* _exit_critical_bh(&queue->lock, &irqL);       */
317         _exit_critical(&queue->lock, &irqL);
318
319 exit:
320
321
322         return _SUCCESS;
323 }
324
325 struct  cmd_obj *_rtw_dequeue_cmd(_queue *queue)
326 {
327         _irqL irqL;
328         struct cmd_obj *obj;
329
330
331         /* _enter_critical_bh(&(queue->lock), &irqL); */
332         _enter_critical(&queue->lock, &irqL);
333
334 #ifdef DBG_CMD_QUEUE
335         if (queue->queue.prev->next != &queue->queue) {
336                 RTW_INFO("[%d] head %p, tail %p, tail->prev->next %p[tail], tail->next %p[head]\n", __LINE__,
337                         &queue->queue, queue->queue.prev, queue->queue.prev->prev->next, queue->queue.prev->next);
338         }
339 #endif /* DBG_CMD_QUEUE */
340
341
342         if (rtw_is_list_empty(&(queue->queue)))
343                 obj = NULL;
344         else {
345                 obj = LIST_CONTAINOR(get_next(&(queue->queue)), struct cmd_obj, list);
346
347 #ifdef DBG_CMD_QUEUE
348                 if (queue->queue.prev->next != &queue->queue) {
349                         RTW_INFO("==========%s============\n", __FUNCTION__);
350                         RTW_INFO("head:%p,obj_addr:%p\n", &queue->queue, obj);
351                         RTW_INFO("padapter: %p\n", obj->padapter);
352                         RTW_INFO("cmdcode: 0x%02x\n", obj->cmdcode);
353                         RTW_INFO("res: %d\n", obj->res);
354                         RTW_INFO("parmbuf: %p\n", obj->parmbuf);
355                         RTW_INFO("cmdsz: %d\n", obj->cmdsz);
356                         RTW_INFO("rsp: %p\n", obj->rsp);
357                         RTW_INFO("rspsz: %d\n", obj->rspsz);
358                         RTW_INFO("sctx: %p\n", obj->sctx);
359                         RTW_INFO("list->next: %p\n", obj->list.next);
360                         RTW_INFO("list->prev: %p\n", obj->list.prev);
361                 }
362
363                 if (dump_cmd_id) {
364                         RTW_INFO("%s===> cmdcode:0x%02x\n", __FUNCTION__, obj->cmdcode);
365                         if (obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
366                                 if (obj->parmbuf) {
367                                         struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)(obj->parmbuf);
368                                         printk("pdrvextra_cmd_parm->ec_id:0x%02x\n", pdrvextra_cmd_parm->ec_id);
369                                 }
370                         }
371
372                 }
373 #endif /* DBG_CMD_QUEUE */
374
375                 rtw_list_delete(&obj->list);
376         }
377
378         /* _exit_critical_bh(&(queue->lock), &irqL); */
379         _exit_critical(&queue->lock, &irqL);
380
381
382         return obj;
383 }
384
385 u32     rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
386 {
387         u32     res;
388         res = _rtw_init_cmd_priv(pcmdpriv);
389         return res;
390 }
391
392 u32     rtw_init_evt_priv(struct        evt_priv *pevtpriv)
393 {
394         int     res;
395         res = _rtw_init_evt_priv(pevtpriv);
396         return res;
397 }
398
399 void rtw_free_evt_priv(struct   evt_priv *pevtpriv)
400 {
401         _rtw_free_evt_priv(pevtpriv);
402 }
403
404 void rtw_free_cmd_priv(struct   cmd_priv *pcmdpriv)
405 {
406         _rtw_free_cmd_priv(pcmdpriv);
407 }
408
409 int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj);
410 int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
411 {
412         u8 bAllow = _FALSE; /* set to _TRUE to allow enqueuing cmd when hw_init_completed is _FALSE */
413
414 #ifdef SUPPORT_HW_RFOFF_DETECTED
415         /* To decide allow or not */
416         if ((adapter_to_pwrctl(pcmdpriv->padapter)->bHWPwrPindetect)
417             && (!pcmdpriv->padapter->registrypriv.usbss_enable)
418            ) {
419                 if (cmd_obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
420                         struct drvextra_cmd_parm        *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf;
421                         if (pdrvextra_cmd_parm->ec_id == POWER_SAVING_CTRL_WK_CID) {
422                                 /* RTW_INFO("==>enqueue POWER_SAVING_CTRL_WK_CID\n"); */
423                                 bAllow = _TRUE;
424                         }
425                 }
426         }
427 #endif
428
429         if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan))
430                 bAllow = _TRUE;
431
432         if (cmd_obj->no_io)
433                 bAllow = _TRUE;
434
435         if ((!rtw_is_hw_init_completed(pcmdpriv->padapter) && (bAllow == _FALSE))
436             || ATOMIC_READ(&(pcmdpriv->cmdthd_running)) == _FALSE       /* com_thread not running */
437            ) {
438                 if (DBG_CMD_EXECUTE)
439                         RTW_INFO(ADPT_FMT" drop "CMD_FMT" hw_init_completed:%u, cmdthd_running:%u\n", ADPT_ARG(cmd_obj->padapter)
440                                 , CMD_ARG(cmd_obj), rtw_get_hw_init_completed(cmd_obj->padapter), ATOMIC_READ(&pcmdpriv->cmdthd_running));
441                 if (0)
442                         rtw_warn_on(1);
443
444                 return _FAIL;
445         }
446         return _SUCCESS;
447 }
448
449
450
451 u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
452 {
453         int res = _FAIL;
454         PADAPTER padapter = pcmdpriv->padapter;
455
456
457         if (cmd_obj == NULL)
458                 goto exit;
459
460         cmd_obj->padapter = padapter;
461
462 #ifdef CONFIG_CONCURRENT_MODE
463         /* change pcmdpriv to primary's pcmdpriv */
464         if (padapter->adapter_type != PRIMARY_ADAPTER)
465                 pcmdpriv = &(GET_PRIMARY_ADAPTER(padapter)->cmdpriv);
466 #endif
467
468         res = rtw_cmd_filter(pcmdpriv, cmd_obj);
469         if ((_FAIL == res) || (cmd_obj->cmdsz > MAX_CMDSZ)) {
470                 if (cmd_obj->cmdsz > MAX_CMDSZ) {
471                         RTW_INFO("%s failed due to obj->cmdsz(%d) > MAX_CMDSZ(%d)\n", __func__, cmd_obj->cmdsz, MAX_CMDSZ);
472                         rtw_warn_on(1);
473                 }
474
475                 if (cmd_obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
476                         struct drvextra_cmd_parm *extra_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf;
477
478                         if (extra_parm->pbuf && extra_parm->size > 0)
479                                 rtw_mfree(extra_parm->pbuf, extra_parm->size);
480                 }
481                 rtw_free_cmd_obj(cmd_obj);
482                 goto exit;
483         }
484
485         res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj, 0);
486
487         if (res == _SUCCESS)
488                 _rtw_up_sema(&pcmdpriv->cmd_queue_sema);
489
490 exit:
491
492
493         return res;
494 }
495
496 struct  cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv)
497 {
498         struct cmd_obj *cmd_obj;
499
500
501         cmd_obj = _rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
502
503         return cmd_obj;
504 }
505
506 void rtw_cmd_clr_isr(struct     cmd_priv *pcmdpriv)
507 {
508         pcmdpriv->cmd_done_cnt++;
509         /* _rtw_up_sema(&(pcmdpriv->cmd_done_sema)); */
510 }
511
512 void rtw_free_cmd_obj(struct cmd_obj *pcmd)
513 {
514         struct drvextra_cmd_parm *extra_parm = NULL;
515
516         if (pcmd->parmbuf != NULL) {
517                 /* free parmbuf in cmd_obj */
518                 rtw_mfree((unsigned char *)pcmd->parmbuf, pcmd->cmdsz);
519         }
520         if (pcmd->rsp != NULL) {
521                 if (pcmd->rspsz != 0) {
522                         /* free rsp in cmd_obj */
523                         rtw_mfree((unsigned char *)pcmd->rsp, pcmd->rspsz);
524                 }
525         }
526
527         /* free cmd_obj */
528         rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));
529
530 }
531
532
533 void rtw_stop_cmd_thread(_adapter *adapter)
534 {
535         if (adapter->cmdThread &&
536             ATOMIC_READ(&(adapter->cmdpriv.cmdthd_running)) == _TRUE &&
537             adapter->cmdpriv.stop_req == 0) {
538                 adapter->cmdpriv.stop_req = 1;
539                 _rtw_up_sema(&adapter->cmdpriv.cmd_queue_sema);
540                 _rtw_down_sema(&adapter->cmdpriv.terminate_cmdthread_sema);
541         }
542 }
543
544 thread_return rtw_cmd_thread(thread_context context)
545 {
546         u8 ret;
547         struct cmd_obj *pcmd;
548         u8 *pcmdbuf, *prspbuf;
549         u32 cmd_start_time;
550         u32 cmd_process_time;
551         u8(*cmd_hdl)(_adapter *padapter, u8 *pbuf);
552         void (*pcmd_callback)(_adapter *dev, struct cmd_obj *pcmd);
553         PADAPTER padapter = (PADAPTER)context;
554         struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
555         struct drvextra_cmd_parm *extra_parm = NULL;
556         _irqL irqL;
557
558         thread_enter("RTW_CMD_THREAD");
559
560         pcmdbuf = pcmdpriv->cmd_buf;
561         prspbuf = pcmdpriv->rsp_buf;
562
563         pcmdpriv->stop_req = 0;
564         ATOMIC_SET(&(pcmdpriv->cmdthd_running), _TRUE);
565         _rtw_up_sema(&pcmdpriv->terminate_cmdthread_sema);
566
567
568         while (1) {
569                 if (_rtw_down_sema(&pcmdpriv->cmd_queue_sema) == _FAIL) {
570                         RTW_PRINT(FUNC_ADPT_FMT" _rtw_down_sema(&pcmdpriv->cmd_queue_sema) return _FAIL, break\n", FUNC_ADPT_ARG(padapter));
571                         break;
572                 }
573
574                 if (RTW_CANNOT_RUN(padapter)) {
575                         RTW_PRINT("%s: DriverStopped(%s) SurpriseRemoved(%s) break at line %d\n",
576                                   __func__
577                                 , rtw_is_drv_stopped(padapter) ? "True" : "False"
578                                 , rtw_is_surprise_removed(padapter) ? "True" : "False"
579                                   , __LINE__);
580                         break;
581                 }
582
583                 if (pcmdpriv->stop_req) {
584                         RTW_PRINT(FUNC_ADPT_FMT" stop_req:%u, break\n", FUNC_ADPT_ARG(padapter), pcmdpriv->stop_req);
585                         break;
586                 }
587
588                 _enter_critical(&pcmdpriv->cmd_queue.lock, &irqL);
589                 if (rtw_is_list_empty(&(pcmdpriv->cmd_queue.queue))) {
590                         /* RTW_INFO("%s: cmd queue is empty!\n", __func__); */
591                         _exit_critical(&pcmdpriv->cmd_queue.lock, &irqL);
592                         continue;
593                 }
594                 _exit_critical(&pcmdpriv->cmd_queue.lock, &irqL);
595
596 _next:
597                 if (RTW_CANNOT_RUN(padapter)) {
598                         RTW_PRINT("%s: DriverStopped(%s) SurpriseRemoved(%s) break at line %d\n",
599                                   __func__
600                                 , rtw_is_drv_stopped(padapter) ? "True" : "False"
601                                 , rtw_is_surprise_removed(padapter) ? "True" : "False"
602                                   , __LINE__);
603                         break;
604                 }
605
606                 pcmd = rtw_dequeue_cmd(pcmdpriv);
607                 if (!pcmd) {
608 #ifdef CONFIG_LPS_LCLK
609                         rtw_unregister_cmd_alive(padapter);
610 #endif
611                         continue;
612                 }
613
614                 cmd_start_time = rtw_get_current_time();
615                 pcmdpriv->cmd_issued_cnt++;
616
617                 if (pcmd->cmdsz > MAX_CMDSZ) {
618                         RTW_ERR("%s cmdsz:%d > MAX_CMDSZ:%d\n", __func__, pcmd->cmdsz, MAX_CMDSZ);
619                         pcmd->res = H2C_PARAMETERS_ERROR;
620                         goto post_process;
621                 }
622
623                 if (pcmd->cmdcode >= (sizeof(wlancmds) / sizeof(struct cmd_hdl))) {
624                         RTW_ERR("%s undefined cmdcode:%d\n", __func__, pcmd->cmdcode);
625                         pcmd->res = H2C_PARAMETERS_ERROR;
626                         goto post_process;
627                 }
628
629                 cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
630                 if (!cmd_hdl) {
631                         RTW_ERR("%s no cmd_hdl for cmdcode:%d\n", __func__, pcmd->cmdcode);
632                         pcmd->res = H2C_PARAMETERS_ERROR;
633                         goto post_process;
634                 }
635
636                 if (_FAIL == rtw_cmd_filter(pcmdpriv, pcmd)) {
637                         pcmd->res = H2C_DROPPED;
638                         if (pcmd->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
639                                 extra_parm = (struct drvextra_cmd_parm *)pcmd->parmbuf;
640                                 if (extra_parm && extra_parm->pbuf && extra_parm->size > 0)
641                                         rtw_mfree(extra_parm->pbuf, extra_parm->size);
642                         }
643                         goto post_process;
644                 }
645
646 #ifdef CONFIG_LPS_LCLK
647                 if (pcmd->no_io)
648                         rtw_unregister_cmd_alive(padapter);
649                 else {
650                         if (rtw_register_cmd_alive(padapter) != _SUCCESS) {
651                                 if (DBG_CMD_EXECUTE)
652                                         RTW_PRINT("%s: wait to leave LPS_LCLK\n", __func__);
653
654                                 pcmd->res = H2C_ENQ_HEAD;
655                                 ret = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, pcmd, 1);
656                                 if (ret == _SUCCESS) {
657                                         if (DBG_CMD_EXECUTE)
658                                                 RTW_INFO(ADPT_FMT" "CMD_FMT" ENQ_HEAD\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd));
659                                         continue;
660                                 }
661
662                                 RTW_INFO(ADPT_FMT" "CMD_FMT" ENQ_HEAD_FAIL\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd));
663                                 pcmd->res = H2C_ENQ_HEAD_FAIL;
664                                 rtw_warn_on(1);
665                         }
666                 }
667 #endif /* CONFIG_LPS_LCLK */
668
669                 if (DBG_CMD_EXECUTE)
670                         RTW_INFO(ADPT_FMT" "CMD_FMT" %sexecute\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd)
671                                 , pcmd->res == H2C_ENQ_HEAD ? "ENQ_HEAD " : (pcmd->res == H2C_ENQ_HEAD_FAIL ? "ENQ_HEAD_FAIL " : ""));
672
673                 _rtw_memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
674                 ret = cmd_hdl(pcmd->padapter, pcmdbuf);
675                 pcmd->res = ret;
676
677                 pcmdpriv->cmd_seq++;
678
679 post_process:
680
681                 _enter_critical_mutex(&(pcmd->padapter->cmdpriv.sctx_mutex), NULL);
682                 if (pcmd->sctx) {
683                         if (0)
684                                 RTW_PRINT(FUNC_ADPT_FMT" pcmd->sctx\n",
685                                           FUNC_ADPT_ARG(pcmd->padapter));
686                         if (pcmd->res == H2C_SUCCESS)
687                                 rtw_sctx_done(&pcmd->sctx);
688                         else
689                                 rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_ERROR);
690                 }
691                 _exit_critical_mutex(&(pcmd->padapter->cmdpriv.sctx_mutex), NULL);
692
693                 cmd_process_time = rtw_get_passing_time_ms(cmd_start_time);
694                 if (cmd_process_time > 1000) {
695                         RTW_INFO(ADPT_FMT" "CMD_FMT" process_time=%d\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd), cmd_process_time);
696                         if (0)
697                                 rtw_warn_on(1);
698                 }
699
700                 /* call callback function for post-processed */
701                 if (pcmd->cmdcode < (sizeof(rtw_cmd_callback) / sizeof(struct _cmd_callback))) {
702                         pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
703                         if (pcmd_callback == NULL) {
704                                 rtw_free_cmd_obj(pcmd);
705                         } else {
706                                 /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!=NULL) */
707                                 pcmd_callback(pcmd->padapter, pcmd);/* need conider that free cmd_obj in rtw_cmd_callback */
708                         }
709                 } else {
710                         rtw_free_cmd_obj(pcmd);
711                 }
712
713                 flush_signals_thread();
714
715                 goto _next;
716
717         }
718
719 #ifdef CONFIG_LPS_LCLK
720         rtw_unregister_cmd_alive(padapter);
721 #endif
722
723         /* to avoid enqueue cmd after free all cmd_obj */
724         ATOMIC_SET(&(pcmdpriv->cmdthd_running), _FALSE);
725
726         /* free all cmd_obj resources */
727         do {
728                 pcmd = rtw_dequeue_cmd(pcmdpriv);
729                 if (pcmd == NULL)
730                         break;
731
732                 if (0)
733                         RTW_INFO("%s: leaving... drop "CMD_FMT"\n", __func__, CMD_ARG(pcmd));
734
735                 if (pcmd->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
736                         extra_parm = (struct drvextra_cmd_parm *)pcmd->parmbuf;
737                         if (extra_parm->pbuf && extra_parm->size > 0)
738                                 rtw_mfree(extra_parm->pbuf, extra_parm->size);
739                 }
740
741                 rtw_free_cmd_obj(pcmd);
742         } while (1);
743
744         _rtw_up_sema(&pcmdpriv->terminate_cmdthread_sema);
745
746
747         thread_exit();
748
749 }
750
751
752 #ifdef CONFIG_EVENT_THREAD_MODE
753 u32 rtw_enqueue_evt(struct evt_priv *pevtpriv, struct evt_obj *obj)
754 {
755         _irqL irqL;
756         int     res;
757         _queue *queue = &pevtpriv->evt_queue;
758
759
760         res = _SUCCESS;
761
762         if (obj == NULL) {
763                 res = _FAIL;
764                 goto exit;
765         }
766
767         _enter_critical_bh(&queue->lock, &irqL);
768
769         rtw_list_insert_tail(&obj->list, &queue->queue);
770
771         _exit_critical_bh(&queue->lock, &irqL);
772
773         /* rtw_evt_notify_isr(pevtpriv); */
774
775 exit:
776
777
778         return res;
779 }
780
781 struct evt_obj *rtw_dequeue_evt(_queue *queue)
782 {
783         _irqL irqL;
784         struct  evt_obj *pevtobj;
785
786
787         _enter_critical_bh(&queue->lock, &irqL);
788
789         if (rtw_is_list_empty(&(queue->queue)))
790                 pevtobj = NULL;
791         else {
792                 pevtobj = LIST_CONTAINOR(get_next(&(queue->queue)), struct evt_obj, list);
793                 rtw_list_delete(&pevtobj->list);
794         }
795
796         _exit_critical_bh(&queue->lock, &irqL);
797
798
799         return pevtobj;
800 }
801
802 void rtw_free_evt_obj(struct evt_obj *pevtobj)
803 {
804
805         if (pevtobj->parmbuf)
806                 rtw_mfree((unsigned char *)pevtobj->parmbuf, pevtobj->evtsz);
807
808         rtw_mfree((unsigned char *)pevtobj, sizeof(struct evt_obj));
809
810 }
811
812 void rtw_evt_notify_isr(struct evt_priv *pevtpriv)
813 {
814         pevtpriv->evt_done_cnt++;
815         _rtw_up_sema(&(pevtpriv->evt_notify));
816 }
817 #endif
818
819
820 /*
821 u8 rtw_setstandby_cmd(unsigned char  *adapter)
822 */
823 u8 rtw_setstandby_cmd(_adapter *padapter, uint action)
824 {
825         struct cmd_obj                  *ph2c;
826         struct usb_suspend_parm *psetusbsuspend;
827         struct cmd_priv                 *pcmdpriv = &padapter->cmdpriv;
828
829         u8 ret = _SUCCESS;
830
831
832         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
833         if (ph2c == NULL) {
834                 ret = _FAIL;
835                 goto exit;
836         }
837
838         psetusbsuspend = (struct usb_suspend_parm *)rtw_zmalloc(sizeof(struct usb_suspend_parm));
839         if (psetusbsuspend == NULL) {
840                 rtw_mfree((u8 *) ph2c, sizeof(struct    cmd_obj));
841                 ret = _FAIL;
842                 goto exit;
843         }
844
845         psetusbsuspend->action = action;
846
847         init_h2fwcmd_w_parm_no_rsp(ph2c, psetusbsuspend, GEN_CMD_CODE(_SetUsbSuspend));
848
849         ret = rtw_enqueue_cmd(pcmdpriv, ph2c);
850
851 exit:
852
853
854         return ret;
855 }
856
857 /*
858 rtw_sitesurvey_cmd(~)
859         ### NOTE:#### (!!!!)
860         MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock
861 */
862 u8 rtw_sitesurvey_cmd(_adapter  *padapter, NDIS_802_11_SSID *ssid, int ssid_num,
863                       struct rtw_ieee80211_channel *ch, int ch_num)
864 {
865         u8 res = _FAIL;
866         struct cmd_obj          *ph2c;
867         struct sitesurvey_parm  *psurveyPara;
868         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
869         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
870 #ifdef CONFIG_P2P
871         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
872 #endif /* CONFIG_P2P */
873
874
875 #ifdef CONFIG_LPS
876         if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
877                 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1);
878 #endif
879
880 #ifdef CONFIG_P2P_PS
881         if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
882                 p2p_ps_wk_cmd(padapter, P2P_PS_SCAN, 1);
883 #endif /* CONFIG_P2P_PS */
884
885         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
886         if (ph2c == NULL)
887                 return _FAIL;
888
889         psurveyPara = (struct sitesurvey_parm *)rtw_zmalloc(sizeof(struct sitesurvey_parm));
890         if (psurveyPara == NULL) {
891                 rtw_mfree((unsigned char *) ph2c, sizeof(struct cmd_obj));
892                 return _FAIL;
893         }
894
895         rtw_free_network_queue(padapter, _FALSE);
896
897
898         init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
899
900         /* psurveyPara->bsslimit = 48; */
901         psurveyPara->scan_mode = pmlmepriv->scan_mode;
902
903         /* prepare ssid list */
904         if (ssid) {
905                 int i;
906                 for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {
907                         if (ssid[i].SsidLength) {
908                                 _rtw_memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(NDIS_802_11_SSID));
909                                 psurveyPara->ssid_num++;
910                                 if (0)
911                                         RTW_INFO(FUNC_ADPT_FMT" ssid:(%s, %d)\n", FUNC_ADPT_ARG(padapter),
912                                                 psurveyPara->ssid[i].Ssid, psurveyPara->ssid[i].SsidLength);
913                         }
914                 }
915         }
916
917         /* prepare channel list */
918         if (ch) {
919                 int i;
920                 for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
921                         if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) {
922                                 _rtw_memcpy(&psurveyPara->ch[i], &ch[i], sizeof(struct rtw_ieee80211_channel));
923                                 psurveyPara->ch_num++;
924                                 if (0)
925                                         RTW_INFO(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter),
926                                                  psurveyPara->ch[i].hw_value);
927                         }
928                 }
929         }
930
931         set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
932
933         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
934
935         if (res == _SUCCESS) {
936
937                 pmlmepriv->scan_start_time = rtw_get_current_time();
938
939 #ifdef CONFIG_SCAN_BACKOP
940                 if (rtw_mi_buddy_check_mlmeinfo_state(padapter, WIFI_FW_AP_STATE)) {
941                         if (is_supported_5g(padapter->registrypriv.wireless_mode)
942                             && IsSupported24G(padapter->registrypriv.wireless_mode)) /* dual band */
943                                 mlme_set_scan_to_timer(pmlmepriv, CONC_SCANNING_TIMEOUT_DUAL_BAND);
944                         else /* single band */
945                                 mlme_set_scan_to_timer(pmlmepriv, CONC_SCANNING_TIMEOUT_SINGLE_BAND);
946                 } else
947 #endif /* CONFIG_SCAN_BACKOP */
948                         mlme_set_scan_to_timer(pmlmepriv, SCANNING_TIMEOUT);
949
950                 rtw_led_control(padapter, LED_CTL_SITE_SURVEY);
951         } else
952                 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
953
954
955         return res;
956 }
957
958 u8 rtw_setdatarate_cmd(_adapter *padapter, u8 *rateset)
959 {
960         struct cmd_obj                  *ph2c;
961         struct setdatarate_parm *pbsetdataratepara;
962         struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
963         u8      res = _SUCCESS;
964
965
966         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
967         if (ph2c == NULL) {
968                 res = _FAIL;
969                 goto exit;
970         }
971
972         pbsetdataratepara = (struct setdatarate_parm *)rtw_zmalloc(sizeof(struct setdatarate_parm));
973         if (pbsetdataratepara == NULL) {
974                 rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
975                 res = _FAIL;
976                 goto exit;
977         }
978
979         init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, GEN_CMD_CODE(_SetDataRate));
980 #ifdef MP_FIRMWARE_OFFLOAD
981         pbsetdataratepara->curr_rateidx = *(u32 *)rateset;
982         /*      _rtw_memcpy(pbsetdataratepara, rateset, sizeof(u32)); */
983 #else
984         pbsetdataratepara->mac_id = 5;
985         _rtw_memcpy(pbsetdataratepara->datarates, rateset, NumRates);
986 #endif
987         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
988 exit:
989
990
991         return res;
992 }
993
994 u8 rtw_setbasicrate_cmd(_adapter *padapter, u8 *rateset)
995 {
996         struct cmd_obj                  *ph2c;
997         struct setbasicrate_parm        *pssetbasicratepara;
998         struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
999         u8      res = _SUCCESS;
1000
1001
1002         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1003         if (ph2c == NULL) {
1004                 res = _FAIL;
1005                 goto exit;
1006         }
1007         pssetbasicratepara = (struct setbasicrate_parm *)rtw_zmalloc(sizeof(struct setbasicrate_parm));
1008
1009         if (pssetbasicratepara == NULL) {
1010                 rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
1011                 res = _FAIL;
1012                 goto exit;
1013         }
1014
1015         init_h2fwcmd_w_parm_no_rsp(ph2c, pssetbasicratepara, _SetBasicRate_CMD_);
1016
1017         _rtw_memcpy(pssetbasicratepara->basicrates, rateset, NumRates);
1018
1019         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1020 exit:
1021
1022
1023         return res;
1024 }
1025
1026
1027 /*
1028 unsigned char rtw_setphy_cmd(unsigned char  *adapter)
1029
1030 1.  be called only after rtw_update_registrypriv_dev_network( ~) or mp testing program
1031 2.  for AdHoc/Ap mode or mp mode?
1032
1033 */
1034 u8 rtw_setphy_cmd(_adapter *padapter, u8 modem, u8 ch)
1035 {
1036         struct cmd_obj                  *ph2c;
1037         struct setphy_parm              *psetphypara;
1038         struct cmd_priv                 *pcmdpriv = &padapter->cmdpriv;
1039         /*      struct mlme_priv                        *pmlmepriv = &padapter->mlmepriv;
1040          *      struct registry_priv*           pregistry_priv = &padapter->registrypriv; */
1041         u8      res = _SUCCESS;
1042
1043
1044         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1045         if (ph2c == NULL) {
1046                 res = _FAIL;
1047                 goto exit;
1048         }
1049         psetphypara = (struct setphy_parm *)rtw_zmalloc(sizeof(struct setphy_parm));
1050
1051         if (psetphypara == NULL) {
1052                 rtw_mfree((u8 *) ph2c, sizeof(struct    cmd_obj));
1053                 res = _FAIL;
1054                 goto exit;
1055         }
1056
1057         init_h2fwcmd_w_parm_no_rsp(ph2c, psetphypara, _SetPhy_CMD_);
1058
1059
1060         psetphypara->modem = modem;
1061         psetphypara->rfchannel = ch;
1062
1063         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1064 exit:
1065         return res;
1066 }
1067
1068 u8 rtw_getmacreg_cmd(_adapter *padapter, u8 len, u32 addr)
1069 {
1070         struct cmd_obj *ph2c;
1071         struct readMAC_parm *preadmacparm;
1072         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1073         u8      res = _SUCCESS;
1074
1075         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1076         if (ph2c == NULL) {
1077                 res = _FAIL;
1078                 goto exit;
1079         }
1080         preadmacparm = (struct readMAC_parm *)rtw_zmalloc(sizeof(struct readMAC_parm));
1081
1082         if (preadmacparm == NULL) {
1083                 rtw_mfree((u8 *) ph2c, sizeof(struct    cmd_obj));
1084                 res = _FAIL;
1085                 goto exit;
1086         }
1087
1088         init_h2fwcmd_w_parm_no_rsp(ph2c, preadmacparm, GEN_CMD_CODE(_GetMACReg));
1089
1090         preadmacparm->len = len;
1091         preadmacparm->addr = addr;
1092
1093         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1094
1095 exit:
1096         return res;
1097 }
1098
1099 void rtw_usb_catc_trigger_cmd(_adapter *padapter, const char *caller)
1100 {
1101         RTW_INFO("%s caller:%s\n", __func__, caller);
1102         rtw_getmacreg_cmd(padapter, 1, 0x1c4);
1103 }
1104
1105 u8 rtw_setbbreg_cmd(_adapter *padapter, u8 offset, u8 val)
1106 {
1107         struct cmd_obj                  *ph2c;
1108         struct writeBB_parm             *pwritebbparm;
1109         struct cmd_priv                 *pcmdpriv = &padapter->cmdpriv;
1110         u8      res = _SUCCESS;
1111         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1112         if (ph2c == NULL) {
1113                 res = _FAIL;
1114                 goto exit;
1115         }
1116         pwritebbparm = (struct writeBB_parm *)rtw_zmalloc(sizeof(struct writeBB_parm));
1117
1118         if (pwritebbparm == NULL) {
1119                 rtw_mfree((u8 *) ph2c, sizeof(struct    cmd_obj));
1120                 res = _FAIL;
1121                 goto exit;
1122         }
1123
1124         init_h2fwcmd_w_parm_no_rsp(ph2c, pwritebbparm, GEN_CMD_CODE(_SetBBReg));
1125
1126         pwritebbparm->offset = offset;
1127         pwritebbparm->value = val;
1128
1129         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1130 exit:
1131         return res;
1132 }
1133
1134 u8 rtw_getbbreg_cmd(_adapter  *padapter, u8 offset, u8 *pval)
1135 {
1136         struct cmd_obj                  *ph2c;
1137         struct readBB_parm              *prdbbparm;
1138         struct cmd_priv                 *pcmdpriv = &padapter->cmdpriv;
1139         u8      res = _SUCCESS;
1140
1141         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1142         if (ph2c == NULL) {
1143                 res = _FAIL;
1144                 goto exit;
1145         }
1146         prdbbparm = (struct readBB_parm *)rtw_zmalloc(sizeof(struct readBB_parm));
1147
1148         if (prdbbparm == NULL) {
1149                 rtw_mfree((unsigned char *) ph2c, sizeof(struct cmd_obj));
1150                 return _FAIL;
1151         }
1152
1153         _rtw_init_listhead(&ph2c->list);
1154         ph2c->cmdcode = GEN_CMD_CODE(_GetBBReg);
1155         ph2c->parmbuf = (unsigned char *)prdbbparm;
1156         ph2c->cmdsz =  sizeof(struct readBB_parm);
1157         ph2c->rsp = pval;
1158         ph2c->rspsz = sizeof(struct readBB_rsp);
1159
1160         prdbbparm->offset = offset;
1161
1162         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1163 exit:
1164         return res;
1165 }
1166
1167 u8 rtw_setrfreg_cmd(_adapter  *padapter, u8 offset, u32 val)
1168 {
1169         struct cmd_obj                  *ph2c;
1170         struct writeRF_parm             *pwriterfparm;
1171         struct cmd_priv                 *pcmdpriv = &padapter->cmdpriv;
1172         u8      res = _SUCCESS;
1173         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1174         if (ph2c == NULL) {
1175                 res = _FAIL;
1176                 goto exit;
1177         }
1178         pwriterfparm = (struct writeRF_parm *)rtw_zmalloc(sizeof(struct writeRF_parm));
1179
1180         if (pwriterfparm == NULL) {
1181                 rtw_mfree((u8 *) ph2c, sizeof(struct    cmd_obj));
1182                 res = _FAIL;
1183                 goto exit;
1184         }
1185
1186         init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg));
1187
1188         pwriterfparm->offset = offset;
1189         pwriterfparm->value = val;
1190
1191         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1192 exit:
1193         return res;
1194 }
1195
1196 u8 rtw_getrfreg_cmd(_adapter  *padapter, u8 offset, u8 *pval)
1197 {
1198         struct cmd_obj                  *ph2c;
1199         struct readRF_parm              *prdrfparm;
1200         struct cmd_priv                 *pcmdpriv = &padapter->cmdpriv;
1201         u8      res = _SUCCESS;
1202
1203
1204         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1205         if (ph2c == NULL) {
1206                 res = _FAIL;
1207                 goto exit;
1208         }
1209
1210         prdrfparm = (struct readRF_parm *)rtw_zmalloc(sizeof(struct readRF_parm));
1211         if (prdrfparm == NULL) {
1212                 rtw_mfree((u8 *) ph2c, sizeof(struct    cmd_obj));
1213                 res = _FAIL;
1214                 goto exit;
1215         }
1216
1217         _rtw_init_listhead(&ph2c->list);
1218         ph2c->cmdcode = GEN_CMD_CODE(_GetRFReg);
1219         ph2c->parmbuf = (unsigned char *)prdrfparm;
1220         ph2c->cmdsz =  sizeof(struct readRF_parm);
1221         ph2c->rsp = pval;
1222         ph2c->rspsz = sizeof(struct readRF_rsp);
1223
1224         prdrfparm->offset = offset;
1225
1226         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1227
1228 exit:
1229
1230
1231         return res;
1232 }
1233
1234 void rtw_getbbrfreg_cmdrsp_callback(_adapter    *padapter,  struct cmd_obj *pcmd)
1235 {
1236
1237         /* rtw_free_cmd_obj(pcmd); */
1238         rtw_mfree((unsigned char *) pcmd->parmbuf, pcmd->cmdsz);
1239         rtw_mfree((unsigned char *) pcmd, sizeof(struct cmd_obj));
1240
1241 #ifdef CONFIG_MP_INCLUDED
1242         if (padapter->registrypriv.mp_mode == 1)
1243                 padapter->mppriv.workparam.bcompleted = _TRUE;
1244 #endif
1245 }
1246
1247 void rtw_readtssi_cmdrsp_callback(_adapter      *padapter,  struct cmd_obj *pcmd)
1248 {
1249
1250         rtw_mfree((unsigned char *) pcmd->parmbuf, pcmd->cmdsz);
1251         rtw_mfree((unsigned char *) pcmd, sizeof(struct cmd_obj));
1252
1253 #ifdef CONFIG_MP_INCLUDED
1254         if (padapter->registrypriv.mp_mode == 1)
1255                 padapter->mppriv.workparam.bcompleted = _TRUE;
1256 #endif
1257
1258 }
1259
1260 static u8 rtw_createbss_cmd(_adapter  *adapter, int flags, bool adhoc
1261                             , s16 req_ch, s8 req_bw, s8 req_offset)
1262 {
1263         struct cmd_obj *cmdobj;
1264         struct createbss_parm *parm;
1265         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1266         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1267         struct submit_ctx sctx;
1268         u8 res = _SUCCESS;
1269
1270         if (req_ch > 0 && req_bw >= 0 && req_offset >= 0) {
1271                 if (!rtw_chset_is_chbw_valid(adapter->mlmeextpriv.channel_set, req_ch, req_bw, req_offset)) {
1272                         res = _FAIL;
1273                         goto exit;
1274                 }
1275         }
1276
1277         /* prepare cmd parameter */
1278         parm = (struct createbss_parm *)rtw_zmalloc(sizeof(*parm));
1279         if (parm == NULL) {
1280                 res = _FAIL;
1281                 goto exit;
1282         }
1283
1284         if (adhoc) {
1285                 /* for now, adhoc doesn't support ch,bw,offset request */
1286                 parm->adhoc = 1;
1287         } else {
1288                 parm->adhoc = 0;
1289                 parm->req_ch = req_ch;
1290                 parm->req_bw = req_bw;
1291                 parm->req_offset = req_offset;
1292         }
1293
1294         if (flags & RTW_CMDF_DIRECTLY) {
1295                 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1296                 if (H2C_SUCCESS != createbss_hdl(adapter, (u8 *)parm))
1297                         res = _FAIL;
1298                 rtw_mfree((u8 *)parm, sizeof(*parm));
1299         } else {
1300                 /* need enqueue, prepare cmd_obj and enqueue */
1301                 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1302                 if (cmdobj == NULL) {
1303                         res = _FAIL;
1304                         rtw_mfree((u8 *)parm, sizeof(*parm));
1305                         goto exit;
1306                 }
1307
1308                 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_CreateBss));
1309
1310                 if (flags & RTW_CMDF_WAIT_ACK) {
1311                         cmdobj->sctx = &sctx;
1312                         rtw_sctx_init(&sctx, 2000);
1313                 }
1314
1315                 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
1316
1317                 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1318                         rtw_sctx_wait(&sctx, __func__);
1319                         _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1320                         if (sctx.status == RTW_SCTX_SUBMITTED)
1321                                 cmdobj->sctx = NULL;
1322                         _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1323                 }
1324         }
1325
1326 exit:
1327         return res;
1328 }
1329
1330 inline u8 rtw_create_ibss_cmd(_adapter *adapter, int flags)
1331 {
1332         return rtw_createbss_cmd(adapter, flags
1333                 , 1
1334                 , 0, -1, -1 /* for now, adhoc doesn't support ch,bw,offset request */
1335         );
1336 }
1337
1338 inline u8 rtw_startbss_cmd(_adapter *adapter, int flags)
1339 {
1340         return rtw_createbss_cmd(adapter, flags
1341                 , 0
1342                 , 0, -1, -1 /* excute entire AP setup cmd */
1343         );
1344 }
1345
1346 inline u8 rtw_change_bss_chbw_cmd(_adapter *adapter, int flags, s16 req_ch, s8 req_bw, s8 req_offset)
1347 {
1348         return rtw_createbss_cmd(adapter, flags
1349                 , 0
1350                 , req_ch, req_bw, req_offset
1351         );
1352 }
1353
1354 u8 rtw_joinbss_cmd(_adapter  *padapter, struct wlan_network *pnetwork)
1355 {
1356         u8      *auth, res = _SUCCESS;
1357         uint    t_len = 0;
1358         WLAN_BSSID_EX           *psecnetwork;
1359         struct cmd_obj          *pcmd;
1360         struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
1361         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
1362         struct qos_priv         *pqospriv = &pmlmepriv->qospriv;
1363         struct security_priv    *psecuritypriv = &padapter->securitypriv;
1364         struct registry_priv    *pregistrypriv = &padapter->registrypriv;
1365 #ifdef CONFIG_80211N_HT
1366         struct ht_priv                  *phtpriv = &pmlmepriv->htpriv;
1367 #endif /* CONFIG_80211N_HT */
1368 #ifdef CONFIG_80211AC_VHT
1369         struct vht_priv         *pvhtpriv = &pmlmepriv->vhtpriv;
1370 #endif /* CONFIG_80211AC_VHT */
1371         NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = pnetwork->network.InfrastructureMode;
1372         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1373         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1374         u32 tmp_len;
1375         u8 *ptmp = NULL;
1376 #ifdef CONFIG_RTW_80211R
1377         struct _ft_priv                 *pftpriv = &pmlmepriv->ftpriv;
1378 #endif
1379
1380         rtw_led_control(padapter, LED_CTL_START_TO_LINK);
1381
1382         pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1383         if (pcmd == NULL) {
1384                 res = _FAIL;
1385                 goto exit;
1386         }
1387 #if 0
1388         /*  for IEs is pointer */
1389         t_len = sizeof(ULONG) + sizeof(NDIS_802_11_MAC_ADDRESS) + 2 +
1390                 sizeof(NDIS_802_11_SSID) + sizeof(ULONG) +
1391                 sizeof(NDIS_802_11_RSSI) + sizeof(NDIS_802_11_NETWORK_TYPE) +
1392                 sizeof(NDIS_802_11_CONFIGURATION) +
1393                 sizeof(NDIS_802_11_NETWORK_INFRASTRUCTURE) +
1394                 sizeof(NDIS_802_11_RATES_EX) + sizeof(WLAN_PHY_INFO) + sizeof(ULONG) + MAX_IE_SZ;
1395 #endif
1396         /* for IEs is fix buf size */
1397         t_len = sizeof(WLAN_BSSID_EX);
1398
1399
1400         /* for hidden ap to set fw_state here */
1401         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) != _TRUE) {
1402                 switch (ndis_network_mode) {
1403                 case Ndis802_11IBSS:
1404                         set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
1405                         break;
1406
1407                 case Ndis802_11Infrastructure:
1408                         set_fwstate(pmlmepriv, WIFI_STATION_STATE);
1409                         break;
1410
1411                 case Ndis802_11APMode:
1412                 case Ndis802_11AutoUnknown:
1413                 case Ndis802_11InfrastructureMax:
1414                 case Ndis802_11Monitor:
1415                         break;
1416
1417                 }
1418         }
1419
1420         pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength);
1421
1422         /*
1423                 Modified by Arvin 2015/05/13
1424                 Solution for allocating a new WLAN_BSSID_EX to avoid race condition issue between disconnect and joinbss
1425         */
1426         psecnetwork = (WLAN_BSSID_EX *)rtw_zmalloc(sizeof(WLAN_BSSID_EX));
1427         if (psecnetwork == NULL) {
1428                 if (pcmd != NULL)
1429                         rtw_mfree((unsigned char *)pcmd, sizeof(struct  cmd_obj));
1430
1431                 res = _FAIL;
1432
1433
1434                 goto exit;
1435         }
1436
1437         _rtw_memset(psecnetwork, 0, t_len);
1438
1439         _rtw_memcpy(psecnetwork, &pnetwork->network, get_WLAN_BSSID_EX_sz(&pnetwork->network));
1440
1441         auth = &psecuritypriv->authenticator_ie[0];
1442         psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength;
1443
1444         if ((psecnetwork->IELength - 12) < (256 - 1))
1445                 _rtw_memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength - 12);
1446         else
1447                 _rtw_memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256 - 1));
1448
1449         psecnetwork->IELength = 0;
1450         /* Added by Albert 2009/02/18 */
1451         /* If the the driver wants to use the bssid to create the connection. */
1452         /* If not,  we have to copy the connecting AP's MAC address to it so that */
1453         /* the driver just has the bssid information for PMKIDList searching. */
1454
1455         if (pmlmepriv->assoc_by_bssid == _FALSE)
1456                 _rtw_memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
1457
1458         psecnetwork->IELength = rtw_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength);
1459
1460
1461         pqospriv->qos_option = 0;
1462
1463         if (pregistrypriv->wmm_enable) {
1464                 tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength);
1465
1466                 if (psecnetwork->IELength != tmp_len) {
1467                         psecnetwork->IELength = tmp_len;
1468                         pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
1469                 } else {
1470                         pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
1471                 }
1472         }
1473
1474 #ifdef CONFIG_80211N_HT
1475         phtpriv->ht_option = _FALSE;
1476         ptmp = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &tmp_len, pnetwork->network.IELength - 12);
1477         if (pregistrypriv->ht_enable && ptmp && tmp_len > 0) {
1478                 /*      Added by Albert 2010/06/23 */
1479                 /*      For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */
1480                 /*      Especially for Realtek 8192u SoftAP. */
1481                 if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
1482                     (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
1483                     (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
1484                         rtw_ht_use_default_setting(padapter);
1485
1486                         rtw_build_wmm_ie_ht(padapter, &psecnetwork->IEs[0], &psecnetwork->IELength);
1487
1488                         /* rtw_restructure_ht_ie */
1489                         rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[12], &psecnetwork->IEs[0],
1490                                 pnetwork->network.IELength - 12, &psecnetwork->IELength,
1491                                 pnetwork->network.Configuration.DSConfig);
1492                 }
1493         }
1494
1495 #ifdef CONFIG_80211AC_VHT
1496         pvhtpriv->vht_option = _FALSE;
1497         if (phtpriv->ht_option
1498             && REGSTY_IS_11AC_ENABLE(pregistrypriv)
1499             && hal_chk_proto_cap(padapter, PROTO_CAP_11AC)
1500             && (!pmlmepriv->country_ent || COUNTRY_CHPLAN_EN_11AC(pmlmepriv->country_ent))
1501            ) {
1502                 rtw_restructure_vht_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0],
1503                         pnetwork->network.IELength, &psecnetwork->IELength);
1504         }
1505 #endif
1506
1507         rtw_append_exented_cap(padapter, &psecnetwork->IEs[0], &psecnetwork->IELength);
1508
1509 #endif /* CONFIG_80211N_HT */
1510
1511 #ifdef CONFIG_RTW_80211R
1512         /*IEEE802.11-2012 Std. Table 8-101¡XAKM suite selectors*/
1513         if ((rtw_chk_ft_flags(padapter, RTW_FT_STA_SUPPORTED)) &&
1514                 ((psecuritypriv->rsn_akm_suite_type == 3) || (psecuritypriv->rsn_akm_suite_type == 4))
1515                 ) {
1516                 ptmp = rtw_get_ie(&pnetwork->network.IEs[12], _MDIE_, &tmp_len, pnetwork->network.IELength-12);
1517                 if (ptmp) {
1518                         _rtw_memcpy(&pftpriv->mdid, ptmp+2, 2);
1519                         pftpriv->ft_cap = *(ptmp+4);
1520
1521                         RTW_INFO("FT: Target AP "MAC_FMT" MDID=(0x%2x), capacity=(0x%2x)\n", MAC_ARG(pnetwork->network.MacAddress), pftpriv->mdid, pftpriv->ft_cap);
1522                         rtw_set_ft_flags(padapter, RTW_FT_SUPPORTED);
1523                         if ((rtw_chk_ft_flags(padapter, RTW_FT_STA_OVER_DS_SUPPORTED)) && (pftpriv->ft_roam_on_expired == _FALSE) && (pftpriv->ft_cap & 0x01))
1524                                 rtw_set_ft_flags(padapter, RTW_FT_OVER_DS_SUPPORTED);
1525                 } else {
1526                                 /*Don't use FT roaming if Target AP cannot support FT*/
1527                                 RTW_INFO("FT: Target AP "MAC_FMT" could not support FT\n", MAC_ARG(pnetwork->network.MacAddress));
1528                                 rtw_clr_ft_flags(padapter, RTW_FT_SUPPORTED|RTW_FT_OVER_DS_SUPPORTED);
1529                                 rtw_reset_ft_status(padapter);
1530                 }
1531         } else {
1532                 /*It could be a non-FT connection*/
1533                 RTW_INFO("FT: non-FT rtw_joinbss_cmd\n");
1534                 rtw_clr_ft_flags(padapter, RTW_FT_SUPPORTED|RTW_FT_OVER_DS_SUPPORTED);
1535                 rtw_reset_ft_status(padapter);
1536         }
1537 #endif
1538
1539 #if 0
1540         psecuritypriv->supplicant_ie[0] = (u8)psecnetwork->IELength;
1541
1542         if (psecnetwork->IELength < (256 - 1))
1543                 _rtw_memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], psecnetwork->IELength);
1544         else
1545                 _rtw_memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], (256 - 1));
1546 #endif
1547
1548         pcmd->cmdsz = sizeof(WLAN_BSSID_EX);
1549
1550 #ifdef CONFIG_RTL8712
1551         /* wlan_network endian conversion        */
1552         psecnetwork->Length = cpu_to_le32(psecnetwork->Length);
1553         psecnetwork->Ssid.SsidLength = cpu_to_le32(psecnetwork->Ssid.SsidLength);
1554         psecnetwork->Privacy = cpu_to_le32(psecnetwork->Privacy);
1555         psecnetwork->Rssi = cpu_to_le32(psecnetwork->Rssi);
1556         psecnetwork->NetworkTypeInUse = cpu_to_le32(psecnetwork->NetworkTypeInUse);
1557         psecnetwork->Configuration.ATIMWindow = cpu_to_le32(psecnetwork->Configuration.ATIMWindow);
1558         psecnetwork->Configuration.BeaconPeriod = cpu_to_le32(psecnetwork->Configuration.BeaconPeriod);
1559         psecnetwork->Configuration.DSConfig = cpu_to_le32(psecnetwork->Configuration.DSConfig);
1560         psecnetwork->Configuration.FHConfig.DwellTime = cpu_to_le32(psecnetwork->Configuration.FHConfig.DwellTime);
1561         psecnetwork->Configuration.FHConfig.HopPattern = cpu_to_le32(psecnetwork->Configuration.FHConfig.HopPattern);
1562         psecnetwork->Configuration.FHConfig.HopSet = cpu_to_le32(psecnetwork->Configuration.FHConfig.HopSet);
1563         psecnetwork->Configuration.FHConfig.Length = cpu_to_le32(psecnetwork->Configuration.FHConfig.Length);
1564         psecnetwork->Configuration.Length = cpu_to_le32(psecnetwork->Configuration.Length);
1565         psecnetwork->InfrastructureMode = cpu_to_le32(psecnetwork->InfrastructureMode);
1566         psecnetwork->IELength = cpu_to_le32(psecnetwork->IELength);
1567 #endif
1568
1569         _rtw_init_listhead(&pcmd->list);
1570         pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */
1571         pcmd->parmbuf = (unsigned char *)psecnetwork;
1572         pcmd->rsp = NULL;
1573         pcmd->rspsz = 0;
1574
1575         res = rtw_enqueue_cmd(pcmdpriv, pcmd);
1576
1577 exit:
1578
1579
1580         return res;
1581 }
1582
1583 u8 rtw_disassoc_cmd(_adapter *padapter, u32 deauth_timeout_ms, int flags) /* for sta_mode */
1584 {
1585         struct cmd_obj *cmdobj = NULL;
1586         struct disconnect_parm *param = NULL;
1587         struct cmd_priv *cmdpriv = &padapter->cmdpriv;
1588         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1589         struct submit_ctx sctx;
1590         u8 res = _SUCCESS;
1591
1592
1593
1594         /* prepare cmd parameter */
1595         param = (struct disconnect_parm *)rtw_zmalloc(sizeof(*param));
1596         if (param == NULL) {
1597                 res = _FAIL;
1598                 goto exit;
1599         }
1600         param->deauth_timeout_ms = deauth_timeout_ms;
1601
1602         if (flags & RTW_CMDF_DIRECTLY) {
1603                 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
1604                 if (disconnect_hdl(padapter, (u8 *)param) != H2C_SUCCESS)
1605                         res = _FAIL;
1606                 rtw_mfree((u8 *)param, sizeof(*param));
1607
1608         } else {
1609                 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
1610                 if (cmdobj == NULL) {
1611                         res = _FAIL;
1612                         rtw_mfree((u8 *)param, sizeof(*param));
1613                         goto exit;
1614                 }
1615                 init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
1616                 if (flags & RTW_CMDF_WAIT_ACK) {
1617                         cmdobj->sctx = &sctx;
1618                         rtw_sctx_init(&sctx, 2000);
1619                 }
1620                 res = rtw_enqueue_cmd(cmdpriv, cmdobj);
1621                 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
1622                         rtw_sctx_wait(&sctx, __func__);
1623                         _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1624                         if (sctx.status == RTW_SCTX_SUBMITTED)
1625                                 cmdobj->sctx = NULL;
1626                         _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
1627                 }
1628         }
1629
1630 exit:
1631
1632
1633         return res;
1634 }
1635
1636 u8 rtw_setopmode_cmd(_adapter  *padapter, NDIS_802_11_NETWORK_INFRASTRUCTURE networktype, bool enqueue)
1637 {
1638         struct  cmd_obj *ph2c;
1639         struct  setopmode_parm *psetop;
1640
1641         struct  cmd_priv   *pcmdpriv = &padapter->cmdpriv;
1642         u8      res = _SUCCESS;
1643
1644         psetop = (struct setopmode_parm *)rtw_zmalloc(sizeof(struct setopmode_parm));
1645
1646         if (psetop == NULL) {
1647                 res = _FAIL;
1648                 goto exit;
1649         }
1650         psetop->mode = (u8)networktype;
1651
1652         if (enqueue) {
1653                 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1654                 if (ph2c == NULL) {
1655                         rtw_mfree((u8 *)psetop, sizeof(*psetop));
1656                         res = _FAIL;
1657                         goto exit;
1658                 }
1659
1660                 init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
1661                 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1662         } else {
1663                 setopmode_hdl(padapter, (u8 *)psetop);
1664                 rtw_mfree((u8 *)psetop, sizeof(*psetop));
1665         }
1666 exit:
1667
1668
1669         return res;
1670 }
1671
1672 u8 rtw_setstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 key_type, bool enqueue)
1673 {
1674         struct cmd_obj                  *ph2c;
1675         struct set_stakey_parm  *psetstakey_para;
1676         struct cmd_priv                 *pcmdpriv = &padapter->cmdpriv;
1677         struct set_stakey_rsp           *psetstakey_rsp = NULL;
1678
1679         struct mlme_priv                        *pmlmepriv = &padapter->mlmepriv;
1680         struct security_priv            *psecuritypriv = &padapter->securitypriv;
1681         u8      res = _SUCCESS;
1682
1683
1684         psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
1685         if (psetstakey_para == NULL) {
1686                 res = _FAIL;
1687                 goto exit;
1688         }
1689
1690         _rtw_memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN);
1691
1692         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
1693                 psetstakey_para->algorithm = (unsigned char) psecuritypriv->dot11PrivacyAlgrthm;
1694         else
1695                 GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, _FALSE);
1696
1697         if (key_type == GROUP_KEY)
1698                 _rtw_memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16);
1699         else if (key_type == UNICAST_KEY)
1700                 _rtw_memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);
1701 #ifdef CONFIG_TDLS
1702         else if (key_type == TDLS_KEY) {
1703                 _rtw_memcpy(&psetstakey_para->key, sta->tpk.tk, 16);
1704                 psetstakey_para->algorithm = (u8)sta->dot118021XPrivacy;
1705         }
1706 #endif /* CONFIG_TDLS */
1707
1708         /* jeff: set this becasue at least sw key is ready */
1709         padapter->securitypriv.busetkipkey = _TRUE;
1710
1711         if (enqueue) {
1712                 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1713                 if (ph2c == NULL) {
1714                         rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1715                         res = _FAIL;
1716                         goto exit;
1717                 }
1718
1719                 psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp));
1720                 if (psetstakey_rsp == NULL) {
1721                         rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
1722                         rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1723                         res = _FAIL;
1724                         goto exit;
1725                 }
1726
1727                 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
1728                 ph2c->rsp = (u8 *) psetstakey_rsp;
1729                 ph2c->rspsz = sizeof(struct set_stakey_rsp);
1730                 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1731         } else {
1732                 set_stakey_hdl(padapter, (u8 *)psetstakey_para);
1733                 rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1734         }
1735 exit:
1736
1737
1738         return res;
1739 }
1740
1741 u8 rtw_clearstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 enqueue)
1742 {
1743         struct cmd_obj                  *ph2c;
1744         struct set_stakey_parm  *psetstakey_para;
1745         struct cmd_priv                 *pcmdpriv = &padapter->cmdpriv;
1746         struct set_stakey_rsp           *psetstakey_rsp = NULL;
1747         struct mlme_priv                        *pmlmepriv = &padapter->mlmepriv;
1748         struct security_priv            *psecuritypriv = &padapter->securitypriv;
1749         s16 cam_id = 0;
1750         u8      res = _SUCCESS;
1751
1752
1753         if (!enqueue) {
1754                 while ((cam_id = rtw_camid_search(padapter, sta->hwaddr, -1, -1)) >= 0) {
1755                         RTW_PRINT("clear key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(sta->hwaddr), cam_id);
1756                         clear_cam_entry(padapter, cam_id);
1757                         rtw_camid_free(padapter, cam_id);
1758                 }
1759         } else {
1760                 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1761                 if (ph2c == NULL) {
1762                         res = _FAIL;
1763                         goto exit;
1764                 }
1765
1766                 psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
1767                 if (psetstakey_para == NULL) {
1768                         rtw_mfree((u8 *) ph2c, sizeof(struct    cmd_obj));
1769                         res = _FAIL;
1770                         goto exit;
1771                 }
1772
1773                 psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp));
1774                 if (psetstakey_rsp == NULL) {
1775                         rtw_mfree((u8 *) ph2c, sizeof(struct    cmd_obj));
1776                         rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
1777                         res = _FAIL;
1778                         goto exit;
1779                 }
1780
1781                 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
1782                 ph2c->rsp = (u8 *) psetstakey_rsp;
1783                 ph2c->rspsz = sizeof(struct set_stakey_rsp);
1784
1785                 _rtw_memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN);
1786
1787                 psetstakey_para->algorithm = _NO_PRIVACY_;
1788
1789                 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1790
1791         }
1792
1793 exit:
1794
1795
1796         return res;
1797 }
1798
1799 u8 rtw_setrttbl_cmd(_adapter  *padapter, struct setratable_parm *prate_table)
1800 {
1801         struct cmd_obj                  *ph2c;
1802         struct setratable_parm  *psetrttblparm;
1803         struct cmd_priv                 *pcmdpriv = &padapter->cmdpriv;
1804         u8      res = _SUCCESS;
1805
1806         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1807         if (ph2c == NULL) {
1808                 res = _FAIL;
1809                 goto exit;
1810         }
1811         psetrttblparm = (struct setratable_parm *)rtw_zmalloc(sizeof(struct setratable_parm));
1812
1813         if (psetrttblparm == NULL) {
1814                 rtw_mfree((unsigned char *) ph2c, sizeof(struct cmd_obj));
1815                 res = _FAIL;
1816                 goto exit;
1817         }
1818
1819         init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, GEN_CMD_CODE(_SetRaTable));
1820
1821         _rtw_memcpy(psetrttblparm, prate_table, sizeof(struct setratable_parm));
1822
1823         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1824 exit:
1825         return res;
1826
1827 }
1828
1829 u8 rtw_getrttbl_cmd(_adapter  *padapter, struct getratable_rsp *pval)
1830 {
1831         struct cmd_obj                  *ph2c;
1832         struct getratable_parm  *pgetrttblparm;
1833         struct cmd_priv                 *pcmdpriv = &padapter->cmdpriv;
1834         u8      res = _SUCCESS;
1835
1836         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1837         if (ph2c == NULL) {
1838                 res = _FAIL;
1839                 goto exit;
1840         }
1841         pgetrttblparm = (struct getratable_parm *)rtw_zmalloc(sizeof(struct getratable_parm));
1842
1843         if (pgetrttblparm == NULL) {
1844                 rtw_mfree((unsigned char *) ph2c, sizeof(struct cmd_obj));
1845                 res = _FAIL;
1846                 goto exit;
1847         }
1848
1849         /*      init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, GEN_CMD_CODE(_SetRaTable)); */
1850
1851         _rtw_init_listhead(&ph2c->list);
1852         ph2c->cmdcode = GEN_CMD_CODE(_GetRaTable);
1853         ph2c->parmbuf = (unsigned char *)pgetrttblparm;
1854         ph2c->cmdsz =  sizeof(struct getratable_parm);
1855         ph2c->rsp = (u8 *)pval;
1856         ph2c->rspsz = sizeof(struct getratable_rsp);
1857
1858         pgetrttblparm->rsvd = 0x0;
1859
1860         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1861 exit:
1862         return res;
1863
1864 }
1865
1866 u8 rtw_setassocsta_cmd(_adapter  *padapter, u8 *mac_addr)
1867 {
1868         struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
1869         struct cmd_obj                  *ph2c;
1870         struct set_assocsta_parm        *psetassocsta_para;
1871         struct set_stakey_rsp           *psetassocsta_rsp = NULL;
1872
1873         u8      res = _SUCCESS;
1874
1875
1876         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1877         if (ph2c == NULL) {
1878                 res = _FAIL;
1879                 goto exit;
1880         }
1881
1882         psetassocsta_para = (struct set_assocsta_parm *)rtw_zmalloc(sizeof(struct set_assocsta_parm));
1883         if (psetassocsta_para == NULL) {
1884                 rtw_mfree((u8 *) ph2c, sizeof(struct    cmd_obj));
1885                 res = _FAIL;
1886                 goto exit;
1887         }
1888
1889         psetassocsta_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_assocsta_rsp));
1890         if (psetassocsta_rsp == NULL) {
1891                 rtw_mfree((u8 *) ph2c, sizeof(struct    cmd_obj));
1892                 rtw_mfree((u8 *) psetassocsta_para, sizeof(struct set_assocsta_parm));
1893                 return _FAIL;
1894         }
1895
1896         init_h2fwcmd_w_parm_no_rsp(ph2c, psetassocsta_para, _SetAssocSta_CMD_);
1897         ph2c->rsp = (u8 *) psetassocsta_rsp;
1898         ph2c->rspsz = sizeof(struct set_assocsta_rsp);
1899
1900         _rtw_memcpy(psetassocsta_para->addr, mac_addr, ETH_ALEN);
1901
1902         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1903
1904 exit:
1905
1906
1907         return res;
1908 }
1909
1910 u8 rtw_addbareq_cmd(_adapter *padapter, u8 tid, u8 *addr)
1911 {
1912         struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
1913         struct cmd_obj          *ph2c;
1914         struct addBaReq_parm    *paddbareq_parm;
1915
1916         u8      res = _SUCCESS;
1917
1918
1919         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1920         if (ph2c == NULL) {
1921                 res = _FAIL;
1922                 goto exit;
1923         }
1924
1925         paddbareq_parm = (struct addBaReq_parm *)rtw_zmalloc(sizeof(struct addBaReq_parm));
1926         if (paddbareq_parm == NULL) {
1927                 rtw_mfree((unsigned char *)ph2c, sizeof(struct  cmd_obj));
1928                 res = _FAIL;
1929                 goto exit;
1930         }
1931
1932         paddbareq_parm->tid = tid;
1933         _rtw_memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
1934
1935         init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq));
1936
1937         /* RTW_INFO("rtw_addbareq_cmd, tid=%d\n", tid); */
1938
1939         /* rtw_enqueue_cmd(pcmdpriv, ph2c);      */
1940         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1941
1942 exit:
1943
1944
1945         return res;
1946 }
1947
1948 u8 rtw_addbarsp_cmd(_adapter *padapter, u8 *addr, u16 tid, u8 status, u8 size, u16 start_seq)
1949 {
1950         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1951         struct cmd_obj *ph2c;
1952         struct addBaRsp_parm *paddBaRsp_parm;
1953         u8 res = _SUCCESS;
1954
1955
1956         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1957         if (ph2c == NULL) {
1958                 res = _FAIL;
1959                 goto exit;
1960         }
1961
1962         paddBaRsp_parm = (struct addBaRsp_parm *)rtw_zmalloc(sizeof(struct addBaRsp_parm));
1963
1964         if (paddBaRsp_parm == NULL) {
1965                 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
1966                 res = _FAIL;
1967                 goto exit;
1968         }
1969
1970         _rtw_memcpy(paddBaRsp_parm->addr, addr, ETH_ALEN);
1971         paddBaRsp_parm->tid = tid;
1972         paddBaRsp_parm->status = status;
1973         paddBaRsp_parm->size = size;
1974         paddBaRsp_parm->start_seq = start_seq;
1975
1976         init_h2fwcmd_w_parm_no_rsp(ph2c, paddBaRsp_parm, GEN_CMD_CODE(_AddBARsp));
1977
1978         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1979
1980 exit:
1981
1982
1983         return res;
1984 }
1985 /* add for CONFIG_IEEE80211W, none 11w can use it */
1986 u8 rtw_reset_securitypriv_cmd(_adapter *padapter)
1987 {
1988         struct cmd_obj          *ph2c;
1989         struct drvextra_cmd_parm  *pdrvextra_cmd_parm;
1990         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1991         u8      res = _SUCCESS;
1992
1993
1994         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1995         if (ph2c == NULL) {
1996                 res = _FAIL;
1997                 goto exit;
1998         }
1999
2000         pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2001         if (pdrvextra_cmd_parm == NULL) {
2002                 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
2003                 res = _FAIL;
2004                 goto exit;
2005         }
2006
2007         pdrvextra_cmd_parm->ec_id = RESET_SECURITYPRIV;
2008         pdrvextra_cmd_parm->type = 0;
2009         pdrvextra_cmd_parm->size = 0;
2010         pdrvextra_cmd_parm->pbuf = NULL;
2011
2012         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
2013
2014
2015         /* rtw_enqueue_cmd(pcmdpriv, ph2c);      */
2016         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
2017
2018 exit:
2019
2020
2021         return res;
2022
2023 }
2024
2025 u8 rtw_free_assoc_resources_cmd(_adapter *padapter)
2026 {
2027         struct cmd_obj          *ph2c;
2028         struct drvextra_cmd_parm  *pdrvextra_cmd_parm;
2029         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2030         u8      res = _SUCCESS;
2031
2032
2033         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2034         if (ph2c == NULL) {
2035                 res = _FAIL;
2036                 goto exit;
2037         }
2038
2039         pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2040         if (pdrvextra_cmd_parm == NULL) {
2041                 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
2042                 res = _FAIL;
2043                 goto exit;
2044         }
2045
2046         pdrvextra_cmd_parm->ec_id = FREE_ASSOC_RESOURCES;
2047         pdrvextra_cmd_parm->type = 0;
2048         pdrvextra_cmd_parm->size = 0;
2049         pdrvextra_cmd_parm->pbuf = NULL;
2050
2051         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
2052
2053
2054         /* rtw_enqueue_cmd(pcmdpriv, ph2c);      */
2055         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
2056
2057 exit:
2058
2059
2060         return res;
2061
2062 }
2063
2064 u8 rtw_dynamic_chk_wk_cmd(_adapter *padapter)
2065 {
2066         struct cmd_obj          *ph2c;
2067         struct drvextra_cmd_parm  *pdrvextra_cmd_parm;
2068         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2069         u8      res = _SUCCESS;
2070
2071
2072         /* only  primary padapter does this cmd */
2073
2074         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2075         if (ph2c == NULL) {
2076                 res = _FAIL;
2077                 goto exit;
2078         }
2079
2080         pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2081         if (pdrvextra_cmd_parm == NULL) {
2082                 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
2083                 res = _FAIL;
2084                 goto exit;
2085         }
2086
2087         pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
2088         pdrvextra_cmd_parm->type = 0;
2089         pdrvextra_cmd_parm->size = 0;
2090         pdrvextra_cmd_parm->pbuf = NULL;
2091         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
2092
2093
2094         /* rtw_enqueue_cmd(pcmdpriv, ph2c);      */
2095         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
2096
2097 exit:
2098
2099
2100         return res;
2101
2102 }
2103
2104 u8 rtw_set_ch_cmd(_adapter *padapter, u8 ch, u8 bw, u8 ch_offset, u8 enqueue)
2105 {
2106         struct cmd_obj *pcmdobj;
2107         struct set_ch_parm *set_ch_parm;
2108         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2109
2110         u8 res = _SUCCESS;
2111
2112
2113         RTW_INFO(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
2114                  FUNC_NDEV_ARG(padapter->pnetdev), ch, bw, ch_offset);
2115
2116         /* check input parameter */
2117
2118         /* prepare cmd parameter */
2119         set_ch_parm = (struct set_ch_parm *)rtw_zmalloc(sizeof(*set_ch_parm));
2120         if (set_ch_parm == NULL) {
2121                 res = _FAIL;
2122                 goto exit;
2123         }
2124         set_ch_parm->ch = ch;
2125         set_ch_parm->bw = bw;
2126         set_ch_parm->ch_offset = ch_offset;
2127
2128         if (enqueue) {
2129                 /* need enqueue, prepare cmd_obj and enqueue */
2130                 pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct   cmd_obj));
2131                 if (pcmdobj == NULL) {
2132                         rtw_mfree((u8 *)set_ch_parm, sizeof(*set_ch_parm));
2133                         res = _FAIL;
2134                         goto exit;
2135                 }
2136
2137                 init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm, GEN_CMD_CODE(_SetChannel));
2138                 res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
2139         } else {
2140                 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
2141                 if (H2C_SUCCESS != set_ch_hdl(padapter, (u8 *)set_ch_parm))
2142                         res = _FAIL;
2143
2144                 rtw_mfree((u8 *)set_ch_parm, sizeof(*set_ch_parm));
2145         }
2146
2147         /* do something based on res... */
2148
2149 exit:
2150
2151         RTW_INFO(FUNC_NDEV_FMT" res:%u\n", FUNC_NDEV_ARG(padapter->pnetdev), res);
2152
2153
2154         return res;
2155 }
2156
2157 u8 _rtw_set_chplan_cmd(_adapter *adapter, int flags, u8 chplan, const struct country_chplan *country_ent, u8 swconfig)
2158 {
2159         struct cmd_obj *cmdobj;
2160         struct  SetChannelPlan_param *parm;
2161         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
2162         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2163         struct submit_ctx sctx;
2164         u8 res = _SUCCESS;
2165
2166
2167         /* check if allow software config */
2168         if (swconfig && rtw_hal_is_disable_sw_channel_plan(adapter) == _TRUE) {
2169                 res = _FAIL;
2170                 goto exit;
2171         }
2172
2173         /* if country_entry is provided, replace chplan */
2174         if (country_ent)
2175                 chplan = country_ent->chplan;
2176
2177         /* check input parameter */
2178         if (!rtw_is_channel_plan_valid(chplan)) {
2179                 res = _FAIL;
2180                 goto exit;
2181         }
2182
2183         /* prepare cmd parameter */
2184         parm = (struct SetChannelPlan_param *)rtw_zmalloc(sizeof(*parm));
2185         if (parm == NULL) {
2186                 res = _FAIL;
2187                 goto exit;
2188         }
2189         parm->country_ent = country_ent;
2190         parm->channel_plan = chplan;
2191
2192         if (flags & RTW_CMDF_DIRECTLY) {
2193                 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
2194                 if (H2C_SUCCESS != set_chplan_hdl(adapter, (u8 *)parm))
2195                         res = _FAIL;
2196                 rtw_mfree((u8 *)parm, sizeof(*parm));
2197         } else {
2198                 /* need enqueue, prepare cmd_obj and enqueue */
2199                 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
2200                 if (cmdobj == NULL) {
2201                         res = _FAIL;
2202                         rtw_mfree((u8 *)parm, sizeof(*parm));
2203                         goto exit;
2204                 }
2205
2206                 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_SetChannelPlan));
2207
2208                 if (flags & RTW_CMDF_WAIT_ACK) {
2209                         cmdobj->sctx = &sctx;
2210                         rtw_sctx_init(&sctx, 2000);
2211                 }
2212
2213                 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
2214
2215                 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
2216                         rtw_sctx_wait(&sctx, __func__);
2217                         _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
2218                         if (sctx.status == RTW_SCTX_SUBMITTED)
2219                                 cmdobj->sctx = NULL;
2220                         _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
2221                 }
2222         }
2223
2224 exit:
2225
2226
2227         return res;
2228 }
2229
2230 inline u8 rtw_set_chplan_cmd(_adapter *adapter, int flags, u8 chplan, u8 swconfig)
2231 {
2232         return _rtw_set_chplan_cmd(adapter, flags, chplan, NULL, swconfig);
2233 }
2234
2235 inline u8 rtw_set_country_cmd(_adapter *adapter, int flags, const char *country_code, u8 swconfig)
2236 {
2237         const struct country_chplan *ent;
2238
2239         if (is_alpha(country_code[0]) == _FALSE
2240             || is_alpha(country_code[1]) == _FALSE
2241            ) {
2242                 RTW_PRINT("%s input country_code is not alpha2\n", __func__);
2243                 return _FAIL;
2244         }
2245
2246         ent = rtw_get_chplan_from_country(country_code);
2247
2248         if (ent == NULL) {
2249                 RTW_PRINT("%s unsupported country_code:\"%c%c\"\n", __func__, country_code[0], country_code[1]);
2250                 return _FAIL;
2251         }
2252
2253         RTW_PRINT("%s country_code:\"%c%c\" mapping to chplan:0x%02x\n", __func__, country_code[0], country_code[1], ent->chplan);
2254
2255         return _rtw_set_chplan_cmd(adapter, flags, RTW_CHPLAN_MAX, ent, swconfig);
2256 }
2257
2258 u8 rtw_led_blink_cmd(_adapter *padapter, PVOID pLed)
2259 {
2260         struct  cmd_obj *pcmdobj;
2261         struct  LedBlink_param *ledBlink_param;
2262         struct  cmd_priv   *pcmdpriv = &padapter->cmdpriv;
2263
2264         u8      res = _SUCCESS;
2265
2266
2267
2268         pcmdobj = (struct       cmd_obj *)rtw_zmalloc(sizeof(struct     cmd_obj));
2269         if (pcmdobj == NULL) {
2270                 res = _FAIL;
2271                 goto exit;
2272         }
2273
2274         ledBlink_param = (struct        LedBlink_param *)rtw_zmalloc(sizeof(struct      LedBlink_param));
2275         if (ledBlink_param == NULL) {
2276                 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
2277                 res = _FAIL;
2278                 goto exit;
2279         }
2280
2281         ledBlink_param->pLed = pLed;
2282
2283         init_h2fwcmd_w_parm_no_rsp(pcmdobj, ledBlink_param, GEN_CMD_CODE(_LedBlink));
2284         res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
2285
2286 exit:
2287
2288
2289         return res;
2290 }
2291
2292 u8 rtw_set_csa_cmd(_adapter *padapter, u8 new_ch_no)
2293 {
2294         struct  cmd_obj *pcmdobj;
2295         struct  SetChannelSwitch_param *setChannelSwitch_param;
2296         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
2297         struct  cmd_priv   *pcmdpriv = &padapter->cmdpriv;
2298
2299         u8      res = _SUCCESS;
2300
2301
2302
2303         pcmdobj = (struct       cmd_obj *)rtw_zmalloc(sizeof(struct     cmd_obj));
2304         if (pcmdobj == NULL) {
2305                 res = _FAIL;
2306                 goto exit;
2307         }
2308
2309         setChannelSwitch_param = (struct SetChannelSwitch_param *)rtw_zmalloc(sizeof(struct     SetChannelSwitch_param));
2310         if (setChannelSwitch_param == NULL) {
2311                 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
2312                 res = _FAIL;
2313                 goto exit;
2314         }
2315
2316         setChannelSwitch_param->new_ch_no = new_ch_no;
2317
2318         init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelSwitch_param, GEN_CMD_CODE(_SetChannelSwitch));
2319         res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
2320
2321 exit:
2322
2323
2324         return res;
2325 }
2326
2327 u8 rtw_tdls_cmd(_adapter *padapter, u8 *addr, u8 option)
2328 {
2329         struct  cmd_obj *pcmdobj;
2330         struct  TDLSoption_param        *TDLSoption;
2331         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
2332         struct  cmd_priv   *pcmdpriv = &padapter->cmdpriv;
2333
2334         u8      res = _SUCCESS;
2335
2336
2337 #ifdef CONFIG_TDLS
2338
2339
2340         pcmdobj = (struct       cmd_obj *)rtw_zmalloc(sizeof(struct     cmd_obj));
2341         if (pcmdobj == NULL) {
2342                 res = _FAIL;
2343                 goto exit;
2344         }
2345
2346         TDLSoption = (struct TDLSoption_param *)rtw_zmalloc(sizeof(struct TDLSoption_param));
2347         if (TDLSoption == NULL) {
2348                 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
2349                 res = _FAIL;
2350                 goto exit;
2351         }
2352
2353         _rtw_spinlock(&(padapter->tdlsinfo.cmd_lock));
2354         if (addr != NULL)
2355                 _rtw_memcpy(TDLSoption->addr, addr, 6);
2356         TDLSoption->option = option;
2357         _rtw_spinunlock(&(padapter->tdlsinfo.cmd_lock));
2358         init_h2fwcmd_w_parm_no_rsp(pcmdobj, TDLSoption, GEN_CMD_CODE(_TDLS));
2359         res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
2360
2361 #endif /* CONFIG_TDLS */
2362
2363 exit:
2364
2365
2366
2367         return res;
2368 }
2369
2370 u8 rtw_enable_hw_update_tsf_cmd(_adapter *padapter)
2371 {
2372         struct cmd_obj *ph2c;
2373         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
2374         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2375         u8      res = _SUCCESS;
2376
2377
2378         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2379         if (ph2c == NULL) {
2380                 res = _FAIL;
2381                 goto exit;
2382         }
2383
2384         pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2385         if (pdrvextra_cmd_parm == NULL) {
2386                 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
2387                 res = _FAIL;
2388                 goto exit;
2389         }
2390
2391         pdrvextra_cmd_parm->ec_id = EN_HW_UPDATE_TSF_WK_CID;
2392         pdrvextra_cmd_parm->type = 0;
2393         pdrvextra_cmd_parm->size = 0;
2394         pdrvextra_cmd_parm->pbuf = NULL;
2395
2396         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
2397
2398         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
2399
2400 exit:
2401         return res;
2402 }
2403
2404 /* from_timer == 1 means driver is in LPS */
2405 u8 traffic_status_watchdog(_adapter *padapter, u8 from_timer)
2406 {
2407         u8      bEnterPS = _FALSE;
2408         u16 BusyThresholdHigh;
2409         u16     BusyThresholdLow;
2410         u16     BusyThreshold;
2411         u8      bBusyTraffic = _FALSE, bTxBusyTraffic = _FALSE, bRxBusyTraffic = _FALSE;
2412         u8      bHigherBusyTraffic = _FALSE, bHigherBusyRxTraffic = _FALSE, bHigherBusyTxTraffic = _FALSE;
2413
2414         struct mlme_priv                *pmlmepriv = &(padapter->mlmepriv);
2415 #ifdef CONFIG_TDLS
2416         struct tdls_info *ptdlsinfo = &(padapter->tdlsinfo);
2417         struct tdls_txmgmt txmgmt;
2418         u8 baddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2419 #endif /* CONFIG_TDLS */
2420
2421         RT_LINK_DETECT_T *link_detect = &pmlmepriv->LinkDetectInfo;
2422
2423 #ifdef CONFIG_BT_COEXIST
2424         if (padapter->registrypriv.wifi_spec != 1) {
2425                 BusyThresholdHigh = 25;
2426                 BusyThresholdLow = 10;
2427         } else
2428 #endif /* CONFIG_BT_COEXIST */
2429         {
2430                 BusyThresholdHigh = 100;
2431                 BusyThresholdLow = 75;
2432         }
2433         BusyThreshold = BusyThresholdHigh;
2434
2435
2436         /*  */
2437         /* Determine if our traffic is busy now */
2438         /*  */
2439         if ((check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
2440             /*&& !MgntInitAdapterInProgress(pMgntInfo)*/) {
2441                 /* if we raise bBusyTraffic in last watchdog, using lower threshold. */
2442                 if (pmlmepriv->LinkDetectInfo.bBusyTraffic)
2443                         BusyThreshold = BusyThresholdLow;
2444
2445                 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold ||
2446                     pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold) {
2447                         bBusyTraffic = _TRUE;
2448
2449                         if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
2450                                 bRxBusyTraffic = _TRUE;
2451                         else
2452                                 bTxBusyTraffic = _TRUE;
2453                 }
2454
2455                 /* Higher Tx/Rx data. */
2456                 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
2457                     pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
2458                         bHigherBusyTraffic = _TRUE;
2459
2460                         if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
2461                                 bHigherBusyRxTraffic = _TRUE;
2462                         else
2463                                 bHigherBusyTxTraffic = _TRUE;
2464                 }
2465
2466 #ifdef CONFIG_TRAFFIC_PROTECT
2467 #define TX_ACTIVE_TH 10
2468 #define RX_ACTIVE_TH 20
2469 #define TRAFFIC_PROTECT_PERIOD_MS 4500
2470
2471                 if (link_detect->NumTxOkInPeriod > TX_ACTIVE_TH
2472                     || link_detect->NumRxUnicastOkInPeriod > RX_ACTIVE_TH) {
2473
2474                         RTW_INFO(FUNC_ADPT_FMT" acqiure wake_lock for %u ms(tx:%d,rx_unicast:%d)\n",
2475                                  FUNC_ADPT_ARG(padapter),
2476                                  TRAFFIC_PROTECT_PERIOD_MS,
2477                                  link_detect->NumTxOkInPeriod,
2478                                  link_detect->NumRxUnicastOkInPeriod);
2479
2480                         rtw_lock_traffic_suspend_timeout(TRAFFIC_PROTECT_PERIOD_MS);
2481                 }
2482 #endif
2483
2484 #ifdef CONFIG_TDLS
2485 #ifdef CONFIG_TDLS_AUTOSETUP
2486                 /* TDLS_WATCHDOG_PERIOD * 2sec, periodically send */
2487                 if (hal_chk_wl_func(padapter, WL_FUNC_TDLS) == _TRUE) {
2488                         if ((ptdlsinfo->watchdog_count % TDLS_WATCHDOG_PERIOD) == 0) {
2489                                 _rtw_memcpy(txmgmt.peer, baddr, ETH_ALEN);
2490                                 issue_tdls_dis_req(padapter, &txmgmt);
2491                         }
2492                         ptdlsinfo->watchdog_count++;
2493                 }
2494 #endif /* CONFIG_TDLS_AUTOSETUP */
2495 #endif /* CONFIG_TDLS */
2496
2497 #ifdef CONFIG_LPS
2498                 /* check traffic for  powersaving. */
2499                 if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
2500 #ifdef CONFIG_LPS_SLOW_TRANSITION
2501                     (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2)
2502 #else /* CONFIG_LPS_SLOW_TRANSITION */
2503                     (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 4)
2504 #endif /* CONFIG_LPS_SLOW_TRANSITION */
2505                    ) {
2506 #ifdef DBG_RX_COUNTER_DUMP
2507                         if (padapter->dump_rx_cnt_mode & DUMP_DRV_TRX_COUNTER_DATA)
2508                                 RTW_INFO("(-)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);
2509 #endif
2510                         bEnterPS = _FALSE;
2511 #ifdef CONFIG_LPS_SLOW_TRANSITION
2512                         if (bBusyTraffic == _TRUE) {
2513                                 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount <= 4)
2514                                         pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 4;
2515
2516                                 pmlmepriv->LinkDetectInfo.TrafficTransitionCount++;
2517
2518                                 /* RTW_INFO("Set TrafficTransitionCount to %d\n", pmlmepriv->LinkDetectInfo.TrafficTransitionCount); */
2519
2520                                 if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount > 30/*TrafficTransitionLevel*/)
2521                                         pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 30;
2522                         }
2523 #endif /* CONFIG_LPS_SLOW_TRANSITION */
2524
2525                 } else {
2526 #ifdef DBG_RX_COUNTER_DUMP
2527                         if (padapter->dump_rx_cnt_mode & DUMP_DRV_TRX_COUNTER_DATA)
2528                                 RTW_INFO("(+)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);
2529 #endif
2530 #ifdef CONFIG_LPS_SLOW_TRANSITION
2531                         if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount >= 2)
2532                                 pmlmepriv->LinkDetectInfo.TrafficTransitionCount -= 2;
2533                         else
2534                                 pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
2535
2536                         if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount == 0)
2537                                 bEnterPS = _TRUE;
2538 #else /* CONFIG_LPS_SLOW_TRANSITION */
2539                         bEnterPS = _TRUE;
2540 #endif /* CONFIG_LPS_SLOW_TRANSITION */
2541                 }
2542
2543 #ifdef CONFIG_DYNAMIC_DTIM
2544                 if (pmlmepriv->LinkDetectInfo.LowPowerTransitionCount == 8)
2545                         bEnterPS = _FALSE;
2546
2547                 RTW_INFO("LowPowerTransitionCount=%d\n", pmlmepriv->LinkDetectInfo.LowPowerTransitionCount);
2548 #endif /* CONFIG_DYNAMIC_DTIM */
2549
2550                 /* LeisurePS only work in infra mode. */
2551                 if (bEnterPS) {
2552                         if (!from_timer) {
2553 #ifdef CONFIG_DYNAMIC_DTIM
2554                                 if (pmlmepriv->LinkDetectInfo.LowPowerTransitionCount < 8)
2555                                         adapter_to_pwrctl(padapter)->dtim = 1;
2556                                 else
2557                                         adapter_to_pwrctl(padapter)->dtim = 3;
2558 #endif /* CONFIG_DYNAMIC_DTIM */
2559                                 LPS_Enter(padapter, "TRAFFIC_IDLE");
2560                         } else {
2561                                 /* do this at caller */
2562                                 /* rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_ENTER, 1); */
2563                                 /* rtw_hal_dm_watchdog_in_lps(padapter); */
2564                         }
2565 #ifdef CONFIG_DYNAMIC_DTIM
2566                         if (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
2567                                 pmlmepriv->LinkDetectInfo.LowPowerTransitionCount++;
2568 #endif /* CONFIG_DYNAMIC_DTIM */
2569                 } else {
2570 #ifdef CONFIG_DYNAMIC_DTIM
2571                         if (pmlmepriv->LinkDetectInfo.LowPowerTransitionCount != 8)
2572                                 pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
2573                         else
2574                                 pmlmepriv->LinkDetectInfo.LowPowerTransitionCount++;
2575 #endif /* CONFIG_DYNAMIC_DTIM                    */
2576                         if (!from_timer)
2577                                 LPS_Leave(padapter, "TRAFFIC_BUSY");
2578                         else {
2579 #ifdef CONFIG_CONCURRENT_MODE
2580                                 #ifndef CONFIG_FW_MULTI_PORT_SUPPORT
2581                                 if (padapter->hw_port == HW_PORT0)
2582                                 #endif
2583 #endif
2584                                         rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_TRAFFIC_BUSY, 1);
2585                         }
2586                 }
2587
2588 #endif /* CONFIG_LPS */
2589         } else {
2590 #ifdef CONFIG_LPS
2591                 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2592                 int n_assoc_iface = 0;
2593                 int i;
2594
2595                 for (i = 0; i < dvobj->iface_nums; i++) {
2596                         if (check_fwstate(&(dvobj->padapters[i]->mlmepriv), WIFI_ASOC_STATE))
2597                                 n_assoc_iface++;
2598                 }
2599
2600                 if (!from_timer && n_assoc_iface == 0)
2601                         LPS_Leave(padapter, "NON_LINKED");
2602 #endif
2603         }
2604
2605         session_tracker_chk_cmd(padapter, NULL);
2606
2607 #ifdef CONFIG_BEAMFORMING
2608 #ifdef RTW_BEAMFORMING_VERSION_2
2609         rtw_bf_update_traffic(padapter);
2610 #endif /* RTW_BEAMFORMING_VERSION_2 */
2611 #endif /* CONFIG_BEAMFORMING */
2612
2613         pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
2614         pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
2615         pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
2616         pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
2617         pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
2618         pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
2619         pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
2620         pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
2621         pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
2622
2623         return bEnterPS;
2624
2625 }
2626
2627
2628 /* for 11n Logo 4.2.31/4.2.32 */
2629 static void dynamic_update_bcn_check(_adapter *padapter)
2630 {
2631         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2632         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2633
2634         if (!padapter->registrypriv.wifi_spec)
2635                 return;
2636
2637         if (!MLME_IS_AP(padapter))
2638                 return;
2639
2640         if (pmlmeext->bstart_bss) {
2641                 /* In 10 * 2 = 20s, there are no legacy AP, update HT info  */
2642                 static u8 count = 1;
2643
2644                 if (count % 10 == 0) {
2645                         count = 1;
2646
2647                         if (_FALSE == ATOMIC_READ(&pmlmepriv->olbc)
2648                                 && _FALSE == ATOMIC_READ(&pmlmepriv->olbc_ht)) {
2649
2650                                 if (rtw_ht_operation_update(padapter) > 0) {
2651                                         update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE);
2652                                         update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);
2653                                 }
2654                         }
2655                 }
2656
2657                 /* In 2s, there are any legacy AP, update HT info, and then reset count  */
2658
2659                 if (_FALSE != ATOMIC_READ(&pmlmepriv->olbc)
2660                         && _FALSE != ATOMIC_READ(&pmlmepriv->olbc_ht)) {
2661                                         
2662                         if (rtw_ht_operation_update(padapter) > 0) {
2663                                 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE);
2664                                 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);
2665
2666                         }
2667                         ATOMIC_SET(&pmlmepriv->olbc, _FALSE);
2668                         ATOMIC_SET(&pmlmepriv->olbc_ht, _FALSE);
2669                         count = 0;
2670                 }
2671
2672                 count ++;
2673         }
2674 }
2675 void rtw_iface_dynamic_chk_wk_hdl(_adapter *padapter)
2676 {
2677         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2678
2679         #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
2680         #ifdef CONFIG_AP_MODE
2681         if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
2682                 expire_timeout_chk(padapter);
2683         #endif
2684         #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
2685         dynamic_update_bcn_check(padapter);
2686
2687         linked_status_chk(padapter, 0);
2688         traffic_status_watchdog(padapter, 0);
2689
2690         /* for debug purpose */
2691         _linked_info_dump(padapter);
2692
2693         #ifdef CONFIG_BEAMFORMING
2694         #ifndef RTW_BEAMFORMING_VERSION_2
2695         #if (BEAMFORMING_SUPPORT == 0) /*for diver defined beamforming*/
2696         beamforming_watchdog(padapter);
2697         #endif
2698         #endif /* !RTW_BEAMFORMING_VERSION_2 */
2699         #endif
2700
2701 }
2702 void rtw_dynamic_chk_wk_hdl(_adapter *padapter)
2703 {
2704         rtw_mi_dynamic_chk_wk_hdl(padapter);
2705
2706 #ifdef DBG_CONFIG_ERROR_DETECT
2707         rtw_hal_sreset_xmit_status_check(padapter);
2708         rtw_hal_sreset_linked_status_check(padapter);
2709 #endif
2710
2711         /* if(check_fwstate(pmlmepriv, _FW_UNDER_LINKING|_FW_UNDER_SURVEY)==_FALSE) */
2712         {
2713 #ifdef DBG_RX_COUNTER_DUMP
2714                 rtw_dump_rx_counters(padapter);
2715 #endif
2716                 dm_DynamicUsbTxAgg(padapter, 0);
2717         }
2718         rtw_hal_dm_watchdog(padapter);
2719
2720         /* check_hw_pbc(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type); */
2721
2722 #ifdef CONFIG_BT_COEXIST
2723         /* BT-Coexist */
2724         rtw_btcoex_Handler(padapter);
2725 #endif
2726
2727 #ifdef CONFIG_IPS_CHECK_IN_WD
2728         /* always call rtw_ps_processor() at last one. */
2729         rtw_ps_processor(padapter);
2730 #endif
2731
2732 #ifdef CONFIG_MCC_MODE
2733         rtw_hal_mcc_sw_status_check(padapter);
2734 #endif /* CONFIG_MCC_MODE */
2735
2736 }
2737
2738 #ifdef CONFIG_LPS
2739
2740 void lps_ctrl_wk_hdl(_adapter *padapter, u8 lps_ctrl_type);
2741 void lps_ctrl_wk_hdl(_adapter *padapter, u8 lps_ctrl_type)
2742 {
2743         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
2744         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2745         u8      mstatus;
2746
2747
2748         if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)
2749             || (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE))
2750                 return;
2751
2752         switch (lps_ctrl_type) {
2753         case LPS_CTRL_SCAN:
2754                 /* RTW_INFO("LPS_CTRL_SCAN\n"); */
2755 #ifdef CONFIG_BT_COEXIST
2756                 rtw_btcoex_ScanNotify(padapter, _TRUE);
2757 #endif /* CONFIG_BT_COEXIST */
2758                 if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
2759                         /* connect */
2760                         LPS_Leave(padapter, "LPS_CTRL_SCAN");
2761                 }
2762                 break;
2763         case LPS_CTRL_JOINBSS:
2764                 /* RTW_INFO("LPS_CTRL_JOINBSS\n"); */
2765                 LPS_Leave(padapter, "LPS_CTRL_JOINBSS");
2766                 break;
2767         case LPS_CTRL_CONNECT:
2768                 /* RTW_INFO("LPS_CTRL_CONNECT\n"); */
2769                 mstatus = 1;/* connect */
2770                 /* Reset LPS Setting */
2771                 pwrpriv->LpsIdleCount = 0;
2772                 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
2773 #ifdef CONFIG_BT_COEXIST
2774                 rtw_btcoex_MediaStatusNotify(padapter, mstatus);
2775 #endif /* CONFIG_BT_COEXIST */
2776                 break;
2777         case LPS_CTRL_DISCONNECT:
2778                 /* RTW_INFO("LPS_CTRL_DISCONNECT\n"); */
2779                 mstatus = 0;/* disconnect */
2780 #ifdef CONFIG_BT_COEXIST
2781                 rtw_btcoex_MediaStatusNotify(padapter, mstatus);
2782 #endif /* CONFIG_BT_COEXIST */
2783                 LPS_Leave(padapter, "LPS_CTRL_DISCONNECT");
2784                 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
2785                 break;
2786         case LPS_CTRL_SPECIAL_PACKET:
2787                 /* RTW_INFO("LPS_CTRL_SPECIAL_PACKET\n"); */
2788                 pwrpriv->DelayLPSLastTimeStamp = rtw_get_current_time();
2789 #ifdef CONFIG_BT_COEXIST
2790                 rtw_btcoex_SpecialPacketNotify(padapter, PACKET_DHCP);
2791 #endif /* CONFIG_BT_COEXIST */
2792                 LPS_Leave(padapter, "LPS_CTRL_SPECIAL_PACKET");
2793                 break;
2794         case LPS_CTRL_LEAVE:
2795                 LPS_Leave(padapter, "LPS_CTRL_LEAVE");
2796                 break;
2797         case LPS_CTRL_LEAVE_CFG80211_PWRMGMT:
2798                 LPS_Leave(padapter, "CFG80211_PWRMGMT");
2799                 break;
2800         case LPS_CTRL_TRAFFIC_BUSY:
2801                 LPS_Leave(padapter, "LPS_CTRL_TRAFFIC_BUSY");
2802                 break;
2803         case LPS_CTRL_TX_TRAFFIC_LEAVE:
2804                 LPS_Leave(padapter, "LPS_CTRL_TX_TRAFFIC_LEAVE");
2805                 break;
2806         case LPS_CTRL_RX_TRAFFIC_LEAVE:
2807                 LPS_Leave(padapter, "LPS_CTRL_RX_TRAFFIC_LEAVE");
2808                 break;
2809         case LPS_CTRL_ENTER:
2810                 LPS_Enter(padapter, "TRAFFIC_IDLE_1");
2811                 break;
2812         default:
2813                 break;
2814         }
2815
2816 }
2817
2818 u8 rtw_lps_ctrl_wk_cmd(_adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
2819 {
2820         struct cmd_obj  *ph2c;
2821         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
2822         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2823         /* struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); */
2824         u8      res = _SUCCESS;
2825
2826
2827         /* if(!pwrctrlpriv->bLeisurePs) */
2828         /*      return res; */
2829
2830         if (enqueue) {
2831                 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2832                 if (ph2c == NULL) {
2833                         res = _FAIL;
2834                         goto exit;
2835                 }
2836
2837                 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2838                 if (pdrvextra_cmd_parm == NULL) {
2839                         rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
2840                         res = _FAIL;
2841                         goto exit;
2842                 }
2843
2844                 pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
2845                 pdrvextra_cmd_parm->type = lps_ctrl_type;
2846                 pdrvextra_cmd_parm->size = 0;
2847                 pdrvextra_cmd_parm->pbuf = NULL;
2848
2849                 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
2850
2851                 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
2852         } else
2853                 lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
2854
2855 exit:
2856
2857
2858         return res;
2859
2860 }
2861
2862 void rtw_dm_in_lps_hdl(_adapter *padapter)
2863 {
2864         rtw_hal_set_hwreg(padapter, HW_VAR_DM_IN_LPS, NULL);
2865 }
2866
2867 u8 rtw_dm_in_lps_wk_cmd(_adapter *padapter)
2868 {
2869         struct cmd_obj  *ph2c;
2870         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
2871         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2872         u8      res = _SUCCESS;
2873
2874
2875         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2876         if (ph2c == NULL) {
2877                 res = _FAIL;
2878                 goto exit;
2879         }
2880
2881         pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2882         if (pdrvextra_cmd_parm == NULL) {
2883                 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
2884                 res = _FAIL;
2885                 goto exit;
2886         }
2887
2888         pdrvextra_cmd_parm->ec_id = DM_IN_LPS_WK_CID;
2889         pdrvextra_cmd_parm->type = 0;
2890         pdrvextra_cmd_parm->size = 0;
2891         pdrvextra_cmd_parm->pbuf = NULL;
2892
2893         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
2894
2895         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
2896
2897 exit:
2898
2899         return res;
2900
2901 }
2902
2903 void rtw_lps_change_dtim_hdl(_adapter *padapter, u8 dtim)
2904 {
2905         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
2906
2907         if (dtim <= 0 || dtim > 16)
2908                 return;
2909
2910 #ifdef CONFIG_BT_COEXIST
2911         if (rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
2912                 return;
2913 #endif
2914
2915 #ifdef CONFIG_LPS_LCLK
2916         _enter_pwrlock(&pwrpriv->lock);
2917 #endif
2918
2919         if (pwrpriv->dtim != dtim) {
2920                 RTW_INFO("change DTIM from %d to %d, bFwCurrentInPSMode=%d, ps_mode=%d\n", pwrpriv->dtim, dtim,
2921                          pwrpriv->bFwCurrentInPSMode, pwrpriv->pwr_mode);
2922
2923                 pwrpriv->dtim = dtim;
2924         }
2925
2926         if ((pwrpriv->bFwCurrentInPSMode == _TRUE) && (pwrpriv->pwr_mode > PS_MODE_ACTIVE)) {
2927                 u8 ps_mode = pwrpriv->pwr_mode;
2928
2929                 /* RTW_INFO("change DTIM from %d to %d, ps_mode=%d\n", pwrpriv->dtim, dtim, ps_mode); */
2930
2931                 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
2932         }
2933
2934 #ifdef CONFIG_LPS_LCLK
2935         _exit_pwrlock(&pwrpriv->lock);
2936 #endif
2937
2938 }
2939
2940 #endif
2941
2942 u8 rtw_lps_change_dtim_cmd(_adapter *padapter, u8 dtim)
2943 {
2944         struct cmd_obj  *ph2c;
2945         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
2946         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2947         u8      res = _SUCCESS;
2948         /*
2949         #ifdef CONFIG_CONCURRENT_MODE
2950                 if (padapter->hw_port != HW_PORT0)
2951                         return res;
2952         #endif
2953         */
2954         {
2955                 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2956                 if (ph2c == NULL) {
2957                         res = _FAIL;
2958                         goto exit;
2959                 }
2960
2961                 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2962                 if (pdrvextra_cmd_parm == NULL) {
2963                         rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
2964                         res = _FAIL;
2965                         goto exit;
2966                 }
2967
2968                 pdrvextra_cmd_parm->ec_id = LPS_CHANGE_DTIM_CID;
2969                 pdrvextra_cmd_parm->type = dtim;
2970                 pdrvextra_cmd_parm->size = 0;
2971                 pdrvextra_cmd_parm->pbuf = NULL;
2972
2973                 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
2974
2975                 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
2976         }
2977
2978 exit:
2979
2980         return res;
2981
2982 }
2983
2984 #if (RATE_ADAPTIVE_SUPPORT == 1)
2985 void rpt_timer_setting_wk_hdl(_adapter *padapter, u16 minRptTime)
2986 {
2987         rtw_hal_set_hwreg(padapter, HW_VAR_RPT_TIMER_SETTING, (u8 *)(&minRptTime));
2988 }
2989
2990 u8 rtw_rpt_timer_cfg_cmd(_adapter *padapter, u16 minRptTime)
2991 {
2992         struct cmd_obj          *ph2c;
2993         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
2994         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2995
2996         u8      res = _SUCCESS;
2997
2998         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2999         if (ph2c == NULL) {
3000                 res = _FAIL;
3001                 goto exit;
3002         }
3003
3004         pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3005         if (pdrvextra_cmd_parm == NULL) {
3006                 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3007                 res = _FAIL;
3008                 goto exit;
3009         }
3010
3011         pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID;
3012         pdrvextra_cmd_parm->type = minRptTime;
3013         pdrvextra_cmd_parm->size = 0;
3014         pdrvextra_cmd_parm->pbuf = NULL;
3015         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
3016         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3017 exit:
3018
3019
3020         return res;
3021
3022 }
3023
3024 #endif
3025
3026 #ifdef CONFIG_ANTENNA_DIVERSITY
3027 void antenna_select_wk_hdl(_adapter *padapter, u8 antenna)
3028 {
3029         rtw_hal_set_odm_var(padapter, HAL_ODM_ANTDIV_SELECT, &antenna, _TRUE);
3030 }
3031
3032 u8 rtw_antenna_select_cmd(_adapter *padapter, u8 antenna, u8 enqueue)
3033 {
3034         struct cmd_obj          *ph2c;
3035         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
3036         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3037         struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3038         u8      bSupportAntDiv = _FALSE;
3039         u8      res = _SUCCESS;
3040         int     i;
3041
3042         rtw_hal_get_def_var(padapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &(bSupportAntDiv));
3043         if (_FALSE == bSupportAntDiv)
3044                 return _FAIL;
3045
3046         for (i = 0; i < dvobj->iface_nums; i++) {
3047                 if (rtw_linked_check(dvobj->padapters[i]))
3048                         return _FAIL;
3049         }
3050
3051         if (_TRUE == enqueue) {
3052                 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3053                 if (ph2c == NULL) {
3054                         res = _FAIL;
3055                         goto exit;
3056                 }
3057
3058                 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3059                 if (pdrvextra_cmd_parm == NULL) {
3060                         rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3061                         res = _FAIL;
3062                         goto exit;
3063                 }
3064
3065                 pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID;
3066                 pdrvextra_cmd_parm->type = antenna;
3067                 pdrvextra_cmd_parm->size = 0;
3068                 pdrvextra_cmd_parm->pbuf = NULL;
3069                 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
3070
3071                 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3072         } else
3073                 antenna_select_wk_hdl(padapter, antenna);
3074 exit:
3075
3076
3077         return res;
3078
3079 }
3080 #endif
3081
3082 void rtw_dm_ra_mask_hdl(_adapter *padapter, struct sta_info *psta)
3083 {
3084         if (psta)
3085                 set_sta_rate(padapter, psta);
3086 }
3087
3088 u8 rtw_dm_ra_mask_wk_cmd(_adapter *padapter, u8 *psta)
3089 {
3090         struct cmd_obj  *ph2c;
3091         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
3092         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3093         u8      res = _SUCCESS;
3094
3095
3096         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3097         if (ph2c == NULL) {
3098                 res = _FAIL;
3099                 goto exit;
3100         }
3101
3102         pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3103         if (pdrvextra_cmd_parm == NULL) {
3104                 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3105                 res = _FAIL;
3106                 goto exit;
3107         }
3108
3109         pdrvextra_cmd_parm->ec_id = DM_RA_MSK_WK_CID;
3110         pdrvextra_cmd_parm->type = 0;
3111         pdrvextra_cmd_parm->size = 0;
3112         pdrvextra_cmd_parm->pbuf = psta;
3113
3114         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
3115
3116         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3117
3118 exit:
3119
3120         return res;
3121
3122 }
3123
3124 void power_saving_wk_hdl(_adapter *padapter)
3125 {
3126         rtw_ps_processor(padapter);
3127 }
3128
3129 /* add for CONFIG_IEEE80211W, none 11w can use it */
3130 void reset_securitypriv_hdl(_adapter *padapter)
3131 {
3132         rtw_reset_securitypriv(padapter);
3133 }
3134
3135 void free_assoc_resources_hdl(_adapter *padapter)
3136 {
3137         rtw_free_assoc_resources(padapter, 1);
3138 }
3139
3140 #ifdef CONFIG_P2P
3141 u8 p2p_protocol_wk_cmd(_adapter *padapter, int intCmdType)
3142 {
3143         struct cmd_obj  *ph2c;
3144         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
3145         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
3146         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3147         u8      res = _SUCCESS;
3148
3149
3150         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3151                 return res;
3152
3153         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3154         if (ph2c == NULL) {
3155                 res = _FAIL;
3156                 goto exit;
3157         }
3158
3159         pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3160         if (pdrvextra_cmd_parm == NULL) {
3161                 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3162                 res = _FAIL;
3163                 goto exit;
3164         }
3165
3166         pdrvextra_cmd_parm->ec_id = P2P_PROTO_WK_CID;
3167         pdrvextra_cmd_parm->type = intCmdType;  /*      As the command tppe. */
3168         pdrvextra_cmd_parm->size = 0;
3169         pdrvextra_cmd_parm->pbuf = NULL;                /*      Must be NULL here */
3170
3171         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
3172
3173         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3174
3175 exit:
3176
3177
3178         return res;
3179
3180 }
3181
3182 #ifdef CONFIG_IOCTL_CFG80211
3183 static u8 _p2p_roch_cmd(_adapter *adapter
3184         , u64 cookie, struct wireless_dev *wdev
3185         , struct ieee80211_channel *ch, enum nl80211_channel_type ch_type
3186         , unsigned int duration
3187         , u8 flags
3188 )
3189 {
3190         struct cmd_obj *cmdobj;
3191         struct drvextra_cmd_parm *parm;
3192         struct p2p_roch_parm *roch_parm;
3193         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
3194         struct submit_ctx sctx;
3195         u8 cancel = duration ? 0 : 1;
3196         u8      res = _SUCCESS;
3197
3198         roch_parm = (struct p2p_roch_parm *)rtw_zmalloc(sizeof(struct p2p_roch_parm));
3199         if (roch_parm == NULL) {
3200                 res = _FAIL;
3201                 goto exit;
3202         }
3203
3204         roch_parm->cookie = cookie;
3205         roch_parm->wdev = wdev;
3206         if (!cancel) {
3207                 _rtw_memcpy(&roch_parm->ch, ch, sizeof(struct ieee80211_channel));
3208                 roch_parm->ch_type = ch_type;
3209                 roch_parm->duration = duration;
3210         }
3211
3212         if (flags & RTW_CMDF_DIRECTLY) {
3213                 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
3214                 if (H2C_SUCCESS != p2p_protocol_wk_hdl(adapter, cancel ? P2P_CANCEL_RO_CH_WK : P2P_RO_CH_WK, (u8 *)roch_parm))
3215                         res = _FAIL;
3216                 rtw_mfree((u8 *)roch_parm, sizeof(*roch_parm));
3217         } else {
3218                 /* need enqueue, prepare cmd_obj and enqueue */
3219                 parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3220                 if (parm == NULL) {
3221                         rtw_mfree((u8 *)roch_parm, sizeof(*roch_parm));
3222                         res = _FAIL;
3223                         goto exit;
3224                 }
3225
3226                 parm->ec_id = P2P_PROTO_WK_CID;
3227                 parm->type = cancel ? P2P_CANCEL_RO_CH_WK : P2P_RO_CH_WK;
3228                 parm->size = sizeof(*roch_parm);
3229                 parm->pbuf = (u8 *)roch_parm;
3230
3231                 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
3232                 if (cmdobj == NULL) {
3233                         res = _FAIL;
3234                         rtw_mfree((u8 *)roch_parm, sizeof(*roch_parm));
3235                         rtw_mfree((u8 *)parm, sizeof(*parm));
3236                         goto exit;
3237                 }
3238
3239                 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_Set_Drv_Extra));
3240
3241                 if (flags & RTW_CMDF_WAIT_ACK) {
3242                         cmdobj->sctx = &sctx;
3243                         rtw_sctx_init(&sctx, 10 * 1000);
3244                 }
3245
3246                 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
3247
3248                 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
3249                         rtw_sctx_wait(&sctx, __func__);
3250                         _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
3251                         if (sctx.status == RTW_SCTX_SUBMITTED)
3252                                 cmdobj->sctx = NULL;
3253                         _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
3254                         if (sctx.status != RTW_SCTX_DONE_SUCCESS)
3255                                 res = _FAIL;
3256                 }
3257         }
3258
3259 exit:
3260         return res;
3261 }
3262
3263 inline u8 p2p_roch_cmd(_adapter *adapter
3264         , u64 cookie, struct wireless_dev *wdev
3265         , struct ieee80211_channel *ch, enum nl80211_channel_type ch_type
3266         , unsigned int duration
3267         , u8 flags
3268 )
3269 {
3270         return _p2p_roch_cmd(adapter, cookie, wdev, ch, ch_type, duration, flags);
3271 }
3272
3273 inline u8 p2p_cancel_roch_cmd(_adapter *adapter, u64 cookie, struct wireless_dev *wdev, u8 flags)
3274 {
3275         return _p2p_roch_cmd(adapter, cookie, wdev, NULL, 0, 0, flags);
3276 }
3277 #endif /* CONFIG_IOCTL_CFG80211 */
3278 #endif /* CONFIG_P2P */
3279
3280 u8 rtw_ps_cmd(_adapter *padapter)
3281 {
3282         struct cmd_obj          *ppscmd;
3283         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
3284         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3285
3286         u8      res = _SUCCESS;
3287
3288 #ifdef CONFIG_CONCURRENT_MODE
3289         if (padapter->adapter_type != PRIMARY_ADAPTER)
3290                 goto exit;
3291 #endif
3292
3293         ppscmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3294         if (ppscmd == NULL) {
3295                 res = _FAIL;
3296                 goto exit;
3297         }
3298
3299         pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3300         if (pdrvextra_cmd_parm == NULL) {
3301                 rtw_mfree((unsigned char *)ppscmd, sizeof(struct cmd_obj));
3302                 res = _FAIL;
3303                 goto exit;
3304         }
3305
3306         pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
3307         pdrvextra_cmd_parm->type = 0;
3308         pdrvextra_cmd_parm->size = 0;
3309         pdrvextra_cmd_parm->pbuf = NULL;
3310         init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
3311
3312         res = rtw_enqueue_cmd(pcmdpriv, ppscmd);
3313
3314 exit:
3315
3316
3317         return res;
3318
3319 }
3320
3321 #ifdef CONFIG_AP_MODE
3322
3323 static void rtw_chk_hi_queue_hdl(_adapter *padapter)
3324 {
3325         struct sta_info *psta_bmc;
3326         struct sta_priv *pstapriv = &padapter->stapriv;
3327         u32 start = rtw_get_current_time();
3328         u8 empty = _FALSE;
3329
3330         psta_bmc = rtw_get_bcmc_stainfo(padapter);
3331         if (!psta_bmc)
3332                 return;
3333
3334         rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
3335
3336         while (_FALSE == empty && rtw_get_passing_time_ms(start) < rtw_get_wait_hiq_empty_ms()) {
3337                 rtw_msleep_os(100);
3338                 rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
3339         }
3340
3341         if (psta_bmc->sleepq_len == 0) {
3342                 if (empty == _SUCCESS) {
3343                         bool update_tim = _FALSE;
3344
3345                         if (pstapriv->tim_bitmap & BIT(0))
3346                                 update_tim = _TRUE;
3347
3348                         pstapriv->tim_bitmap &= ~BIT(0);
3349                         pstapriv->sta_dz_bitmap &= ~BIT(0);
3350
3351                         if (update_tim == _TRUE)
3352                                 _update_beacon(padapter, _TIM_IE_, NULL, _TRUE, "bmc sleepq and HIQ empty");
3353                 } else /* re check again */
3354                         rtw_chk_hi_queue_cmd(padapter);
3355
3356         }
3357
3358 }
3359
3360 u8 rtw_chk_hi_queue_cmd(_adapter *padapter)
3361 {
3362         struct cmd_obj  *ph2c;
3363         struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
3364         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3365         u8      res = _SUCCESS;
3366
3367         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3368         if (ph2c == NULL) {
3369                 res = _FAIL;
3370                 goto exit;
3371         }
3372
3373         pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3374         if (pdrvextra_cmd_parm == NULL) {
3375                 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
3376                 res = _FAIL;
3377                 goto exit;
3378         }
3379
3380         pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
3381         pdrvextra_cmd_parm->type = 0;
3382         pdrvextra_cmd_parm->size = 0;
3383         pdrvextra_cmd_parm->pbuf = NULL;
3384
3385         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
3386
3387         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3388
3389 exit:
3390
3391         return res;
3392
3393 }
3394
3395 #ifdef CONFIG_DFS_MASTER
3396 u8 rtw_dfs_master_hdl(_adapter *adapter)
3397 {
3398         struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
3399         struct mlme_priv *mlme = &adapter->mlmepriv;
3400
3401         if (!rfctl->dfs_master_enabled)
3402                 goto exit;
3403
3404         if (rtw_get_on_cur_ch_time(adapter) == 0
3405                 || rtw_get_passing_time_ms(rtw_get_on_cur_ch_time(adapter)) < 300
3406         ) {
3407                 /* offchannel , bypass radar detect */
3408                 goto cac_status_chk;
3409         }
3410
3411         if (IS_CH_WAITING(rfctl) && !IS_UNDER_CAC(rfctl)) {
3412                 /* non_ocp, bypass radar detect */
3413                 goto cac_status_chk;
3414         }
3415
3416         if (!rfctl->dbg_dfs_master_fake_radar_detect_cnt
3417                 && rtw_odm_radar_detect(adapter) != _TRUE)
3418                 goto cac_status_chk;
3419
3420         if (rfctl->dbg_dfs_master_fake_radar_detect_cnt != 0) {
3421                 RTW_INFO(FUNC_ADPT_FMT" fake radar detect, cnt:%d\n", FUNC_ADPT_ARG(adapter)
3422                         , rfctl->dbg_dfs_master_fake_radar_detect_cnt);
3423                 rfctl->dbg_dfs_master_fake_radar_detect_cnt--;
3424         }
3425
3426         if (rfctl->dbg_dfs_master_radar_detect_trigger_non) {
3427                 /* radar detect debug mode, trigger no mlme flow */
3428                 if (0)
3429                         RTW_INFO(FUNC_ADPT_FMT" radar detected, trigger no mlme flow for debug\n", FUNC_ADPT_ARG(adapter));
3430         } else {
3431                 /* TODO: move timer to rfctl */
3432                 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
3433                 int i;
3434
3435                 for (i = 0; i < dvobj->iface_nums; i++) {
3436                         if (!dvobj->padapters[i])
3437                                 continue;
3438                         if (check_fwstate(&dvobj->padapters[i]->mlmepriv, WIFI_AP_STATE)
3439                                 && check_fwstate(&dvobj->padapters[i]->mlmepriv, WIFI_ASOC_STATE))
3440                                 break;
3441                 }
3442
3443                 if (i >= dvobj->iface_nums) {
3444                         /* what? */
3445                         rtw_warn_on(1);
3446                 } else {
3447                         rtw_chset_update_non_ocp(dvobj->padapters[i]->mlmeextpriv.channel_set
3448                                 , rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset);
3449                         rfctl->radar_detected = 1;
3450
3451                         /* trigger channel selection */
3452                         rtw_change_bss_chbw_cmd(dvobj->padapters[i], RTW_CMDF_DIRECTLY, -1, dvobj->padapters[i]->mlmepriv.ori_bw, -1);
3453                 }
3454
3455                 if (rfctl->dfs_master_enabled)
3456                         goto set_timer;
3457                 goto exit;
3458         }
3459
3460 cac_status_chk:
3461
3462         if (!IS_CH_WAITING(rfctl) && !IS_CAC_STOPPED(rfctl)) {
3463                 u8 pause = 0x00;
3464
3465                 rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);
3466                 rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;
3467         }
3468
3469 set_timer:
3470         _set_timer(&mlme->dfs_master_timer, DFS_MASTER_TIMER_MS);
3471
3472 exit:
3473         return H2C_SUCCESS;
3474 }
3475
3476 u8 rtw_dfs_master_cmd(_adapter *adapter, bool enqueue)
3477 {
3478         struct cmd_obj *cmdobj;
3479         struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3480         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
3481         u8 res = _FAIL;
3482
3483         if (enqueue) {
3484                 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3485                 if (cmdobj == NULL)
3486                         goto exit;
3487
3488                 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3489                 if (pdrvextra_cmd_parm == NULL) {
3490                         rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
3491                         goto exit;
3492                 }
3493
3494                 pdrvextra_cmd_parm->ec_id = DFS_MASTER_WK_CID;
3495                 pdrvextra_cmd_parm->type = 0;
3496                 pdrvextra_cmd_parm->size = 0;
3497                 pdrvextra_cmd_parm->pbuf = NULL;
3498
3499                 init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
3500                 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
3501         } else {
3502                 rtw_dfs_master_hdl(adapter);
3503                 res = _SUCCESS;
3504         }
3505
3506 exit:
3507         return res;
3508 }
3509
3510 void rtw_dfs_master_timer_hdl(RTW_TIMER_HDL_ARGS)
3511 {
3512         _adapter *adapter = (_adapter *)FunctionContext;
3513
3514         rtw_dfs_master_cmd(adapter, _TRUE);
3515 }
3516
3517 void rtw_dfs_master_enable(_adapter *adapter, u8 ch, u8 bw, u8 offset)
3518 {
3519         struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
3520
3521         /* TODO: move timer to rfctl */
3522         adapter = GET_PRIMARY_ADAPTER(adapter);
3523
3524         RTW_INFO(FUNC_ADPT_FMT" on %u,%u,%u\n", FUNC_ADPT_ARG(adapter), ch, bw, offset);
3525
3526         if (rtw_is_cac_reset_needed(adapter, ch, bw, offset) == _TRUE)
3527                 rtw_reset_cac(adapter, ch, bw, offset);
3528
3529         rfctl->radar_detect_by_others = _FALSE;
3530         rfctl->radar_detect_ch = ch;
3531         rfctl->radar_detect_bw = bw;
3532         rfctl->radar_detect_offset = offset;
3533
3534         rfctl->radar_detected = 0;
3535
3536         if (!rfctl->dfs_master_enabled) {
3537                 RTW_INFO(FUNC_ADPT_FMT" set dfs_master_enabled\n", FUNC_ADPT_ARG(adapter));
3538                 rfctl->dfs_master_enabled = 1;
3539                 _set_timer(&adapter->mlmepriv.dfs_master_timer, DFS_MASTER_TIMER_MS);
3540
3541                 if (rtw_rfctl_overlap_radar_detect_ch(rfctl)) {
3542                         if (IS_CH_WAITING(rfctl)) {
3543                                 u8 pause = 0xFF;
3544
3545                                 rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);
3546                         }
3547                         rtw_odm_radar_detect_enable(adapter);
3548                 }
3549         }
3550 }
3551
3552 void rtw_dfs_master_disable(_adapter *adapter, u8 ch, u8 bw, u8 offset, bool by_others)
3553 {
3554         struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
3555
3556         /* TODO: move timer to rfctl */
3557         adapter = GET_PRIMARY_ADAPTER(adapter);
3558
3559         rfctl->radar_detect_by_others = by_others;
3560
3561         if (rfctl->dfs_master_enabled) {
3562                 bool overlap_radar_detect_ch = rtw_rfctl_overlap_radar_detect_ch(rfctl);
3563
3564                 RTW_INFO(FUNC_ADPT_FMT" clear dfs_master_enabled\n", FUNC_ADPT_ARG(adapter));
3565
3566                 rfctl->dfs_master_enabled = 0;
3567                 rfctl->radar_detected = 0;
3568                 rfctl->radar_detect_ch = 0;
3569                 rfctl->radar_detect_bw = 0;
3570                 rfctl->radar_detect_offset = 0;
3571                 rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;
3572                 _cancel_timer_ex(&adapter->mlmepriv.dfs_master_timer);
3573
3574                 if (overlap_radar_detect_ch) {
3575                         u8 pause = 0x00;
3576
3577                         rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);
3578                         rtw_odm_radar_detect_disable(adapter);
3579                 }
3580         }
3581
3582         if (by_others) {
3583                 rfctl->radar_detect_ch = ch;
3584                 rfctl->radar_detect_bw = bw;
3585                 rfctl->radar_detect_offset = offset;
3586         }
3587 }
3588
3589 void rtw_dfs_master_status_apply(_adapter *adapter, u8 self_action)
3590 {
3591         struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
3592         struct mi_state mstate;
3593         u8 u_ch, u_bw, u_offset;
3594         bool ld_sta_in_dfs = _FALSE;
3595         bool sync_ch = _FALSE; /* _FALSE: asign channel directly */
3596         bool needed = _FALSE;
3597
3598         rtw_mi_status_no_self(adapter, &mstate);
3599         rtw_mi_get_ch_setting_union_no_self(adapter, &u_ch, &u_bw, &u_offset);
3600         if (u_ch != 0)
3601                 sync_ch = _TRUE;
3602
3603         switch (self_action) {
3604         case MLME_STA_CONNECTING:
3605                 MSTATE_STA_LG_NUM(&mstate)++;
3606                 break;
3607         case MLME_STA_CONNECTED:
3608                 MSTATE_STA_LD_NUM(&mstate)++;
3609                 break;
3610         case MLME_AP_STARTED:
3611                 MSTATE_AP_NUM(&mstate)++;
3612                 break;
3613         case MLME_AP_STOPPED:
3614         case MLME_STA_DISCONNECTED:
3615         default:
3616                 break;
3617         }
3618
3619         if (sync_ch == _TRUE) {
3620                 if (!rtw_is_chbw_grouped(mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset, u_ch, u_bw, u_offset)) {
3621                         RTW_INFO(FUNC_ADPT_FMT" can't sync %u,%u,%u with %u,%u,%u\n", FUNC_ADPT_ARG(adapter)
3622                                 , mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset, u_ch, u_bw, u_offset);
3623                         goto apply;
3624                 }
3625
3626                 rtw_sync_chbw(&mlmeext->cur_channel, &mlmeext->cur_bwmode, &mlmeext->cur_ch_offset
3627                         , &u_ch, &u_bw, &u_offset);
3628         } else {
3629                 u_ch = mlmeext->cur_channel;
3630                 u_bw = mlmeext->cur_bwmode;
3631                 u_offset = mlmeext->cur_ch_offset;
3632         }
3633
3634         if (MSTATE_STA_LD_NUM(&mstate) > 0) {
3635                 /* rely on AP on which STA mode connects */
3636                 if (rtw_is_dfs_ch(u_ch, u_bw, u_offset))
3637                         ld_sta_in_dfs = _TRUE;
3638                 goto apply;
3639         }
3640
3641         if (MSTATE_STA_LG_NUM(&mstate) > 0) {
3642                 /* STA mode is linking */
3643                 goto apply;
3644         }
3645
3646         if (MSTATE_AP_NUM(&mstate) == 0) {
3647                 /* No working AP mode */
3648                 goto apply;
3649         }
3650
3651         if (rtw_is_dfs_ch(u_ch, u_bw, u_offset))
3652                 needed = _TRUE;
3653
3654 apply:
3655
3656         RTW_INFO(FUNC_ADPT_FMT" needed:%d, self_action:%u\n"
3657                 , FUNC_ADPT_ARG(adapter), needed, self_action);
3658         RTW_INFO(FUNC_ADPT_FMT" ld_sta_num:%u, lg_sta_num:%u, ap_num:%u, %u,%u,%u\n"
3659                 , FUNC_ADPT_ARG(adapter), MSTATE_STA_LD_NUM(&mstate), MSTATE_STA_LG_NUM(&mstate), MSTATE_AP_NUM(&mstate)
3660                 , u_ch, u_bw, u_offset);
3661
3662         if (needed == _TRUE)
3663                 rtw_dfs_master_enable(adapter, u_ch, u_bw, u_offset);
3664         else
3665                 rtw_dfs_master_disable(adapter, u_ch, u_bw, u_offset, ld_sta_in_dfs);
3666 }
3667 #endif /* CONFIG_DFS_MASTER */
3668
3669 #endif /* CONFIG_AP_MODE */
3670
3671 #ifdef CONFIG_BT_COEXIST
3672 struct btinfo {
3673         u8 cid;
3674         u8 len;
3675
3676         u8 bConnection:1;
3677         u8 bSCOeSCO:1;
3678         u8 bInQPage:1;
3679         u8 bACLBusy:1;
3680         u8 bSCOBusy:1;
3681         u8 bHID:1;
3682         u8 bA2DP:1;
3683         u8 bFTP:1;
3684
3685         u8 retry_cnt:4;
3686         u8 rsvd_34:1;
3687         u8 rsvd_35:1;
3688         u8 rsvd_36:1;
3689         u8 rsvd_37:1;
3690
3691         u8 rssi;
3692
3693         u8 rsvd_50:1;
3694         u8 rsvd_51:1;
3695         u8 rsvd_52:1;
3696         u8 rsvd_53:1;
3697         u8 rsvd_54:1;
3698         u8 rsvd_55:1;
3699         u8 eSCO_SCO:1;
3700         u8 Master_Slave:1;
3701
3702         u8 rsvd_6;
3703         u8 rsvd_7;
3704 };
3705
3706 void btinfo_evt_dump(void *sel, void *buf)
3707 {
3708         struct btinfo *info = (struct btinfo *)buf;
3709
3710         RTW_PRINT_SEL(sel, "cid:0x%02x, len:%u\n", info->cid, info->len);
3711
3712         if (info->len > 2)
3713                 RTW_PRINT_SEL(sel, "byte2:%s%s%s%s%s%s%s%s\n"
3714                               , info->bConnection ? "bConnection " : ""
3715                               , info->bSCOeSCO ? "bSCOeSCO " : ""
3716                               , info->bInQPage ? "bInQPage " : ""
3717                               , info->bACLBusy ? "bACLBusy " : ""
3718                               , info->bSCOBusy ? "bSCOBusy " : ""
3719                               , info->bHID ? "bHID " : ""
3720                               , info->bA2DP ? "bA2DP " : ""
3721                               , info->bFTP ? "bFTP" : ""
3722                              );
3723
3724         if (info->len > 3)
3725                 RTW_PRINT_SEL(sel, "retry_cnt:%u\n", info->retry_cnt);
3726
3727         if (info->len > 4)
3728                 RTW_PRINT_SEL(sel, "rssi:%u\n", info->rssi);
3729
3730         if (info->len > 5)
3731                 RTW_PRINT_SEL(sel, "byte5:%s%s\n"
3732                               , info->eSCO_SCO ? "eSCO_SCO " : ""
3733                               , info->Master_Slave ? "Master_Slave " : ""
3734                              );
3735 }
3736
3737 static void rtw_btinfo_hdl(_adapter *adapter, u8 *buf, u16 buf_len)
3738 {
3739 #define BTINFO_WIFI_FETCH 0x23
3740 #define BTINFO_BT_AUTO_RPT 0x27
3741 #ifdef CONFIG_BT_COEXIST_SOCKET_TRX
3742         struct btinfo_8761ATV *info = (struct btinfo_8761ATV *)buf;
3743 #else /* !CONFIG_BT_COEXIST_SOCKET_TRX */
3744         struct btinfo *info = (struct btinfo *)buf;
3745 #endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
3746         u8 cmd_idx;
3747         u8 len;
3748
3749         cmd_idx = info->cid;
3750
3751         if (info->len > buf_len - 2) {
3752                 rtw_warn_on(1);
3753                 len = buf_len - 2;
3754         } else
3755                 len = info->len;
3756
3757         /* #define DBG_PROC_SET_BTINFO_EVT */
3758 #ifdef DBG_PROC_SET_BTINFO_EVT
3759 #ifdef CONFIG_BT_COEXIST_SOCKET_TRX
3760         RTW_INFO("%s: btinfo[0]=%x,btinfo[1]=%x,btinfo[2]=%x,btinfo[3]=%x btinfo[4]=%x,btinfo[5]=%x,btinfo[6]=%x,btinfo[7]=%x\n"
3761                 , __func__, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
3762 #else/* !CONFIG_BT_COEXIST_SOCKET_TRX */
3763         btinfo_evt_dump(RTW_DBGDUMP, info);
3764 #endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
3765 #endif /* DBG_PROC_SET_BTINFO_EVT */
3766
3767         /* transform BT-FW btinfo to WiFI-FW C2H format and notify */
3768         if (cmd_idx == BTINFO_WIFI_FETCH)
3769                 buf[1] = 0;
3770         else if (cmd_idx == BTINFO_BT_AUTO_RPT)
3771                 buf[1] = 2;
3772 #ifdef CONFIG_BT_COEXIST_SOCKET_TRX
3773         else if (0x01 == cmd_idx || 0x02 == cmd_idx)
3774                 buf[1] = buf[0];
3775 #endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
3776         rtw_btcoex_BtInfoNotify(adapter , len + 1, &buf[1]);
3777 }
3778
3779 u8 rtw_btinfo_cmd(_adapter *adapter, u8 *buf, u16 len)
3780 {
3781         struct cmd_obj *ph2c;
3782         struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3783         u8 *btinfo;
3784         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
3785         u8      res = _SUCCESS;
3786
3787         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3788         if (ph2c == NULL) {
3789                 res = _FAIL;
3790                 goto exit;
3791         }
3792
3793         pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3794         if (pdrvextra_cmd_parm == NULL) {
3795                 rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
3796                 res = _FAIL;
3797                 goto exit;
3798         }
3799
3800         btinfo = rtw_zmalloc(len);
3801         if (btinfo == NULL) {
3802                 rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
3803                 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
3804                 res = _FAIL;
3805                 goto exit;
3806         }
3807
3808         pdrvextra_cmd_parm->ec_id = BTINFO_WK_CID;
3809         pdrvextra_cmd_parm->type = 0;
3810         pdrvextra_cmd_parm->size = len;
3811         pdrvextra_cmd_parm->pbuf = btinfo;
3812
3813         _rtw_memcpy(btinfo, buf, len);
3814
3815         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
3816
3817         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
3818
3819 exit:
3820         return res;
3821 }
3822 #endif /* CONFIG_BT_COEXIST */
3823
3824 u8 rtw_test_h2c_cmd(_adapter *adapter, u8 *buf, u8 len)
3825 {
3826         struct cmd_obj *pcmdobj;
3827         struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3828         u8 *ph2c_content;
3829         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
3830         u8      res = _SUCCESS;
3831
3832         pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3833         if (pcmdobj == NULL) {
3834                 res = _FAIL;
3835                 goto exit;
3836         }
3837
3838         pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3839         if (pdrvextra_cmd_parm == NULL) {
3840                 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
3841                 res = _FAIL;
3842                 goto exit;
3843         }
3844
3845         ph2c_content = rtw_zmalloc(len);
3846         if (ph2c_content == NULL) {
3847                 rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
3848                 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
3849                 res = _FAIL;
3850                 goto exit;
3851         }
3852
3853         pdrvextra_cmd_parm->ec_id = TEST_H2C_CID;
3854         pdrvextra_cmd_parm->type = 0;
3855         pdrvextra_cmd_parm->size = len;
3856         pdrvextra_cmd_parm->pbuf = ph2c_content;
3857
3858         _rtw_memcpy(ph2c_content, buf, len);
3859
3860         init_h2fwcmd_w_parm_no_rsp(pcmdobj, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
3861
3862         res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
3863
3864 exit:
3865         return res;
3866 }
3867
3868 static s32 rtw_mp_cmd_hdl(_adapter *padapter, u8 mp_cmd_id)
3869 {
3870         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
3871         int ret = H2C_SUCCESS;
3872         u8 rfreg0;
3873
3874         if (mp_cmd_id == MP_START) {
3875                 if (padapter->registrypriv.mp_mode == 0) {
3876                         rtw_hal_deinit(padapter);
3877                         padapter->registrypriv.mp_mode = 1;
3878 #ifdef CONFIG_RF_POWER_TRIM
3879                         if (!IS_HARDWARE_TYPE_8814A(padapter) && !IS_HARDWARE_TYPE_8822B(padapter)) {
3880                                 padapter->registrypriv.RegPwrTrimEnable = 1;
3881                                 rtw_hal_read_chip_info(padapter);
3882                         }
3883 #endif /*CONFIG_RF_POWER_TRIM*/
3884                         rtw_hal_init(padapter);
3885 #ifdef RTW_HALMAC /*for New IC*/
3886                         MPT_InitializeAdapter(padapter, 1);
3887 #endif /* CONFIG_MP_INCLUDED */
3888                 }
3889
3890                 if (padapter->registrypriv.mp_mode == 0) {
3891                         ret = H2C_REJECTED;
3892                         goto exit;
3893                 }
3894
3895                 if (padapter->mppriv.mode == MP_OFF) {
3896                         if (mp_start_test(padapter) == _FAIL) {
3897                                 ret = H2C_REJECTED;
3898                                 goto exit;
3899                         }
3900                         padapter->mppriv.mode = MP_ON;
3901                         MPT_PwrCtlDM(padapter, 0);
3902                 }
3903                 padapter->mppriv.bmac_filter = _FALSE;
3904 #ifdef CONFIG_RTL8723B
3905 #ifdef CONFIG_USB_HCI
3906                 rtw_write32(padapter, 0x765, 0x0000);
3907                 rtw_write32(padapter, 0x948, 0x0280);
3908 #else
3909                 rtw_write32(padapter, 0x765, 0x0000);
3910                 rtw_write32(padapter, 0x948, 0x0000);
3911 #endif
3912 #ifdef CONFIG_FOR_RTL8723BS_VQ0
3913                 rtw_write32(padapter, 0x765, 0x0000);
3914                 rtw_write32(padapter, 0x948, 0x0280);
3915 #endif
3916                 rtw_write8(padapter, 0x66, 0x27); /*Open BT uart Log*/
3917                 rtw_write8(padapter, 0xc50, 0x20); /*for RX init Gain*/
3918 #endif
3919 #ifdef CONFIG_RTL8188F
3920                         RTW_INFO("Set reg 0x88c, 0x58, 0x00\n");
3921                         rfreg0 = phy_query_rf_reg(padapter, RF_PATH_A, 0x0, 0x1f);
3922                         phy_set_bb_reg(padapter, 0x88c, BIT21|BIT20, 0x3);
3923                         phy_set_rf_reg(padapter, RF_PATH_A, 0x58, BIT1, 0x1);
3924                         phy_set_rf_reg(padapter, RF_PATH_A, 0x0, 0xF001f, 0x2001f);
3925                         rtw_msleep_os(200);
3926                         phy_set_rf_reg(padapter, RF_PATH_A, 0x0, 0xF001f, 0x30000 | rfreg0);
3927                         phy_set_rf_reg(padapter, RF_PATH_A, 0x58, BIT1, 0x0);
3928                         phy_set_bb_reg(padapter, 0x88c, BIT21|BIT20, 0x0);
3929                         rtw_msleep_os(1000);
3930 #endif
3931
3932                 odm_write_dig(&pHalData->odmpriv, 0x20);
3933
3934         } else if (mp_cmd_id == MP_STOP) {
3935                 if (padapter->registrypriv.mp_mode == 1) {
3936                         MPT_DeInitAdapter(padapter);
3937                         rtw_hal_deinit(padapter);
3938                         padapter->registrypriv.mp_mode = 0;
3939                         rtw_hal_init(padapter);
3940                 }
3941
3942                 if (padapter->mppriv.mode != MP_OFF) {
3943                         mp_stop_test(padapter);
3944                         padapter->mppriv.mode = MP_OFF;
3945                 }
3946
3947         } else {
3948                 RTW_INFO(FUNC_ADPT_FMT"invalid id:%d\n", FUNC_ADPT_ARG(padapter), mp_cmd_id);
3949                 ret = H2C_PARAMETERS_ERROR;
3950                 rtw_warn_on(1);
3951         }
3952
3953 exit:
3954         return ret;
3955 }
3956
3957 u8 rtw_mp_cmd(_adapter *adapter, u8 mp_cmd_id, u8 flags)
3958 {
3959         struct cmd_obj *cmdobj;
3960         struct drvextra_cmd_parm *parm;
3961         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
3962         struct submit_ctx sctx;
3963         u8      res = _SUCCESS;
3964
3965         parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3966         if (parm == NULL) {
3967                 res = _FAIL;
3968                 goto exit;
3969         }
3970
3971         parm->ec_id = MP_CMD_WK_CID;
3972         parm->type = mp_cmd_id;
3973         parm->size = 0;
3974         parm->pbuf = NULL;
3975
3976         if (flags & RTW_CMDF_DIRECTLY) {
3977                 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
3978                 if (H2C_SUCCESS != rtw_mp_cmd_hdl(adapter, mp_cmd_id))
3979                         res = _FAIL;
3980                 rtw_mfree((u8 *)parm, sizeof(*parm));
3981         } else {
3982                 /* need enqueue, prepare cmd_obj and enqueue */
3983                 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
3984                 if (cmdobj == NULL) {
3985                         res = _FAIL;
3986                         rtw_mfree((u8 *)parm, sizeof(*parm));
3987                         goto exit;
3988                 }
3989
3990                 init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_Set_Drv_Extra));
3991
3992                 if (flags & RTW_CMDF_WAIT_ACK) {
3993                         cmdobj->sctx = &sctx;
3994                         rtw_sctx_init(&sctx, 10 * 1000);
3995                 }
3996
3997                 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
3998
3999                 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
4000                         rtw_sctx_wait(&sctx, __func__);
4001                         _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4002                         if (sctx.status == RTW_SCTX_SUBMITTED)
4003                                 cmdobj->sctx = NULL;
4004                         _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4005                         if (sctx.status != RTW_SCTX_DONE_SUCCESS)
4006                                 res = _FAIL;
4007                 }
4008         }
4009
4010 exit:
4011         return res;
4012 }
4013
4014 #ifdef CONFIG_RTW_CUSTOMER_STR
4015 static s32 rtw_customer_str_cmd_hdl(_adapter *adapter, u8 write, const u8 *cstr)
4016 {
4017         int ret = H2C_SUCCESS;
4018
4019         if (write)
4020                 ret = rtw_hal_h2c_customer_str_write(adapter, cstr);
4021         else
4022                 ret = rtw_hal_h2c_customer_str_req(adapter);
4023
4024         return ret == _SUCCESS ? H2C_SUCCESS : H2C_REJECTED;
4025 }
4026
4027 static u8 rtw_customer_str_cmd(_adapter *adapter, u8 write, const u8 *cstr)
4028 {
4029         struct cmd_obj *cmdobj;
4030         struct drvextra_cmd_parm *parm;
4031         u8 *str = NULL;
4032         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4033         struct submit_ctx sctx;
4034         u8 res = _SUCCESS;
4035
4036         parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4037         if (parm == NULL) {
4038                 res = _FAIL;
4039                 goto exit;
4040         }
4041
4042         if (write) {
4043                 str = rtw_zmalloc(RTW_CUSTOMER_STR_LEN);
4044                 if (str == NULL) {
4045                         rtw_mfree((u8 *)parm, sizeof(struct drvextra_cmd_parm));
4046                         res = _FAIL;
4047                         goto exit;
4048                 }
4049         }
4050
4051         parm->ec_id = CUSTOMER_STR_WK_CID;
4052         parm->type = write;
4053         parm->size = write ? RTW_CUSTOMER_STR_LEN : 0;
4054         parm->pbuf = write ? str : NULL;
4055
4056         if (write)
4057                 _rtw_memcpy(str, cstr, RTW_CUSTOMER_STR_LEN);
4058
4059         /* need enqueue, prepare cmd_obj and enqueue */
4060         cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
4061         if (cmdobj == NULL) {
4062                 res = _FAIL;
4063                 rtw_mfree((u8 *)parm, sizeof(*parm));
4064                 if (write)
4065                         rtw_mfree(str, RTW_CUSTOMER_STR_LEN);
4066                 goto exit;
4067         }
4068
4069         init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_Set_Drv_Extra));
4070
4071         cmdobj->sctx = &sctx;
4072         rtw_sctx_init(&sctx, 2 * 1000);
4073
4074         res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
4075
4076         if (res == _SUCCESS) {
4077                 rtw_sctx_wait(&sctx, __func__);
4078                 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4079                 if (sctx.status == RTW_SCTX_SUBMITTED)
4080                         cmdobj->sctx = NULL;
4081                 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
4082                 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
4083                         res = _FAIL;
4084         }
4085
4086 exit:
4087         return res;
4088 }
4089
4090 inline u8 rtw_customer_str_req_cmd(_adapter *adapter)
4091 {
4092         return rtw_customer_str_cmd(adapter, 0, NULL);
4093 }
4094
4095 inline u8 rtw_customer_str_write_cmd(_adapter *adapter, const u8 *cstr)
4096 {
4097         return rtw_customer_str_cmd(adapter, 1, cstr);
4098 }
4099 #endif /* CONFIG_RTW_CUSTOMER_STR */
4100
4101 u8 rtw_c2h_wk_cmd(PADAPTER padapter, u8 *pbuf, u16 length, u8 type)
4102 {
4103         struct cmd_obj *ph2c;
4104         struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4105         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4106         u8 *extra_cmd_buf;
4107         u8 res = _SUCCESS;
4108
4109         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4110         if (ph2c == NULL) {
4111                 res = _FAIL;
4112                 goto exit;
4113         }
4114
4115         pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4116         if (pdrvextra_cmd_parm == NULL) {
4117                 rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4118                 res = _FAIL;
4119                 goto exit;
4120         }
4121
4122         extra_cmd_buf = rtw_zmalloc(length);
4123         if (extra_cmd_buf == NULL) {
4124                 rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4125                 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
4126                 res = _FAIL;
4127                 goto exit;
4128         }
4129
4130         _rtw_memcpy(extra_cmd_buf, pbuf, length);
4131         pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
4132         pdrvextra_cmd_parm->type = type;
4133         pdrvextra_cmd_parm->size = length;
4134         pdrvextra_cmd_parm->pbuf = extra_cmd_buf;
4135
4136         init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
4137
4138         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
4139
4140 exit:
4141         return res;
4142 }
4143
4144 #ifdef CONFIG_FW_C2H_REG
4145 inline u8 rtw_c2h_reg_wk_cmd(_adapter *adapter, u8 *c2h_evt)
4146 {
4147         return rtw_c2h_wk_cmd(adapter, c2h_evt, c2h_evt ? C2H_REG_LEN : 0, C2H_TYPE_REG);
4148 }
4149 #endif
4150
4151 #ifdef CONFIG_FW_C2H_PKT
4152 inline u8 rtw_c2h_packet_wk_cmd(_adapter *adapter, u8 *c2h_evt, u16 length)
4153 {
4154         return rtw_c2h_wk_cmd(adapter, c2h_evt, length, C2H_TYPE_PKT);
4155 }
4156 #endif
4157
4158 u8 rtw_run_in_thread_cmd(PADAPTER padapter, void (*func)(void *), void *context)
4159 {
4160         struct cmd_priv *pcmdpriv;
4161         struct cmd_obj *ph2c;
4162         struct RunInThread_param *parm;
4163         s32 res = _SUCCESS;
4164
4165
4166         pcmdpriv = &padapter->cmdpriv;
4167
4168         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4169         if (NULL == ph2c) {
4170                 res = _FAIL;
4171                 goto exit;
4172         }
4173
4174         parm = (struct RunInThread_param *)rtw_zmalloc(sizeof(struct RunInThread_param));
4175         if (NULL == parm) {
4176                 rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
4177                 res = _FAIL;
4178                 goto exit;
4179         }
4180
4181         parm->func = func;
4182         parm->context = context;
4183         init_h2fwcmd_w_parm_no_rsp(ph2c, parm, GEN_CMD_CODE(_RunInThreadCMD));
4184
4185         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
4186 exit:
4187
4188
4189         return res;
4190 }
4191
4192 #ifdef CONFIG_FW_C2H_REG
4193 s32 c2h_evt_hdl(_adapter *adapter, u8 *c2h_evt, c2h_id_filter filter)
4194 {
4195         s32 ret = _FAIL;
4196         u8 buf[C2H_REG_LEN] = {0};
4197         u8 id, seq, plen;
4198         u8 *payload;
4199
4200         if (!c2h_evt) {
4201                 /* No c2h event in cmd_obj, read c2h event before handling*/
4202                 if (rtw_hal_c2h_evt_read(adapter, buf) != _SUCCESS)
4203                         goto exit;
4204                 c2h_evt = buf;
4205         }
4206
4207         rtw_hal_c2h_reg_hdr_parse(adapter, c2h_evt, &id, &seq, &plen, &payload);
4208
4209         if (filter && filter(adapter, id, seq, plen, payload) == _FALSE)
4210                 goto exit;
4211
4212         ret = rtw_hal_c2h_handler(adapter, id, seq, plen, payload);
4213
4214 exit:
4215         return ret;
4216 }
4217 #endif /* CONFIG_FW_C2H_REG */
4218
4219 u8 session_tracker_cmd(_adapter *adapter, u8 cmd, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
4220 {
4221         struct cmd_priv *cmdpriv = &adapter->cmdpriv;
4222         struct cmd_obj *cmdobj;
4223         struct drvextra_cmd_parm *cmd_parm;
4224         struct st_cmd_parm *st_parm;
4225         u8      res = _SUCCESS;
4226
4227         cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4228         if (cmdobj == NULL) {
4229                 res = _FAIL;
4230                 goto exit;
4231         }
4232
4233         cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4234         if (cmd_parm == NULL) {
4235                 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
4236                 res = _FAIL;
4237                 goto exit;
4238         }
4239
4240         st_parm = (struct st_cmd_parm *)rtw_zmalloc(sizeof(struct st_cmd_parm));
4241         if (st_parm == NULL) {
4242                 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
4243                 rtw_mfree((u8 *)cmd_parm, sizeof(struct drvextra_cmd_parm));
4244                 res = _FAIL;
4245                 goto exit;
4246         }
4247
4248         st_parm->cmd = cmd;
4249         st_parm->sta = sta;
4250         if (cmd != ST_CMD_CHK) {
4251                 _rtw_memcpy(&st_parm->local_naddr, local_naddr, 4);
4252                 _rtw_memcpy(&st_parm->local_port, local_port, 2);
4253                 _rtw_memcpy(&st_parm->remote_naddr, remote_naddr, 4);
4254                 _rtw_memcpy(&st_parm->remote_port, remote_port, 2);
4255         }
4256
4257         cmd_parm->ec_id = SESSION_TRACKER_WK_CID;
4258         cmd_parm->type = 0;
4259         cmd_parm->size = sizeof(struct st_cmd_parm);
4260         cmd_parm->pbuf = (u8 *)st_parm;
4261         init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
4262         cmdobj->no_io = 1;
4263
4264         res = rtw_enqueue_cmd(cmdpriv, cmdobj);
4265
4266 exit:
4267         return res;
4268 }
4269
4270 inline u8 session_tracker_chk_cmd(_adapter *adapter, struct sta_info *sta)
4271 {
4272         return session_tracker_cmd(adapter, ST_CMD_CHK, sta, NULL, NULL, NULL, NULL);
4273 }
4274
4275 inline u8 session_tracker_add_cmd(_adapter *adapter, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
4276 {
4277         return session_tracker_cmd(adapter, ST_CMD_ADD, sta, local_naddr, local_port, remote_naddr, remote_port);
4278 }
4279
4280 inline u8 session_tracker_del_cmd(_adapter *adapter, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
4281 {
4282         return session_tracker_cmd(adapter, ST_CMD_DEL, sta, local_naddr, local_port, remote_naddr, remote_port);
4283 }
4284
4285 void session_tracker_chk_for_sta(_adapter *adapter, struct sta_info *sta)
4286 {
4287         struct st_ctl_t *st_ctl = &sta->st_ctl;
4288         int i;
4289         _irqL irqL;
4290         _list *plist, *phead, *pnext;
4291         _list dlist;
4292         struct session_tracker *st = NULL;
4293         u8 op_wfd_mode = MIRACAST_DISABLED;
4294
4295         if (DBG_SESSION_TRACKER)
4296                 RTW_INFO(FUNC_ADPT_FMT" sta:%p\n", FUNC_ADPT_ARG(adapter), sta);
4297
4298         if (!(sta->state & _FW_LINKED))
4299                 goto exit;
4300
4301         for (i = 0; i < SESSION_TRACKER_REG_ID_NUM; i++) {
4302                 if (st_ctl->reg[i].s_proto != 0)
4303                         break;
4304         }
4305         if (i >= SESSION_TRACKER_REG_ID_NUM)
4306                 goto chk_sta;
4307
4308         _rtw_init_listhead(&dlist);
4309
4310         _enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
4311
4312         phead = &st_ctl->tracker_q.queue;
4313         plist = get_next(phead);
4314         pnext = get_next(plist);
4315         while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
4316                 st = LIST_CONTAINOR(plist, struct session_tracker, list);
4317                 plist = pnext;
4318                 pnext = get_next(pnext);
4319
4320                 if (st->status != ST_STATUS_ESTABLISH
4321                         && rtw_get_passing_time_ms(st->set_time) > ST_EXPIRE_MS
4322                 ) {
4323                         rtw_list_delete(&st->list);
4324                         rtw_list_insert_tail(&st->list, &dlist);
4325                 }
4326
4327                 /* TODO: check OS for status update */
4328                 if (st->status == ST_STATUS_CHECK)
4329                         st->status = ST_STATUS_ESTABLISH;
4330
4331                 if (st->status != ST_STATUS_ESTABLISH)
4332                         continue;
4333
4334                 #ifdef CONFIG_WFD
4335                 if (0)
4336                         RTW_INFO(FUNC_ADPT_FMT" local:%u, remote:%u, rtsp:%u, %u, %u\n", FUNC_ADPT_ARG(adapter)
4337                                 , ntohs(st->local_port), ntohs(st->remote_port), adapter->wfd_info.rtsp_ctrlport, adapter->wfd_info.tdls_rtsp_ctrlport
4338                                 , adapter->wfd_info.peer_rtsp_ctrlport);
4339                 if (ntohs(st->local_port) == adapter->wfd_info.rtsp_ctrlport)
4340                         op_wfd_mode |= MIRACAST_SINK;
4341                 if (ntohs(st->local_port) == adapter->wfd_info.tdls_rtsp_ctrlport)
4342                         op_wfd_mode |= MIRACAST_SINK;
4343                 if (ntohs(st->remote_port) == adapter->wfd_info.peer_rtsp_ctrlport)
4344                         op_wfd_mode |= MIRACAST_SOURCE;
4345                 #endif
4346         }
4347
4348         _exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
4349
4350         plist = get_next(&dlist);
4351         while (rtw_end_of_queue_search(&dlist, plist) == _FALSE) {
4352                 st = LIST_CONTAINOR(plist, struct session_tracker, list);
4353                 plist = get_next(plist);
4354                 rtw_mfree((u8 *)st, sizeof(struct session_tracker));
4355         }
4356
4357 chk_sta:
4358         if (STA_OP_WFD_MODE(sta) != op_wfd_mode) {
4359                 STA_SET_OP_WFD_MODE(sta, op_wfd_mode);
4360                 rtw_sta_media_status_rpt_cmd(adapter, sta, 1);
4361         }
4362
4363 exit:
4364         return;
4365 }
4366
4367 void session_tracker_chk_for_adapter(_adapter *adapter)
4368 {
4369         struct sta_priv *stapriv = &adapter->stapriv;
4370         struct sta_info *sta;
4371         int i;
4372         _irqL irqL;
4373         _list *plist, *phead;
4374         u8 op_wfd_mode = MIRACAST_DISABLED;
4375
4376         _enter_critical_bh(&stapriv->sta_hash_lock, &irqL);
4377
4378         for (i = 0; i < NUM_STA; i++) {
4379                 phead = &(stapriv->sta_hash[i]);
4380                 plist = get_next(phead);
4381
4382                 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
4383                         sta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
4384                         plist = get_next(plist);
4385
4386                         session_tracker_chk_for_sta(adapter, sta);
4387
4388                         op_wfd_mode |= STA_OP_WFD_MODE(sta);
4389                 }
4390         }
4391
4392         _exit_critical_bh(&stapriv->sta_hash_lock, &irqL);
4393
4394 #ifdef CONFIG_WFD
4395         adapter->wfd_info.op_wfd_mode = MIRACAST_MODE_REVERSE(op_wfd_mode);
4396 #endif
4397 }
4398
4399 void session_tracker_cmd_hdl(_adapter *adapter, struct st_cmd_parm *parm)
4400 {
4401         u8 cmd = parm->cmd;
4402         struct sta_info *sta = parm->sta;
4403
4404         if (cmd == ST_CMD_CHK) {
4405                 if (sta)
4406                         session_tracker_chk_for_sta(adapter, sta);
4407                 else
4408                         session_tracker_chk_for_adapter(adapter);
4409
4410                 goto exit;
4411
4412         } else if (cmd == ST_CMD_ADD || cmd == ST_CMD_DEL) {
4413                 struct st_ctl_t *st_ctl;
4414                 u32 local_naddr = parm->local_naddr;
4415                 u16 local_port = parm->local_port;
4416                 u32 remote_naddr = parm->remote_naddr;
4417                 u16 remote_port = parm->remote_port;
4418                 struct session_tracker *st = NULL;
4419                 _irqL irqL;
4420                 _list *plist, *phead;
4421                 u8 free_st = 0;
4422                 u8 alloc_st = 0;
4423
4424                 if (DBG_SESSION_TRACKER)
4425                         RTW_INFO(FUNC_ADPT_FMT" cmd:%u, sta:%p, local:"IP_FMT":"PORT_FMT", remote:"IP_FMT":"PORT_FMT"\n"
4426                                 , FUNC_ADPT_ARG(adapter), cmd, sta
4427                                 , IP_ARG(&local_naddr), PORT_ARG(&local_port)
4428                                 , IP_ARG(&remote_naddr), PORT_ARG(&remote_port)
4429                         );
4430
4431                 if (!(sta->state & _FW_LINKED))
4432                         goto exit;
4433
4434                 st_ctl = &sta->st_ctl;
4435
4436                 _enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
4437
4438                 phead = &st_ctl->tracker_q.queue;
4439                 plist = get_next(phead);
4440                 while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
4441                         st = LIST_CONTAINOR(plist, struct session_tracker, list);
4442
4443                         if (st->local_naddr == local_naddr
4444                                 && st->local_port == local_port
4445                                 && st->remote_naddr == remote_naddr
4446                                 && st->remote_port == remote_port)
4447                                 break;
4448
4449                         plist = get_next(plist);
4450                 }
4451
4452                 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
4453                         st = NULL;
4454
4455                 switch (cmd) {
4456                 case ST_CMD_DEL:
4457                         if (st) {
4458                                 rtw_list_delete(plist);
4459                                 free_st = 1;
4460                         }
4461                         goto unlock;
4462                 case ST_CMD_ADD:
4463                         if (!st)
4464                                 alloc_st = 1;
4465                 }
4466
4467 unlock:
4468                 _exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
4469
4470                 if (free_st) {
4471                         rtw_mfree((u8 *)st, sizeof(struct session_tracker));
4472                         goto exit;
4473                 }
4474
4475                 if (alloc_st) {
4476                         st = (struct session_tracker *)rtw_zmalloc(sizeof(struct session_tracker));
4477                         if (!st)
4478                                 goto exit;
4479
4480                         st->local_naddr = local_naddr;
4481                         st->local_port = local_port;
4482                         st->remote_naddr = remote_naddr;
4483                         st->remote_port = remote_port;
4484                         st->set_time = rtw_get_current_time();
4485                         st->status = ST_STATUS_CHECK;
4486
4487                         _enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
4488                         rtw_list_insert_tail(&st->list, phead);
4489                         _exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
4490                 }
4491         }
4492
4493 exit:
4494         return;
4495 }
4496
4497 u8 rtw_drvextra_cmd_hdl(_adapter *padapter, unsigned char *pbuf)
4498 {
4499         int ret = H2C_SUCCESS;
4500         struct drvextra_cmd_parm *pdrvextra_cmd;
4501
4502         if (!pbuf)
4503                 return H2C_PARAMETERS_ERROR;
4504
4505         pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
4506
4507         switch (pdrvextra_cmd->ec_id) {
4508         case STA_MSTATUS_RPT_WK_CID:
4509                 rtw_sta_media_status_rpt_cmd_hdl(padapter, (struct sta_media_status_rpt_cmd_parm *)pdrvextra_cmd->pbuf);
4510                 break;
4511
4512         case DYNAMIC_CHK_WK_CID:/*only  primary padapter go to this cmd, but execute dynamic_chk_wk_hdl() for two interfaces */
4513                 rtw_dynamic_chk_wk_hdl(padapter);
4514                 break;
4515         case POWER_SAVING_CTRL_WK_CID:
4516                 power_saving_wk_hdl(padapter);
4517                 break;
4518 #ifdef CONFIG_LPS
4519         case LPS_CTRL_WK_CID:
4520                 lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type);
4521                 break;
4522         case DM_IN_LPS_WK_CID:
4523                 rtw_dm_in_lps_hdl(padapter);
4524                 break;
4525         case LPS_CHANGE_DTIM_CID:
4526                 rtw_lps_change_dtim_hdl(padapter, (u8)pdrvextra_cmd->type);
4527                 break;
4528 #endif
4529 #if (RATE_ADAPTIVE_SUPPORT == 1)
4530         case RTP_TIMER_CFG_WK_CID:
4531                 rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type);
4532                 break;
4533 #endif
4534 #ifdef CONFIG_ANTENNA_DIVERSITY
4535         case ANT_SELECT_WK_CID:
4536                 antenna_select_wk_hdl(padapter, pdrvextra_cmd->type);
4537                 break;
4538 #endif
4539 #ifdef CONFIG_P2P_PS
4540         case P2P_PS_WK_CID:
4541                 p2p_ps_wk_hdl(padapter, pdrvextra_cmd->type);
4542                 break;
4543 #endif
4544 #ifdef CONFIG_P2P
4545         case P2P_PROTO_WK_CID:
4546                 /*
4547                 * Commented by Albert 2011/07/01
4548                 * I used the type_size as the type command
4549                 */
4550                 ret = p2p_protocol_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
4551                 break;
4552 #endif
4553 #ifdef CONFIG_AP_MODE
4554         case CHECK_HIQ_WK_CID:
4555                 rtw_chk_hi_queue_hdl(padapter);
4556                 break;
4557 #endif
4558 #ifdef CONFIG_INTEL_WIDI
4559         case INTEl_WIDI_WK_CID:
4560                 intel_widi_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
4561                 break;
4562 #endif
4563         /* add for CONFIG_IEEE80211W, none 11w can use it */
4564         case RESET_SECURITYPRIV:
4565                 reset_securitypriv_hdl(padapter);
4566                 break;
4567         case FREE_ASSOC_RESOURCES:
4568                 free_assoc_resources_hdl(padapter);
4569                 break;
4570         case C2H_WK_CID:
4571                 switch (pdrvextra_cmd->type) {
4572                 #ifdef CONFIG_FW_C2H_REG
4573                 case C2H_TYPE_REG:
4574                         c2h_evt_hdl(padapter, pdrvextra_cmd->pbuf, NULL);
4575                         break;
4576                 #endif
4577                 #ifdef CONFIG_FW_C2H_PKT
4578                 case C2H_TYPE_PKT:
4579                         rtw_hal_c2h_pkt_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
4580                         break;
4581                 #endif
4582                 default:
4583                         RTW_ERR("unknown C2H type:%d\n", pdrvextra_cmd->type);
4584                         rtw_warn_on(1);
4585                         break;
4586                 }
4587                 break;
4588 #ifdef CONFIG_BEAMFORMING
4589         case BEAMFORMING_WK_CID:
4590                 beamforming_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
4591                 break;
4592 #endif
4593         case DM_RA_MSK_WK_CID:
4594                 rtw_dm_ra_mask_hdl(padapter, (struct sta_info *)pdrvextra_cmd->pbuf);
4595                 break;
4596 #ifdef CONFIG_BT_COEXIST
4597         case BTINFO_WK_CID:
4598                 rtw_btinfo_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
4599                 break;
4600 #endif
4601 #ifdef CONFIG_DFS_MASTER
4602         case DFS_MASTER_WK_CID:
4603                 rtw_dfs_master_hdl(padapter);
4604                 break;
4605 #endif
4606         case SESSION_TRACKER_WK_CID:
4607                 session_tracker_cmd_hdl(padapter, (struct st_cmd_parm *)pdrvextra_cmd->pbuf);
4608                 break;
4609         case EN_HW_UPDATE_TSF_WK_CID:
4610                 rtw_hal_set_hwreg(padapter, HW_VAR_EN_HW_UPDATE_TSF, NULL);
4611                 break;
4612         case TEST_H2C_CID:
4613                 rtw_hal_fill_h2c_cmd(padapter, pdrvextra_cmd->pbuf[0], pdrvextra_cmd->size - 1, &pdrvextra_cmd->pbuf[1]);
4614                 break;
4615         case MP_CMD_WK_CID:
4616                 ret = rtw_mp_cmd_hdl(padapter, pdrvextra_cmd->type);
4617                 break;
4618 #ifdef CONFIG_RTW_CUSTOMER_STR
4619         case CUSTOMER_STR_WK_CID:
4620                 ret = rtw_customer_str_cmd_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
4621                 break;
4622 #endif
4623         default:
4624                 break;
4625         }
4626
4627         if (pdrvextra_cmd->pbuf && pdrvextra_cmd->size > 0)
4628                 rtw_mfree(pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
4629
4630         return ret;
4631 }
4632
4633 void rtw_survey_cmd_callback(_adapter   *padapter ,  struct cmd_obj *pcmd)
4634 {
4635         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
4636
4637
4638         if (pcmd->res == H2C_DROPPED) {
4639                 /* TODO: cancel timer and do timeout handler directly... */
4640                 /* need to make timeout handlerOS independent */
4641                 mlme_set_scan_to_timer(pmlmepriv, 1);
4642         } else if (pcmd->res != H2C_SUCCESS) {
4643                 mlme_set_scan_to_timer(pmlmepriv, 1);
4644         }
4645
4646         /* free cmd */
4647         rtw_free_cmd_obj(pcmd);
4648
4649 }
4650 void rtw_disassoc_cmd_callback(_adapter *padapter,  struct cmd_obj *pcmd)
4651 {
4652         _irqL   irqL;
4653         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
4654
4655
4656         if (pcmd->res != H2C_SUCCESS) {
4657                 _enter_critical_bh(&pmlmepriv->lock, &irqL);
4658                 set_fwstate(pmlmepriv, _FW_LINKED);
4659                 _exit_critical_bh(&pmlmepriv->lock, &irqL);
4660                 goto exit;
4661         }
4662 #ifdef CONFIG_BR_EXT
4663         else /* clear bridge database */
4664                 nat25_db_cleanup(padapter);
4665 #endif /* CONFIG_BR_EXT */
4666
4667         /* free cmd */
4668         rtw_free_cmd_obj(pcmd);
4669
4670 exit:
4671         return;
4672 }
4673
4674
4675 void rtw_getmacreg_cmdrsp_callback(_adapter *padapter,  struct cmd_obj *pcmd)
4676 {
4677
4678
4679         rtw_free_cmd_obj(pcmd);
4680
4681 }
4682
4683 void rtw_joinbss_cmd_callback(_adapter  *padapter,  struct cmd_obj *pcmd)
4684 {
4685         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
4686
4687
4688         if (pcmd->res == H2C_DROPPED) {
4689                 /* TODO: cancel timer and do timeout handler directly... */
4690                 /* need to make timeout handlerOS independent */
4691                 _set_timer(&pmlmepriv->assoc_timer, 1);
4692         } else if (pcmd->res != H2C_SUCCESS)
4693                 _set_timer(&pmlmepriv->assoc_timer, 1);
4694
4695         rtw_free_cmd_obj(pcmd);
4696
4697 }
4698
4699 void rtw_create_ibss_post_hdl(_adapter *padapter, int status)
4700 {
4701         _irqL irqL;
4702         u8 timer_cancelled;
4703         struct sta_info *psta = NULL;
4704         struct wlan_network *pwlan = NULL;
4705         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
4706         WLAN_BSSID_EX *pdev_network = &padapter->registrypriv.dev_network;
4707         struct wlan_network *mlme_cur_network = &(pmlmepriv->cur_network);
4708
4709         if (status != H2C_SUCCESS)
4710                 _set_timer(&pmlmepriv->assoc_timer, 1);
4711
4712         _cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
4713
4714         _enter_critical_bh(&pmlmepriv->lock, &irqL);
4715
4716         {
4717                 _irqL irqL;
4718
4719                 pwlan = _rtw_alloc_network(pmlmepriv);
4720                 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4721                 if (pwlan == NULL) {
4722                         pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
4723                         if (pwlan == NULL) {
4724                                 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4725                                 goto createbss_cmd_fail;
4726                         }
4727                         pwlan->last_scanned = rtw_get_current_time();
4728                 } else
4729                         rtw_list_insert_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
4730
4731                 pdev_network->Length = get_WLAN_BSSID_EX_sz(pdev_network);
4732                 _rtw_memcpy(&(pwlan->network), pdev_network, pdev_network->Length);
4733                 /* pwlan->fixed = _TRUE; */
4734
4735                 /* copy pdev_network information to pmlmepriv->cur_network */
4736                 _rtw_memcpy(&mlme_cur_network->network, pdev_network, (get_WLAN_BSSID_EX_sz(pdev_network)));
4737
4738 #if 0
4739                 /* reset DSConfig */
4740                 mlme_cur_network->network.Configuration.DSConfig = (u32)rtw_ch2freq(pdev_network->Configuration.DSConfig);
4741 #endif
4742
4743                 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
4744                 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4745                 /* we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */
4746         }
4747
4748 createbss_cmd_fail:
4749         _exit_critical_bh(&pmlmepriv->lock, &irqL);
4750 exit:
4751         return;
4752 }
4753
4754
4755
4756 void rtw_setstaKey_cmdrsp_callback(_adapter     *padapter ,  struct cmd_obj *pcmd)
4757 {
4758
4759         struct sta_priv *pstapriv = &padapter->stapriv;
4760         struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp);
4761         struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
4762
4763
4764         if (psta == NULL) {
4765                 goto exit;
4766         }
4767
4768         /* psta->aid = psta->mac_id = psetstakey_rsp->keyid; */ /* CAM_ID(CAM_ENTRY) */
4769
4770 exit:
4771
4772         rtw_free_cmd_obj(pcmd);
4773
4774
4775 }
4776 void rtw_setassocsta_cmdrsp_callback(_adapter   *padapter,  struct cmd_obj *pcmd)
4777 {
4778         _irqL   irqL;
4779         struct sta_priv *pstapriv = &padapter->stapriv;
4780         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
4781         struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
4782         struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *)(pcmd->rsp);
4783         struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr);
4784
4785
4786         if (psta == NULL) {
4787                 goto exit;
4788         }
4789
4790         psta->aid = psta->mac_id = passocsta_rsp->cam_id;
4791
4792         _enter_critical_bh(&pmlmepriv->lock, &irqL);
4793
4794         if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE) && (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE))
4795                 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
4796
4797         set_fwstate(pmlmepriv, _FW_LINKED);
4798         _exit_critical_bh(&pmlmepriv->lock, &irqL);
4799
4800 exit:
4801         rtw_free_cmd_obj(pcmd);
4802
4803 }
4804
4805 void rtw_getrttbl_cmd_cmdrsp_callback(_adapter  *padapter,  struct cmd_obj *pcmd);
4806 void rtw_getrttbl_cmd_cmdrsp_callback(_adapter  *padapter,  struct cmd_obj *pcmd)
4807 {
4808
4809         rtw_free_cmd_obj(pcmd);
4810 #ifdef CONFIG_MP_INCLUDED
4811         if (padapter->registrypriv.mp_mode == 1)
4812                 padapter->mppriv.workparam.bcompleted = _TRUE;
4813 #endif
4814
4815
4816 }