Path: blob/master/ALFA-W1F1/RTL8814AU/core/rtw_cmd.c
1307 views
/******************************************************************************1*2* Copyright(c) 2007 - 2017 Realtek Corporation.3*4* This program is free software; you can redistribute it and/or modify it5* under the terms of version 2 of the GNU General Public License as6* published by the Free Software Foundation.7*8* This program is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for11* more details.12*13*****************************************************************************/14#define _RTW_CMD_C_1516#include <drv_types.h>17#include <hal_data.h>1819#ifndef DBG_CMD_EXECUTE20#define DBG_CMD_EXECUTE 021#endif2223/*24Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.25No irqsave is necessary.26*/2728sint _rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)29{30sint res = _SUCCESS;313233_rtw_init_sema(&(pcmdpriv->cmd_queue_sema), 0);34/* _rtw_init_sema(&(pcmdpriv->cmd_done_sema), 0); */35_rtw_init_sema(&(pcmdpriv->start_cmdthread_sema), 0);3637_rtw_init_queue(&(pcmdpriv->cmd_queue));3839/* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */4041pcmdpriv->cmd_seq = 1;4243pcmdpriv->cmd_allocated_buf = rtw_zmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ);4445if (pcmdpriv->cmd_allocated_buf == NULL) {46res = _FAIL;47goto exit;48}4950pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ - ((SIZE_PTR)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ - 1));5152pcmdpriv->rsp_allocated_buf = rtw_zmalloc(MAX_RSPSZ + 4);5354if (pcmdpriv->rsp_allocated_buf == NULL) {55res = _FAIL;56goto exit;57}5859pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 - ((SIZE_PTR)(pcmdpriv->rsp_allocated_buf) & 3);6061pcmdpriv->cmd_issued_cnt = pcmdpriv->cmd_done_cnt = pcmdpriv->rsp_cnt = 0;6263_rtw_mutex_init(&pcmdpriv->sctx_mutex);64exit:656667return res;6869}7071#ifdef CONFIG_C2H_WK72static void c2h_wk_callback(_workitem *work)73{74struct evt_priv *evtpriv = container_of(work, struct evt_priv, c2h_wk);75_adapter *adapter = container_of(evtpriv, _adapter, evtpriv);76u8 *c2h_evt;77c2h_id_filter direct_hdl_filter = rtw_hal_c2h_id_handle_directly;78u8 id, seq, plen;79u8 *payload;8081evtpriv->c2h_wk_alive = _TRUE;8283while (!rtw_cbuf_empty(evtpriv->c2h_queue)) {84c2h_evt = (u8 *)rtw_cbuf_pop(evtpriv->c2h_queue);85if (c2h_evt != NULL) {86/* This C2H event is read, clear it */87c2h_evt_clear(adapter);88} else {89c2h_evt = (u8 *)rtw_malloc(C2H_REG_LEN);90if (c2h_evt == NULL) {91rtw_warn_on(1);92continue;93}9495/* This C2H event is not read, read & clear now */96if (rtw_hal_c2h_evt_read(adapter, c2h_evt) != _SUCCESS) {97rtw_mfree(c2h_evt, C2H_REG_LEN);98continue;99}100}101102/* Special pointer to trigger c2h_evt_clear only */103if ((void *)c2h_evt == (void *)evtpriv)104continue;105106if (!rtw_hal_c2h_valid(adapter, c2h_evt)107|| rtw_hal_c2h_reg_hdr_parse(adapter, c2h_evt, &id, &seq, &plen, &payload) != _SUCCESS108) {109rtw_mfree(c2h_evt, C2H_REG_LEN);110continue;111}112113if (direct_hdl_filter(adapter, id, seq, plen, payload) == _TRUE) {114/* Handle directly */115rtw_hal_c2h_handler(adapter, id, seq, plen, payload);116rtw_mfree(c2h_evt, C2H_REG_LEN);117} else {118/* Enqueue into cmd_thread for others */119rtw_c2h_reg_wk_cmd(adapter, c2h_evt);120rtw_mfree(c2h_evt, C2H_REG_LEN);121}122}123124evtpriv->c2h_wk_alive = _FALSE;125}126#endif /* CONFIG_C2H_WK */127128sint _rtw_init_evt_priv(struct evt_priv *pevtpriv)129{130sint res = _SUCCESS;131132133#ifdef CONFIG_H2CLBK134_rtw_init_sema(&(pevtpriv->lbkevt_done), 0);135pevtpriv->lbkevt_limit = 0;136pevtpriv->lbkevt_num = 0;137pevtpriv->cmdevt_parm = NULL;138#endif139140/* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */141ATOMIC_SET(&pevtpriv->event_seq, 0);142pevtpriv->evt_done_cnt = 0;143144#ifdef CONFIG_EVENT_THREAD_MODE145146_rtw_init_sema(&(pevtpriv->evt_notify), 0);147148pevtpriv->evt_allocated_buf = rtw_zmalloc(MAX_EVTSZ + 4);149if (pevtpriv->evt_allocated_buf == NULL) {150res = _FAIL;151goto exit;152}153pevtpriv->evt_buf = pevtpriv->evt_allocated_buf + 4 - ((unsigned int)(pevtpriv->evt_allocated_buf) & 3);154155156#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)157pevtpriv->allocated_c2h_mem = rtw_zmalloc(C2H_MEM_SZ + 4);158159if (pevtpriv->allocated_c2h_mem == NULL) {160res = _FAIL;161goto exit;162}163164pevtpriv->c2h_mem = pevtpriv->allocated_c2h_mem + 4\165- ((u32)(pevtpriv->allocated_c2h_mem) & 3);166#endif /* end of CONFIG_SDIO_HCI */167168_rtw_init_queue(&(pevtpriv->evt_queue));169170exit:171172#endif /* end of CONFIG_EVENT_THREAD_MODE */173174#ifdef CONFIG_C2H_WK175_init_workitem(&pevtpriv->c2h_wk, c2h_wk_callback, NULL);176pevtpriv->c2h_wk_alive = _FALSE;177pevtpriv->c2h_queue = rtw_cbuf_alloc(C2H_QUEUE_MAX_LEN + 1);178#endif179180181return res;182}183184void _rtw_free_evt_priv(struct evt_priv *pevtpriv)185{186187188#ifdef CONFIG_EVENT_THREAD_MODE189_rtw_free_sema(&(pevtpriv->evt_notify));190191if (pevtpriv->evt_allocated_buf)192rtw_mfree(pevtpriv->evt_allocated_buf, MAX_EVTSZ + 4);193#endif194195#ifdef CONFIG_C2H_WK196_cancel_workitem_sync(&pevtpriv->c2h_wk);197while (pevtpriv->c2h_wk_alive)198rtw_msleep_os(10);199200while (!rtw_cbuf_empty(pevtpriv->c2h_queue)) {201void *c2h;202c2h = rtw_cbuf_pop(pevtpriv->c2h_queue);203if (c2h != NULL && c2h != (void *)pevtpriv)204rtw_mfree(c2h, 16);205}206rtw_cbuf_free(pevtpriv->c2h_queue);207#endif208209210211}212213void _rtw_free_cmd_priv(struct cmd_priv *pcmdpriv)214{215216if (pcmdpriv) {217_rtw_spinlock_free(&(pcmdpriv->cmd_queue.lock));218_rtw_free_sema(&(pcmdpriv->cmd_queue_sema));219/* _rtw_free_sema(&(pcmdpriv->cmd_done_sema)); */220_rtw_free_sema(&(pcmdpriv->start_cmdthread_sema));221222if (pcmdpriv->cmd_allocated_buf)223rtw_mfree(pcmdpriv->cmd_allocated_buf, MAX_CMDSZ + CMDBUFF_ALIGN_SZ);224225if (pcmdpriv->rsp_allocated_buf)226rtw_mfree(pcmdpriv->rsp_allocated_buf, MAX_RSPSZ + 4);227228_rtw_mutex_free(&pcmdpriv->sctx_mutex);229}230}231232/*233Calling Context:234235rtw_enqueue_cmd can only be called between kernel thread,236since only spin_lock is used.237238ISR/Call-Back functions can't call this sub-function.239240*/241#ifdef DBG_CMD_QUEUE242extern u8 dump_cmd_id;243#endif244245sint _rtw_enqueue_cmd(_queue *queue, struct cmd_obj *obj, bool to_head)246{247_irqL irqL;248249250if (obj == NULL)251goto exit;252253/* _enter_critical_bh(&queue->lock, &irqL); */254_enter_critical(&queue->lock, &irqL);255256if (to_head)257rtw_list_insert_head(&obj->list, &queue->queue);258else259rtw_list_insert_tail(&obj->list, &queue->queue);260261#ifdef DBG_CMD_QUEUE262if (dump_cmd_id) {263printk("%s===> cmdcode:0x%02x\n", __FUNCTION__, obj->cmdcode);264if (obj->cmdcode == GEN_CMD_CODE(_Set_MLME_EVT)) {265if (obj->parmbuf) {266struct C2HEvent_Header *pc2h_evt_hdr = (struct C2HEvent_Header *)(obj->parmbuf);267printk("pc2h_evt_hdr->ID:0x%02x(%d)\n", pc2h_evt_hdr->ID, pc2h_evt_hdr->ID);268}269}270if (obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {271if (obj->parmbuf) {272struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)(obj->parmbuf);273printk("pdrvextra_cmd_parm->ec_id:0x%02x\n", pdrvextra_cmd_parm->ec_id);274}275}276}277278if (queue->queue.prev->next != &queue->queue) {279RTW_INFO("[%d] head %p, tail %p, tail->prev->next %p[tail], tail->next %p[head]\n", __LINE__,280&queue->queue, queue->queue.prev, queue->queue.prev->prev->next, queue->queue.prev->next);281282RTW_INFO("==========%s============\n", __FUNCTION__);283RTW_INFO("head:%p,obj_addr:%p\n", &queue->queue, obj);284RTW_INFO("padapter: %p\n", obj->padapter);285RTW_INFO("cmdcode: 0x%02x\n", obj->cmdcode);286RTW_INFO("res: %d\n", obj->res);287RTW_INFO("parmbuf: %p\n", obj->parmbuf);288RTW_INFO("cmdsz: %d\n", obj->cmdsz);289RTW_INFO("rsp: %p\n", obj->rsp);290RTW_INFO("rspsz: %d\n", obj->rspsz);291RTW_INFO("sctx: %p\n", obj->sctx);292RTW_INFO("list->next: %p\n", obj->list.next);293RTW_INFO("list->prev: %p\n", obj->list.prev);294}295#endif /* DBG_CMD_QUEUE */296297/* _exit_critical_bh(&queue->lock, &irqL); */298_exit_critical(&queue->lock, &irqL);299300exit:301302303return _SUCCESS;304}305306struct cmd_obj *_rtw_dequeue_cmd(_queue *queue)307{308_irqL irqL;309struct cmd_obj *obj;310311312/* _enter_critical_bh(&(queue->lock), &irqL); */313_enter_critical(&queue->lock, &irqL);314315#ifdef DBG_CMD_QUEUE316if (queue->queue.prev->next != &queue->queue) {317RTW_INFO("[%d] head %p, tail %p, tail->prev->next %p[tail], tail->next %p[head]\n", __LINE__,318&queue->queue, queue->queue.prev, queue->queue.prev->prev->next, queue->queue.prev->next);319}320#endif /* DBG_CMD_QUEUE */321322323if (rtw_is_list_empty(&(queue->queue)))324obj = NULL;325else {326obj = LIST_CONTAINOR(get_next(&(queue->queue)), struct cmd_obj, list);327328#ifdef DBG_CMD_QUEUE329if (queue->queue.prev->next != &queue->queue) {330RTW_INFO("==========%s============\n", __FUNCTION__);331RTW_INFO("head:%p,obj_addr:%p\n", &queue->queue, obj);332RTW_INFO("padapter: %p\n", obj->padapter);333RTW_INFO("cmdcode: 0x%02x\n", obj->cmdcode);334RTW_INFO("res: %d\n", obj->res);335RTW_INFO("parmbuf: %p\n", obj->parmbuf);336RTW_INFO("cmdsz: %d\n", obj->cmdsz);337RTW_INFO("rsp: %p\n", obj->rsp);338RTW_INFO("rspsz: %d\n", obj->rspsz);339RTW_INFO("sctx: %p\n", obj->sctx);340RTW_INFO("list->next: %p\n", obj->list.next);341RTW_INFO("list->prev: %p\n", obj->list.prev);342}343344if (dump_cmd_id) {345RTW_INFO("%s===> cmdcode:0x%02x\n", __FUNCTION__, obj->cmdcode);346if (obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {347if (obj->parmbuf) {348struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)(obj->parmbuf);349printk("pdrvextra_cmd_parm->ec_id:0x%02x\n", pdrvextra_cmd_parm->ec_id);350}351}352353}354#endif /* DBG_CMD_QUEUE */355356rtw_list_delete(&obj->list);357}358359/* _exit_critical_bh(&(queue->lock), &irqL); */360_exit_critical(&queue->lock, &irqL);361362363return obj;364}365366u32 rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)367{368u32 res;369res = _rtw_init_cmd_priv(pcmdpriv);370return res;371}372373u32 rtw_init_evt_priv(struct evt_priv *pevtpriv)374{375int res;376res = _rtw_init_evt_priv(pevtpriv);377return res;378}379380void rtw_free_evt_priv(struct evt_priv *pevtpriv)381{382_rtw_free_evt_priv(pevtpriv);383}384385void rtw_free_cmd_priv(struct cmd_priv *pcmdpriv)386{387_rtw_free_cmd_priv(pcmdpriv);388}389390int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj);391int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)392{393u8 bAllow = _FALSE; /* set to _TRUE to allow enqueuing cmd when hw_init_completed is _FALSE */394395#ifdef SUPPORT_HW_RFOFF_DETECTED396/* To decide allow or not */397if ((adapter_to_pwrctl(pcmdpriv->padapter)->bHWPwrPindetect)398&& (!pcmdpriv->padapter->registrypriv.usbss_enable)399) {400if (cmd_obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {401struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf;402if (pdrvextra_cmd_parm->ec_id == POWER_SAVING_CTRL_WK_CID) {403/* RTW_INFO("==>enqueue POWER_SAVING_CTRL_WK_CID\n"); */404bAllow = _TRUE;405}406}407}408#endif409410if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan))411bAllow = _TRUE;412413if (cmd_obj->no_io)414bAllow = _TRUE;415416if ((!rtw_is_hw_init_completed(pcmdpriv->padapter) && (bAllow == _FALSE))417|| ATOMIC_READ(&(pcmdpriv->cmdthd_running)) == _FALSE /* com_thread not running */418) {419if (DBG_CMD_EXECUTE)420RTW_INFO(ADPT_FMT" drop "CMD_FMT" hw_init_completed:%u, cmdthd_running:%u\n", ADPT_ARG(cmd_obj->padapter)421, CMD_ARG(cmd_obj), rtw_get_hw_init_completed(cmd_obj->padapter), ATOMIC_READ(&pcmdpriv->cmdthd_running));422if (0)423rtw_warn_on(1);424425return _FAIL;426}427return _SUCCESS;428}429430431432u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)433{434int res = _FAIL;435PADAPTER padapter = pcmdpriv->padapter;436437438if (cmd_obj == NULL)439goto exit;440441cmd_obj->padapter = padapter;442443#ifdef CONFIG_CONCURRENT_MODE444/* change pcmdpriv to primary's pcmdpriv */445if (!is_primary_adapter(padapter))446pcmdpriv = &(GET_PRIMARY_ADAPTER(padapter)->cmdpriv);447#endif448449res = rtw_cmd_filter(pcmdpriv, cmd_obj);450if ((_FAIL == res) || (cmd_obj->cmdsz > MAX_CMDSZ)) {451if (cmd_obj->cmdsz > MAX_CMDSZ) {452RTW_INFO("%s failed due to obj->cmdsz(%d) > MAX_CMDSZ(%d)\n", __func__, cmd_obj->cmdsz, MAX_CMDSZ);453rtw_warn_on(1);454}455456if (cmd_obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {457struct drvextra_cmd_parm *extra_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf;458459if (extra_parm->pbuf && extra_parm->size > 0)460rtw_mfree(extra_parm->pbuf, extra_parm->size);461}462rtw_free_cmd_obj(cmd_obj);463goto exit;464}465466res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj, 0);467468if (res == _SUCCESS)469_rtw_up_sema(&pcmdpriv->cmd_queue_sema);470471exit:472473474return res;475}476477struct cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv)478{479struct cmd_obj *cmd_obj;480481482cmd_obj = _rtw_dequeue_cmd(&pcmdpriv->cmd_queue);483484return cmd_obj;485}486487void rtw_cmd_clr_isr(struct cmd_priv *pcmdpriv)488{489pcmdpriv->cmd_done_cnt++;490/* _rtw_up_sema(&(pcmdpriv->cmd_done_sema)); */491}492493void rtw_free_cmd_obj(struct cmd_obj *pcmd)494{495if (pcmd->parmbuf != NULL) {496/* free parmbuf in cmd_obj */497rtw_mfree((unsigned char *)pcmd->parmbuf, pcmd->cmdsz);498}499if (pcmd->rsp != NULL) {500if (pcmd->rspsz != 0) {501/* free rsp in cmd_obj */502rtw_mfree((unsigned char *)pcmd->rsp, pcmd->rspsz);503}504}505506/* free cmd_obj */507rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));508}509510511void rtw_stop_cmd_thread(_adapter *adapter)512{513if (adapter->cmdThread) {514_rtw_up_sema(&adapter->cmdpriv.cmd_queue_sema);515rtw_thread_stop(adapter->cmdThread);516adapter->cmdThread = NULL;517}518}519520thread_return rtw_cmd_thread(thread_context context)521{522u8 ret;523struct cmd_obj *pcmd;524u8 *pcmdbuf, *prspbuf;525systime cmd_start_time;526u32 cmd_process_time;527u8(*cmd_hdl)(_adapter *padapter, u8 *pbuf);528void (*pcmd_callback)(_adapter *dev, struct cmd_obj *pcmd);529PADAPTER padapter = (PADAPTER)context;530struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);531struct drvextra_cmd_parm *extra_parm = NULL;532_irqL irqL;533534thread_enter("RTW_CMD_THREAD");535536pcmdbuf = pcmdpriv->cmd_buf;537prspbuf = pcmdpriv->rsp_buf;538ATOMIC_SET(&(pcmdpriv->cmdthd_running), _TRUE);539_rtw_up_sema(&pcmdpriv->start_cmdthread_sema);540541542while (1) {543if (_rtw_down_sema(&pcmdpriv->cmd_queue_sema) == _FAIL) {544RTW_PRINT(FUNC_ADPT_FMT" _rtw_down_sema(&pcmdpriv->cmd_queue_sema) return _FAIL, break\n", FUNC_ADPT_ARG(padapter));545break;546}547548if (RTW_CANNOT_RUN(padapter)) {549RTW_DBG(FUNC_ADPT_FMT "- bDriverStopped(%s) bSurpriseRemoved(%s)\n",550FUNC_ADPT_ARG(padapter),551rtw_is_drv_stopped(padapter) ? "True" : "False",552rtw_is_surprise_removed(padapter) ? "True" : "False");553break;554}555556_enter_critical(&pcmdpriv->cmd_queue.lock, &irqL);557if (rtw_is_list_empty(&(pcmdpriv->cmd_queue.queue))) {558/* RTW_INFO("%s: cmd queue is empty!\n", __func__); */559_exit_critical(&pcmdpriv->cmd_queue.lock, &irqL);560continue;561}562_exit_critical(&pcmdpriv->cmd_queue.lock, &irqL);563564_next:565if (RTW_CANNOT_RUN(padapter)) {566RTW_PRINT("%s: DriverStopped(%s) SurpriseRemoved(%s) break at line %d\n",567__func__568, rtw_is_drv_stopped(padapter) ? "True" : "False"569, rtw_is_surprise_removed(padapter) ? "True" : "False"570, __LINE__);571break;572}573574pcmd = rtw_dequeue_cmd(pcmdpriv);575if (!pcmd) {576#ifdef CONFIG_LPS_LCLK577rtw_unregister_cmd_alive(padapter);578#endif579continue;580}581582cmd_start_time = rtw_get_current_time();583pcmdpriv->cmd_issued_cnt++;584585if (pcmd->cmdsz > MAX_CMDSZ) {586RTW_ERR("%s cmdsz:%d > MAX_CMDSZ:%d\n", __func__, pcmd->cmdsz, MAX_CMDSZ);587pcmd->res = H2C_PARAMETERS_ERROR;588goto post_process;589}590591if (pcmd->cmdcode >= (sizeof(wlancmds) / sizeof(struct cmd_hdl))) {592RTW_ERR("%s undefined cmdcode:%d\n", __func__, pcmd->cmdcode);593pcmd->res = H2C_PARAMETERS_ERROR;594goto post_process;595}596597cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;598if (!cmd_hdl) {599RTW_ERR("%s no cmd_hdl for cmdcode:%d\n", __func__, pcmd->cmdcode);600pcmd->res = H2C_PARAMETERS_ERROR;601goto post_process;602}603604if (_FAIL == rtw_cmd_filter(pcmdpriv, pcmd)) {605pcmd->res = H2C_DROPPED;606if (pcmd->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {607extra_parm = (struct drvextra_cmd_parm *)pcmd->parmbuf;608if (extra_parm && extra_parm->pbuf && extra_parm->size > 0)609rtw_mfree(extra_parm->pbuf, extra_parm->size);610}611#ifdef CONFIG_DFS612else if (pcmd->cmdcode == GEN_CMD_CODE(_SetChannelSwitch))613adapter_to_rfctl(padapter)->csa_ch = 0;614#endif615goto post_process;616}617618#ifdef CONFIG_LPS_LCLK619if (pcmd->no_io)620rtw_unregister_cmd_alive(padapter);621else {622if (rtw_register_cmd_alive(padapter) != _SUCCESS) {623if (DBG_CMD_EXECUTE)624RTW_PRINT("%s: wait to leave LPS_LCLK\n", __func__);625626pcmd->res = H2C_ENQ_HEAD;627ret = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, pcmd, 1);628if (ret == _SUCCESS) {629if (DBG_CMD_EXECUTE)630RTW_INFO(ADPT_FMT" "CMD_FMT" ENQ_HEAD\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd));631continue;632}633634RTW_INFO(ADPT_FMT" "CMD_FMT" ENQ_HEAD_FAIL\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd));635pcmd->res = H2C_ENQ_HEAD_FAIL;636rtw_warn_on(1);637}638}639#endif /* CONFIG_LPS_LCLK */640641if (DBG_CMD_EXECUTE)642RTW_INFO(ADPT_FMT" "CMD_FMT" %sexecute\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd)643, pcmd->res == H2C_ENQ_HEAD ? "ENQ_HEAD " : (pcmd->res == H2C_ENQ_HEAD_FAIL ? "ENQ_HEAD_FAIL " : ""));644645_rtw_memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);646ret = cmd_hdl(pcmd->padapter, pcmdbuf);647pcmd->res = ret;648649pcmdpriv->cmd_seq++;650651post_process:652653_enter_critical_mutex(&(pcmd->padapter->cmdpriv.sctx_mutex), NULL);654if (pcmd->sctx) {655if (0)656RTW_PRINT(FUNC_ADPT_FMT" pcmd->sctx\n", FUNC_ADPT_ARG(pcmd->padapter));657if (pcmd->res == H2C_SUCCESS)658rtw_sctx_done(&pcmd->sctx);659else660rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_ERROR);661}662_exit_critical_mutex(&(pcmd->padapter->cmdpriv.sctx_mutex), NULL);663664cmd_process_time = rtw_get_passing_time_ms(cmd_start_time);665if (cmd_process_time > 1000) {666RTW_INFO(ADPT_FMT" "CMD_FMT" process_time=%d\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd), cmd_process_time);667if (0)668rtw_warn_on(1);669}670671/* call callback function for post-processed */672if (pcmd->cmdcode < (sizeof(rtw_cmd_callback) / sizeof(struct _cmd_callback))) {673pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;674if (pcmd_callback == NULL) {675rtw_free_cmd_obj(pcmd);676} else {677/* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!=NULL) */678pcmd_callback(pcmd->padapter, pcmd);/* need conider that free cmd_obj in rtw_cmd_callback */679}680} else {681rtw_free_cmd_obj(pcmd);682}683684flush_signals_thread();685686goto _next;687688}689690#ifdef CONFIG_LPS_LCLK691rtw_unregister_cmd_alive(padapter);692#endif693694/* to avoid enqueue cmd after free all cmd_obj */695ATOMIC_SET(&(pcmdpriv->cmdthd_running), _FALSE);696697/* free all cmd_obj resources */698do {699pcmd = rtw_dequeue_cmd(pcmdpriv);700if (pcmd == NULL)701break;702703if (0)704RTW_INFO("%s: leaving... drop "CMD_FMT"\n", __func__, CMD_ARG(pcmd));705706if (pcmd->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {707extra_parm = (struct drvextra_cmd_parm *)pcmd->parmbuf;708if (extra_parm->pbuf && extra_parm->size > 0)709rtw_mfree(extra_parm->pbuf, extra_parm->size);710}711#ifdef CONFIG_DFS712else if (pcmd->cmdcode == GEN_CMD_CODE(_SetChannelSwitch))713adapter_to_rfctl(padapter)->csa_ch = 0;714#endif715716_enter_critical_mutex(&(pcmd->padapter->cmdpriv.sctx_mutex), NULL);717if (pcmd->sctx) {718if (0)719RTW_PRINT(FUNC_ADPT_FMT" pcmd->sctx\n", FUNC_ADPT_ARG(pcmd->padapter));720rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_DROP);721}722_exit_critical_mutex(&(pcmd->padapter->cmdpriv.sctx_mutex), NULL);723724rtw_free_cmd_obj(pcmd);725} while (1);726727RTW_INFO(FUNC_ADPT_FMT " Exit\n", FUNC_ADPT_ARG(padapter));728729rtw_thread_wait_stop();730731return 0;732}733734735#ifdef CONFIG_EVENT_THREAD_MODE736u32 rtw_enqueue_evt(struct evt_priv *pevtpriv, struct evt_obj *obj)737{738_irqL irqL;739int res;740_queue *queue = &pevtpriv->evt_queue;741742743res = _SUCCESS;744745if (obj == NULL) {746res = _FAIL;747goto exit;748}749750_enter_critical_bh(&queue->lock, &irqL);751752rtw_list_insert_tail(&obj->list, &queue->queue);753754_exit_critical_bh(&queue->lock, &irqL);755756/* rtw_evt_notify_isr(pevtpriv); */757758exit:759760761return res;762}763764struct evt_obj *rtw_dequeue_evt(_queue *queue)765{766_irqL irqL;767struct evt_obj *pevtobj;768769770_enter_critical_bh(&queue->lock, &irqL);771772if (rtw_is_list_empty(&(queue->queue)))773pevtobj = NULL;774else {775pevtobj = LIST_CONTAINOR(get_next(&(queue->queue)), struct evt_obj, list);776rtw_list_delete(&pevtobj->list);777}778779_exit_critical_bh(&queue->lock, &irqL);780781782return pevtobj;783}784785void rtw_free_evt_obj(struct evt_obj *pevtobj)786{787788if (pevtobj->parmbuf)789rtw_mfree((unsigned char *)pevtobj->parmbuf, pevtobj->evtsz);790791rtw_mfree((unsigned char *)pevtobj, sizeof(struct evt_obj));792793}794795void rtw_evt_notify_isr(struct evt_priv *pevtpriv)796{797pevtpriv->evt_done_cnt++;798_rtw_up_sema(&(pevtpriv->evt_notify));799}800#endif801802803/*804u8 rtw_setstandby_cmd(unsigned char *adapter)805*/806u8 rtw_setstandby_cmd(_adapter *padapter, uint action)807{808struct cmd_obj *ph2c;809struct usb_suspend_parm *psetusbsuspend;810struct cmd_priv *pcmdpriv = &padapter->cmdpriv;811812u8 ret = _SUCCESS;813814815ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));816if (ph2c == NULL) {817ret = _FAIL;818goto exit;819}820821psetusbsuspend = (struct usb_suspend_parm *)rtw_zmalloc(sizeof(struct usb_suspend_parm));822if (psetusbsuspend == NULL) {823rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));824ret = _FAIL;825goto exit;826}827828psetusbsuspend->action = action;829830init_h2fwcmd_w_parm_no_rsp(ph2c, psetusbsuspend, GEN_CMD_CODE(_SetUsbSuspend));831832ret = rtw_enqueue_cmd(pcmdpriv, ph2c);833834exit:835836837return ret;838}839840void rtw_init_sitesurvey_parm(_adapter *padapter, struct sitesurvey_parm *pparm)841{842struct mlme_priv *pmlmepriv = &padapter->mlmepriv;843844845_rtw_memset(pparm, 0, sizeof(struct sitesurvey_parm));846pparm->scan_mode = pmlmepriv->scan_mode;847}848849/*850rtw_sitesurvey_cmd(~)851### NOTE:#### (!!!!)852MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock853*/854u8 rtw_sitesurvey_cmd(_adapter *padapter, struct sitesurvey_parm *pparm)855{856u8 res = _FAIL;857struct cmd_obj *ph2c;858struct sitesurvey_parm *psurveyPara;859struct cmd_priv *pcmdpriv = &padapter->cmdpriv;860struct mlme_priv *pmlmepriv = &padapter->mlmepriv;861862#ifdef CONFIG_LPS863if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)864rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 0);865#endif866867#ifdef CONFIG_P2P_PS868if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)869p2p_ps_wk_cmd(padapter, P2P_PS_SCAN, 1);870#endif /* CONFIG_P2P_PS */871872ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));873if (ph2c == NULL)874return _FAIL;875876psurveyPara = (struct sitesurvey_parm *)rtw_zmalloc(sizeof(struct sitesurvey_parm));877if (psurveyPara == NULL) {878rtw_mfree((unsigned char *) ph2c, sizeof(struct cmd_obj));879return _FAIL;880}881882if (pparm)883_rtw_memcpy(psurveyPara, pparm, sizeof(struct sitesurvey_parm));884else885psurveyPara->scan_mode = pmlmepriv->scan_mode;886887rtw_free_network_queue(padapter, _FALSE);888889init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));890891set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);892893res = rtw_enqueue_cmd(pcmdpriv, ph2c);894895if (res == _SUCCESS) {896u32 scan_timeout_ms;897898pmlmepriv->scan_start_time = rtw_get_current_time();899scan_timeout_ms = rtw_scan_timeout_decision(padapter);900mlme_set_scan_to_timer(pmlmepriv,scan_timeout_ms);901902rtw_led_control(padapter, LED_CTL_SITE_SURVEY);903} else904_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);905906907return res;908}909910u8 rtw_setdatarate_cmd(_adapter *padapter, u8 *rateset)911{912struct cmd_obj *ph2c;913struct setdatarate_parm *pbsetdataratepara;914struct cmd_priv *pcmdpriv = &padapter->cmdpriv;915u8 res = _SUCCESS;916917918ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));919if (ph2c == NULL) {920res = _FAIL;921goto exit;922}923924pbsetdataratepara = (struct setdatarate_parm *)rtw_zmalloc(sizeof(struct setdatarate_parm));925if (pbsetdataratepara == NULL) {926rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));927res = _FAIL;928goto exit;929}930931init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, GEN_CMD_CODE(_SetDataRate));932#ifdef MP_FIRMWARE_OFFLOAD933pbsetdataratepara->curr_rateidx = *(u32 *)rateset;934/* _rtw_memcpy(pbsetdataratepara, rateset, sizeof(u32)); */935#else936pbsetdataratepara->mac_id = 5;937_rtw_memcpy(pbsetdataratepara->datarates, rateset, NumRates);938#endif939res = rtw_enqueue_cmd(pcmdpriv, ph2c);940exit:941942943return res;944}945946u8 rtw_setbasicrate_cmd(_adapter *padapter, u8 *rateset)947{948struct cmd_obj *ph2c;949struct setbasicrate_parm *pssetbasicratepara;950struct cmd_priv *pcmdpriv = &padapter->cmdpriv;951u8 res = _SUCCESS;952953954ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));955if (ph2c == NULL) {956res = _FAIL;957goto exit;958}959pssetbasicratepara = (struct setbasicrate_parm *)rtw_zmalloc(sizeof(struct setbasicrate_parm));960961if (pssetbasicratepara == NULL) {962rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));963res = _FAIL;964goto exit;965}966967init_h2fwcmd_w_parm_no_rsp(ph2c, pssetbasicratepara, _SetBasicRate_CMD_);968969_rtw_memcpy(pssetbasicratepara->basicrates, rateset, NumRates);970971res = rtw_enqueue_cmd(pcmdpriv, ph2c);972exit:973974975return res;976}977978979/*980unsigned char rtw_setphy_cmd(unsigned char *adapter)9819821. be called only after rtw_update_registrypriv_dev_network( ~) or mp testing program9832. for AdHoc/Ap mode or mp mode?984985*/986u8 rtw_setphy_cmd(_adapter *padapter, u8 modem, u8 ch)987{988struct cmd_obj *ph2c;989struct setphy_parm *psetphypara;990struct cmd_priv *pcmdpriv = &padapter->cmdpriv;991/* struct mlme_priv *pmlmepriv = &padapter->mlmepriv;992* struct registry_priv* pregistry_priv = &padapter->registrypriv; */993u8 res = _SUCCESS;994995996ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));997if (ph2c == NULL) {998res = _FAIL;999goto exit;1000}1001psetphypara = (struct setphy_parm *)rtw_zmalloc(sizeof(struct setphy_parm));10021003if (psetphypara == NULL) {1004rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));1005res = _FAIL;1006goto exit;1007}10081009init_h2fwcmd_w_parm_no_rsp(ph2c, psetphypara, _SetPhy_CMD_);101010111012psetphypara->modem = modem;1013psetphypara->rfchannel = ch;10141015res = rtw_enqueue_cmd(pcmdpriv, ph2c);1016exit:1017return res;1018}10191020u8 rtw_getmacreg_cmd(_adapter *padapter, u8 len, u32 addr)1021{1022struct cmd_obj *ph2c;1023struct readMAC_parm *preadmacparm;1024struct cmd_priv *pcmdpriv = &padapter->cmdpriv;1025u8 res = _SUCCESS;10261027ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));1028if (ph2c == NULL) {1029res = _FAIL;1030goto exit;1031}1032preadmacparm = (struct readMAC_parm *)rtw_zmalloc(sizeof(struct readMAC_parm));10331034if (preadmacparm == NULL) {1035rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));1036res = _FAIL;1037goto exit;1038}10391040init_h2fwcmd_w_parm_no_rsp(ph2c, preadmacparm, GEN_CMD_CODE(_GetMACReg));10411042preadmacparm->len = len;1043preadmacparm->addr = addr;10441045res = rtw_enqueue_cmd(pcmdpriv, ph2c);10461047exit:1048return res;1049}10501051void rtw_usb_catc_trigger_cmd(_adapter *padapter, const char *caller)1052{1053RTW_INFO("%s caller:%s\n", __func__, caller);1054rtw_getmacreg_cmd(padapter, 1, 0x1c4);1055}10561057u8 rtw_setbbreg_cmd(_adapter *padapter, u8 offset, u8 val)1058{1059struct cmd_obj *ph2c;1060struct writeBB_parm *pwritebbparm;1061struct cmd_priv *pcmdpriv = &padapter->cmdpriv;1062u8 res = _SUCCESS;1063ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));1064if (ph2c == NULL) {1065res = _FAIL;1066goto exit;1067}1068pwritebbparm = (struct writeBB_parm *)rtw_zmalloc(sizeof(struct writeBB_parm));10691070if (pwritebbparm == NULL) {1071rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));1072res = _FAIL;1073goto exit;1074}10751076init_h2fwcmd_w_parm_no_rsp(ph2c, pwritebbparm, GEN_CMD_CODE(_SetBBReg));10771078pwritebbparm->offset = offset;1079pwritebbparm->value = val;10801081res = rtw_enqueue_cmd(pcmdpriv, ph2c);1082exit:1083return res;1084}10851086u8 rtw_getbbreg_cmd(_adapter *padapter, u8 offset, u8 *pval)1087{1088struct cmd_obj *ph2c;1089struct readBB_parm *prdbbparm;1090struct cmd_priv *pcmdpriv = &padapter->cmdpriv;1091u8 res = _SUCCESS;10921093ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));1094if (ph2c == NULL) {1095res = _FAIL;1096goto exit;1097}1098prdbbparm = (struct readBB_parm *)rtw_zmalloc(sizeof(struct readBB_parm));10991100if (prdbbparm == NULL) {1101rtw_mfree((unsigned char *) ph2c, sizeof(struct cmd_obj));1102return _FAIL;1103}11041105_rtw_init_listhead(&ph2c->list);1106ph2c->cmdcode = GEN_CMD_CODE(_GetBBReg);1107ph2c->parmbuf = (unsigned char *)prdbbparm;1108ph2c->cmdsz = sizeof(struct readBB_parm);1109ph2c->rsp = pval;1110ph2c->rspsz = sizeof(struct readBB_rsp);11111112prdbbparm->offset = offset;11131114res = rtw_enqueue_cmd(pcmdpriv, ph2c);1115exit:1116return res;1117}11181119u8 rtw_setrfreg_cmd(_adapter *padapter, u8 offset, u32 val)1120{1121struct cmd_obj *ph2c;1122struct writeRF_parm *pwriterfparm;1123struct cmd_priv *pcmdpriv = &padapter->cmdpriv;1124u8 res = _SUCCESS;1125ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));1126if (ph2c == NULL) {1127res = _FAIL;1128goto exit;1129}1130pwriterfparm = (struct writeRF_parm *)rtw_zmalloc(sizeof(struct writeRF_parm));11311132if (pwriterfparm == NULL) {1133rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));1134res = _FAIL;1135goto exit;1136}11371138init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg));11391140pwriterfparm->offset = offset;1141pwriterfparm->value = val;11421143res = rtw_enqueue_cmd(pcmdpriv, ph2c);1144exit:1145return res;1146}11471148u8 rtw_getrfreg_cmd(_adapter *padapter, u8 offset, u8 *pval)1149{1150struct cmd_obj *ph2c;1151struct readRF_parm *prdrfparm;1152struct cmd_priv *pcmdpriv = &padapter->cmdpriv;1153u8 res = _SUCCESS;115411551156ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));1157if (ph2c == NULL) {1158res = _FAIL;1159goto exit;1160}11611162prdrfparm = (struct readRF_parm *)rtw_zmalloc(sizeof(struct readRF_parm));1163if (prdrfparm == NULL) {1164rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));1165res = _FAIL;1166goto exit;1167}11681169_rtw_init_listhead(&ph2c->list);1170ph2c->cmdcode = GEN_CMD_CODE(_GetRFReg);1171ph2c->parmbuf = (unsigned char *)prdrfparm;1172ph2c->cmdsz = sizeof(struct readRF_parm);1173ph2c->rsp = pval;1174ph2c->rspsz = sizeof(struct readRF_rsp);11751176prdrfparm->offset = offset;11771178res = rtw_enqueue_cmd(pcmdpriv, ph2c);11791180exit:118111821183return res;1184}11851186void rtw_getbbrfreg_cmdrsp_callback(_adapter *padapter, struct cmd_obj *pcmd)1187{11881189/* rtw_free_cmd_obj(pcmd); */1190rtw_mfree((unsigned char *) pcmd->parmbuf, pcmd->cmdsz);1191rtw_mfree((unsigned char *) pcmd, sizeof(struct cmd_obj));11921193#ifdef CONFIG_MP_INCLUDED1194if (padapter->registrypriv.mp_mode == 1)1195padapter->mppriv.workparam.bcompleted = _TRUE;1196#endif1197}11981199void rtw_readtssi_cmdrsp_callback(_adapter *padapter, struct cmd_obj *pcmd)1200{12011202rtw_mfree((unsigned char *) pcmd->parmbuf, pcmd->cmdsz);1203rtw_mfree((unsigned char *) pcmd, sizeof(struct cmd_obj));12041205#ifdef CONFIG_MP_INCLUDED1206if (padapter->registrypriv.mp_mode == 1)1207padapter->mppriv.workparam.bcompleted = _TRUE;1208#endif12091210}12111212static u8 rtw_createbss_cmd(_adapter *adapter, int flags, bool adhoc1213, u8 ifbmp, u8 excl_ifbmp, s16 req_ch, s8 req_bw, s8 req_offset)1214{1215struct cmd_obj *cmdobj;1216struct createbss_parm *parm;1217struct cmd_priv *pcmdpriv = &adapter->cmdpriv;1218struct submit_ctx sctx;1219u8 res = _SUCCESS;12201221if (req_ch > 0 && req_bw >= 0 && req_offset >= 0) {1222if (!rtw_chset_is_chbw_valid(adapter_to_chset(adapter), req_ch, req_bw, req_offset)) {1223res = _FAIL;1224goto exit;1225}1226}12271228/* prepare cmd parameter */1229parm = (struct createbss_parm *)rtw_zmalloc(sizeof(*parm));1230if (parm == NULL) {1231res = _FAIL;1232goto exit;1233}12341235if (adhoc) {1236/* for now, adhoc doesn't support ch,bw,offset request */1237parm->adhoc = 1;1238} else {1239parm->adhoc = 0;1240parm->ifbmp = ifbmp;1241parm->excl_ifbmp = excl_ifbmp;1242parm->req_ch = req_ch;1243parm->req_bw = req_bw;1244parm->req_offset = req_offset;1245}12461247if (flags & RTW_CMDF_DIRECTLY) {1248/* no need to enqueue, do the cmd hdl directly and free cmd parameter */1249if (H2C_SUCCESS != createbss_hdl(adapter, (u8 *)parm))1250res = _FAIL;1251rtw_mfree((u8 *)parm, sizeof(*parm));1252} else {1253/* need enqueue, prepare cmd_obj and enqueue */1254cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));1255if (cmdobj == NULL) {1256res = _FAIL;1257rtw_mfree((u8 *)parm, sizeof(*parm));1258goto exit;1259}12601261init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_CreateBss));12621263if (flags & RTW_CMDF_WAIT_ACK) {1264cmdobj->sctx = &sctx;1265rtw_sctx_init(&sctx, 2000);1266}12671268res = rtw_enqueue_cmd(pcmdpriv, cmdobj);12691270if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {1271rtw_sctx_wait(&sctx, __func__);1272_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);1273if (sctx.status == RTW_SCTX_SUBMITTED)1274cmdobj->sctx = NULL;1275_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);1276}1277}12781279exit:1280return res;1281}12821283inline u8 rtw_create_ibss_cmd(_adapter *adapter, int flags)1284{1285return rtw_createbss_cmd(adapter, flags1286, 11287, 0, 01288, 0, REQ_BW_NONE, REQ_OFFSET_NONE /* for now, adhoc doesn't support ch,bw,offset request */1289);1290}12911292inline u8 rtw_startbss_cmd(_adapter *adapter, int flags)1293{1294return rtw_createbss_cmd(adapter, flags1295, 01296, BIT(adapter->iface_id), 01297, 0, REQ_BW_NONE, REQ_OFFSET_NONE /* excute entire AP setup cmd */1298);1299}13001301inline u8 rtw_change_bss_chbw_cmd(_adapter *adapter, int flags1302, u8 ifbmp, u8 excl_ifbmp, s16 req_ch, s8 req_bw, s8 req_offset)1303{1304return rtw_createbss_cmd(adapter, flags1305, 01306, ifbmp, excl_ifbmp1307, req_ch, req_bw, req_offset1308);1309}13101311#ifdef CONFIG_RTW_80211R1312static void rtw_ft_validate_akm_type(_adapter *padapter,1313struct wlan_network *pnetwork)1314{1315struct security_priv *psecuritypriv = &(padapter->securitypriv);1316struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);1317u32 tmp_len;1318u8 *ptmp;13191320/*IEEE802.11-2012 Std. Table 8-101-AKM suite selectors*/1321if (rtw_ft_valid_akm(padapter, psecuritypriv->rsn_akm_suite_type)) {1322ptmp = rtw_get_ie(&pnetwork->network.IEs[12],1323_MDIE_, &tmp_len, (pnetwork->network.IELength-12));1324if (ptmp) {1325pft_roam->mdid = *(u16 *)(ptmp+2);1326pft_roam->ft_cap = *(ptmp+4);13271328RTW_INFO("FT: target " MAC_FMT " mdid=(0x%2x), capacity=(0x%2x)\n",1329MAC_ARG(pnetwork->network.MacAddress), pft_roam->mdid, pft_roam->ft_cap);1330rtw_ft_set_flags(padapter, RTW_FT_PEER_EN);13311332if (rtw_ft_otd_roam_en(padapter))1333rtw_ft_set_flags(padapter, RTW_FT_PEER_OTD_EN);1334} else {1335/* Don't use FT roaming if target AP cannot support FT */1336rtw_ft_clr_flags(padapter, (RTW_FT_PEER_EN|RTW_FT_PEER_OTD_EN));1337rtw_ft_reset_status(padapter);1338}1339} else {1340/* It could be a non-FT connection */1341rtw_ft_clr_flags(padapter, (RTW_FT_PEER_EN|RTW_FT_PEER_OTD_EN));1342rtw_ft_reset_status(padapter);1343}1344}1345#endif13461347u8 rtw_joinbss_cmd(_adapter *padapter, struct wlan_network *pnetwork)1348{1349u8 *auth, res = _SUCCESS;1350uint t_len = 0;1351WLAN_BSSID_EX *psecnetwork;1352struct cmd_obj *pcmd;1353struct cmd_priv *pcmdpriv = &padapter->cmdpriv;1354struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1355struct qos_priv *pqospriv = &pmlmepriv->qospriv;1356struct security_priv *psecuritypriv = &padapter->securitypriv;1357struct registry_priv *pregistrypriv = &padapter->registrypriv;1358#ifdef CONFIG_80211N_HT1359struct ht_priv *phtpriv = &pmlmepriv->htpriv;1360#endif /* CONFIG_80211N_HT */1361#ifdef CONFIG_80211AC_VHT1362struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;1363#endif /* CONFIG_80211AC_VHT */1364NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = pnetwork->network.InfrastructureMode;1365struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;1366struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);1367struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);1368u32 tmp_len;1369u8 *ptmp = NULL;13701371rtw_led_control(padapter, LED_CTL_START_TO_LINK);13721373pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));1374if (pcmd == NULL) {1375res = _FAIL;1376goto exit;1377}1378#if 01379/* for IEs is pointer */1380t_len = sizeof(u32) + sizeof(NDIS_802_11_MAC_ADDRESS) + 2 +1381sizeof(NDIS_802_11_SSID) + sizeof(u32) +1382sizeof(NDIS_802_11_RSSI) + sizeof(NDIS_802_11_NETWORK_TYPE) +1383sizeof(NDIS_802_11_CONFIGURATION) +1384sizeof(NDIS_802_11_NETWORK_INFRASTRUCTURE) +1385sizeof(NDIS_802_11_RATES_EX) + sizeof(WLAN_PHY_INFO) + sizeof(u32) + MAX_IE_SZ;1386#endif1387/* for IEs is fix buf size */1388t_len = sizeof(WLAN_BSSID_EX);138913901391/* for hidden ap to set fw_state here */1392if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) != _TRUE) {1393switch (ndis_network_mode) {1394case Ndis802_11IBSS:1395set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);1396break;13971398case Ndis802_11Infrastructure:1399set_fwstate(pmlmepriv, WIFI_STATION_STATE);1400break;14011402default:1403rtw_warn_on(1);1404break;1405}1406}14071408pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength);14091410#ifdef CONFIG_80211AC_VHT1411/* save AP beamform_cap info for BCM IOT issue */1412if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_BROADCOM)1413pvhtpriv->ap_is_mu_bfer =1414get_vht_mu_bfer_cap(pnetwork->network.IEs,1415pnetwork->network.IELength);1416#endif1417/*1418Modified by Arvin 2015/05/131419Solution for allocating a new WLAN_BSSID_EX to avoid race condition issue between disconnect and joinbss1420*/1421psecnetwork = (WLAN_BSSID_EX *)rtw_zmalloc(sizeof(WLAN_BSSID_EX));1422if (psecnetwork == NULL) {1423if (pcmd != NULL)1424rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));14251426res = _FAIL;142714281429goto exit;1430}14311432_rtw_memset(psecnetwork, 0, t_len);14331434_rtw_memcpy(psecnetwork, &pnetwork->network, get_WLAN_BSSID_EX_sz(&pnetwork->network));14351436auth = &psecuritypriv->authenticator_ie[0];1437psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength;14381439if ((psecnetwork->IELength - 12) < (256 - 1))1440_rtw_memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength - 12);1441else1442_rtw_memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256 - 1));14431444psecnetwork->IELength = 0;1445/* Added by Albert 2009/02/18 */1446/* If the the driver wants to use the bssid to create the connection. */1447/* If not, we have to copy the connecting AP's MAC address to it so that */1448/* the driver just has the bssid information for PMKIDList searching. */14491450if (pmlmepriv->assoc_by_bssid == _FALSE)1451_rtw_memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);14521453/* copy fixed ie */1454_rtw_memcpy(psecnetwork->IEs, pnetwork->network.IEs, 12);1455psecnetwork->IELength = 12;14561457psecnetwork->IELength += rtw_restruct_sec_ie(padapter, psecnetwork->IEs + psecnetwork->IELength);145814591460pqospriv->qos_option = 0;14611462if (pregistrypriv->wmm_enable) {1463#ifdef CONFIG_WMMPS_STA1464rtw_uapsd_use_default_setting(padapter);1465#endif /* CONFIG_WMMPS_STA */1466tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength);14671468if (psecnetwork->IELength != tmp_len) {1469psecnetwork->IELength = tmp_len;1470pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */1471} else {1472pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */1473}1474}14751476#ifdef CONFIG_80211N_HT1477phtpriv->ht_option = _FALSE;1478if (pregistrypriv->ht_enable && is_supported_ht(pregistrypriv->wireless_mode)) {1479ptmp = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &tmp_len, pnetwork->network.IELength - 12);1480if (ptmp && tmp_len > 0) {1481/* Added by Albert 2010/06/23 */1482/* For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */1483/* Especially for Realtek 8192u SoftAP. */1484if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&1485(padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&1486(padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {1487rtw_ht_use_default_setting(padapter);14881489/* rtw_restructure_ht_ie */1490rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[12], &psecnetwork->IEs[0],1491pnetwork->network.IELength - 12, &psecnetwork->IELength,1492pnetwork->network.Configuration.DSConfig);1493}1494}1495}14961497#ifdef CONFIG_80211AC_VHT1498pvhtpriv->vht_option = _FALSE;1499if (phtpriv->ht_option1500&& REGSTY_IS_11AC_ENABLE(pregistrypriv)1501&& is_supported_vht(pregistrypriv->wireless_mode)1502&& (!rfctl->country_ent || COUNTRY_CHPLAN_EN_11AC(rfctl->country_ent))1503) {1504rtw_restructure_vht_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0],1505pnetwork->network.IELength, &psecnetwork->IELength);1506}1507#endif1508#endif /* CONFIG_80211N_HT */15091510rtw_append_exented_cap(padapter, &psecnetwork->IEs[0], &psecnetwork->IELength);15111512#ifdef CONFIG_RTW_80211R1513rtw_ft_validate_akm_type(padapter, pnetwork);1514#endif15151516#if 01517psecuritypriv->supplicant_ie[0] = (u8)psecnetwork->IELength;15181519if (psecnetwork->IELength < (256 - 1))1520_rtw_memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], psecnetwork->IELength);1521else1522_rtw_memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], (256 - 1));1523#endif15241525pcmd->cmdsz = sizeof(WLAN_BSSID_EX);15261527_rtw_init_listhead(&pcmd->list);1528pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */1529pcmd->parmbuf = (unsigned char *)psecnetwork;1530pcmd->rsp = NULL;1531pcmd->rspsz = 0;15321533res = rtw_enqueue_cmd(pcmdpriv, pcmd);15341535exit:153615371538return res;1539}15401541u8 rtw_disassoc_cmd(_adapter *padapter, u32 deauth_timeout_ms, int flags) /* for sta_mode */1542{1543struct cmd_obj *cmdobj = NULL;1544struct disconnect_parm *param = NULL;1545struct cmd_priv *cmdpriv = &padapter->cmdpriv;1546struct cmd_priv *pcmdpriv = &padapter->cmdpriv;1547struct submit_ctx sctx;1548u8 res = _SUCCESS;15491550/* prepare cmd parameter */1551param = (struct disconnect_parm *)rtw_zmalloc(sizeof(*param));1552if (param == NULL) {1553res = _FAIL;1554goto exit;1555}1556param->deauth_timeout_ms = deauth_timeout_ms;15571558if (flags & RTW_CMDF_DIRECTLY) {1559/* no need to enqueue, do the cmd hdl directly and free cmd parameter */1560if (disconnect_hdl(padapter, (u8 *)param) != H2C_SUCCESS)1561res = _FAIL;1562rtw_mfree((u8 *)param, sizeof(*param));15631564} else {1565cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));1566if (cmdobj == NULL) {1567res = _FAIL;1568rtw_mfree((u8 *)param, sizeof(*param));1569goto exit;1570}1571init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);1572if (flags & RTW_CMDF_WAIT_ACK) {1573cmdobj->sctx = &sctx;1574rtw_sctx_init(&sctx, 2000);1575}1576res = rtw_enqueue_cmd(cmdpriv, cmdobj);1577if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {1578rtw_sctx_wait(&sctx, __func__);1579_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);1580if (sctx.status == RTW_SCTX_SUBMITTED)1581cmdobj->sctx = NULL;1582_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);1583}1584}15851586exit:158715881589return res;1590}159115921593u8 rtw_stop_ap_cmd(_adapter *adapter, u8 flags)1594{1595#ifdef CONFIG_AP_MODE1596struct cmd_obj *cmdobj;1597struct drvextra_cmd_parm *parm;1598struct cmd_priv *pcmdpriv = &adapter->cmdpriv;1599struct submit_ctx sctx;1600u8 res = _SUCCESS;16011602if (flags & RTW_CMDF_DIRECTLY) {1603/* no need to enqueue, do the cmd hdl directly and free cmd parameter */1604if (H2C_SUCCESS != stop_ap_hdl(adapter))1605res = _FAIL;1606} else {1607parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));1608if (parm == NULL) {1609res = _FAIL;1610goto exit;1611}16121613parm->ec_id = STOP_AP_WK_CID;1614parm->type = 0;1615parm->size = 0;1616parm->pbuf = NULL;16171618/* need enqueue, prepare cmd_obj and enqueue */1619cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));1620if (cmdobj == NULL) {1621res = _FAIL;1622goto exit;1623}16241625init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_Set_Drv_Extra));16261627if (flags & RTW_CMDF_WAIT_ACK) {1628cmdobj->sctx = &sctx;1629rtw_sctx_init(&sctx, 2000);1630}16311632res = rtw_enqueue_cmd(pcmdpriv, cmdobj);16331634if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {1635rtw_sctx_wait(&sctx, __func__);1636_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);1637if (sctx.status == RTW_SCTX_SUBMITTED)1638cmdobj->sctx = NULL;1639_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);1640}1641}16421643exit:1644return res;1645#endif1646}16471648u8 rtw_setopmode_cmd(_adapter *adapter, NDIS_802_11_NETWORK_INFRASTRUCTURE networktype, u8 flags)1649{1650struct cmd_obj *cmdobj;1651struct setopmode_parm *parm;1652struct cmd_priv *pcmdpriv = &adapter->cmdpriv;1653struct submit_ctx sctx;1654u8 res = _SUCCESS;16551656/* prepare cmd parameter */1657parm = (struct setopmode_parm *)rtw_zmalloc(sizeof(*parm));1658if (parm == NULL) {1659res = _FAIL;1660goto exit;1661}1662parm->mode = (u8)networktype;16631664if (flags & RTW_CMDF_DIRECTLY) {1665/* no need to enqueue, do the cmd hdl directly and free cmd parameter */1666if (H2C_SUCCESS != setopmode_hdl(adapter, (u8 *)parm))1667res = _FAIL;1668rtw_mfree((u8 *)parm, sizeof(*parm));1669} else {1670/* need enqueue, prepare cmd_obj and enqueue */1671cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));1672if (cmdobj == NULL) {1673res = _FAIL;1674rtw_mfree((u8 *)parm, sizeof(*parm));1675goto exit;1676}16771678init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, _SetOpMode_CMD_);16791680if (flags & RTW_CMDF_WAIT_ACK) {1681cmdobj->sctx = &sctx;1682rtw_sctx_init(&sctx, 2000);1683}16841685res = rtw_enqueue_cmd(pcmdpriv, cmdobj);16861687if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {1688rtw_sctx_wait(&sctx, __func__);1689_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);1690if (sctx.status == RTW_SCTX_SUBMITTED)1691cmdobj->sctx = NULL;1692_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);1693}1694}16951696exit:1697return res;1698}16991700u8 rtw_setstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 key_type, bool enqueue)1701{1702struct cmd_obj *ph2c;1703struct set_stakey_parm *psetstakey_para;1704struct cmd_priv *pcmdpriv = &padapter->cmdpriv;1705struct set_stakey_rsp *psetstakey_rsp = NULL;17061707struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1708struct security_priv *psecuritypriv = &padapter->securitypriv;1709u8 res = _SUCCESS;171017111712psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));1713if (psetstakey_para == NULL) {1714res = _FAIL;1715goto exit;1716}17171718_rtw_memcpy(psetstakey_para->addr, sta->cmn.mac_addr, ETH_ALEN);17191720if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))1721psetstakey_para->algorithm = (unsigned char) psecuritypriv->dot11PrivacyAlgrthm;1722else1723GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, _FALSE);17241725if (key_type == GROUP_KEY) {1726_rtw_memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16);1727psetstakey_para->gk = 1;1728} else if (key_type == UNICAST_KEY)1729_rtw_memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);1730#ifdef CONFIG_TDLS1731else if (key_type == TDLS_KEY) {1732_rtw_memcpy(&psetstakey_para->key, sta->tpk.tk, 16);1733psetstakey_para->algorithm = (u8)sta->dot118021XPrivacy;1734}1735#endif /* CONFIG_TDLS */17361737/* jeff: set this becasue at least sw key is ready */1738padapter->securitypriv.busetkipkey = _TRUE;17391740if (enqueue) {1741ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));1742if (ph2c == NULL) {1743rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));1744res = _FAIL;1745goto exit;1746}17471748psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp));1749if (psetstakey_rsp == NULL) {1750rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));1751rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));1752res = _FAIL;1753goto exit;1754}17551756init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);1757ph2c->rsp = (u8 *) psetstakey_rsp;1758ph2c->rspsz = sizeof(struct set_stakey_rsp);1759res = rtw_enqueue_cmd(pcmdpriv, ph2c);1760} else {1761set_stakey_hdl(padapter, (u8 *)psetstakey_para);1762rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));1763}1764exit:176517661767return res;1768}17691770u8 rtw_clearstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 enqueue)1771{1772struct cmd_obj *ph2c;1773struct set_stakey_parm *psetstakey_para;1774struct cmd_priv *pcmdpriv = &padapter->cmdpriv;1775struct set_stakey_rsp *psetstakey_rsp = NULL;1776s16 cam_id = 0;1777u8 res = _SUCCESS;17781779if (!sta) {1780RTW_ERR("%s sta == NULL\n", __func__);1781goto exit;1782}17831784if (!enqueue) {1785while ((cam_id = rtw_camid_search(padapter, sta->cmn.mac_addr, -1, -1)) >= 0) {1786RTW_PRINT("clear key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(sta->cmn.mac_addr), cam_id);1787clear_cam_entry(padapter, cam_id);1788rtw_camid_free(padapter, cam_id);1789}1790} else {1791ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));1792if (ph2c == NULL) {1793res = _FAIL;1794goto exit;1795}17961797psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));1798if (psetstakey_para == NULL) {1799rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));1800res = _FAIL;1801goto exit;1802}18031804psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp));1805if (psetstakey_rsp == NULL) {1806rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));1807rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));1808res = _FAIL;1809goto exit;1810}18111812init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);1813ph2c->rsp = (u8 *) psetstakey_rsp;1814ph2c->rspsz = sizeof(struct set_stakey_rsp);18151816_rtw_memcpy(psetstakey_para->addr, sta->cmn.mac_addr, ETH_ALEN);18171818psetstakey_para->algorithm = _NO_PRIVACY_;18191820res = rtw_enqueue_cmd(pcmdpriv, ph2c);18211822}18231824exit:182518261827return res;1828}18291830u8 rtw_setrttbl_cmd(_adapter *padapter, struct setratable_parm *prate_table)1831{1832struct cmd_obj *ph2c;1833struct setratable_parm *psetrttblparm;1834struct cmd_priv *pcmdpriv = &padapter->cmdpriv;1835u8 res = _SUCCESS;18361837ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));1838if (ph2c == NULL) {1839res = _FAIL;1840goto exit;1841}1842psetrttblparm = (struct setratable_parm *)rtw_zmalloc(sizeof(struct setratable_parm));18431844if (psetrttblparm == NULL) {1845rtw_mfree((unsigned char *) ph2c, sizeof(struct cmd_obj));1846res = _FAIL;1847goto exit;1848}18491850init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, GEN_CMD_CODE(_SetRaTable));18511852_rtw_memcpy(psetrttblparm, prate_table, sizeof(struct setratable_parm));18531854res = rtw_enqueue_cmd(pcmdpriv, ph2c);1855exit:1856return res;18571858}18591860u8 rtw_getrttbl_cmd(_adapter *padapter, struct getratable_rsp *pval)1861{1862struct cmd_obj *ph2c;1863struct getratable_parm *pgetrttblparm;1864struct cmd_priv *pcmdpriv = &padapter->cmdpriv;1865u8 res = _SUCCESS;18661867ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));1868if (ph2c == NULL) {1869res = _FAIL;1870goto exit;1871}1872pgetrttblparm = (struct getratable_parm *)rtw_zmalloc(sizeof(struct getratable_parm));18731874if (pgetrttblparm == NULL) {1875rtw_mfree((unsigned char *) ph2c, sizeof(struct cmd_obj));1876res = _FAIL;1877goto exit;1878}18791880/* init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, GEN_CMD_CODE(_SetRaTable)); */18811882_rtw_init_listhead(&ph2c->list);1883ph2c->cmdcode = GEN_CMD_CODE(_GetRaTable);1884ph2c->parmbuf = (unsigned char *)pgetrttblparm;1885ph2c->cmdsz = sizeof(struct getratable_parm);1886ph2c->rsp = (u8 *)pval;1887ph2c->rspsz = sizeof(struct getratable_rsp);18881889pgetrttblparm->rsvd = 0x0;18901891res = rtw_enqueue_cmd(pcmdpriv, ph2c);1892exit:1893return res;18941895}18961897u8 rtw_setassocsta_cmd(_adapter *padapter, u8 *mac_addr)1898{1899struct cmd_priv *pcmdpriv = &padapter->cmdpriv;1900struct cmd_obj *ph2c;1901struct set_assocsta_parm *psetassocsta_para;1902struct set_stakey_rsp *psetassocsta_rsp = NULL;19031904u8 res = _SUCCESS;190519061907ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));1908if (ph2c == NULL) {1909res = _FAIL;1910goto exit;1911}19121913psetassocsta_para = (struct set_assocsta_parm *)rtw_zmalloc(sizeof(struct set_assocsta_parm));1914if (psetassocsta_para == NULL) {1915rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));1916res = _FAIL;1917goto exit;1918}19191920psetassocsta_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_assocsta_rsp));1921if (psetassocsta_rsp == NULL) {1922rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));1923rtw_mfree((u8 *) psetassocsta_para, sizeof(struct set_assocsta_parm));1924return _FAIL;1925}19261927init_h2fwcmd_w_parm_no_rsp(ph2c, psetassocsta_para, _SetAssocSta_CMD_);1928ph2c->rsp = (u8 *) psetassocsta_rsp;1929ph2c->rspsz = sizeof(struct set_assocsta_rsp);19301931_rtw_memcpy(psetassocsta_para->addr, mac_addr, ETH_ALEN);19321933res = rtw_enqueue_cmd(pcmdpriv, ph2c);19341935exit:193619371938return res;1939}19401941u8 rtw_addbareq_cmd(_adapter *padapter, u8 tid, u8 *addr)1942{1943struct cmd_priv *pcmdpriv = &padapter->cmdpriv;1944struct cmd_obj *ph2c;1945struct addBaReq_parm *paddbareq_parm;19461947u8 res = _SUCCESS;194819491950ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));1951if (ph2c == NULL) {1952res = _FAIL;1953goto exit;1954}19551956paddbareq_parm = (struct addBaReq_parm *)rtw_zmalloc(sizeof(struct addBaReq_parm));1957if (paddbareq_parm == NULL) {1958rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));1959res = _FAIL;1960goto exit;1961}19621963paddbareq_parm->tid = tid;1964_rtw_memcpy(paddbareq_parm->addr, addr, ETH_ALEN);19651966init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq));19671968/* RTW_INFO("rtw_addbareq_cmd, tid=%d\n", tid); */19691970/* rtw_enqueue_cmd(pcmdpriv, ph2c); */1971res = rtw_enqueue_cmd(pcmdpriv, ph2c);19721973exit:197419751976return res;1977}19781979u8 rtw_addbarsp_cmd(_adapter *padapter, u8 *addr, u16 tid, u8 status, u8 size, u16 start_seq)1980{1981struct cmd_priv *pcmdpriv = &padapter->cmdpriv;1982struct cmd_obj *ph2c;1983struct addBaRsp_parm *paddBaRsp_parm;1984u8 res = _SUCCESS;198519861987ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));1988if (ph2c == NULL) {1989res = _FAIL;1990goto exit;1991}19921993paddBaRsp_parm = (struct addBaRsp_parm *)rtw_zmalloc(sizeof(struct addBaRsp_parm));19941995if (paddBaRsp_parm == NULL) {1996rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));1997res = _FAIL;1998goto exit;1999}20002001_rtw_memcpy(paddBaRsp_parm->addr, addr, ETH_ALEN);2002paddBaRsp_parm->tid = tid;2003paddBaRsp_parm->status = status;2004paddBaRsp_parm->size = size;2005paddBaRsp_parm->start_seq = start_seq;20062007init_h2fwcmd_w_parm_no_rsp(ph2c, paddBaRsp_parm, GEN_CMD_CODE(_AddBARsp));20082009res = rtw_enqueue_cmd(pcmdpriv, ph2c);20102011exit:201220132014return res;2015}2016/* add for CONFIG_IEEE80211W, none 11w can use it */2017u8 rtw_reset_securitypriv_cmd(_adapter *padapter)2018{2019struct cmd_obj *ph2c;2020struct drvextra_cmd_parm *pdrvextra_cmd_parm;2021struct cmd_priv *pcmdpriv = &padapter->cmdpriv;2022u8 res = _SUCCESS;202320242025ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));2026if (ph2c == NULL) {2027res = _FAIL;2028goto exit;2029}20302031pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));2032if (pdrvextra_cmd_parm == NULL) {2033rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));2034res = _FAIL;2035goto exit;2036}20372038pdrvextra_cmd_parm->ec_id = RESET_SECURITYPRIV;2039pdrvextra_cmd_parm->type = 0;2040pdrvextra_cmd_parm->size = 0;2041pdrvextra_cmd_parm->pbuf = NULL;20422043init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));204420452046/* rtw_enqueue_cmd(pcmdpriv, ph2c); */2047res = rtw_enqueue_cmd(pcmdpriv, ph2c);20482049exit:205020512052return res;20532054}20552056void free_assoc_resources_hdl(_adapter *padapter, u8 lock_scanned_queue)2057{2058rtw_free_assoc_resources(padapter, lock_scanned_queue);2059}20602061u8 rtw_free_assoc_resources_cmd(_adapter *padapter, u8 lock_scanned_queue, int flags)2062{2063struct cmd_obj *cmd;2064struct drvextra_cmd_parm *pdrvextra_cmd_parm;2065struct cmd_priv *pcmdpriv = &padapter->cmdpriv;2066struct submit_ctx sctx;2067u8 res = _SUCCESS;20682069if (flags & RTW_CMDF_DIRECTLY) {2070free_assoc_resources_hdl(padapter, lock_scanned_queue);2071}2072else {2073cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));2074if (cmd == NULL) {2075res = _FAIL;2076goto exit;2077}20782079pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));2080if (pdrvextra_cmd_parm == NULL) {2081rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj));2082res = _FAIL;2083goto exit;2084}20852086pdrvextra_cmd_parm->ec_id = FREE_ASSOC_RESOURCES;2087pdrvextra_cmd_parm->type = lock_scanned_queue;2088pdrvextra_cmd_parm->size = 0;2089pdrvextra_cmd_parm->pbuf = NULL;20902091init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));2092if (flags & RTW_CMDF_WAIT_ACK) {2093cmd->sctx = &sctx;2094rtw_sctx_init(&sctx, 2000);2095}20962097res = rtw_enqueue_cmd(pcmdpriv, cmd);20982099if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {2100rtw_sctx_wait(&sctx, __func__);2101_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);2102if (sctx.status == RTW_SCTX_SUBMITTED)2103cmd->sctx = NULL;2104_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);2105}2106}2107exit:2108return res;21092110}21112112u8 rtw_dynamic_chk_wk_cmd(_adapter *padapter)2113{2114struct cmd_obj *ph2c;2115struct drvextra_cmd_parm *pdrvextra_cmd_parm;2116struct cmd_priv *pcmdpriv = &padapter->cmdpriv;2117u8 res = _SUCCESS;211821192120/* only primary padapter does this cmd */21212122ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));2123if (ph2c == NULL) {2124res = _FAIL;2125goto exit;2126}21272128pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));2129if (pdrvextra_cmd_parm == NULL) {2130rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));2131res = _FAIL;2132goto exit;2133}21342135pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;2136pdrvextra_cmd_parm->type = 0;2137pdrvextra_cmd_parm->size = 0;2138pdrvextra_cmd_parm->pbuf = NULL;2139init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));214021412142/* rtw_enqueue_cmd(pcmdpriv, ph2c); */2143res = rtw_enqueue_cmd(pcmdpriv, ph2c);21442145exit:214621472148return res;21492150}21512152u8 rtw_set_chbw_cmd(_adapter *padapter, u8 ch, u8 bw, u8 ch_offset, u8 flags)2153{2154struct cmd_obj *pcmdobj;2155struct set_ch_parm *set_ch_parm;2156struct cmd_priv *pcmdpriv = &padapter->cmdpriv;2157struct submit_ctx sctx;2158u8 res = _SUCCESS;215921602161RTW_INFO(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",2162FUNC_NDEV_ARG(padapter->pnetdev), ch, bw, ch_offset);21632164/* check input parameter */21652166/* prepare cmd parameter */2167set_ch_parm = (struct set_ch_parm *)rtw_zmalloc(sizeof(*set_ch_parm));2168if (set_ch_parm == NULL) {2169res = _FAIL;2170goto exit;2171}2172set_ch_parm->ch = ch;2173set_ch_parm->bw = bw;2174set_ch_parm->ch_offset = ch_offset;21752176if (flags & RTW_CMDF_DIRECTLY) {2177/* no need to enqueue, do the cmd hdl directly and free cmd parameter */2178if (H2C_SUCCESS != rtw_set_chbw_hdl(padapter, (u8 *)set_ch_parm))2179res = _FAIL;21802181rtw_mfree((u8 *)set_ch_parm, sizeof(*set_ch_parm));2182} else {2183/* need enqueue, prepare cmd_obj and enqueue */2184pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));2185if (pcmdobj == NULL) {2186rtw_mfree((u8 *)set_ch_parm, sizeof(*set_ch_parm));2187res = _FAIL;2188goto exit;2189}21902191init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm, GEN_CMD_CODE(_SetChannel));21922193if (flags & RTW_CMDF_WAIT_ACK) {2194pcmdobj->sctx = &sctx;2195rtw_sctx_init(&sctx, 10 * 1000);2196}21972198res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);21992200if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {2201rtw_sctx_wait(&sctx, __func__);2202_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);2203if (sctx.status == RTW_SCTX_SUBMITTED)2204pcmdobj->sctx = NULL;2205_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);2206}2207}22082209/* do something based on res... */22102211exit:22122213RTW_INFO(FUNC_NDEV_FMT" res:%u\n", FUNC_NDEV_ARG(padapter->pnetdev), res);221422152216return res;2217}22182219u8 _rtw_set_chplan_cmd(_adapter *adapter, int flags, u8 chplan, const struct country_chplan *country_ent, u8 swconfig)2220{2221struct cmd_obj *cmdobj;2222struct SetChannelPlan_param *parm;2223struct cmd_priv *pcmdpriv = &adapter->cmdpriv;2224struct submit_ctx sctx;2225u8 res = _SUCCESS;222622272228/* check if allow software config */2229if (swconfig && rtw_hal_is_disable_sw_channel_plan(adapter) == _TRUE) {2230res = _FAIL;2231goto exit;2232}22332234/* if country_entry is provided, replace chplan */2235if (country_ent)2236chplan = country_ent->chplan;22372238/* check input parameter */2239if (!rtw_is_channel_plan_valid(chplan)) {2240res = _FAIL;2241goto exit;2242}22432244/* prepare cmd parameter */2245parm = (struct SetChannelPlan_param *)rtw_zmalloc(sizeof(*parm));2246if (parm == NULL) {2247res = _FAIL;2248goto exit;2249}2250parm->country_ent = country_ent;2251parm->channel_plan = chplan;22522253if (flags & RTW_CMDF_DIRECTLY) {2254/* no need to enqueue, do the cmd hdl directly and free cmd parameter */2255if (H2C_SUCCESS != set_chplan_hdl(adapter, (u8 *)parm))2256res = _FAIL;2257rtw_mfree((u8 *)parm, sizeof(*parm));2258} else {2259/* need enqueue, prepare cmd_obj and enqueue */2260cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));2261if (cmdobj == NULL) {2262res = _FAIL;2263rtw_mfree((u8 *)parm, sizeof(*parm));2264goto exit;2265}22662267init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_SetChannelPlan));22682269if (flags & RTW_CMDF_WAIT_ACK) {2270cmdobj->sctx = &sctx;2271rtw_sctx_init(&sctx, 2000);2272}22732274res = rtw_enqueue_cmd(pcmdpriv, cmdobj);22752276if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {2277rtw_sctx_wait(&sctx, __func__);2278_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);2279if (sctx.status == RTW_SCTX_SUBMITTED)2280cmdobj->sctx = NULL;2281_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);2282if (sctx.status != RTW_SCTX_DONE_SUCCESS)2283res = _FAIL;2284}22852286/* allow set channel plan when cmd_thread is not running */2287if (res != _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {2288parm = (struct SetChannelPlan_param *)rtw_zmalloc(sizeof(*parm));2289if (parm == NULL) {2290res = _FAIL;2291goto exit;2292}2293parm->country_ent = country_ent;2294parm->channel_plan = chplan;22952296if (H2C_SUCCESS != set_chplan_hdl(adapter, (u8 *)parm))2297res = _FAIL;2298else2299res = _SUCCESS;2300rtw_mfree((u8 *)parm, sizeof(*parm));2301}2302}23032304exit:2305return res;2306}23072308inline u8 rtw_set_chplan_cmd(_adapter *adapter, int flags, u8 chplan, u8 swconfig)2309{2310return _rtw_set_chplan_cmd(adapter, flags, chplan, NULL, swconfig);2311}23122313inline u8 rtw_set_country_cmd(_adapter *adapter, int flags, const char *country_code, u8 swconfig)2314{2315const struct country_chplan *ent;23162317if (is_alpha(country_code[0]) == _FALSE2318|| is_alpha(country_code[1]) == _FALSE2319) {2320RTW_PRINT("%s input country_code is not alpha2\n", __func__);2321return _FAIL;2322}23232324ent = rtw_get_chplan_from_country(country_code);23252326if (ent == NULL) {2327RTW_PRINT("%s unsupported country_code:\"%c%c\"\n", __func__, country_code[0], country_code[1]);2328return _FAIL;2329}23302331RTW_PRINT("%s country_code:\"%c%c\" mapping to chplan:0x%02x\n", __func__, country_code[0], country_code[1], ent->chplan);23322333return _rtw_set_chplan_cmd(adapter, flags, RTW_CHPLAN_UNSPECIFIED, ent, swconfig);2334}23352336u8 rtw_led_blink_cmd(_adapter *padapter, void *pLed)2337{2338struct cmd_obj *pcmdobj;2339struct LedBlink_param *ledBlink_param;2340struct cmd_priv *pcmdpriv = &padapter->cmdpriv;23412342u8 res = _SUCCESS;2343234423452346pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));2347if (pcmdobj == NULL) {2348res = _FAIL;2349goto exit;2350}23512352ledBlink_param = (struct LedBlink_param *)rtw_zmalloc(sizeof(struct LedBlink_param));2353if (ledBlink_param == NULL) {2354rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));2355res = _FAIL;2356goto exit;2357}23582359ledBlink_param->pLed = pLed;23602361init_h2fwcmd_w_parm_no_rsp(pcmdobj, ledBlink_param, GEN_CMD_CODE(_LedBlink));2362res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);23632364exit:236523662367return res;2368}23692370u8 rtw_set_csa_cmd(_adapter *adapter)2371{2372struct cmd_obj *cmdobj;2373struct cmd_priv *cmdpriv = &adapter->cmdpriv;2374u8 res = _SUCCESS;23752376cmdobj = rtw_zmalloc(sizeof(struct cmd_obj));2377if (cmdobj == NULL) {2378res = _FAIL;2379goto exit;2380}23812382init_h2fwcmd_w_parm_no_parm_rsp(cmdobj, GEN_CMD_CODE(_SetChannelSwitch));2383res = rtw_enqueue_cmd(cmdpriv, cmdobj);23842385exit:2386return res;2387}23882389u8 rtw_tdls_cmd(_adapter *padapter, u8 *addr, u8 option)2390{2391u8 res = _SUCCESS;2392#ifdef CONFIG_TDLS2393struct cmd_obj *pcmdobj;2394struct TDLSoption_param *TDLSoption;2395struct mlme_priv *pmlmepriv = &padapter->mlmepriv;2396struct cmd_priv *pcmdpriv = &padapter->cmdpriv;23972398pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));2399if (pcmdobj == NULL) {2400res = _FAIL;2401goto exit;2402}24032404TDLSoption = (struct TDLSoption_param *)rtw_zmalloc(sizeof(struct TDLSoption_param));2405if (TDLSoption == NULL) {2406rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));2407res = _FAIL;2408goto exit;2409}24102411_rtw_spinlock(&(padapter->tdlsinfo.cmd_lock));2412if (addr != NULL)2413_rtw_memcpy(TDLSoption->addr, addr, 6);2414TDLSoption->option = option;2415_rtw_spinunlock(&(padapter->tdlsinfo.cmd_lock));2416init_h2fwcmd_w_parm_no_rsp(pcmdobj, TDLSoption, GEN_CMD_CODE(_TDLS));2417res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);24182419exit:2420#endif /* CONFIG_TDLS */24212422return res;2423}24242425u8 rtw_enable_hw_update_tsf_cmd(_adapter *padapter)2426{2427struct cmd_obj *ph2c;2428struct drvextra_cmd_parm *pdrvextra_cmd_parm;2429struct cmd_priv *pcmdpriv = &padapter->cmdpriv;2430u8 res = _SUCCESS;243124322433ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));2434if (ph2c == NULL) {2435res = _FAIL;2436goto exit;2437}24382439pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));2440if (pdrvextra_cmd_parm == NULL) {2441rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));2442res = _FAIL;2443goto exit;2444}24452446pdrvextra_cmd_parm->ec_id = EN_HW_UPDATE_TSF_WK_CID;2447pdrvextra_cmd_parm->type = 0;2448pdrvextra_cmd_parm->size = 0;2449pdrvextra_cmd_parm->pbuf = NULL;24502451init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));24522453res = rtw_enqueue_cmd(pcmdpriv, ph2c);24542455exit:2456return res;2457}24582459u8 rtw_periodic_tsf_update_end_cmd(_adapter *adapter)2460{2461struct cmd_obj *cmdobj;2462struct drvextra_cmd_parm *parm;2463struct cmd_priv *cmdpriv = &adapter->cmdpriv;2464u8 res = _SUCCESS;24652466cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));2467if (cmdobj == NULL) {2468res = _FAIL;2469goto exit;2470}24712472parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));2473if (parm == NULL) {2474rtw_mfree((unsigned char *)cmdobj, sizeof(struct cmd_obj));2475res = _FAIL;2476goto exit;2477}24782479parm->ec_id = PERIOD_TSF_UPDATE_END_WK_CID;2480parm->type = 0;2481parm->size = 0;2482parm->pbuf = NULL;24832484init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_Set_Drv_Extra));24852486res = rtw_enqueue_cmd(cmdpriv, cmdobj);24872488exit:2489return res;2490}2491u8 rtw_ssmps_wk_hdl(_adapter *adapter, struct ssmps_cmd_parm *ssmp_param)2492{2493u8 res = _SUCCESS;2494struct sta_info *sta = ssmp_param->sta;2495u8 smps = ssmp_param->smps;24962497if (sta == NULL)2498return _FALSE;24992500if (smps)2501rtw_ssmps_enter(adapter, sta);2502else2503rtw_ssmps_leave(adapter, sta);2504return res;2505}25062507u8 rtw_ssmps_wk_cmd(_adapter *adapter, struct sta_info *sta, u8 smps, u8 enqueue)2508{2509struct cmd_obj *cmdobj;2510struct drvextra_cmd_parm *cmd_parm;2511struct ssmps_cmd_parm *ssmp_param;2512struct cmd_priv *pcmdpriv = &adapter->cmdpriv;2513u8 res = _SUCCESS;25142515if (enqueue) {2516cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));2517if (cmdobj == NULL) {2518res = _FAIL;2519goto exit;2520}25212522cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));2523if (cmd_parm == NULL) {2524rtw_mfree((unsigned char *)cmdobj, sizeof(struct cmd_obj));2525res = _FAIL;2526goto exit;2527}25282529ssmp_param = (struct ssmps_cmd_parm *)rtw_zmalloc(sizeof(struct ssmps_cmd_parm));2530if (ssmp_param == NULL) {2531rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));2532rtw_mfree((u8 *)cmd_parm, sizeof(struct drvextra_cmd_parm));2533res = _FAIL;2534goto exit;2535}25362537ssmp_param->smps = smps;2538ssmp_param->sta = sta;25392540cmd_parm->ec_id = SSMPS_WK_CID;2541cmd_parm->type = 0;2542cmd_parm->size = sizeof(struct ssmps_cmd_parm);2543cmd_parm->pbuf = (u8 *)ssmp_param;25442545init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));25462547res = rtw_enqueue_cmd(pcmdpriv, cmdobj);2548} else {2549struct ssmps_cmd_parm tmp_ssmp_param;25502551tmp_ssmp_param.smps = smps;2552tmp_ssmp_param.sta = sta;2553rtw_ssmps_wk_hdl(adapter, &tmp_ssmp_param);2554}25552556exit:2557return res;2558}25592560#ifdef CONFIG_SUPPORT_STATIC_SMPS2561u8 _ssmps_chk_by_tp(_adapter *adapter, u8 from_timer)2562{2563u8 enter_smps = _FALSE;2564struct mlme_priv *pmlmepriv = &adapter->mlmepriv;2565struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);2566struct sta_priv *pstapriv = &adapter->stapriv;2567struct sta_info *psta;2568u32 tx_tp_mbits, rx_tp_mbits;25692570if (!MLME_IS_STA(adapter) ||2571!hal_is_mimo_support(adapter) ||2572!pmlmeext->ssmps_en ||2573(pmlmeext->cur_channel > 14)2574)2575return enter_smps;25762577psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));2578if (psta == NULL) {2579RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));2580rtw_warn_on(1);2581return enter_smps;2582}25832584if (psta->cmn.mimo_type == RF_1T1R)2585return enter_smps;25862587tx_tp_mbits = psta->sta_stats.tx_tp_kbits >> 10;2588rx_tp_mbits = psta->sta_stats.rx_tp_kbits >> 10;25892590#ifdef DBG_STATIC_SMPS2591if (pmlmeext->ssmps_test) {2592enter_smps = (pmlmeext->ssmps_test_en == 1) ? _TRUE : _FALSE;2593}2594else2595#endif2596{2597if ((tx_tp_mbits <= pmlmeext->ssmps_tx_tp_th) &&2598(rx_tp_mbits <= pmlmeext->ssmps_rx_tp_th))2599enter_smps = _TRUE;2600else2601enter_smps = _FALSE;2602}26032604if (1) {2605RTW_INFO(FUNC_ADPT_FMT" tx_tp:%d [%d], rx_tp:%d [%d] , SSMPS enter :%s\n",2606FUNC_ADPT_ARG(adapter),2607tx_tp_mbits, pmlmeext->ssmps_tx_tp_th,2608rx_tp_mbits, pmlmeext->ssmps_rx_tp_th,2609(enter_smps == _TRUE) ? "True" : "False");2610#ifdef DBG_STATIC_SMPS2611RTW_INFO(FUNC_ADPT_FMT" test:%d test_en:%d\n",2612FUNC_ADPT_ARG(adapter),2613pmlmeext->ssmps_test,2614pmlmeext->ssmps_test_en);2615#endif2616}26172618if (enter_smps) {2619if (!from_timer && psta->cmn.sm_ps != SM_PS_STATIC)2620rtw_ssmps_enter(adapter, psta);2621} else {2622if (!from_timer && psta->cmn.sm_ps != SM_PS_DISABLE)2623rtw_ssmps_leave(adapter, psta);2624else {2625u8 ps_change = _FALSE;26262627if (enter_smps && psta->cmn.sm_ps != SM_PS_STATIC)2628ps_change = _TRUE;2629else if (!enter_smps && psta->cmn.sm_ps != SM_PS_DISABLE)2630ps_change = _TRUE;26312632if (ps_change)2633rtw_ssmps_wk_cmd(adapter, psta, enter_smps, 1);2634}2635}26362637return enter_smps;2638}2639#endif /*CONFIG_SUPPORT_STATIC_SMPS*/26402641#ifdef CONFIG_CTRL_TXSS_BY_TP2642void rtw_ctrl_txss_update_mimo_type(_adapter *adapter, struct sta_info *sta)2643{2644struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);26452646pmlmeext->txss_momi_type_bk = sta->cmn.mimo_type;2647}26482649u8 rtw_ctrl_txss(_adapter *adapter, struct sta_info *sta, bool tx_1ss)2650{2651struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);2652struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);2653u8 lps_changed = _FALSE;2654u8 rst = _SUCCESS;26552656if (pmlmeext->txss_1ss == tx_1ss)2657return _FALSE;26582659if (pwrpriv->bLeisurePs && pwrpriv->pwr_mode != PS_MODE_ACTIVE) {2660lps_changed = _TRUE;2661LPS_Leave(adapter, "LPS_CTRL_TXSS");2662}26632664RTW_INFO(ADPT_FMT" STA [" MAC_FMT "] set tx to %d ss\n",2665ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr),2666(tx_1ss) ? 1 : rtw_get_sta_tx_nss(adapter, sta));26672668/*ra re-registed*/2669sta->cmn.mimo_type = (tx_1ss) ? RF_1T1R : pmlmeext->txss_momi_type_bk;2670rtw_phydm_ra_registed(adapter, sta);26712672/*configure trx mode*/2673rtw_phydm_trx_cfg(adapter, tx_1ss);2674pmlmeext->txss_1ss = tx_1ss;26752676if (lps_changed)2677LPS_Enter(adapter, "LPS_CTRL_TXSS");26782679return rst;2680}26812682u8 rtw_ctrl_txss_wk_hdl(_adapter *adapter, struct txss_cmd_parm *txss_param)2683{2684if (!txss_param->sta)2685return _FALSE;26862687return rtw_ctrl_txss(adapter, txss_param->sta, txss_param->tx_1ss);2688}26892690u8 rtw_ctrl_txss_wk_cmd(_adapter *adapter, struct sta_info *sta, bool tx_1ss, u8 flag)2691{2692struct cmd_obj *cmdobj;2693struct drvextra_cmd_parm *cmd_parm;2694struct txss_cmd_parm *txss_param;2695struct cmd_priv *pcmdpriv = &adapter->cmdpriv;2696struct submit_ctx sctx;2697u8 res = _SUCCESS;26982699txss_param = (struct txss_cmd_parm *)rtw_zmalloc(sizeof(struct txss_cmd_parm));2700if (txss_param == NULL) {2701res = _FAIL;2702goto exit;2703}27042705txss_param->tx_1ss = tx_1ss;2706txss_param->sta = sta;27072708if (flag & RTW_CMDF_DIRECTLY) {2709res = rtw_ctrl_txss_wk_hdl(adapter, txss_param);2710rtw_mfree((u8 *)txss_param, sizeof(*txss_param));2711} else {2712cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));2713if (cmdobj == NULL) {2714res = _FAIL;2715goto exit;2716}27172718cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));2719if (cmd_parm == NULL) {2720rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));2721res = _FAIL;2722goto exit;2723}27242725cmd_parm->ec_id = TXSS_WK_CID;2726cmd_parm->type = 0;2727cmd_parm->size = sizeof(struct txss_cmd_parm);2728cmd_parm->pbuf = (u8 *)txss_param;27292730init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));27312732if (flag & RTW_CMDF_WAIT_ACK) {2733cmdobj->sctx = &sctx;2734rtw_sctx_init(&sctx, 10 * 1000);2735}27362737res = rtw_enqueue_cmd(pcmdpriv, cmdobj);2738if (res == _SUCCESS && (flag & RTW_CMDF_WAIT_ACK)) {2739rtw_sctx_wait(&sctx, __func__);2740_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);2741if (sctx.status == RTW_SCTX_SUBMITTED)2742cmdobj->sctx = NULL;2743_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);2744if (sctx.status != RTW_SCTX_DONE_SUCCESS)2745res = _FAIL;2746}2747}27482749exit:2750return res;2751}27522753void rtw_ctrl_tx_ss_by_tp(_adapter *adapter, u8 from_timer)2754{2755bool tx_1ss = _FALSE; /*change tx from 2ss to 1ss*/2756struct mlme_priv *pmlmepriv = &adapter->mlmepriv;2757struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);2758struct sta_priv *pstapriv = &adapter->stapriv;2759struct sta_info *psta;2760u32 tx_tp_mbits;27612762if (!MLME_IS_STA(adapter) ||2763!hal_is_mimo_support(adapter) ||2764!pmlmeext->txss_ctrl_en2765)2766return;27672768psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));2769if (psta == NULL) {2770RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));2771rtw_warn_on(1);2772return;2773}27742775tx_tp_mbits = psta->sta_stats.tx_tp_kbits >> 10;2776if (tx_tp_mbits >= pmlmeext->txss_tp_th) {2777tx_1ss = _FALSE;2778} else {2779if (pmlmeext->txss_tp_chk_cnt && --pmlmeext->txss_tp_chk_cnt)2780tx_1ss = _FALSE;2781else2782tx_1ss = _TRUE;2783}27842785if (1) {2786RTW_INFO(FUNC_ADPT_FMT" tx_tp:%d [%d] tx_1ss(%d):%s\n",2787FUNC_ADPT_ARG(adapter),2788tx_tp_mbits, pmlmeext->txss_tp_th,2789pmlmeext->txss_tp_chk_cnt,2790(tx_1ss == _TRUE) ? "True" : "False");2791}27922793if (pmlmeext->txss_1ss != tx_1ss) {2794if (from_timer)2795rtw_ctrl_txss_wk_cmd(adapter, psta, tx_1ss, 0);2796else2797rtw_ctrl_txss(adapter, psta, tx_1ss);2798}2799}2800#ifdef DBG_CTRL_TXSS2801void dbg_ctrl_txss(_adapter *adapter, bool tx_1ss)2802{2803struct mlme_priv *pmlmepriv = &adapter->mlmepriv;2804struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);2805struct sta_priv *pstapriv = &adapter->stapriv;2806struct sta_info *psta;28072808if (!MLME_IS_STA(adapter) ||2809!hal_is_mimo_support(adapter)2810)2811return;28122813psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));2814if (psta == NULL) {2815RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));2816rtw_warn_on(1);2817return;2818}28192820rtw_ctrl_txss(adapter, psta, tx_1ss);2821}2822#endif2823#endif /*CONFIG_CTRL_TXSS_BY_TP*/28242825#ifdef CONFIG_LPS2826#ifdef CONFIG_LPS_CHK_BY_TP2827#ifdef LPS_BCN_CNT_MONITOR2828static u8 _bcn_cnt_expected(struct sta_info *psta)2829{2830_adapter *adapter = psta->padapter;2831struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;2832struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);2833u8 dtim = rtw_get_bcn_dtim_period(adapter);2834u8 bcn_cnt = 0;28352836if ((pmlmeinfo->bcn_interval !=0) && (dtim != 0))2837bcn_cnt = 2000 / pmlmeinfo->bcn_interval / dtim * 4 / 5; /*2s*/2838if (0)2839RTW_INFO("%s bcn_cnt:%d\n", __func__, bcn_cnt);28402841if (bcn_cnt == 0) {2842RTW_ERR(FUNC_ADPT_FMT" bcn_cnt == 0\n", FUNC_ADPT_ARG(adapter));2843rtw_warn_on(1);2844}28452846return bcn_cnt;2847}2848#endif2849u8 _lps_chk_by_tp(_adapter *adapter, u8 from_timer)2850{2851u8 enter_ps = _FALSE;2852struct mlme_priv *pmlmepriv = &adapter->mlmepriv;2853struct sta_priv *pstapriv = &adapter->stapriv;2854struct sta_info *psta;2855struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);2856u32 tx_tp_mbits, rx_tp_mbits, bi_tp_mbits;2857u8 rx_bcn_cnt;28582859psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));2860if (psta == NULL) {2861RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter));2862rtw_warn_on(1);2863return enter_ps;2864}28652866rx_bcn_cnt = rtw_get_bcn_cnt(psta->padapter);2867psta->sta_stats.acc_tx_bytes = psta->sta_stats.tx_bytes;2868psta->sta_stats.acc_rx_bytes = psta->sta_stats.rx_bytes;28692870#if 12871tx_tp_mbits = psta->sta_stats.tx_tp_kbits >> 10;2872rx_tp_mbits = psta->sta_stats.rx_tp_kbits >> 10;2873bi_tp_mbits = tx_tp_mbits + rx_tp_mbits;2874#else2875tx_tp_mbits = psta->sta_stats.smooth_tx_tp_kbits >> 10;2876rx_tp_mbits = psta->sta_stats.smooth_rx_tp_kbits >> 10;2877bi_tp_mbits = tx_tp_mbits + rx_tp_mbits;2878#endif28792880if ((bi_tp_mbits >= pwrpriv->lps_bi_tp_th) ||2881(tx_tp_mbits >= pwrpriv->lps_tx_tp_th) ||2882(rx_tp_mbits >= pwrpriv->lps_rx_tp_th)) {2883enter_ps = _FALSE;2884pwrpriv->lps_chk_cnt = pwrpriv->lps_chk_cnt_th;2885}2886else {2887#ifdef LPS_BCN_CNT_MONITOR2888u8 bcn_cnt = _bcn_cnt_expected(psta);28892890if (bcn_cnt && (rx_bcn_cnt < bcn_cnt)) {2891pwrpriv->lps_chk_cnt = 2;2892RTW_ERR(FUNC_ADPT_FMT" BCN_CNT:%d(%d) invalid\n",2893FUNC_ADPT_ARG(adapter), rx_bcn_cnt, bcn_cnt);2894}2895#endif28962897if (pwrpriv->lps_chk_cnt && --pwrpriv->lps_chk_cnt)2898enter_ps = _FALSE;2899else2900enter_ps = _TRUE;2901}29022903if (1) {2904RTW_INFO(FUNC_ADPT_FMT" tx_tp:%d [%d], rx_tp:%d [%d], bi_tp:%d [%d], enter_ps(%d):%s\n",2905FUNC_ADPT_ARG(adapter),2906tx_tp_mbits, pwrpriv->lps_tx_tp_th,2907rx_tp_mbits, pwrpriv->lps_rx_tp_th,2908bi_tp_mbits, pwrpriv->lps_bi_tp_th,2909pwrpriv->lps_chk_cnt,2910(enter_ps == _TRUE) ? "True" : "False");2911RTW_INFO(FUNC_ADPT_FMT" tx_pkt_cnt :%d [%d], rx_pkt_cnt :%d [%d]\n",2912FUNC_ADPT_ARG(adapter),2913pmlmepriv->LinkDetectInfo.NumTxOkInPeriod,2914pwrpriv->lps_tx_pkts,2915pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod,2916pwrpriv->lps_rx_pkts);2917if (!adapter->bsta_tp_dump)2918RTW_INFO(FUNC_ADPT_FMT" bcn_cnt:%d (per-%d second)\n",2919FUNC_ADPT_ARG(adapter),2920rx_bcn_cnt,29212);2922}29232924if (enter_ps) {2925if (!from_timer)2926LPS_Enter(adapter, "TRAFFIC_IDLE");2927} else {2928if (!from_timer)2929LPS_Leave(adapter, "TRAFFIC_BUSY");2930else {2931#ifdef CONFIG_CONCURRENT_MODE2932#ifndef CONFIG_FW_MULTI_PORT_SUPPORT2933if (adapter->hw_port == HW_PORT0)2934#endif2935#endif2936rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_TRAFFIC_BUSY, 0);2937}2938}29392940return enter_ps;2941}2942#endif29432944static u8 _lps_chk_by_pkt_cnts(_adapter *padapter, u8 from_timer, u8 bBusyTraffic)2945{2946struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);2947u8 bEnterPS = _FALSE;29482949/* check traffic for powersaving. */2950if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||2951#ifdef CONFIG_LPS_SLOW_TRANSITION2952(pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2)2953#else /* CONFIG_LPS_SLOW_TRANSITION */2954(pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 4)2955#endif /* CONFIG_LPS_SLOW_TRANSITION */2956) {2957#ifdef DBG_RX_COUNTER_DUMP2958if (padapter->dump_rx_cnt_mode & DUMP_DRV_TRX_COUNTER_DATA)2959RTW_INFO("(-)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);2960#endif29612962bEnterPS = _FALSE;2963#ifdef CONFIG_LPS_SLOW_TRANSITION2964if (bBusyTraffic == _TRUE) {2965if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount <= 4)2966pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 4;29672968pmlmepriv->LinkDetectInfo.TrafficTransitionCount++;29692970/* RTW_INFO("Set TrafficTransitionCount to %d\n", pmlmepriv->LinkDetectInfo.TrafficTransitionCount); */29712972if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount > 30/*TrafficTransitionLevel*/)2973pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 30;2974}2975#endif /* CONFIG_LPS_SLOW_TRANSITION */2976} else {2977#ifdef DBG_RX_COUNTER_DUMP2978if (padapter->dump_rx_cnt_mode & DUMP_DRV_TRX_COUNTER_DATA)2979RTW_INFO("(+)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);2980#endif29812982#ifdef CONFIG_LPS_SLOW_TRANSITION2983if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount >= 2)2984pmlmepriv->LinkDetectInfo.TrafficTransitionCount -= 2;2985else2986pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;29872988if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount == 0)2989bEnterPS = _TRUE;2990#else /* CONFIG_LPS_SLOW_TRANSITION */2991bEnterPS = _TRUE;2992#endif /* CONFIG_LPS_SLOW_TRANSITION */2993}29942995#ifdef CONFIG_DYNAMIC_DTIM2996if (pmlmepriv->LinkDetectInfo.LowPowerTransitionCount == 8)2997bEnterPS = _FALSE;29982999RTW_INFO("LowPowerTransitionCount=%d\n", pmlmepriv->LinkDetectInfo.LowPowerTransitionCount);3000#endif /* CONFIG_DYNAMIC_DTIM */30013002/* LeisurePS only work in infra mode. */3003if (bEnterPS) {3004if (!from_timer) {3005#ifdef CONFIG_DYNAMIC_DTIM3006if (pmlmepriv->LinkDetectInfo.LowPowerTransitionCount < 8)3007adapter_to_pwrctl(padapter)->dtim = 1;3008else3009adapter_to_pwrctl(padapter)->dtim = 3;3010#endif /* CONFIG_DYNAMIC_DTIM */3011LPS_Enter(padapter, "TRAFFIC_IDLE");3012} else {3013/* do this at caller */3014/* rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_ENTER, 0); */3015/* rtw_hal_dm_watchdog_in_lps(padapter); */3016}30173018#ifdef CONFIG_DYNAMIC_DTIM3019if (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)3020pmlmepriv->LinkDetectInfo.LowPowerTransitionCount++;3021#endif /* CONFIG_DYNAMIC_DTIM */3022} else {3023#ifdef CONFIG_DYNAMIC_DTIM3024if (pmlmepriv->LinkDetectInfo.LowPowerTransitionCount != 8)3025pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;3026else3027pmlmepriv->LinkDetectInfo.LowPowerTransitionCount++;3028#endif /* CONFIG_DYNAMIC_DTIM */30293030if (!from_timer)3031LPS_Leave(padapter, "TRAFFIC_BUSY");3032else {3033#ifdef CONFIG_CONCURRENT_MODE3034#ifndef CONFIG_FW_MULTI_PORT_SUPPORT3035if (padapter->hw_port == HW_PORT0)3036#endif3037#endif3038rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_TRAFFIC_BUSY, 0);3039}3040}30413042return bEnterPS;3043}3044#endif /* CONFIG_LPS */30453046/* from_timer == 1 means driver is in LPS */3047u8 traffic_status_watchdog(_adapter *padapter, u8 from_timer)3048{3049u8 bEnterPS = _FALSE;3050u16 BusyThresholdHigh;3051u16 BusyThresholdLow;3052u16 BusyThreshold;3053u8 bBusyTraffic = _FALSE, bTxBusyTraffic = _FALSE, bRxBusyTraffic = _FALSE;3054u8 bHigherBusyTraffic = _FALSE, bHigherBusyRxTraffic = _FALSE, bHigherBusyTxTraffic = _FALSE;30553056struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);3057#ifdef CONFIG_TDLS3058struct tdls_info *ptdlsinfo = &(padapter->tdlsinfo);3059struct tdls_txmgmt txmgmt;3060u8 baddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };3061#endif /* CONFIG_TDLS */3062#ifdef CONFIG_TRAFFIC_PROTECT3063RT_LINK_DETECT_T *link_detect = &pmlmepriv->LinkDetectInfo;3064#endif30653066#ifdef CONFIG_BT_COEXIST3067if (padapter->registrypriv.wifi_spec != 1) {3068BusyThresholdHigh = 25;3069BusyThresholdLow = 10;3070} else3071#endif /* CONFIG_BT_COEXIST */3072{3073BusyThresholdHigh = 100;3074BusyThresholdLow = 75;3075}3076BusyThreshold = BusyThresholdHigh;307730783079/* */3080/* Determine if our traffic is busy now */3081/* */3082if ((check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)3083/*&& !MgntInitAdapterInProgress(pMgntInfo)*/) {3084/* if we raise bBusyTraffic in last watchdog, using lower threshold. */3085if (pmlmepriv->LinkDetectInfo.bBusyTraffic)3086BusyThreshold = BusyThresholdLow;30873088if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold ||3089pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold) {3090bBusyTraffic = _TRUE;30913092if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)3093bRxBusyTraffic = _TRUE;3094else3095bTxBusyTraffic = _TRUE;3096}30973098/* Higher Tx/Rx data. */3099if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||3100pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {3101bHigherBusyTraffic = _TRUE;31023103if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)3104bHigherBusyRxTraffic = _TRUE;3105else3106bHigherBusyTxTraffic = _TRUE;3107}31083109#ifdef CONFIG_TRAFFIC_PROTECT3110#define TX_ACTIVE_TH 103111#define RX_ACTIVE_TH 203112#define TRAFFIC_PROTECT_PERIOD_MS 450031133114if (link_detect->NumTxOkInPeriod > TX_ACTIVE_TH3115|| link_detect->NumRxUnicastOkInPeriod > RX_ACTIVE_TH) {31163117RTW_INFO(FUNC_ADPT_FMT" acqiure wake_lock for %u ms(tx:%d,rx_unicast:%d)\n",3118FUNC_ADPT_ARG(padapter),3119TRAFFIC_PROTECT_PERIOD_MS,3120link_detect->NumTxOkInPeriod,3121link_detect->NumRxUnicastOkInPeriod);31223123rtw_lock_traffic_suspend_timeout(TRAFFIC_PROTECT_PERIOD_MS);3124}3125#endif31263127#ifdef CONFIG_TDLS3128#ifdef CONFIG_TDLS_AUTOSETUP3129/* TDLS_WATCHDOG_PERIOD * 2sec, periodically send */3130if (hal_chk_wl_func(padapter, WL_FUNC_TDLS) == _TRUE) {3131if ((ptdlsinfo->watchdog_count % TDLS_WATCHDOG_PERIOD) == 0) {3132_rtw_memcpy(txmgmt.peer, baddr, ETH_ALEN);3133issue_tdls_dis_req(padapter, &txmgmt);3134}3135ptdlsinfo->watchdog_count++;3136}3137#endif /* CONFIG_TDLS_AUTOSETUP */3138#endif /* CONFIG_TDLS */31393140#ifdef CONFIG_SUPPORT_STATIC_SMPS3141_ssmps_chk_by_tp(padapter, from_timer);3142#endif3143#ifdef CONFIG_CTRL_TXSS_BY_TP3144rtw_ctrl_tx_ss_by_tp(padapter, from_timer);3145#endif31463147#ifdef CONFIG_LPS3148if (adapter_to_pwrctl(padapter)->bLeisurePs && MLME_IS_STA(padapter)) {3149#ifdef CONFIG_LPS_CHK_BY_TP3150if (adapter_to_pwrctl(padapter)->lps_chk_by_tp)3151bEnterPS = _lps_chk_by_tp(padapter, from_timer);3152else3153#endif /*CONFIG_LPS_CHK_BY_TP*/3154bEnterPS = _lps_chk_by_pkt_cnts(padapter, from_timer, bBusyTraffic);3155}3156#endif /* CONFIG_LPS */31573158} else {3159#ifdef CONFIG_LPS3160if (!from_timer && rtw_mi_get_assoc_if_num(padapter) == 0)3161LPS_Leave(padapter, "NON_LINKED");3162#endif3163}31643165session_tracker_chk_cmd(padapter, NULL);31663167#ifdef CONFIG_BEAMFORMING3168#ifdef RTW_BEAMFORMING_VERSION_23169rtw_bf_update_traffic(padapter);3170#endif /* RTW_BEAMFORMING_VERSION_2 */3171#endif /* CONFIG_BEAMFORMING */31723173pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;3174pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;3175pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;3176pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;3177pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;3178pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;3179pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;3180pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;3181pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;31823183return bEnterPS;31843185}318631873188/* for 11n Logo 4.2.31/4.2.32 */3189static void dynamic_update_bcn_check(_adapter *padapter)3190{3191struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);3192struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;31933194if (!padapter->registrypriv.wifi_spec)3195return;31963197if (!padapter->registrypriv.ht_enable || !is_supported_ht(padapter->registrypriv.wireless_mode))3198return;31993200if (!MLME_IS_AP(padapter))3201return;32023203if (pmlmeext->bstart_bss) {3204/* In 10 * 2 = 20s, there are no legacy AP, update HT info */3205static u8 count = 1;32063207if (count % 10 == 0) {3208count = 1;3209#ifdef CONFIG_80211N_HT3210if (_FALSE == ATOMIC_READ(&pmlmepriv->olbc)3211&& _FALSE == ATOMIC_READ(&pmlmepriv->olbc_ht)) {32123213if (rtw_ht_operation_update(padapter) > 0) {3214update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE, 0);3215update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE, 0);3216}3217}3218#endif /* CONFIG_80211N_HT */3219}32203221#ifdef CONFIG_80211N_HT3222/* In 2s, there are any legacy AP, update HT info, and then reset count */32233224if (_FALSE != ATOMIC_READ(&pmlmepriv->olbc)3225&& _FALSE != ATOMIC_READ(&pmlmepriv->olbc_ht)) {32263227if (rtw_ht_operation_update(padapter) > 0) {3228update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE, 0);3229update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE, 0);32303231}3232ATOMIC_SET(&pmlmepriv->olbc, _FALSE);3233ATOMIC_SET(&pmlmepriv->olbc_ht, _FALSE);3234count = 0;3235}3236#endif /* CONFIG_80211N_HT */3237count ++;3238}3239}3240void rtw_iface_dynamic_chk_wk_hdl(_adapter *padapter)3241{3242#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK3243#ifdef CONFIG_AP_MODE3244if (MLME_IS_AP(padapter) || MLME_IS_MESH(padapter)) {3245expire_timeout_chk(padapter);3246#ifdef CONFIG_RTW_MESH3247if (MLME_IS_MESH(padapter) && MLME_IS_ASOC(padapter))3248rtw_mesh_peer_status_chk(padapter);3249#endif3250}3251#endif3252#endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */3253dynamic_update_bcn_check(padapter);32543255linked_status_chk(padapter, 0);3256traffic_status_watchdog(padapter, 0);32573258/* for debug purpose */3259_linked_info_dump(padapter);32603261#ifdef CONFIG_RTW_CFGVEDNOR_RSSIMONITOR3262rtw_cfgvendor_rssi_monitor_evt(padapter);3263#endif326432653266}3267void rtw_dynamic_chk_wk_hdl(_adapter *padapter)3268{3269rtw_mi_dynamic_chk_wk_hdl(padapter);32703271#ifdef DBG_CONFIG_ERROR_DETECT3272rtw_hal_sreset_xmit_status_check(padapter);3273rtw_hal_sreset_linked_status_check(padapter);3274#endif32753276/* if(check_fwstate(pmlmepriv, _FW_UNDER_LINKING|_FW_UNDER_SURVEY)==_FALSE) */3277{3278#ifdef DBG_RX_COUNTER_DUMP3279rtw_dump_rx_counters(padapter);3280#endif3281dm_DynamicUsbTxAgg(padapter, 0);3282}3283rtw_hal_dm_watchdog(padapter);32843285/* check_hw_pbc(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type); */32863287#ifdef CONFIG_BT_COEXIST3288/* BT-Coexist */3289rtw_btcoex_Handler(padapter);3290#endif32913292#ifdef CONFIG_IPS_CHECK_IN_WD3293/* always call rtw_ps_processor() at last one. */3294rtw_ps_processor(padapter);3295#endif32963297#ifdef CONFIG_MCC_MODE3298rtw_hal_mcc_sw_status_check(padapter);3299#endif /* CONFIG_MCC_MODE */33003301rtw_hal_periodic_tsf_update_chk(padapter);3302}33033304#ifdef CONFIG_LPS3305struct lps_ctrl_wk_parm {3306s8 lps_level;3307#ifdef CONFIG_LPS_1T1R3308s8 lps_1t1r;3309#endif3310};33113312void lps_ctrl_wk_hdl(_adapter *padapter, u8 lps_ctrl_type, u8 *buf)3313{3314struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);3315struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);3316struct lps_ctrl_wk_parm *parm = (struct lps_ctrl_wk_parm *)buf;3317u8 mstatus;33183319if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)3320|| (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE))3321return;33223323switch (lps_ctrl_type) {3324case LPS_CTRL_SCAN:3325/* RTW_INFO("LPS_CTRL_SCAN\n"); */3326#ifdef CONFIG_BT_COEXIST3327rtw_btcoex_ScanNotify(padapter, _TRUE);3328#endif /* CONFIG_BT_COEXIST */3329if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {3330/* connect */3331LPS_Leave(padapter, "LPS_CTRL_SCAN");3332}3333break;3334case LPS_CTRL_JOINBSS:3335/* RTW_INFO("LPS_CTRL_JOINBSS\n"); */3336LPS_Leave(padapter, "LPS_CTRL_JOINBSS");3337break;3338case LPS_CTRL_CONNECT:3339/* RTW_INFO("LPS_CTRL_CONNECT\n"); */3340mstatus = 1;/* connect */3341/* Reset LPS Setting */3342pwrpriv->LpsIdleCount = 0;3343rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));3344#ifdef CONFIG_BT_COEXIST3345rtw_btcoex_MediaStatusNotify(padapter, mstatus);3346#endif /* CONFIG_BT_COEXIST */3347break;3348case LPS_CTRL_DISCONNECT:3349/* RTW_INFO("LPS_CTRL_DISCONNECT\n"); */3350mstatus = 0;/* disconnect */3351#ifdef CONFIG_BT_COEXIST3352rtw_btcoex_MediaStatusNotify(padapter, mstatus);3353#endif /* CONFIG_BT_COEXIST */3354LPS_Leave(padapter, "LPS_CTRL_DISCONNECT");3355rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));3356break;3357case LPS_CTRL_SPECIAL_PACKET:3358/* RTW_INFO("LPS_CTRL_SPECIAL_PACKET\n"); */3359rtw_set_lps_deny(padapter, LPS_DELAY_MS);3360#ifdef CONFIG_BT_COEXIST3361rtw_btcoex_SpecialPacketNotify(padapter, PACKET_DHCP);3362#endif /* CONFIG_BT_COEXIST */3363LPS_Leave(padapter, "LPS_CTRL_SPECIAL_PACKET");3364break;3365case LPS_CTRL_LEAVE:3366LPS_Leave(padapter, "LPS_CTRL_LEAVE");3367break;3368case LPS_CTRL_LEAVE_SET_OPTION:3369LPS_Leave(padapter, "LPS_CTRL_LEAVE_SET_OPTION");3370if (parm) {3371if (parm->lps_level >= 0)3372pwrpriv->lps_level = parm->lps_level;3373#ifdef CONFIG_LPS_1T1R3374if (parm->lps_1t1r >= 0)3375pwrpriv->lps_1t1r = parm->lps_1t1r;3376#endif3377}3378break;3379case LPS_CTRL_LEAVE_CFG80211_PWRMGMT:3380LPS_Leave(padapter, "CFG80211_PWRMGMT");3381break;3382case LPS_CTRL_TRAFFIC_BUSY:3383LPS_Leave(padapter, "LPS_CTRL_TRAFFIC_BUSY");3384break;3385case LPS_CTRL_TX_TRAFFIC_LEAVE:3386LPS_Leave(padapter, "LPS_CTRL_TX_TRAFFIC_LEAVE");3387break;3388case LPS_CTRL_RX_TRAFFIC_LEAVE:3389LPS_Leave(padapter, "LPS_CTRL_RX_TRAFFIC_LEAVE");3390break;3391case LPS_CTRL_ENTER:3392LPS_Enter(padapter, "TRAFFIC_IDLE_1");3393break;3394default:3395break;3396}33973398}33993400static u8 _rtw_lps_ctrl_wk_cmd(_adapter *adapter, u8 lps_ctrl_type, s8 lps_level, s8 lps_1t1r, u8 flags)3401{3402struct cmd_obj *cmdobj;3403struct drvextra_cmd_parm *parm;3404struct lps_ctrl_wk_parm *wk_parm = NULL;3405struct cmd_priv *pcmdpriv = &adapter->cmdpriv;3406struct submit_ctx sctx;3407u8 res = _SUCCESS;34083409if (lps_ctrl_type == LPS_CTRL_LEAVE_SET_OPTION) {3410wk_parm = rtw_zmalloc(sizeof(*wk_parm));3411if (wk_parm == NULL) {3412res = _FAIL;3413goto exit;3414}3415wk_parm->lps_level = lps_level;3416#ifdef CONFIG_LPS_1T1R3417wk_parm->lps_1t1r = lps_1t1r;3418#endif3419}34203421if (flags & RTW_CMDF_DIRECTLY) {3422/* no need to enqueue, do the cmd hdl directly */3423lps_ctrl_wk_hdl(adapter, lps_ctrl_type, (u8 *)wk_parm);3424if (wk_parm)3425rtw_mfree(wk_parm, sizeof(*wk_parm));3426} else {3427/* need enqueue, prepare cmd_obj and enqueue */3428parm = rtw_zmalloc(sizeof(*parm));3429if (parm == NULL) {3430if (wk_parm)3431rtw_mfree(wk_parm, sizeof(*wk_parm));3432res = _FAIL;3433goto exit;3434}34353436parm->ec_id = LPS_CTRL_WK_CID;3437parm->type = lps_ctrl_type;3438parm->size = wk_parm ? sizeof(*wk_parm) : 0;3439parm->pbuf = (u8 *)wk_parm;34403441cmdobj = rtw_zmalloc(sizeof(*cmdobj));3442if (cmdobj == NULL) {3443rtw_mfree(parm, sizeof(*parm));3444if (wk_parm)3445rtw_mfree(wk_parm, sizeof(*wk_parm));3446res = _FAIL;3447goto exit;3448}34493450init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_Set_Drv_Extra));34513452if (flags & RTW_CMDF_WAIT_ACK) {3453cmdobj->sctx = &sctx;3454rtw_sctx_init(&sctx, 2000);3455}34563457res = rtw_enqueue_cmd(pcmdpriv, cmdobj);34583459if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {3460rtw_sctx_wait(&sctx, __func__);3461_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);3462if (sctx.status == RTW_SCTX_SUBMITTED)3463cmdobj->sctx = NULL;3464_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);3465if (sctx.status != RTW_SCTX_DONE_SUCCESS)3466res = _FAIL;3467}3468}34693470exit:3471return res;3472}34733474u8 rtw_lps_ctrl_wk_cmd(_adapter *adapter, u8 lps_ctrl_type, u8 flags)3475{3476return _rtw_lps_ctrl_wk_cmd(adapter, lps_ctrl_type, -1, -1, flags);3477}34783479u8 rtw_lps_ctrl_leave_set_level_cmd(_adapter *adapter, u8 lps_level, u8 flags)3480{3481return _rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_LEAVE_SET_OPTION, lps_level, -1, flags);3482}34833484#ifdef CONFIG_LPS_1T1R3485u8 rtw_lps_ctrl_leave_set_1t1r_cmd(_adapter *adapter, u8 lps_1t1r, u8 flags)3486{3487return _rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_LEAVE_SET_OPTION, -1, lps_1t1r, flags);3488}3489#endif34903491void rtw_dm_in_lps_hdl(_adapter *padapter)3492{3493rtw_hal_set_hwreg(padapter, HW_VAR_DM_IN_LPS_LCLK, NULL);3494}34953496u8 rtw_dm_in_lps_wk_cmd(_adapter *padapter)3497{3498struct cmd_obj *ph2c;3499struct drvextra_cmd_parm *pdrvextra_cmd_parm;3500struct cmd_priv *pcmdpriv = &padapter->cmdpriv;3501u8 res = _SUCCESS;350235033504ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));3505if (ph2c == NULL) {3506res = _FAIL;3507goto exit;3508}35093510pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));3511if (pdrvextra_cmd_parm == NULL) {3512rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));3513res = _FAIL;3514goto exit;3515}35163517pdrvextra_cmd_parm->ec_id = DM_IN_LPS_WK_CID;3518pdrvextra_cmd_parm->type = 0;3519pdrvextra_cmd_parm->size = 0;3520pdrvextra_cmd_parm->pbuf = NULL;35213522init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));35233524res = rtw_enqueue_cmd(pcmdpriv, ph2c);35253526exit:35273528return res;35293530}35313532void rtw_lps_change_dtim_hdl(_adapter *padapter, u8 dtim)3533{3534struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);35353536if (dtim <= 0 || dtim > 16)3537return;35383539#ifdef CONFIG_BT_COEXIST3540if (rtw_btcoex_IsBtControlLps(padapter) == _TRUE)3541return;3542#endif35433544#ifdef CONFIG_LPS_LCLK3545_enter_pwrlock(&pwrpriv->lock);3546#endif35473548if (pwrpriv->dtim != dtim) {3549RTW_INFO("change DTIM from %d to %d, bFwCurrentInPSMode=%d, ps_mode=%d\n", pwrpriv->dtim, dtim,3550pwrpriv->bFwCurrentInPSMode, pwrpriv->pwr_mode);35513552pwrpriv->dtim = dtim;3553}35543555if ((pwrpriv->bFwCurrentInPSMode == _TRUE) && (pwrpriv->pwr_mode > PS_MODE_ACTIVE)) {3556u8 ps_mode = pwrpriv->pwr_mode;35573558/* RTW_INFO("change DTIM from %d to %d, ps_mode=%d\n", pwrpriv->dtim, dtim, ps_mode); */35593560rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));3561}35623563#ifdef CONFIG_LPS_LCLK3564_exit_pwrlock(&pwrpriv->lock);3565#endif35663567}35683569#endif35703571u8 rtw_lps_change_dtim_cmd(_adapter *padapter, u8 dtim)3572{3573struct cmd_obj *ph2c;3574struct drvextra_cmd_parm *pdrvextra_cmd_parm;3575struct cmd_priv *pcmdpriv = &padapter->cmdpriv;3576u8 res = _SUCCESS;3577/*3578#ifdef CONFIG_CONCURRENT_MODE3579if (padapter->hw_port != HW_PORT0)3580return res;3581#endif3582*/3583{3584ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));3585if (ph2c == NULL) {3586res = _FAIL;3587goto exit;3588}35893590pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));3591if (pdrvextra_cmd_parm == NULL) {3592rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));3593res = _FAIL;3594goto exit;3595}35963597pdrvextra_cmd_parm->ec_id = LPS_CHANGE_DTIM_CID;3598pdrvextra_cmd_parm->type = dtim;3599pdrvextra_cmd_parm->size = 0;3600pdrvextra_cmd_parm->pbuf = NULL;36013602init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));36033604res = rtw_enqueue_cmd(pcmdpriv, ph2c);3605}36063607exit:36083609return res;36103611}36123613#if (RATE_ADAPTIVE_SUPPORT == 1)3614void rpt_timer_setting_wk_hdl(_adapter *padapter, u16 minRptTime)3615{3616rtw_hal_set_hwreg(padapter, HW_VAR_RPT_TIMER_SETTING, (u8 *)(&minRptTime));3617}36183619u8 rtw_rpt_timer_cfg_cmd(_adapter *padapter, u16 minRptTime)3620{3621struct cmd_obj *ph2c;3622struct drvextra_cmd_parm *pdrvextra_cmd_parm;3623struct cmd_priv *pcmdpriv = &padapter->cmdpriv;36243625u8 res = _SUCCESS;36263627ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));3628if (ph2c == NULL) {3629res = _FAIL;3630goto exit;3631}36323633pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));3634if (pdrvextra_cmd_parm == NULL) {3635rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));3636res = _FAIL;3637goto exit;3638}36393640pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID;3641pdrvextra_cmd_parm->type = minRptTime;3642pdrvextra_cmd_parm->size = 0;3643pdrvextra_cmd_parm->pbuf = NULL;3644init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));3645res = rtw_enqueue_cmd(pcmdpriv, ph2c);3646exit:364736483649return res;36503651}36523653#endif36543655#ifdef CONFIG_ANTENNA_DIVERSITY3656void antenna_select_wk_hdl(_adapter *padapter, u8 antenna)3657{3658rtw_hal_set_odm_var(padapter, HAL_ODM_ANTDIV_SELECT, &antenna, _TRUE);3659}36603661u8 rtw_antenna_select_cmd(_adapter *padapter, u8 antenna, u8 enqueue)3662{3663struct cmd_obj *ph2c;3664struct drvextra_cmd_parm *pdrvextra_cmd_parm;3665struct cmd_priv *pcmdpriv = &padapter->cmdpriv;3666struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);3667u8 bSupportAntDiv = _FALSE;3668u8 res = _SUCCESS;3669int i;36703671rtw_hal_get_def_var(padapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &(bSupportAntDiv));3672if (_FALSE == bSupportAntDiv)3673return _FAIL;36743675for (i = 0; i < dvobj->iface_nums; i++) {3676if (rtw_linked_check(dvobj->padapters[i]))3677return _FAIL;3678}36793680if (_TRUE == enqueue) {3681ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));3682if (ph2c == NULL) {3683res = _FAIL;3684goto exit;3685}36863687pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));3688if (pdrvextra_cmd_parm == NULL) {3689rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));3690res = _FAIL;3691goto exit;3692}36933694pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID;3695pdrvextra_cmd_parm->type = antenna;3696pdrvextra_cmd_parm->size = 0;3697pdrvextra_cmd_parm->pbuf = NULL;3698init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));36993700res = rtw_enqueue_cmd(pcmdpriv, ph2c);3701} else3702antenna_select_wk_hdl(padapter, antenna);3703exit:370437053706return res;37073708}3709#endif37103711void rtw_dm_ra_mask_hdl(_adapter *padapter, struct sta_info *psta)3712{3713if (psta)3714set_sta_rate(padapter, psta);3715}37163717u8 rtw_dm_ra_mask_wk_cmd(_adapter *padapter, u8 *psta)3718{3719struct cmd_obj *ph2c;3720struct drvextra_cmd_parm *pdrvextra_cmd_parm;3721struct cmd_priv *pcmdpriv = &padapter->cmdpriv;3722u8 res = _SUCCESS;372337243725ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));3726if (ph2c == NULL) {3727res = _FAIL;3728goto exit;3729}37303731pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));3732if (pdrvextra_cmd_parm == NULL) {3733rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));3734res = _FAIL;3735goto exit;3736}37373738pdrvextra_cmd_parm->ec_id = DM_RA_MSK_WK_CID;3739pdrvextra_cmd_parm->type = 0;3740pdrvextra_cmd_parm->size = 0;3741pdrvextra_cmd_parm->pbuf = psta;37423743init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));37443745res = rtw_enqueue_cmd(pcmdpriv, ph2c);37463747exit:37483749return res;37503751}37523753void power_saving_wk_hdl(_adapter *padapter)3754{3755rtw_ps_processor(padapter);3756}37573758/* add for CONFIG_IEEE80211W, none 11w can use it */3759void reset_securitypriv_hdl(_adapter *padapter)3760{3761rtw_reset_securitypriv(padapter);3762}37633764#ifdef CONFIG_P2P3765u8 p2p_protocol_wk_cmd(_adapter *padapter, int intCmdType)3766{3767struct cmd_obj *ph2c;3768struct drvextra_cmd_parm *pdrvextra_cmd_parm;3769struct wifidirect_info *pwdinfo = &(padapter->wdinfo);3770struct cmd_priv *pcmdpriv = &padapter->cmdpriv;3771u8 res = _SUCCESS;377237733774if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))3775return res;37763777ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));3778if (ph2c == NULL) {3779res = _FAIL;3780goto exit;3781}37823783pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));3784if (pdrvextra_cmd_parm == NULL) {3785rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));3786res = _FAIL;3787goto exit;3788}37893790pdrvextra_cmd_parm->ec_id = P2P_PROTO_WK_CID;3791pdrvextra_cmd_parm->type = intCmdType; /* As the command tppe. */3792pdrvextra_cmd_parm->size = 0;3793pdrvextra_cmd_parm->pbuf = NULL; /* Must be NULL here */37943795init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));37963797res = rtw_enqueue_cmd(pcmdpriv, ph2c);37983799exit:380038013802return res;38033804}38053806#ifdef CONFIG_IOCTL_CFG802113807static u8 _p2p_roch_cmd(_adapter *adapter3808, u64 cookie, struct wireless_dev *wdev3809, struct ieee80211_channel *ch, enum nl80211_channel_type ch_type3810, unsigned int duration3811, u8 flags3812)3813{3814struct cmd_obj *cmdobj;3815struct drvextra_cmd_parm *parm;3816struct p2p_roch_parm *roch_parm;3817struct cmd_priv *pcmdpriv = &adapter->cmdpriv;3818struct submit_ctx sctx;3819u8 cancel = duration ? 0 : 1;3820u8 res = _SUCCESS;38213822roch_parm = (struct p2p_roch_parm *)rtw_zmalloc(sizeof(struct p2p_roch_parm));3823if (roch_parm == NULL) {3824res = _FAIL;3825goto exit;3826}38273828roch_parm->cookie = cookie;3829roch_parm->wdev = wdev;3830if (!cancel) {3831_rtw_memcpy(&roch_parm->ch, ch, sizeof(struct ieee80211_channel));3832roch_parm->ch_type = ch_type;3833roch_parm->duration = duration;3834}38353836if (flags & RTW_CMDF_DIRECTLY) {3837/* no need to enqueue, do the cmd hdl directly and free cmd parameter */3838if (H2C_SUCCESS != p2p_protocol_wk_hdl(adapter, cancel ? P2P_CANCEL_RO_CH_WK : P2P_RO_CH_WK, (u8 *)roch_parm))3839res = _FAIL;3840rtw_mfree((u8 *)roch_parm, sizeof(*roch_parm));3841} else {3842/* need enqueue, prepare cmd_obj and enqueue */3843parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));3844if (parm == NULL) {3845rtw_mfree((u8 *)roch_parm, sizeof(*roch_parm));3846res = _FAIL;3847goto exit;3848}38493850parm->ec_id = P2P_PROTO_WK_CID;3851parm->type = cancel ? P2P_CANCEL_RO_CH_WK : P2P_RO_CH_WK;3852parm->size = sizeof(*roch_parm);3853parm->pbuf = (u8 *)roch_parm;38543855cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));3856if (cmdobj == NULL) {3857res = _FAIL;3858rtw_mfree((u8 *)roch_parm, sizeof(*roch_parm));3859rtw_mfree((u8 *)parm, sizeof(*parm));3860goto exit;3861}38623863init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_Set_Drv_Extra));38643865if (flags & RTW_CMDF_WAIT_ACK) {3866cmdobj->sctx = &sctx;3867rtw_sctx_init(&sctx, 10 * 1000);3868}38693870res = rtw_enqueue_cmd(pcmdpriv, cmdobj);38713872if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {3873rtw_sctx_wait(&sctx, __func__);3874_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);3875if (sctx.status == RTW_SCTX_SUBMITTED)3876cmdobj->sctx = NULL;3877_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);3878if (sctx.status != RTW_SCTX_DONE_SUCCESS)3879res = _FAIL;3880}3881}38823883exit:3884return res;3885}38863887inline u8 p2p_roch_cmd(_adapter *adapter3888, u64 cookie, struct wireless_dev *wdev3889, struct ieee80211_channel *ch, enum nl80211_channel_type ch_type3890, unsigned int duration3891, u8 flags3892)3893{3894return _p2p_roch_cmd(adapter, cookie, wdev, ch, ch_type, duration, flags);3895}38963897inline u8 p2p_cancel_roch_cmd(_adapter *adapter, u64 cookie, struct wireless_dev *wdev, u8 flags)3898{3899return _p2p_roch_cmd(adapter, cookie, wdev, NULL, 0, 0, flags);3900}39013902#endif /* CONFIG_IOCTL_CFG80211 */3903#endif /* CONFIG_P2P */39043905#ifdef CONFIG_IOCTL_CFG802113906inline u8 rtw_mgnt_tx_cmd(_adapter *adapter, u8 tx_ch, u8 no_cck, const u8 *buf, size_t len, int wait_ack, u8 flags)3907{3908struct cmd_obj *cmdobj;3909struct drvextra_cmd_parm *parm;3910struct mgnt_tx_parm *mgnt_parm;3911struct cmd_priv *pcmdpriv = &adapter->cmdpriv;3912struct submit_ctx sctx;3913u8 res = _SUCCESS;39143915mgnt_parm = (struct mgnt_tx_parm *)rtw_zmalloc(sizeof(struct mgnt_tx_parm));3916if (mgnt_parm == NULL) {3917res = _FAIL;3918goto exit;3919}39203921mgnt_parm->tx_ch = tx_ch;3922mgnt_parm->no_cck = no_cck;3923mgnt_parm->buf = buf;3924mgnt_parm->len = len;3925mgnt_parm->wait_ack = wait_ack;39263927if (flags & RTW_CMDF_DIRECTLY) {3928/* no need to enqueue, do the cmd hdl directly and free cmd parameter */3929if (H2C_SUCCESS != rtw_mgnt_tx_handler(adapter, (u8 *)mgnt_parm))3930res = _FAIL;3931rtw_mfree((u8 *)mgnt_parm, sizeof(*mgnt_parm));3932} else {3933/* need enqueue, prepare cmd_obj and enqueue */3934parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));3935if (parm == NULL) {3936rtw_mfree((u8 *)mgnt_parm, sizeof(*mgnt_parm));3937res = _FAIL;3938goto exit;3939}39403941parm->ec_id = MGNT_TX_WK_CID;3942parm->type = 0;3943parm->size = sizeof(*mgnt_parm);3944parm->pbuf = (u8 *)mgnt_parm;39453946cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));3947if (cmdobj == NULL) {3948res = _FAIL;3949rtw_mfree((u8 *)mgnt_parm, sizeof(*mgnt_parm));3950rtw_mfree((u8 *)parm, sizeof(*parm));3951goto exit;3952}39533954init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_Set_Drv_Extra));39553956if (flags & RTW_CMDF_WAIT_ACK) {3957cmdobj->sctx = &sctx;3958rtw_sctx_init(&sctx, 10 * 1000);3959}39603961res = rtw_enqueue_cmd(pcmdpriv, cmdobj);39623963if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {3964rtw_sctx_wait(&sctx, __func__);3965_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);3966if (sctx.status == RTW_SCTX_SUBMITTED)3967cmdobj->sctx = NULL;3968_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);3969if (sctx.status != RTW_SCTX_DONE_SUCCESS)3970res = _FAIL;3971}3972}39733974exit:3975return res;3976}3977#endif39783979u8 rtw_ps_cmd(_adapter *padapter)3980{3981struct cmd_obj *ppscmd;3982struct drvextra_cmd_parm *pdrvextra_cmd_parm;3983struct cmd_priv *pcmdpriv = &padapter->cmdpriv;39843985u8 res = _SUCCESS;39863987#ifdef CONFIG_CONCURRENT_MODE3988if (!is_primary_adapter(padapter))3989goto exit;3990#endif39913992ppscmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));3993if (ppscmd == NULL) {3994res = _FAIL;3995goto exit;3996}39973998pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));3999if (pdrvextra_cmd_parm == NULL) {4000rtw_mfree((unsigned char *)ppscmd, sizeof(struct cmd_obj));4001res = _FAIL;4002goto exit;4003}40044005pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;4006pdrvextra_cmd_parm->type = 0;4007pdrvextra_cmd_parm->size = 0;4008pdrvextra_cmd_parm->pbuf = NULL;4009init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));40104011res = rtw_enqueue_cmd(pcmdpriv, ppscmd);40124013exit:401440154016return res;40174018}40194020#ifdef CONFIG_DFS4021void rtw_dfs_ch_switch_hdl(struct dvobj_priv *dvobj)4022{4023struct rf_ctl_t *rfctl = dvobj_to_rfctl(dvobj);4024_adapter *pri_adapter = dvobj_get_primary_adapter(dvobj);4025u8 ifbmp_m = rtw_mi_get_ap_mesh_ifbmp(pri_adapter);4026u8 ifbmp_s = rtw_mi_get_ld_sta_ifbmp(pri_adapter);4027s16 req_ch;40284029rtw_hal_macid_sleep_all_used(pri_adapter);40304031if (rtw_chset_search_ch(rfctl->channel_set, rfctl->csa_ch) >= 04032&& !rtw_chset_is_ch_non_ocp(rfctl->channel_set, rfctl->csa_ch)4033) {4034/* CSA channel available and valid */4035req_ch = rfctl->csa_ch;4036RTW_INFO("%s valid CSA ch%u\n", __func__, rfctl->csa_ch);4037} else if (ifbmp_m) {4038/* no available or valid CSA channel, having AP/MESH ifaces */4039req_ch = REQ_CH_NONE;4040RTW_INFO("%s ch sel by AP/MESH ifaces\n", __func__);4041} else {4042/* no available or valid CSA channel and no AP/MESH ifaces */4043if (!IsSupported24G(dvobj_to_regsty(dvobj)->wireless_mode)4044#ifdef CONFIG_DFS_MASTER4045|| rfctl->radar_detected4046#endif4047)4048req_ch = 36;4049else4050req_ch = 1;4051RTW_INFO("%s switch to ch%d\n", __func__, req_ch);4052}40534054/* issue deauth for all asoc STA ifaces */4055if (ifbmp_s) {4056_adapter *iface;4057int i;40584059for (i = 0; i < dvobj->iface_nums; i++) {4060iface = dvobj->padapters[i];4061if (!iface || !(ifbmp_s & BIT(iface->iface_id)))4062continue;4063set_fwstate(&iface->mlmepriv, WIFI_OP_CH_SWITCHING);40644065/* TODO: true op ch switching */4066issue_deauth(iface, get_bssid(&iface->mlmepriv), WLAN_REASON_DEAUTH_LEAVING);4067}4068}40694070#ifdef CONFIG_AP_MODE4071if (ifbmp_m) {4072/* trigger channel selection without consideraton of asoc STA ifaces */4073rtw_change_bss_chbw_cmd(dvobj_get_primary_adapter(dvobj), RTW_CMDF_DIRECTLY4074, ifbmp_m, ifbmp_s, req_ch, REQ_BW_ORI, REQ_OFFSET_NONE);4075} else4076#endif4077{4078/* no AP/MESH iface, switch DFS status and channel directly */4079rtw_warn_on(req_ch <= 0);4080#ifdef CONFIG_DFS_MASTER4081rtw_dfs_rd_en_decision(pri_adapter, MLME_OPCH_SWITCH, ifbmp_s);4082#endif4083set_channel_bwmode(pri_adapter, req_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);4084}40854086/* make asoc STA ifaces disconnect */4087/* TODO: true op ch switching */4088if (ifbmp_s) {4089_adapter *iface;4090int i;40914092for (i = 0; i < dvobj->iface_nums; i++) {4093iface = dvobj->padapters[i];4094if (!iface || !(ifbmp_s & BIT(iface->iface_id)))4095continue;4096rtw_disassoc_cmd(iface, 0, RTW_CMDF_DIRECTLY);4097rtw_indicate_disconnect(iface, 0, _FALSE);4098rtw_free_assoc_resources(iface, _TRUE);4099rtw_free_network_queue(iface, _TRUE);4100}4101}41024103rfctl->csa_ch = 0;41044105rtw_hal_macid_wakeup_all_used(pri_adapter);4106rtw_mi_os_xmit_schedule(pri_adapter);4107}4108#endif /* CONFIG_DFS */41094110#ifdef CONFIG_AP_MODE41114112static void rtw_chk_hi_queue_hdl(_adapter *padapter)4113{4114struct sta_info *psta_bmc;4115struct sta_priv *pstapriv = &padapter->stapriv;4116systime start = rtw_get_current_time();4117u8 empty = _FALSE;41184119psta_bmc = rtw_get_bcmc_stainfo(padapter);4120if (!psta_bmc)4121return;41224123rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);41244125while (_FALSE == empty && rtw_get_passing_time_ms(start) < rtw_get_wait_hiq_empty_ms()) {4126rtw_msleep_os(100);4127rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);4128}41294130if (psta_bmc->sleepq_len == 0) {4131if (empty == _SUCCESS) {4132bool update_tim = _FALSE;41334134if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0))4135update_tim = _TRUE;41364137rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, 0);4138rtw_tim_map_clear(padapter, pstapriv->sta_dz_bitmap, 0);41394140if (update_tim == _TRUE)4141_update_beacon(padapter, _TIM_IE_, NULL, _TRUE, 0,"bmc sleepq and HIQ empty");4142} else /* re check again */4143rtw_chk_hi_queue_cmd(padapter);41444145}41464147}41484149u8 rtw_chk_hi_queue_cmd(_adapter *padapter)4150{4151struct cmd_obj *ph2c;4152struct drvextra_cmd_parm *pdrvextra_cmd_parm;4153struct cmd_priv *pcmdpriv = &padapter->cmdpriv;4154u8 res = _SUCCESS;41554156ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));4157if (ph2c == NULL) {4158res = _FAIL;4159goto exit;4160}41614162pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));4163if (pdrvextra_cmd_parm == NULL) {4164rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));4165res = _FAIL;4166goto exit;4167}41684169pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;4170pdrvextra_cmd_parm->type = 0;4171pdrvextra_cmd_parm->size = 0;4172pdrvextra_cmd_parm->pbuf = NULL;41734174init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));41754176res = rtw_enqueue_cmd(pcmdpriv, ph2c);41774178exit:41794180return res;41814182}41834184#ifdef CONFIG_DFS_MASTER4185u8 rtw_dfs_rd_hdl(_adapter *adapter)4186{4187struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);4188struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);41894190if (!rfctl->radar_detect_enabled)4191goto exit;41924193if (dvobj->oper_channel != rfctl->radar_detect_ch4194|| rtw_get_passing_time_ms(rtw_get_on_oper_ch_time(adapter)) < 3004195) {4196/* offchannel, bypass radar detect */4197goto cac_status_chk;4198}41994200if (IS_CH_WAITING(rfctl) && !IS_UNDER_CAC(rfctl)) {4201/* non_ocp, bypass radar detect */4202goto cac_status_chk;4203}42044205if (!rfctl->dbg_dfs_fake_radar_detect_cnt4206&& rtw_odm_radar_detect(adapter) != _TRUE)4207goto cac_status_chk;42084209if (!rfctl->dbg_dfs_fake_radar_detect_cnt4210&& rfctl->dbg_dfs_radar_detect_trigger_non4211) {4212/* radar detect debug mode, trigger no mlme flow */4213RTW_INFO("%s radar detected on test mode, trigger no mlme flow\n", __func__);4214goto cac_status_chk;4215}42164217if (rfctl->dbg_dfs_fake_radar_detect_cnt != 0) {4218RTW_INFO("%s fake radar detected, cnt:%d\n", __func__4219, rfctl->dbg_dfs_fake_radar_detect_cnt);4220rfctl->dbg_dfs_fake_radar_detect_cnt--;4221} else4222RTW_INFO("%s radar detected\n", __func__);42234224rfctl->radar_detected = 1;42254226rtw_chset_update_non_ocp(rfctl->channel_set4227, rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset);42284229rtw_dfs_ch_switch_hdl(dvobj);42304231if (rfctl->radar_detect_enabled)4232goto set_timer;4233goto exit;42344235cac_status_chk:42364237if (!IS_CAC_STOPPED(rfctl)4238&& ((IS_UNDER_CAC(rfctl) && rfctl->cac_force_stop)4239|| !IS_CH_WAITING(rfctl)4240)4241) {4242u8 pause = 0x00;42434244rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);4245rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;42464247if (rtw_mi_check_fwstate(adapter, WIFI_UNDER_LINKING|WIFI_SITE_MONITOR) == _FALSE) {4248u8 doiqk = _TRUE;4249u8 u_ch, u_bw, u_offset;42504251rtw_hal_set_hwreg(adapter , HW_VAR_DO_IQK , &doiqk);42524253if (rtw_mi_get_ch_setting_union(adapter, &u_ch, &u_bw, &u_offset))4254set_channel_bwmode(adapter, u_ch, u_offset, u_bw);4255else4256rtw_warn_on(1);42574258doiqk = _FALSE;4259rtw_hal_set_hwreg(adapter , HW_VAR_DO_IQK , &doiqk);42604261ResumeTxBeacon(adapter);4262rtw_mi_tx_beacon_hdl(adapter);4263}4264}42654266set_timer:4267_set_timer(&rfctl->radar_detect_timer4268, rtw_odm_radar_detect_polling_int_ms(dvobj));42694270exit:4271return H2C_SUCCESS;4272}42734274u8 rtw_dfs_rd_cmd(_adapter *adapter, bool enqueue)4275{4276struct cmd_obj *cmdobj;4277struct drvextra_cmd_parm *parm;4278struct cmd_priv *cmdpriv = &adapter->cmdpriv;4279u8 res = _FAIL;42804281if (enqueue) {4282cmdobj = rtw_zmalloc(sizeof(struct cmd_obj));4283if (cmdobj == NULL)4284goto exit;42854286parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));4287if (parm == NULL) {4288rtw_mfree(cmdobj, sizeof(struct cmd_obj));4289goto exit;4290}42914292parm->ec_id = DFS_RADAR_DETECT_WK_CID;4293parm->type = 0;4294parm->size = 0;4295parm->pbuf = NULL;42964297init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_Set_Drv_Extra));4298res = rtw_enqueue_cmd(cmdpriv, cmdobj);4299} else {4300rtw_dfs_rd_hdl(adapter);4301res = _SUCCESS;4302}43034304exit:4305return res;4306}43074308void rtw_dfs_rd_timer_hdl(void *ctx)4309{4310struct rf_ctl_t *rfctl = (struct rf_ctl_t *)ctx;4311struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl);43124313rtw_dfs_rd_cmd(dvobj_get_primary_adapter(dvobj), _TRUE);4314}43154316static void rtw_dfs_rd_enable(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset, bool bypass_cac)4317{4318struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl);4319_adapter *adapter = dvobj_get_primary_adapter(dvobj);43204321RTW_INFO("%s on %u,%u,%u\n", __func__, ch, bw, offset);43224323if (bypass_cac)4324rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;4325else if (rtw_is_cac_reset_needed(rfctl, ch, bw, offset) == _TRUE)4326rtw_reset_cac(rfctl, ch, bw, offset);43274328rfctl->radar_detect_by_others = _FALSE;4329rfctl->radar_detect_ch = ch;4330rfctl->radar_detect_bw = bw;4331rfctl->radar_detect_offset = offset;43324333rfctl->radar_detected = 0;43344335if (IS_CH_WAITING(rfctl))4336StopTxBeacon(adapter);43374338if (!rfctl->radar_detect_enabled) {4339RTW_INFO("%s set radar_detect_enabled\n", __func__);4340rfctl->radar_detect_enabled = 1;4341#ifdef CONFIG_LPS4342LPS_Leave(adapter, "RADAR_DETECT_EN");4343#endif4344_set_timer(&rfctl->radar_detect_timer4345, rtw_odm_radar_detect_polling_int_ms(dvobj));43464347if (rtw_rfctl_overlap_radar_detect_ch(rfctl)) {4348if (IS_CH_WAITING(rfctl)) {4349u8 pause = 0xFF;43504351rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);4352}4353rtw_odm_radar_detect_enable(adapter);4354}4355}4356}43574358static void rtw_dfs_rd_disable(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset, bool by_others)4359{4360_adapter *adapter = dvobj_get_primary_adapter(rfctl_to_dvobj(rfctl));43614362rfctl->radar_detect_by_others = by_others;43634364if (rfctl->radar_detect_enabled) {4365bool overlap_radar_detect_ch = rtw_rfctl_overlap_radar_detect_ch(rfctl);43664367RTW_INFO("%s clear radar_detect_enabled\n", __func__);43684369rfctl->radar_detect_enabled = 0;4370rfctl->radar_detected = 0;4371rfctl->radar_detect_ch = 0;4372rfctl->radar_detect_bw = 0;4373rfctl->radar_detect_offset = 0;4374rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;4375_cancel_timer_ex(&rfctl->radar_detect_timer);43764377if (rtw_mi_check_fwstate(adapter, WIFI_UNDER_LINKING|WIFI_SITE_MONITOR) == _FALSE) {4378ResumeTxBeacon(adapter);4379rtw_mi_tx_beacon_hdl(adapter);4380}43814382if (overlap_radar_detect_ch) {4383u8 pause = 0x00;43844385rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);4386rtw_odm_radar_detect_disable(adapter);4387}4388}43894390if (by_others) {4391rfctl->radar_detect_ch = ch;4392rfctl->radar_detect_bw = bw;4393rfctl->radar_detect_offset = offset;4394}4395}43964397void rtw_dfs_rd_en_decision(_adapter *adapter, u8 mlme_act, u8 excl_ifbmp)4398{4399struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);4400struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);4401struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;4402struct mi_state mstate;4403u8 ifbmp;4404u8 u_ch, u_bw, u_offset;4405bool ld_sta_in_dfs = _FALSE;4406bool sync_ch = _FALSE; /* _FALSE: asign channel directly */4407bool needed = _FALSE;44084409if (mlme_act == MLME_OPCH_SWITCH4410|| mlme_act == MLME_ACTION_NONE4411) {4412ifbmp = ~excl_ifbmp;4413rtw_mi_status_by_ifbmp(dvobj, ifbmp, &mstate);4414rtw_mi_get_ch_setting_union_by_ifbmp(dvobj, ifbmp, &u_ch, &u_bw, &u_offset);4415} else {4416ifbmp = ~excl_ifbmp & ~BIT(adapter->iface_id);4417rtw_mi_status_by_ifbmp(dvobj, ifbmp, &mstate);4418rtw_mi_get_ch_setting_union_by_ifbmp(dvobj, ifbmp, &u_ch, &u_bw, &u_offset);4419if (u_ch != 0)4420sync_ch = _TRUE;44214422switch (mlme_act) {4423case MLME_STA_CONNECTING:4424MSTATE_STA_LG_NUM(&mstate)++;4425break;4426case MLME_STA_CONNECTED:4427MSTATE_STA_LD_NUM(&mstate)++;4428break;4429case MLME_STA_DISCONNECTED:4430break;4431#ifdef CONFIG_AP_MODE4432case MLME_AP_STARTED:4433MSTATE_AP_NUM(&mstate)++;4434break;4435case MLME_AP_STOPPED:4436break;4437#endif4438#ifdef CONFIG_RTW_MESH4439case MLME_MESH_STARTED:4440MSTATE_MESH_NUM(&mstate)++;4441break;4442case MLME_MESH_STOPPED:4443break;4444#endif4445default:4446rtw_warn_on(1);4447break;4448}44494450if (sync_ch == _TRUE) {4451if (!MLME_IS_OPCH_SW(adapter)) {4452if (!rtw_is_chbw_grouped(mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset, u_ch, u_bw, u_offset)) {4453RTW_INFO(FUNC_ADPT_FMT" can't sync %u,%u,%u with %u,%u,%u\n", FUNC_ADPT_ARG(adapter)4454, mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset, u_ch, u_bw, u_offset);4455goto apply;4456}44574458rtw_sync_chbw(&mlmeext->cur_channel, &mlmeext->cur_bwmode, &mlmeext->cur_ch_offset4459, &u_ch, &u_bw, &u_offset);4460}4461} else {4462u_ch = mlmeext->cur_channel;4463u_bw = mlmeext->cur_bwmode;4464u_offset = mlmeext->cur_ch_offset;4465}4466}44674468if (MSTATE_STA_LG_NUM(&mstate) > 0) {4469/* STA mode is linking */4470goto apply;4471}44724473if (MSTATE_STA_LD_NUM(&mstate) > 0) {4474if (rtw_is_dfs_chbw(u_ch, u_bw, u_offset)) {4475/*4476* if operate as slave w/o radar detect,4477* rely on AP on which STA mode connects4478*/4479if (IS_DFS_SLAVE_WITH_RD(rfctl) && !rtw_odm_dfs_domain_unknown(dvobj))4480needed = _TRUE;4481ld_sta_in_dfs = _TRUE;4482}4483goto apply;4484}44854486if (!MSTATE_AP_NUM(&mstate) && !MSTATE_MESH_NUM(&mstate)) {4487/* No working AP/Mesh mode */4488goto apply;4489}44904491if (rtw_is_dfs_chbw(u_ch, u_bw, u_offset))4492needed = _TRUE;44934494apply:44954496RTW_INFO(FUNC_ADPT_FMT" needed:%d, mlme_act:%u, excl_ifbmp:0x%02x\n"4497, FUNC_ADPT_ARG(adapter), needed, mlme_act, excl_ifbmp);4498RTW_INFO(FUNC_ADPT_FMT" ld_sta_num:%u, lg_sta_num:%u, ap_num:%u, mesh_num:%u, %u,%u,%u\n"4499, FUNC_ADPT_ARG(adapter), MSTATE_STA_LD_NUM(&mstate), MSTATE_STA_LG_NUM(&mstate)4500, MSTATE_AP_NUM(&mstate), MSTATE_MESH_NUM(&mstate)4501, u_ch, u_bw, u_offset);45024503if (needed == _TRUE)4504rtw_dfs_rd_enable(rfctl, u_ch, u_bw, u_offset, ld_sta_in_dfs);4505else4506rtw_dfs_rd_disable(rfctl, u_ch, u_bw, u_offset, ld_sta_in_dfs);4507}45084509u8 rtw_dfs_rd_en_decision_cmd(_adapter *adapter)4510{4511struct cmd_obj *cmdobj;4512struct drvextra_cmd_parm *parm;4513struct cmd_priv *cmdpriv = &adapter->cmdpriv;4514u8 res = _FAIL;45154516cmdobj = rtw_zmalloc(sizeof(struct cmd_obj));4517if (cmdobj == NULL)4518goto exit;45194520parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));4521if (parm == NULL) {4522rtw_mfree(cmdobj, sizeof(struct cmd_obj));4523goto exit;4524}45254526parm->ec_id = DFS_RADAR_DETECT_EN_DEC_WK_CID;4527parm->type = 0;4528parm->size = 0;4529parm->pbuf = NULL;45304531init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_Set_Drv_Extra));4532res = rtw_enqueue_cmd(cmdpriv, cmdobj);45334534exit:4535return res;4536}4537#endif /* CONFIG_DFS_MASTER */45384539#endif /* CONFIG_AP_MODE */45404541#ifdef CONFIG_BT_COEXIST4542struct btinfo {4543u8 cid;4544u8 len;45454546u8 bConnection:1;4547u8 bSCOeSCO:1;4548u8 bInQPage:1;4549u8 bACLBusy:1;4550u8 bSCOBusy:1;4551u8 bHID:1;4552u8 bA2DP:1;4553u8 bFTP:1;45544555u8 retry_cnt:4;4556u8 rsvd_34:1;4557u8 rsvd_35:1;4558u8 rsvd_36:1;4559u8 rsvd_37:1;45604561u8 rssi;45624563u8 rsvd_50:1;4564u8 rsvd_51:1;4565u8 rsvd_52:1;4566u8 rsvd_53:1;4567u8 rsvd_54:1;4568u8 rsvd_55:1;4569u8 eSCO_SCO:1;4570u8 Master_Slave:1;45714572u8 rsvd_6;4573u8 rsvd_7;4574};45754576void btinfo_evt_dump(void *sel, void *buf)4577{4578struct btinfo *info = (struct btinfo *)buf;45794580RTW_PRINT_SEL(sel, "cid:0x%02x, len:%u\n", info->cid, info->len);45814582if (info->len > 2)4583RTW_PRINT_SEL(sel, "byte2:%s%s%s%s%s%s%s%s\n"4584, info->bConnection ? "bConnection " : ""4585, info->bSCOeSCO ? "bSCOeSCO " : ""4586, info->bInQPage ? "bInQPage " : ""4587, info->bACLBusy ? "bACLBusy " : ""4588, info->bSCOBusy ? "bSCOBusy " : ""4589, info->bHID ? "bHID " : ""4590, info->bA2DP ? "bA2DP " : ""4591, info->bFTP ? "bFTP" : ""4592);45934594if (info->len > 3)4595RTW_PRINT_SEL(sel, "retry_cnt:%u\n", info->retry_cnt);45964597if (info->len > 4)4598RTW_PRINT_SEL(sel, "rssi:%u\n", info->rssi);45994600if (info->len > 5)4601RTW_PRINT_SEL(sel, "byte5:%s%s\n"4602, info->eSCO_SCO ? "eSCO_SCO " : ""4603, info->Master_Slave ? "Master_Slave " : ""4604);4605}46064607static void rtw_btinfo_hdl(_adapter *adapter, u8 *buf, u16 buf_len)4608{4609#define BTINFO_WIFI_FETCH 0x234610#define BTINFO_BT_AUTO_RPT 0x274611#ifdef CONFIG_BT_COEXIST_SOCKET_TRX4612struct btinfo_8761ATV *info = (struct btinfo_8761ATV *)buf;4613#else /* !CONFIG_BT_COEXIST_SOCKET_TRX */4614struct btinfo *info = (struct btinfo *)buf;4615#endif /* CONFIG_BT_COEXIST_SOCKET_TRX */4616u8 cmd_idx;4617u8 len;46184619cmd_idx = info->cid;46204621if (info->len > buf_len - 2) {4622rtw_warn_on(1);4623len = buf_len - 2;4624} else4625len = info->len;46264627/* #define DBG_PROC_SET_BTINFO_EVT */4628#ifdef DBG_PROC_SET_BTINFO_EVT4629#ifdef CONFIG_BT_COEXIST_SOCKET_TRX4630RTW_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"4631, __func__, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);4632#else/* !CONFIG_BT_COEXIST_SOCKET_TRX */4633btinfo_evt_dump(RTW_DBGDUMP, info);4634#endif /* CONFIG_BT_COEXIST_SOCKET_TRX */4635#endif /* DBG_PROC_SET_BTINFO_EVT */46364637/* transform BT-FW btinfo to WiFI-FW C2H format and notify */4638if (cmd_idx == BTINFO_WIFI_FETCH)4639buf[1] = 0;4640else if (cmd_idx == BTINFO_BT_AUTO_RPT)4641buf[1] = 2;4642#ifdef CONFIG_BT_COEXIST_SOCKET_TRX4643else if (0x01 == cmd_idx || 0x02 == cmd_idx)4644buf[1] = buf[0];4645#endif /* CONFIG_BT_COEXIST_SOCKET_TRX */4646rtw_btcoex_BtInfoNotify(adapter , len + 1, &buf[1]);4647}46484649u8 rtw_btinfo_cmd(_adapter *adapter, u8 *buf, u16 len)4650{4651struct cmd_obj *ph2c;4652struct drvextra_cmd_parm *pdrvextra_cmd_parm;4653u8 *btinfo;4654struct cmd_priv *pcmdpriv = &adapter->cmdpriv;4655u8 res = _SUCCESS;46564657ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));4658if (ph2c == NULL) {4659res = _FAIL;4660goto exit;4661}46624663pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));4664if (pdrvextra_cmd_parm == NULL) {4665rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));4666res = _FAIL;4667goto exit;4668}46694670btinfo = rtw_zmalloc(len);4671if (btinfo == NULL) {4672rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));4673rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));4674res = _FAIL;4675goto exit;4676}46774678pdrvextra_cmd_parm->ec_id = BTINFO_WK_CID;4679pdrvextra_cmd_parm->type = 0;4680pdrvextra_cmd_parm->size = len;4681pdrvextra_cmd_parm->pbuf = btinfo;46824683_rtw_memcpy(btinfo, buf, len);46844685init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));46864687res = rtw_enqueue_cmd(pcmdpriv, ph2c);46884689exit:4690return res;4691}46924693static void rtw_btc_reduce_wl_txpwr_hdl(_adapter *adapter, u32 pwr_lvl)4694{4695rtw_btcoex_set_reduced_wl_pwr_lvl(adapter, pwr_lvl);4696rtw_btcoex_do_reduce_wl_pwr_lvl(adapter);46974698RTW_INFO(FUNC_ADPT_FMT ": BTC reduce WL TxPwr %d dB!\n",4699FUNC_ADPT_ARG(adapter), pwr_lvl);4700}47014702u8 rtw_btc_reduce_wl_txpwr_cmd(_adapter *adapter, u32 val)4703{4704struct cmd_obj *pcmdobj;4705struct drvextra_cmd_parm *pdrvextra_cmd_parm;4706struct cmd_priv *pcmdpriv = &adapter->cmdpriv;4707u8 res = _SUCCESS;47084709pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));4710if (pcmdobj == NULL) {4711res = _FAIL;4712goto exit;4713}47144715pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));4716if (pdrvextra_cmd_parm == NULL) {4717rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));4718res = _FAIL;4719goto exit;4720}47214722pdrvextra_cmd_parm->ec_id = BTC_REDUCE_WL_TXPWR_CID;4723pdrvextra_cmd_parm->type = val;4724pdrvextra_cmd_parm->size = 0;4725pdrvextra_cmd_parm->pbuf = NULL;47264727init_h2fwcmd_w_parm_no_rsp(pcmdobj, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));47284729res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);47304731exit:4732return res;4733}4734#endif /* CONFIG_BT_COEXIST */47354736u8 rtw_test_h2c_cmd(_adapter *adapter, u8 *buf, u8 len)4737{4738struct cmd_obj *pcmdobj;4739struct drvextra_cmd_parm *pdrvextra_cmd_parm;4740u8 *ph2c_content;4741struct cmd_priv *pcmdpriv = &adapter->cmdpriv;4742u8 res = _SUCCESS;47434744pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));4745if (pcmdobj == NULL) {4746res = _FAIL;4747goto exit;4748}47494750pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));4751if (pdrvextra_cmd_parm == NULL) {4752rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));4753res = _FAIL;4754goto exit;4755}47564757ph2c_content = rtw_zmalloc(len);4758if (ph2c_content == NULL) {4759rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));4760rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));4761res = _FAIL;4762goto exit;4763}47644765pdrvextra_cmd_parm->ec_id = TEST_H2C_CID;4766pdrvextra_cmd_parm->type = 0;4767pdrvextra_cmd_parm->size = len;4768pdrvextra_cmd_parm->pbuf = ph2c_content;47694770_rtw_memcpy(ph2c_content, buf, len);47714772init_h2fwcmd_w_parm_no_rsp(pcmdobj, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));47734774res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);47754776exit:4777return res;4778}47794780#ifdef CONFIG_MP_INCLUDED4781static s32 rtw_mp_cmd_hdl(_adapter *padapter, u8 mp_cmd_id)4782{4783HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);4784int ret = H2C_SUCCESS;4785uint status = _SUCCESS;47864787if (mp_cmd_id == MP_START) {4788if (padapter->registrypriv.mp_mode == 0) {4789rtw_intf_stop(padapter);4790rtw_hal_deinit(padapter);4791padapter->registrypriv.mp_mode = 1;4792#if (CONFIG_BTCOEX_SUPPORT_WIFI_ONLY_CFG == 1)4793padapter->mppriv.CureFuseBTCoex = pHalData->EEPROMBluetoothCoexist;4794pHalData->EEPROMBluetoothCoexist = _FALSE;4795#endif4796#ifdef CONFIG_RF_POWER_TRIM4797if (!IS_HARDWARE_TYPE_8814A(padapter) && !IS_HARDWARE_TYPE_8822B(padapter) && !IS_HARDWARE_TYPE_8822C(padapter)) {4798padapter->registrypriv.RegPwrTrimEnable = 1;4799rtw_hal_read_chip_info(padapter);4800}4801#endif /*CONFIG_RF_POWER_TRIM*/4802rtw_reset_drv_sw(padapter);4803#ifdef CONFIG_NEW_NETDEV_HDL4804if (!rtw_is_hw_init_completed(padapter)) {4805status = rtw_hal_init(padapter);4806if (status == _FAIL) {4807ret = H2C_REJECTED;4808goto exit;4809}4810rtw_hal_iface_init(padapter);4811}4812#else4813status = rtw_hal_init(padapter);4814if (status == _FAIL) {4815ret = H2C_REJECTED;4816goto exit;4817}4818#endif /*CONFIG_NEW_NETDEV_HDL*/4819#ifndef RTW_HALMAC4820rtw_intf_start(padapter);4821#endif /* !RTW_HALMAC */4822#ifdef RTW_HALMAC /*for New IC*/4823MPT_InitializeAdapter(padapter, 1);4824#endif /* CONFIG_MP_INCLUDED */4825}48264827if (padapter->registrypriv.mp_mode == 0) {4828ret = H2C_REJECTED;4829goto exit;4830}48314832if (padapter->mppriv.mode == MP_OFF) {4833if (mp_start_test(padapter) == _FAIL) {4834ret = H2C_REJECTED;4835goto exit;4836}4837padapter->mppriv.mode = MP_ON;4838MPT_PwrCtlDM(padapter, 0);4839}4840padapter->mppriv.bmac_filter = _FALSE;4841#ifdef CONFIG_RTL8723B4842#ifdef CONFIG_USB_HCI4843rtw_write32(padapter, 0x765, 0x0000);4844rtw_write32(padapter, 0x948, 0x0280);4845#else4846rtw_write32(padapter, 0x765, 0x0000);4847rtw_write32(padapter, 0x948, 0x0000);4848#endif4849#ifdef CONFIG_FOR_RTL8723BS_VQ04850rtw_write32(padapter, 0x765, 0x0000);4851rtw_write32(padapter, 0x948, 0x0280);4852#endif4853rtw_write8(padapter, 0x66, 0x27); /*Open BT uart Log*/4854rtw_write8(padapter, 0xc50, 0x20); /*for RX init Gain*/4855#endif4856odm_write_dig(&pHalData->odmpriv, 0x20);48574858} else if (mp_cmd_id == MP_STOP) {4859if (padapter->registrypriv.mp_mode == 1) {4860MPT_DeInitAdapter(padapter);4861rtw_intf_stop(padapter);4862rtw_hal_deinit(padapter);4863padapter->registrypriv.mp_mode = 0;4864#if (CONFIG_BTCOEX_SUPPORT_WIFI_ONLY_CFG == 1)4865pHalData->EEPROMBluetoothCoexist = padapter->mppriv.CureFuseBTCoex;4866#endif4867rtw_reset_drv_sw(padapter);4868#ifdef CONFIG_NEW_NETDEV_HDL4869if (!rtw_is_hw_init_completed(padapter)) {4870status = rtw_hal_init(padapter);4871if (status == _FAIL) {4872ret = H2C_REJECTED;4873goto exit;4874}4875rtw_hal_iface_init(padapter);4876}4877#else4878status = rtw_hal_init(padapter);4879if (status == _FAIL) {4880ret = H2C_REJECTED;4881goto exit;4882}4883#endif /*CONFIG_NEW_NETDEV_HDL*/4884#ifndef RTW_HALMAC4885rtw_intf_start(padapter);4886#endif /* !RTW_HALMAC */4887}48884889if (padapter->mppriv.mode != MP_OFF) {4890mp_stop_test(padapter);4891padapter->mppriv.mode = MP_OFF;4892}48934894} else {4895RTW_INFO(FUNC_ADPT_FMT"invalid id:%d\n", FUNC_ADPT_ARG(padapter), mp_cmd_id);4896ret = H2C_PARAMETERS_ERROR;4897rtw_warn_on(1);4898}48994900exit:4901return ret;4902}49034904u8 rtw_mp_cmd(_adapter *adapter, u8 mp_cmd_id, u8 flags)4905{4906struct cmd_obj *cmdobj;4907struct drvextra_cmd_parm *parm;4908struct cmd_priv *pcmdpriv = &adapter->cmdpriv;4909struct submit_ctx sctx;4910u8 res = _SUCCESS;49114912parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));4913if (parm == NULL) {4914res = _FAIL;4915goto exit;4916}49174918parm->ec_id = MP_CMD_WK_CID;4919parm->type = mp_cmd_id;4920parm->size = 0;4921parm->pbuf = NULL;49224923if (flags & RTW_CMDF_DIRECTLY) {4924/* no need to enqueue, do the cmd hdl directly and free cmd parameter */4925if (H2C_SUCCESS != rtw_mp_cmd_hdl(adapter, mp_cmd_id))4926res = _FAIL;4927rtw_mfree((u8 *)parm, sizeof(*parm));4928} else {4929/* need enqueue, prepare cmd_obj and enqueue */4930cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));4931if (cmdobj == NULL) {4932res = _FAIL;4933rtw_mfree((u8 *)parm, sizeof(*parm));4934goto exit;4935}49364937init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_Set_Drv_Extra));49384939if (flags & RTW_CMDF_WAIT_ACK) {4940cmdobj->sctx = &sctx;4941rtw_sctx_init(&sctx, 10 * 1000);4942}49434944res = rtw_enqueue_cmd(pcmdpriv, cmdobj);49454946if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {4947rtw_sctx_wait(&sctx, __func__);4948_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);4949if (sctx.status == RTW_SCTX_SUBMITTED)4950cmdobj->sctx = NULL;4951_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);4952if (sctx.status != RTW_SCTX_DONE_SUCCESS)4953res = _FAIL;4954}4955}49564957exit:4958return res;4959}4960#endif /*CONFIG_MP_INCLUDED*/49614962#ifdef CONFIG_RTW_CUSTOMER_STR4963static s32 rtw_customer_str_cmd_hdl(_adapter *adapter, u8 write, const u8 *cstr)4964{4965int ret = H2C_SUCCESS;49664967if (write)4968ret = rtw_hal_h2c_customer_str_write(adapter, cstr);4969else4970ret = rtw_hal_h2c_customer_str_req(adapter);49714972return ret == _SUCCESS ? H2C_SUCCESS : H2C_REJECTED;4973}49744975static u8 rtw_customer_str_cmd(_adapter *adapter, u8 write, const u8 *cstr)4976{4977struct cmd_obj *cmdobj;4978struct drvextra_cmd_parm *parm;4979u8 *str = NULL;4980struct cmd_priv *pcmdpriv = &adapter->cmdpriv;4981struct submit_ctx sctx;4982u8 res = _SUCCESS;49834984parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));4985if (parm == NULL) {4986res = _FAIL;4987goto exit;4988}49894990if (write) {4991str = rtw_zmalloc(RTW_CUSTOMER_STR_LEN);4992if (str == NULL) {4993rtw_mfree((u8 *)parm, sizeof(struct drvextra_cmd_parm));4994res = _FAIL;4995goto exit;4996}4997}49984999parm->ec_id = CUSTOMER_STR_WK_CID;5000parm->type = write;5001parm->size = write ? RTW_CUSTOMER_STR_LEN : 0;5002parm->pbuf = write ? str : NULL;50035004if (write)5005_rtw_memcpy(str, cstr, RTW_CUSTOMER_STR_LEN);50065007/* need enqueue, prepare cmd_obj and enqueue */5008cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));5009if (cmdobj == NULL) {5010res = _FAIL;5011rtw_mfree((u8 *)parm, sizeof(*parm));5012if (write)5013rtw_mfree(str, RTW_CUSTOMER_STR_LEN);5014goto exit;5015}50165017init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_Set_Drv_Extra));50185019cmdobj->sctx = &sctx;5020rtw_sctx_init(&sctx, 2 * 1000);50215022res = rtw_enqueue_cmd(pcmdpriv, cmdobj);50235024if (res == _SUCCESS) {5025rtw_sctx_wait(&sctx, __func__);5026_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);5027if (sctx.status == RTW_SCTX_SUBMITTED)5028cmdobj->sctx = NULL;5029_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);5030if (sctx.status != RTW_SCTX_DONE_SUCCESS)5031res = _FAIL;5032}50335034exit:5035return res;5036}50375038inline u8 rtw_customer_str_req_cmd(_adapter *adapter)5039{5040return rtw_customer_str_cmd(adapter, 0, NULL);5041}50425043inline u8 rtw_customer_str_write_cmd(_adapter *adapter, const u8 *cstr)5044{5045return rtw_customer_str_cmd(adapter, 1, cstr);5046}5047#endif /* CONFIG_RTW_CUSTOMER_STR */50485049u8 rtw_c2h_wk_cmd(PADAPTER padapter, u8 *pbuf, u16 length, u8 type)5050{5051struct cmd_obj *ph2c;5052struct drvextra_cmd_parm *pdrvextra_cmd_parm;5053struct cmd_priv *pcmdpriv = &padapter->cmdpriv;5054u8 *extra_cmd_buf;5055u8 res = _SUCCESS;50565057ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));5058if (ph2c == NULL) {5059res = _FAIL;5060goto exit;5061}50625063pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));5064if (pdrvextra_cmd_parm == NULL) {5065rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));5066res = _FAIL;5067goto exit;5068}50695070extra_cmd_buf = rtw_zmalloc(length);5071if (extra_cmd_buf == NULL) {5072rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));5073rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));5074res = _FAIL;5075goto exit;5076}50775078_rtw_memcpy(extra_cmd_buf, pbuf, length);5079pdrvextra_cmd_parm->ec_id = C2H_WK_CID;5080pdrvextra_cmd_parm->type = type;5081pdrvextra_cmd_parm->size = length;5082pdrvextra_cmd_parm->pbuf = extra_cmd_buf;50835084init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));50855086res = rtw_enqueue_cmd(pcmdpriv, ph2c);50875088exit:5089return res;5090}50915092#ifdef CONFIG_FW_C2H_REG5093inline u8 rtw_c2h_reg_wk_cmd(_adapter *adapter, u8 *c2h_evt)5094{5095return rtw_c2h_wk_cmd(adapter, c2h_evt, c2h_evt ? C2H_REG_LEN : 0, C2H_TYPE_REG);5096}5097#endif50985099#ifdef CONFIG_FW_C2H_PKT5100inline u8 rtw_c2h_packet_wk_cmd(_adapter *adapter, u8 *c2h_evt, u16 length)5101{5102return rtw_c2h_wk_cmd(adapter, c2h_evt, length, C2H_TYPE_PKT);5103}5104#endif51055106u8 rtw_run_in_thread_cmd(PADAPTER padapter, void (*func)(void *), void *context)5107{5108struct cmd_priv *pcmdpriv;5109struct cmd_obj *ph2c;5110struct RunInThread_param *parm;5111s32 res = _SUCCESS;511251135114pcmdpriv = &padapter->cmdpriv;51155116ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));5117if (NULL == ph2c) {5118res = _FAIL;5119goto exit;5120}51215122parm = (struct RunInThread_param *)rtw_zmalloc(sizeof(struct RunInThread_param));5123if (NULL == parm) {5124rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));5125res = _FAIL;5126goto exit;5127}51285129parm->func = func;5130parm->context = context;5131init_h2fwcmd_w_parm_no_rsp(ph2c, parm, GEN_CMD_CODE(_RunInThreadCMD));51325133res = rtw_enqueue_cmd(pcmdpriv, ph2c);5134exit:513551365137return res;5138}51395140#ifdef CONFIG_FW_C2H_REG5141s32 c2h_evt_hdl(_adapter *adapter, u8 *c2h_evt, c2h_id_filter filter)5142{5143s32 ret = _FAIL;5144u8 buf[C2H_REG_LEN] = {0};5145u8 id, seq, plen;5146u8 *payload;51475148if (!c2h_evt) {5149/* No c2h event in cmd_obj, read c2h event before handling*/5150if (rtw_hal_c2h_evt_read(adapter, buf) != _SUCCESS)5151goto exit;5152c2h_evt = buf;5153}51545155rtw_hal_c2h_reg_hdr_parse(adapter, c2h_evt, &id, &seq, &plen, &payload);51565157if (filter && filter(adapter, id, seq, plen, payload) == _FALSE)5158goto exit;51595160ret = rtw_hal_c2h_handler(adapter, id, seq, plen, payload);51615162exit:5163return ret;5164}5165#endif /* CONFIG_FW_C2H_REG */51665167u8 session_tracker_cmd(_adapter *adapter, u8 cmd, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)5168{5169struct cmd_priv *cmdpriv = &adapter->cmdpriv;5170struct cmd_obj *cmdobj;5171struct drvextra_cmd_parm *cmd_parm;5172struct st_cmd_parm *st_parm;5173u8 res = _SUCCESS;51745175cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));5176if (cmdobj == NULL) {5177res = _FAIL;5178goto exit;5179}51805181cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));5182if (cmd_parm == NULL) {5183rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));5184res = _FAIL;5185goto exit;5186}51875188st_parm = (struct st_cmd_parm *)rtw_zmalloc(sizeof(struct st_cmd_parm));5189if (st_parm == NULL) {5190rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));5191rtw_mfree((u8 *)cmd_parm, sizeof(struct drvextra_cmd_parm));5192res = _FAIL;5193goto exit;5194}51955196st_parm->cmd = cmd;5197st_parm->sta = sta;5198if (cmd != ST_CMD_CHK) {5199_rtw_memcpy(&st_parm->local_naddr, local_naddr, 4);5200_rtw_memcpy(&st_parm->local_port, local_port, 2);5201_rtw_memcpy(&st_parm->remote_naddr, remote_naddr, 4);5202_rtw_memcpy(&st_parm->remote_port, remote_port, 2);5203}52045205cmd_parm->ec_id = SESSION_TRACKER_WK_CID;5206cmd_parm->type = 0;5207cmd_parm->size = sizeof(struct st_cmd_parm);5208cmd_parm->pbuf = (u8 *)st_parm;5209init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));5210cmdobj->no_io = 1;52115212res = rtw_enqueue_cmd(cmdpriv, cmdobj);52135214exit:5215return res;5216}52175218inline u8 session_tracker_chk_cmd(_adapter *adapter, struct sta_info *sta)5219{5220return session_tracker_cmd(adapter, ST_CMD_CHK, sta, NULL, NULL, NULL, NULL);5221}52225223inline u8 session_tracker_add_cmd(_adapter *adapter, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)5224{5225return session_tracker_cmd(adapter, ST_CMD_ADD, sta, local_naddr, local_port, remote_naddr, remote_port);5226}52275228inline u8 session_tracker_del_cmd(_adapter *adapter, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)5229{5230return session_tracker_cmd(adapter, ST_CMD_DEL, sta, local_naddr, local_port, remote_naddr, remote_port);5231}52325233void session_tracker_chk_for_sta(_adapter *adapter, struct sta_info *sta)5234{5235struct st_ctl_t *st_ctl = &sta->st_ctl;5236int i;5237_irqL irqL;5238_list *plist, *phead, *pnext;5239_list dlist;5240struct session_tracker *st = NULL;5241u8 op_wfd_mode = MIRACAST_DISABLED;52425243if (DBG_SESSION_TRACKER)5244RTW_INFO(FUNC_ADPT_FMT" sta:%p\n", FUNC_ADPT_ARG(adapter), sta);52455246if (!(sta->state & _FW_LINKED))5247goto exit;52485249for (i = 0; i < SESSION_TRACKER_REG_ID_NUM; i++) {5250if (st_ctl->reg[i].s_proto != 0)5251break;5252}5253if (i >= SESSION_TRACKER_REG_ID_NUM)5254goto chk_sta;52555256_rtw_init_listhead(&dlist);52575258_enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);52595260phead = &st_ctl->tracker_q.queue;5261plist = get_next(phead);5262pnext = get_next(plist);5263while (rtw_end_of_queue_search(phead, plist) == _FALSE) {5264st = LIST_CONTAINOR(plist, struct session_tracker, list);5265plist = pnext;5266pnext = get_next(pnext);52675268if (st->status != ST_STATUS_ESTABLISH5269&& rtw_get_passing_time_ms(st->set_time) > ST_EXPIRE_MS5270) {5271rtw_list_delete(&st->list);5272rtw_list_insert_tail(&st->list, &dlist);5273}52745275/* TODO: check OS for status update */5276if (st->status == ST_STATUS_CHECK)5277st->status = ST_STATUS_ESTABLISH;52785279if (st->status != ST_STATUS_ESTABLISH)5280continue;52815282#ifdef CONFIG_WFD5283if (0)5284RTW_INFO(FUNC_ADPT_FMT" local:%u, remote:%u, rtsp:%u, %u, %u\n", FUNC_ADPT_ARG(adapter)5285, ntohs(st->local_port), ntohs(st->remote_port), adapter->wfd_info.rtsp_ctrlport, adapter->wfd_info.tdls_rtsp_ctrlport5286, adapter->wfd_info.peer_rtsp_ctrlport);5287if (ntohs(st->local_port) == adapter->wfd_info.rtsp_ctrlport)5288op_wfd_mode |= MIRACAST_SINK;5289if (ntohs(st->local_port) == adapter->wfd_info.tdls_rtsp_ctrlport)5290op_wfd_mode |= MIRACAST_SINK;5291if (ntohs(st->remote_port) == adapter->wfd_info.peer_rtsp_ctrlport)5292op_wfd_mode |= MIRACAST_SOURCE;5293#endif5294}52955296_exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);52975298plist = get_next(&dlist);5299while (rtw_end_of_queue_search(&dlist, plist) == _FALSE) {5300st = LIST_CONTAINOR(plist, struct session_tracker, list);5301plist = get_next(plist);5302rtw_mfree((u8 *)st, sizeof(struct session_tracker));5303}53045305chk_sta:5306if (STA_OP_WFD_MODE(sta) != op_wfd_mode) {5307STA_SET_OP_WFD_MODE(sta, op_wfd_mode);5308rtw_sta_media_status_rpt_cmd(adapter, sta, 1);5309}53105311exit:5312return;5313}53145315void session_tracker_chk_for_adapter(_adapter *adapter)5316{5317struct sta_priv *stapriv = &adapter->stapriv;5318struct sta_info *sta;5319int i;5320_irqL irqL;5321_list *plist, *phead;5322u8 op_wfd_mode = MIRACAST_DISABLED;53235324_enter_critical_bh(&stapriv->sta_hash_lock, &irqL);53255326for (i = 0; i < NUM_STA; i++) {5327phead = &(stapriv->sta_hash[i]);5328plist = get_next(phead);53295330while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {5331sta = LIST_CONTAINOR(plist, struct sta_info, hash_list);5332plist = get_next(plist);53335334session_tracker_chk_for_sta(adapter, sta);53355336op_wfd_mode |= STA_OP_WFD_MODE(sta);5337}5338}53395340_exit_critical_bh(&stapriv->sta_hash_lock, &irqL);53415342#ifdef CONFIG_WFD5343adapter->wfd_info.op_wfd_mode = MIRACAST_MODE_REVERSE(op_wfd_mode);5344#endif5345}53465347void session_tracker_cmd_hdl(_adapter *adapter, struct st_cmd_parm *parm)5348{5349u8 cmd = parm->cmd;5350struct sta_info *sta = parm->sta;53515352if (cmd == ST_CMD_CHK) {5353if (sta)5354session_tracker_chk_for_sta(adapter, sta);5355else5356session_tracker_chk_for_adapter(adapter);53575358goto exit;53595360} else if (cmd == ST_CMD_ADD || cmd == ST_CMD_DEL) {5361struct st_ctl_t *st_ctl;5362u32 local_naddr = parm->local_naddr;5363u16 local_port = parm->local_port;5364u32 remote_naddr = parm->remote_naddr;5365u16 remote_port = parm->remote_port;5366struct session_tracker *st = NULL;5367_irqL irqL;5368_list *plist, *phead;5369u8 free_st = 0;5370u8 alloc_st = 0;53715372if (DBG_SESSION_TRACKER)5373RTW_INFO(FUNC_ADPT_FMT" cmd:%u, sta:%p, local:"IP_FMT":"PORT_FMT", remote:"IP_FMT":"PORT_FMT"\n"5374, FUNC_ADPT_ARG(adapter), cmd, sta5375, IP_ARG(&local_naddr), PORT_ARG(&local_port)5376, IP_ARG(&remote_naddr), PORT_ARG(&remote_port)5377);53785379if (!(sta->state & _FW_LINKED))5380goto exit;53815382st_ctl = &sta->st_ctl;53835384_enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);53855386phead = &st_ctl->tracker_q.queue;5387plist = get_next(phead);5388while (rtw_end_of_queue_search(phead, plist) == _FALSE) {5389st = LIST_CONTAINOR(plist, struct session_tracker, list);53905391if (st->local_naddr == local_naddr5392&& st->local_port == local_port5393&& st->remote_naddr == remote_naddr5394&& st->remote_port == remote_port)5395break;53965397plist = get_next(plist);5398}53995400if (rtw_end_of_queue_search(phead, plist) == _TRUE)5401st = NULL;54025403switch (cmd) {5404case ST_CMD_DEL:5405if (st) {5406rtw_list_delete(plist);5407free_st = 1;5408}5409goto unlock;5410case ST_CMD_ADD:5411if (!st)5412alloc_st = 1;5413}54145415unlock:5416_exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);54175418if (free_st) {5419rtw_mfree((u8 *)st, sizeof(struct session_tracker));5420goto exit;5421}54225423if (alloc_st) {5424st = (struct session_tracker *)rtw_zmalloc(sizeof(struct session_tracker));5425if (!st)5426goto exit;54275428st->local_naddr = local_naddr;5429st->local_port = local_port;5430st->remote_naddr = remote_naddr;5431st->remote_port = remote_port;5432st->set_time = rtw_get_current_time();5433st->status = ST_STATUS_CHECK;54345435_enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);5436rtw_list_insert_tail(&st->list, phead);5437_exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);5438}5439}54405441exit:5442return;5443}54445445#if defined(CONFIG_RTW_MESH) && defined(RTW_PER_CMD_SUPPORT_FW)5446static s32 rtw_req_per_cmd_hdl(_adapter *adapter)5447{5448struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);5449struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);5450struct macid_bmp req_macid_bmp, *macid_bmp;5451u8 i, ret = _FAIL;54525453macid_bmp = &macid_ctl->if_g[adapter->iface_id];5454_rtw_memcpy(&req_macid_bmp, macid_bmp, sizeof(struct macid_bmp));54555456/* Clear none mesh's macid */5457for (i = 0; i < macid_ctl->num; i++) {5458u8 role;5459role = GET_H2CCMD_MSRRPT_PARM_ROLE(&macid_ctl->h2c_msr[i]);5460if (role != H2C_MSR_ROLE_MESH)5461rtw_macid_map_clr(&req_macid_bmp, i);5462}54635464/* group_macid: always be 0 in NIC, so only pass macid_bitmap.m05465* rpt_type: 0 includes all info in 1, use 0 for now5466* macid_bitmap: pass m0 only for NIC5467*/5468ret = rtw_hal_set_req_per_rpt_cmd(adapter, 0, 0, req_macid_bmp.m0);54695470return ret;5471}54725473u8 rtw_req_per_cmd(_adapter *adapter)5474{5475struct cmd_obj *cmdobj;5476struct drvextra_cmd_parm *parm;5477struct cmd_priv *pcmdpriv = &adapter->cmdpriv;5478struct submit_ctx sctx;5479u8 res = _SUCCESS;54805481parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));5482if (parm == NULL) {5483res = _FAIL;5484goto exit;5485}54865487parm->ec_id = REQ_PER_CMD_WK_CID;5488parm->type = 0;5489parm->size = 0;5490parm->pbuf = NULL;54915492cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));5493if (cmdobj == NULL) {5494res = _FAIL;5495rtw_mfree((u8 *)parm, sizeof(*parm));5496goto exit;5497}54985499init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_Set_Drv_Extra));55005501res = rtw_enqueue_cmd(pcmdpriv, cmdobj);55025503exit:5504return res;5505}5506#endif550755085509void rtw_ac_parm_cmd_hdl(_adapter *padapter, u8 *_ac_parm_buf, int ac_type)5510{55115512u32 ac_parm_buf;55135514_rtw_memcpy(&ac_parm_buf, _ac_parm_buf, sizeof(ac_parm_buf));5515switch (ac_type) {5516case XMIT_VO_QUEUE:5517RTW_INFO(FUNC_NDEV_FMT" AC_VO = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);5518rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&ac_parm_buf));5519break;55205521case XMIT_VI_QUEUE:5522RTW_INFO(FUNC_NDEV_FMT" AC_VI = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);5523rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&ac_parm_buf));5524break;55255526case XMIT_BE_QUEUE:5527RTW_INFO(FUNC_NDEV_FMT" AC_BE = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);5528rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&ac_parm_buf));5529break;55305531case XMIT_BK_QUEUE:5532RTW_INFO(FUNC_NDEV_FMT" AC_BK = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf);5533rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&ac_parm_buf));5534break;55355536default:5537break;5538}55395540}554155425543u8 rtw_drvextra_cmd_hdl(_adapter *padapter, unsigned char *pbuf)5544{5545int ret = H2C_SUCCESS;5546struct drvextra_cmd_parm *pdrvextra_cmd;55475548if (!pbuf)5549return H2C_PARAMETERS_ERROR;55505551pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;55525553switch (pdrvextra_cmd->ec_id) {5554case STA_MSTATUS_RPT_WK_CID:5555rtw_sta_media_status_rpt_cmd_hdl(padapter, (struct sta_media_status_rpt_cmd_parm *)pdrvextra_cmd->pbuf);5556break;55575558case DYNAMIC_CHK_WK_CID:/*only primary padapter go to this cmd, but execute dynamic_chk_wk_hdl() for two interfaces */5559rtw_dynamic_chk_wk_hdl(padapter);5560break;5561case POWER_SAVING_CTRL_WK_CID:5562power_saving_wk_hdl(padapter);5563break;5564#ifdef CONFIG_LPS5565case LPS_CTRL_WK_CID:5566lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type, pdrvextra_cmd->pbuf);5567break;5568case DM_IN_LPS_WK_CID:5569rtw_dm_in_lps_hdl(padapter);5570break;5571case LPS_CHANGE_DTIM_CID:5572rtw_lps_change_dtim_hdl(padapter, (u8)pdrvextra_cmd->type);5573break;5574#endif5575#if (RATE_ADAPTIVE_SUPPORT == 1)5576case RTP_TIMER_CFG_WK_CID:5577rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type);5578break;5579#endif5580#ifdef CONFIG_ANTENNA_DIVERSITY5581case ANT_SELECT_WK_CID:5582antenna_select_wk_hdl(padapter, pdrvextra_cmd->type);5583break;5584#endif5585#ifdef CONFIG_P2P_PS5586case P2P_PS_WK_CID:5587p2p_ps_wk_hdl(padapter, pdrvextra_cmd->type);5588break;5589#endif5590#ifdef CONFIG_P2P5591case P2P_PROTO_WK_CID:5592/*5593* Commented by Albert 2011/07/015594* I used the type_size as the type command5595*/5596ret = p2p_protocol_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);5597break;5598#endif5599#ifdef CONFIG_AP_MODE5600case CHECK_HIQ_WK_CID:5601rtw_chk_hi_queue_hdl(padapter);5602break;5603#endif5604/* add for CONFIG_IEEE80211W, none 11w can use it */5605case RESET_SECURITYPRIV:5606reset_securitypriv_hdl(padapter);5607break;5608case FREE_ASSOC_RESOURCES:5609free_assoc_resources_hdl(padapter, (u8)pdrvextra_cmd->type);5610break;5611case C2H_WK_CID:5612switch (pdrvextra_cmd->type) {5613#ifdef CONFIG_FW_C2H_REG5614case C2H_TYPE_REG:5615c2h_evt_hdl(padapter, pdrvextra_cmd->pbuf, NULL);5616break;5617#endif5618#ifdef CONFIG_FW_C2H_PKT5619case C2H_TYPE_PKT:5620rtw_hal_c2h_pkt_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);5621break;5622#endif5623default:5624RTW_ERR("unknown C2H type:%d\n", pdrvextra_cmd->type);5625rtw_warn_on(1);5626break;5627}5628break;5629#ifdef CONFIG_BEAMFORMING5630case BEAMFORMING_WK_CID:5631beamforming_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);5632break;5633#endif5634case DM_RA_MSK_WK_CID:5635rtw_dm_ra_mask_hdl(padapter, (struct sta_info *)pdrvextra_cmd->pbuf);5636break;5637#ifdef CONFIG_BT_COEXIST5638case BTINFO_WK_CID:5639rtw_btinfo_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);5640break;5641case BTC_REDUCE_WL_TXPWR_CID:5642rtw_btc_reduce_wl_txpwr_hdl(padapter, pdrvextra_cmd->type);5643break;5644#endif5645#ifdef CONFIG_DFS_MASTER5646case DFS_RADAR_DETECT_WK_CID:5647rtw_dfs_rd_hdl(padapter);5648break;5649case DFS_RADAR_DETECT_EN_DEC_WK_CID:5650rtw_dfs_rd_en_decision(padapter, MLME_ACTION_NONE, 0);5651break;5652#endif5653case SESSION_TRACKER_WK_CID:5654session_tracker_cmd_hdl(padapter, (struct st_cmd_parm *)pdrvextra_cmd->pbuf);5655break;5656case EN_HW_UPDATE_TSF_WK_CID:5657rtw_hal_set_hwreg(padapter, HW_VAR_EN_HW_UPDATE_TSF, NULL);5658break;5659case PERIOD_TSF_UPDATE_END_WK_CID:5660rtw_hal_periodic_tsf_update_chk(padapter);5661break;5662case TEST_H2C_CID:5663rtw_hal_fill_h2c_cmd(padapter, pdrvextra_cmd->pbuf[0], pdrvextra_cmd->size - 1, &pdrvextra_cmd->pbuf[1]);5664break;5665case MP_CMD_WK_CID:5666#ifdef CONFIG_MP_INCLUDED5667ret = rtw_mp_cmd_hdl(padapter, pdrvextra_cmd->type);5668#endif5669break;5670#ifdef CONFIG_RTW_CUSTOMER_STR5671case CUSTOMER_STR_WK_CID:5672ret = rtw_customer_str_cmd_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);5673break;5674#endif56755676#ifdef CONFIG_RTW_REPEATER_SON5677case RSON_SCAN_WK_CID:5678rtw_rson_scan_cmd_hdl(padapter, pdrvextra_cmd->type);5679break;5680#endif56815682#ifdef CONFIG_IOCTL_CFG802115683case MGNT_TX_WK_CID:5684ret = rtw_mgnt_tx_handler(padapter, pdrvextra_cmd->pbuf);5685break;5686#endif /* CONFIG_IOCTL_CFG80211 */5687#ifdef CONFIG_MCC_MODE5688case MCC_CMD_WK_CID:5689ret = rtw_mcc_cmd_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);5690break;5691#endif /* CONFIG_MCC_MODE */5692#if defined(CONFIG_RTW_MESH) && defined(RTW_PER_CMD_SUPPORT_FW)5693case REQ_PER_CMD_WK_CID:5694ret = rtw_req_per_cmd_hdl(padapter);5695break;5696#endif5697#ifdef CONFIG_SUPPORT_STATIC_SMPS5698case SSMPS_WK_CID :5699rtw_ssmps_wk_hdl(padapter, (struct ssmps_cmd_parm *)pdrvextra_cmd->pbuf);5700break;5701#endif5702#ifdef CONFIG_CTRL_TXSS_BY_TP5703case TXSS_WK_CID :5704rtw_ctrl_txss_wk_hdl(padapter, (struct txss_cmd_parm *)pdrvextra_cmd->pbuf);5705break;5706#endif5707case AC_PARM_CMD_WK_CID:5708rtw_ac_parm_cmd_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type);5709break;5710#ifdef CONFIG_AP_MODE5711case STOP_AP_WK_CID:5712stop_ap_hdl(padapter);5713break;5714#endif5715default:5716break;5717}57185719if (pdrvextra_cmd->pbuf && pdrvextra_cmd->size > 0)5720rtw_mfree(pdrvextra_cmd->pbuf, pdrvextra_cmd->size);57215722return ret;5723}57245725void rtw_survey_cmd_callback(_adapter *padapter , struct cmd_obj *pcmd)5726{5727struct mlme_priv *pmlmepriv = &padapter->mlmepriv;572857295730if (pcmd->res == H2C_DROPPED) {5731/* TODO: cancel timer and do timeout handler directly... */5732/* need to make timeout handlerOS independent */5733mlme_set_scan_to_timer(pmlmepriv, 1);5734} else if (pcmd->res != H2C_SUCCESS) {5735mlme_set_scan_to_timer(pmlmepriv, 1);5736}57375738/* free cmd */5739rtw_free_cmd_obj(pcmd);57405741}5742void rtw_disassoc_cmd_callback(_adapter *padapter, struct cmd_obj *pcmd)5743{5744_irqL irqL;5745struct mlme_priv *pmlmepriv = &padapter->mlmepriv;574657475748if (pcmd->res != H2C_SUCCESS) {5749_enter_critical_bh(&pmlmepriv->lock, &irqL);5750set_fwstate(pmlmepriv, _FW_LINKED);5751_exit_critical_bh(&pmlmepriv->lock, &irqL);5752goto exit;5753}5754#ifdef CONFIG_BR_EXT5755else /* clear bridge database */5756nat25_db_cleanup(padapter);5757#endif /* CONFIG_BR_EXT */57585759/* free cmd */5760rtw_free_cmd_obj(pcmd);57615762exit:5763return;5764}576557665767void rtw_getmacreg_cmdrsp_callback(_adapter *padapter, struct cmd_obj *pcmd)5768{576957705771rtw_free_cmd_obj(pcmd);57725773}57745775void rtw_joinbss_cmd_callback(_adapter *padapter, struct cmd_obj *pcmd)5776{5777struct mlme_priv *pmlmepriv = &padapter->mlmepriv;577857795780if (pcmd->res == H2C_DROPPED) {5781/* TODO: cancel timer and do timeout handler directly... */5782/* need to make timeout handlerOS independent */5783_set_timer(&pmlmepriv->assoc_timer, 1);5784} else if (pcmd->res != H2C_SUCCESS)5785_set_timer(&pmlmepriv->assoc_timer, 1);57865787rtw_free_cmd_obj(pcmd);57885789}57905791void rtw_create_ibss_post_hdl(_adapter *padapter, int status)5792{5793_irqL irqL;5794struct wlan_network *pwlan = NULL;5795struct mlme_priv *pmlmepriv = &padapter->mlmepriv;5796WLAN_BSSID_EX *pdev_network = &padapter->registrypriv.dev_network;5797struct wlan_network *mlme_cur_network = &(pmlmepriv->cur_network);57985799if (status != H2C_SUCCESS)5800_set_timer(&pmlmepriv->assoc_timer, 1);58015802_cancel_timer_ex(&pmlmepriv->assoc_timer);58035804_enter_critical_bh(&pmlmepriv->lock, &irqL);58055806{5807_irqL irqL;58085809pwlan = _rtw_alloc_network(pmlmepriv);5810_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);5811if (pwlan == NULL) {5812pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);5813if (pwlan == NULL) {5814_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);5815goto createbss_cmd_fail;5816}5817pwlan->last_scanned = rtw_get_current_time();5818} else5819rtw_list_insert_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);58205821pdev_network->Length = get_WLAN_BSSID_EX_sz(pdev_network);5822_rtw_memcpy(&(pwlan->network), pdev_network, pdev_network->Length);5823/* pwlan->fixed = _TRUE; */58245825/* copy pdev_network information to pmlmepriv->cur_network */5826_rtw_memcpy(&mlme_cur_network->network, pdev_network, (get_WLAN_BSSID_EX_sz(pdev_network)));58275828#if 05829/* reset DSConfig */5830mlme_cur_network->network.Configuration.DSConfig = (u32)rtw_ch2freq(pdev_network->Configuration.DSConfig);5831#endif58325833_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);5834_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);5835/* we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */5836}58375838createbss_cmd_fail:5839_exit_critical_bh(&pmlmepriv->lock, &irqL);5840return;5841}5842584358445845void rtw_setstaKey_cmdrsp_callback(_adapter *padapter , struct cmd_obj *pcmd)5846{58475848struct sta_priv *pstapriv = &padapter->stapriv;5849struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp);5850struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);585158525853if (psta == NULL) {5854goto exit;5855}58565857/* psta->cmn.aid = psta->cmn.mac_id = psetstakey_rsp->keyid; */ /* CAM_ID(CAM_ENTRY) */58585859exit:58605861rtw_free_cmd_obj(pcmd);586258635864}5865void rtw_setassocsta_cmdrsp_callback(_adapter *padapter, struct cmd_obj *pcmd)5866{5867_irqL irqL;5868struct sta_priv *pstapriv = &padapter->stapriv;5869struct mlme_priv *pmlmepriv = &padapter->mlmepriv;5870struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);5871struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *)(pcmd->rsp);5872struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr);587358745875if (psta == NULL) {5876goto exit;5877}58785879psta->cmn.aid = psta->cmn.mac_id = passocsta_rsp->cam_id;58805881_enter_critical_bh(&pmlmepriv->lock, &irqL);58825883if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE) && (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE))5884_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);58855886set_fwstate(pmlmepriv, _FW_LINKED);5887_exit_critical_bh(&pmlmepriv->lock, &irqL);58885889exit:5890rtw_free_cmd_obj(pcmd);58915892}58935894void rtw_getrttbl_cmd_cmdrsp_callback(_adapter *padapter, struct cmd_obj *pcmd);5895void rtw_getrttbl_cmd_cmdrsp_callback(_adapter *padapter, struct cmd_obj *pcmd)5896{58975898rtw_free_cmd_obj(pcmd);5899#ifdef CONFIG_MP_INCLUDED5900if (padapter->registrypriv.mp_mode == 1)5901padapter->mppriv.workparam.bcompleted = _TRUE;5902#endif590359045905}59065907u8 set_txq_params_cmd(_adapter *adapter, u32 ac_parm, u8 ac_type)5908{5909struct cmd_obj *cmdobj;5910struct drvextra_cmd_parm *pdrvextra_cmd_parm;5911struct cmd_priv *pcmdpriv = &adapter->cmdpriv;5912u8 *ac_parm_buf = NULL;5913u8 sz;5914u8 res = _SUCCESS;591559165917cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));5918if (cmdobj == NULL) {5919res = _FAIL;5920goto exit;5921}59225923pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));5924if (pdrvextra_cmd_parm == NULL) {5925rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));5926res = _FAIL;5927goto exit;5928}59295930sz = sizeof(ac_parm);5931ac_parm_buf = rtw_zmalloc(sz);5932if (ac_parm_buf == NULL) {5933rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));5934rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));5935res = _FAIL;5936goto exit;5937}59385939pdrvextra_cmd_parm->ec_id = AC_PARM_CMD_WK_CID;5940pdrvextra_cmd_parm->type = ac_type;5941pdrvextra_cmd_parm->size = sz;5942pdrvextra_cmd_parm->pbuf = ac_parm_buf;59435944_rtw_memcpy(ac_parm_buf, &ac_parm, sz);59455946init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));5947res = rtw_enqueue_cmd(pcmdpriv, cmdobj);59485949exit:5950return res;5951}595259535954