158391efdSNathan Chancellor // SPDX-License-Identifier: GPL-2.0 2554c0a3aSHans de Goede /****************************************************************************** 3554c0a3aSHans de Goede * 4554c0a3aSHans de Goede * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. 5554c0a3aSHans de Goede * 6554c0a3aSHans de Goede ******************************************************************************/ 7554c0a3aSHans de Goede #define _RTW_CMD_C_ 8554c0a3aSHans de Goede 9554c0a3aSHans de Goede #include <drv_types.h> 10554c0a3aSHans de Goede #include <rtw_debug.h> 11800132aaSNishka Dasgupta #include <hal_btcoex.h> 12554c0a3aSHans de Goede #include <linux/jiffies.h> 13554c0a3aSHans de Goede 14554c0a3aSHans de Goede static struct _cmd_callback rtw_cmd_callback[] = { 15554c0a3aSHans de Goede {GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/ 16554c0a3aSHans de Goede {GEN_CMD_CODE(_Write_MACREG), NULL}, 17554c0a3aSHans de Goede {GEN_CMD_CODE(_Read_BBREG), &rtw_getbbrfreg_cmdrsp_callback}, 18554c0a3aSHans de Goede {GEN_CMD_CODE(_Write_BBREG), NULL}, 19554c0a3aSHans de Goede {GEN_CMD_CODE(_Read_RFREG), &rtw_getbbrfreg_cmdrsp_callback}, 20554c0a3aSHans de Goede {GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/ 21554c0a3aSHans de Goede {GEN_CMD_CODE(_Read_EEPROM), NULL}, 22554c0a3aSHans de Goede {GEN_CMD_CODE(_Write_EEPROM), NULL}, 23554c0a3aSHans de Goede {GEN_CMD_CODE(_Read_EFUSE), NULL}, 24554c0a3aSHans de Goede {GEN_CMD_CODE(_Write_EFUSE), NULL}, 25554c0a3aSHans de Goede 26554c0a3aSHans de Goede {GEN_CMD_CODE(_Read_CAM), NULL}, /*10*/ 27554c0a3aSHans de Goede {GEN_CMD_CODE(_Write_CAM), NULL}, 28554c0a3aSHans de Goede {GEN_CMD_CODE(_setBCNITV), NULL}, 29554c0a3aSHans de Goede {GEN_CMD_CODE(_setMBIDCFG), NULL}, 30554c0a3aSHans de Goede {GEN_CMD_CODE(_JoinBss), &rtw_joinbss_cmd_callback}, /*14*/ 31554c0a3aSHans de Goede {GEN_CMD_CODE(_DisConnect), &rtw_disassoc_cmd_callback}, /*15*/ 32554c0a3aSHans de Goede {GEN_CMD_CODE(_CreateBss), &rtw_createbss_cmd_callback}, 33554c0a3aSHans de Goede {GEN_CMD_CODE(_SetOpMode), NULL}, 34554c0a3aSHans de Goede {GEN_CMD_CODE(_SiteSurvey), &rtw_survey_cmd_callback}, /*18*/ 35554c0a3aSHans de Goede {GEN_CMD_CODE(_SetAuth), NULL}, 36554c0a3aSHans de Goede 37554c0a3aSHans de Goede {GEN_CMD_CODE(_SetKey), NULL}, /*20*/ 38554c0a3aSHans de Goede {GEN_CMD_CODE(_SetStaKey), &rtw_setstaKey_cmdrsp_callback}, 39554c0a3aSHans de Goede {GEN_CMD_CODE(_SetAssocSta), &rtw_setassocsta_cmdrsp_callback}, 40554c0a3aSHans de Goede {GEN_CMD_CODE(_DelAssocSta), NULL}, 41554c0a3aSHans de Goede {GEN_CMD_CODE(_SetStaPwrState), NULL}, 42554c0a3aSHans de Goede {GEN_CMD_CODE(_SetBasicRate), NULL}, /*25*/ 43554c0a3aSHans de Goede {GEN_CMD_CODE(_GetBasicRate), NULL}, 44554c0a3aSHans de Goede {GEN_CMD_CODE(_SetDataRate), NULL}, 45554c0a3aSHans de Goede {GEN_CMD_CODE(_GetDataRate), NULL}, 46554c0a3aSHans de Goede {GEN_CMD_CODE(_SetPhyInfo), NULL}, 47554c0a3aSHans de Goede 48554c0a3aSHans de Goede {GEN_CMD_CODE(_GetPhyInfo), NULL}, /*30*/ 49554c0a3aSHans de Goede {GEN_CMD_CODE(_SetPhy), NULL}, 50554c0a3aSHans de Goede {GEN_CMD_CODE(_GetPhy), NULL}, 51554c0a3aSHans de Goede {GEN_CMD_CODE(_readRssi), NULL}, 52554c0a3aSHans de Goede {GEN_CMD_CODE(_readGain), NULL}, 53554c0a3aSHans de Goede {GEN_CMD_CODE(_SetAtim), NULL}, /*35*/ 54554c0a3aSHans de Goede {GEN_CMD_CODE(_SetPwrMode), NULL}, 55554c0a3aSHans de Goede {GEN_CMD_CODE(_JoinbssRpt), NULL}, 56554c0a3aSHans de Goede {GEN_CMD_CODE(_SetRaTable), NULL}, 57554c0a3aSHans de Goede {GEN_CMD_CODE(_GetRaTable), NULL}, 58554c0a3aSHans de Goede 59554c0a3aSHans de Goede {GEN_CMD_CODE(_GetCCXReport), NULL}, /*40*/ 60554c0a3aSHans de Goede {GEN_CMD_CODE(_GetDTMReport), NULL}, 61554c0a3aSHans de Goede {GEN_CMD_CODE(_GetTXRateStatistics), NULL}, 62554c0a3aSHans de Goede {GEN_CMD_CODE(_SetUsbSuspend), NULL}, 63554c0a3aSHans de Goede {GEN_CMD_CODE(_SetH2cLbk), NULL}, 64554c0a3aSHans de Goede {GEN_CMD_CODE(_AddBAReq), NULL}, /*45*/ 65554c0a3aSHans de Goede {GEN_CMD_CODE(_SetChannel), NULL}, /*46*/ 66554c0a3aSHans de Goede {GEN_CMD_CODE(_SetTxPower), NULL}, 67554c0a3aSHans de Goede {GEN_CMD_CODE(_SwitchAntenna), NULL}, 68554c0a3aSHans de Goede {GEN_CMD_CODE(_SetCrystalCap), NULL}, 69554c0a3aSHans de Goede {GEN_CMD_CODE(_SetSingleCarrierTx), NULL}, /*50*/ 70554c0a3aSHans de Goede 71554c0a3aSHans de Goede {GEN_CMD_CODE(_SetSingleToneTx), NULL}, /*51*/ 72554c0a3aSHans de Goede {GEN_CMD_CODE(_SetCarrierSuppressionTx), NULL}, 73554c0a3aSHans de Goede {GEN_CMD_CODE(_SetContinuousTx), NULL}, 74554c0a3aSHans de Goede {GEN_CMD_CODE(_SwitchBandwidth), NULL}, /*54*/ 75554c0a3aSHans de Goede {GEN_CMD_CODE(_TX_Beacon), NULL},/*55*/ 76554c0a3aSHans de Goede 77554c0a3aSHans de Goede {GEN_CMD_CODE(_Set_MLME_EVT), NULL},/*56*/ 78554c0a3aSHans de Goede {GEN_CMD_CODE(_Set_Drv_Extra), NULL},/*57*/ 79554c0a3aSHans de Goede {GEN_CMD_CODE(_Set_H2C_MSG), NULL},/*58*/ 80554c0a3aSHans de Goede {GEN_CMD_CODE(_SetChannelPlan), NULL},/*59*/ 81554c0a3aSHans de Goede {GEN_CMD_CODE(_LedBlink), NULL},/*60*/ 82554c0a3aSHans de Goede 83554c0a3aSHans de Goede {GEN_CMD_CODE(_SetChannelSwitch), NULL},/*61*/ 84554c0a3aSHans de Goede {GEN_CMD_CODE(_TDLS), NULL},/*62*/ 85554c0a3aSHans de Goede {GEN_CMD_CODE(_ChkBMCSleepq), NULL}, /*63*/ 86554c0a3aSHans de Goede 87554c0a3aSHans de Goede {GEN_CMD_CODE(_RunInThreadCMD), NULL},/*64*/ 88554c0a3aSHans de Goede }; 89554c0a3aSHans de Goede 90554c0a3aSHans de Goede static struct cmd_hdl wlancmds[] = { 91554c0a3aSHans de Goede GEN_DRV_CMD_HANDLER(0, NULL) /*0*/ 92554c0a3aSHans de Goede GEN_DRV_CMD_HANDLER(0, NULL) 93554c0a3aSHans de Goede GEN_DRV_CMD_HANDLER(0, NULL) 94554c0a3aSHans de Goede GEN_DRV_CMD_HANDLER(0, NULL) 95554c0a3aSHans de Goede GEN_DRV_CMD_HANDLER(0, NULL) 96554c0a3aSHans de Goede GEN_DRV_CMD_HANDLER(0, NULL) 97554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 98554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 99554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 100554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 101554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) /*10*/ 102554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 103554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 104554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 105554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct joinbss_parm), join_cmd_hdl) /*14*/ 106554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct disconnect_parm), disconnect_hdl) 107554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct createbss_parm), createbss_hdl) 108554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct setopmode_parm), setopmode_hdl) 109554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct sitesurvey_parm), sitesurvey_cmd_hdl) /*18*/ 110554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct setauth_parm), setauth_hdl) 111554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct setkey_parm), setkey_hdl) /*20*/ 112554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct set_stakey_parm), set_stakey_hdl) 113554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct set_assocsta_parm), NULL) 114554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct del_assocsta_parm), NULL) 115554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct setstapwrstate_parm), NULL) 116554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct setbasicrate_parm), NULL) 117554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct getbasicrate_parm), NULL) 118554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct setdatarate_parm), NULL) 119554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct getdatarate_parm), NULL) 120554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct setphyinfo_parm), NULL) 121554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct getphyinfo_parm), NULL) /*30*/ 122554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct setphy_parm), NULL) 123554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct getphy_parm), NULL) 124554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 125554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 126554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 127554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 128554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 129554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 130554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 131554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) /*40*/ 132554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 133554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 134554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 135554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 136554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct addBaReq_parm), add_ba_hdl) 137554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct set_ch_parm), set_ch_hdl) /* 46 */ 138554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 139554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 140554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 141554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) /*50*/ 142554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 143554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 144554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 145554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 146554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct Tx_Beacon_param), tx_beacon_hdl) /*55*/ 147554c0a3aSHans de Goede 148554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, mlme_evt_hdl) /*56*/ 149554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, rtw_drvextra_cmd_hdl) /*57*/ 150554c0a3aSHans de Goede 151554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, h2c_msg_hdl) /*58*/ 152554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelPlan_param), set_chplan_hdl) /*59*/ 153554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct LedBlink_param), led_blink_hdl) /*60*/ 154554c0a3aSHans de Goede 155554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelSwitch_param), set_csa_hdl) /*61*/ 156554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct TDLSoption_param), tdls_hdl) /*62*/ 157554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, chk_bmc_sleepq_hdl) /*63*/ 158554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct RunInThread_param), run_in_thread_hdl) /*63*/ 159554c0a3aSHans de Goede }; 160554c0a3aSHans de Goede 161554c0a3aSHans de Goede /* 162554c0a3aSHans de Goede Caller and the rtw_cmd_thread can protect cmd_q by spin_lock. 163554c0a3aSHans de Goede No irqsave is necessary. 164554c0a3aSHans de Goede */ 165554c0a3aSHans de Goede 166b1c30bd6SMadhumitha Prabakaran int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv) 167554c0a3aSHans de Goede { 168cfd587d6SMadhumitha Prabakaran int res = 0; 169554c0a3aSHans de Goede 17009a8ea34SArnd Bergmann init_completion(&pcmdpriv->cmd_queue_comp); 17109a8ea34SArnd Bergmann init_completion(&pcmdpriv->terminate_cmdthread_comp); 172554c0a3aSHans de Goede 173554c0a3aSHans de Goede _rtw_init_queue(&(pcmdpriv->cmd_queue)); 174554c0a3aSHans de Goede 175554c0a3aSHans de Goede /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */ 176554c0a3aSHans de Goede 177554c0a3aSHans de Goede pcmdpriv->cmd_seq = 1; 178554c0a3aSHans de Goede 179554c0a3aSHans de Goede pcmdpriv->cmd_allocated_buf = rtw_zmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ); 180554c0a3aSHans de Goede 1814cdf1d0eSMadhumitha Prabakaran if (!pcmdpriv->cmd_allocated_buf) { 182cfd587d6SMadhumitha Prabakaran res = -ENOMEM; 183554c0a3aSHans de Goede goto exit; 184554c0a3aSHans de Goede } 185554c0a3aSHans de Goede 186554c0a3aSHans de Goede pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ - ((SIZE_PTR)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ-1)); 187554c0a3aSHans de Goede 188554c0a3aSHans de Goede pcmdpriv->rsp_allocated_buf = rtw_zmalloc(MAX_RSPSZ + 4); 189554c0a3aSHans de Goede 1904cdf1d0eSMadhumitha Prabakaran if (!pcmdpriv->rsp_allocated_buf) { 191cfd587d6SMadhumitha Prabakaran res = -ENOMEM; 192554c0a3aSHans de Goede goto exit; 193554c0a3aSHans de Goede } 194554c0a3aSHans de Goede 195554c0a3aSHans de Goede pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 - ((SIZE_PTR)(pcmdpriv->rsp_allocated_buf) & 3); 196554c0a3aSHans de Goede 197c42a4ac4SSimran Singhal pcmdpriv->cmd_issued_cnt = 0; 198c42a4ac4SSimran Singhal pcmdpriv->cmd_done_cnt = 0; 199c42a4ac4SSimran Singhal pcmdpriv->rsp_cnt = 0; 200554c0a3aSHans de Goede 201554c0a3aSHans de Goede mutex_init(&pcmdpriv->sctx_mutex); 202554c0a3aSHans de Goede exit: 203554c0a3aSHans de Goede return res; 204554c0a3aSHans de Goede } 205554c0a3aSHans de Goede 20600d5865cSMarco Cesati static void c2h_wk_callback(struct work_struct *work); 207b1c30bd6SMadhumitha Prabakaran int rtw_init_evt_priv(struct evt_priv *pevtpriv) 208554c0a3aSHans de Goede { 209554c0a3aSHans de Goede /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */ 210554c0a3aSHans de Goede atomic_set(&pevtpriv->event_seq, 0); 211554c0a3aSHans de Goede pevtpriv->evt_done_cnt = 0; 212554c0a3aSHans de Goede 213554c0a3aSHans de Goede _init_workitem(&pevtpriv->c2h_wk, c2h_wk_callback, NULL); 214554c0a3aSHans de Goede pevtpriv->c2h_wk_alive = false; 215554c0a3aSHans de Goede pevtpriv->c2h_queue = rtw_cbuf_alloc(C2H_QUEUE_MAX_LEN+1); 21659dbadcdSMadhumitha Prabakaran if (!pevtpriv->c2h_queue) 21759dbadcdSMadhumitha Prabakaran return -ENOMEM; 218554c0a3aSHans de Goede 21991734498SMadhumitha Prabakaran return 0; 220554c0a3aSHans de Goede } 221554c0a3aSHans de Goede 222554c0a3aSHans de Goede void _rtw_free_evt_priv(struct evt_priv *pevtpriv) 223554c0a3aSHans de Goede { 224554c0a3aSHans de Goede _cancel_workitem_sync(&pevtpriv->c2h_wk); 225554c0a3aSHans de Goede while (pevtpriv->c2h_wk_alive) 226554c0a3aSHans de Goede msleep(10); 227554c0a3aSHans de Goede 228554c0a3aSHans de Goede while (!rtw_cbuf_empty(pevtpriv->c2h_queue)) { 229554c0a3aSHans de Goede void *c2h = rtw_cbuf_pop(pevtpriv->c2h_queue); 2308f870aabSManuel Palenzuela if (c2h && c2h != (void *)pevtpriv) 231554c0a3aSHans de Goede kfree(c2h); 232554c0a3aSHans de Goede } 233554c0a3aSHans de Goede kfree(pevtpriv->c2h_queue); 234554c0a3aSHans de Goede } 235554c0a3aSHans de Goede 236554c0a3aSHans de Goede void _rtw_free_cmd_priv(struct cmd_priv *pcmdpriv) 237554c0a3aSHans de Goede { 238554c0a3aSHans de Goede if (pcmdpriv) { 239554c0a3aSHans de Goede kfree(pcmdpriv->cmd_allocated_buf); 240554c0a3aSHans de Goede 241554c0a3aSHans de Goede kfree(pcmdpriv->rsp_allocated_buf); 242554c0a3aSHans de Goede 243554c0a3aSHans de Goede mutex_destroy(&pcmdpriv->sctx_mutex); 244554c0a3aSHans de Goede } 245554c0a3aSHans de Goede } 246554c0a3aSHans de Goede 247554c0a3aSHans de Goede /* 248554c0a3aSHans de Goede Calling Context: 249554c0a3aSHans de Goede 250554c0a3aSHans de Goede rtw_enqueue_cmd can only be called between kernel thread, 251554c0a3aSHans de Goede since only spin_lock is used. 252554c0a3aSHans de Goede 253554c0a3aSHans de Goede ISR/Call-Back functions can't call this sub-function. 254554c0a3aSHans de Goede 255554c0a3aSHans de Goede */ 256554c0a3aSHans de Goede 257e4432160SMadhumitha Prabakaran int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj) 258554c0a3aSHans de Goede { 25900d5865cSMarco Cesati unsigned long irqL; 260554c0a3aSHans de Goede 261554c0a3aSHans de Goede if (obj == NULL) 262554c0a3aSHans de Goede goto exit; 263554c0a3aSHans de Goede 264554c0a3aSHans de Goede /* spin_lock_bh(&queue->lock); */ 265554c0a3aSHans de Goede spin_lock_irqsave(&queue->lock, irqL); 266554c0a3aSHans de Goede 267554c0a3aSHans de Goede list_add_tail(&obj->list, &queue->queue); 268554c0a3aSHans de Goede 269554c0a3aSHans de Goede /* spin_unlock_bh(&queue->lock); */ 270554c0a3aSHans de Goede spin_unlock_irqrestore(&queue->lock, irqL); 271554c0a3aSHans de Goede 272554c0a3aSHans de Goede exit: 273554c0a3aSHans de Goede return _SUCCESS; 274554c0a3aSHans de Goede } 275554c0a3aSHans de Goede 276554c0a3aSHans de Goede struct cmd_obj *_rtw_dequeue_cmd(struct __queue *queue) 277554c0a3aSHans de Goede { 27800d5865cSMarco Cesati unsigned long irqL; 279554c0a3aSHans de Goede struct cmd_obj *obj; 280554c0a3aSHans de Goede 281554c0a3aSHans de Goede /* spin_lock_bh(&(queue->lock)); */ 282554c0a3aSHans de Goede spin_lock_irqsave(&queue->lock, irqL); 283554c0a3aSHans de Goede if (list_empty(&(queue->queue))) 284554c0a3aSHans de Goede obj = NULL; 285554c0a3aSHans de Goede else { 28619cf9d7aSRoss Schmidt obj = container_of(get_next(&(queue->queue)), struct cmd_obj, list); 287554c0a3aSHans de Goede list_del_init(&obj->list); 288554c0a3aSHans de Goede } 289554c0a3aSHans de Goede 290554c0a3aSHans de Goede /* spin_unlock_bh(&(queue->lock)); */ 291554c0a3aSHans de Goede spin_unlock_irqrestore(&queue->lock, irqL); 292554c0a3aSHans de Goede 293554c0a3aSHans de Goede return obj; 294554c0a3aSHans de Goede } 295554c0a3aSHans de Goede 296554c0a3aSHans de Goede void rtw_free_evt_priv(struct evt_priv *pevtpriv) 297554c0a3aSHans de Goede { 298554c0a3aSHans de Goede _rtw_free_evt_priv(pevtpriv); 299554c0a3aSHans de Goede } 300554c0a3aSHans de Goede 301554c0a3aSHans de Goede void rtw_free_cmd_priv(struct cmd_priv *pcmdpriv) 302554c0a3aSHans de Goede { 303554c0a3aSHans de Goede _rtw_free_cmd_priv(pcmdpriv); 304554c0a3aSHans de Goede } 305554c0a3aSHans de Goede 306554c0a3aSHans de Goede int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj); 307554c0a3aSHans de Goede int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) 308554c0a3aSHans de Goede { 309554c0a3aSHans de Goede u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */ 310554c0a3aSHans de Goede 311554c0a3aSHans de Goede if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan)) 312554c0a3aSHans de Goede bAllow = true; 313554c0a3aSHans de Goede 314554c0a3aSHans de Goede if ((pcmdpriv->padapter->hw_init_completed == false && bAllow == false) 315554c0a3aSHans de Goede || atomic_read(&(pcmdpriv->cmdthd_running)) == false /* com_thread not running */ 316554c0a3aSHans de Goede ) { 317554c0a3aSHans de Goede /* DBG_871X("%s:%s: drop cmdcode:%u, hw_init_completed:%u, cmdthd_running:%u\n", caller_func, __func__, */ 318554c0a3aSHans de Goede /* cmd_obj->cmdcode, */ 319554c0a3aSHans de Goede /* pcmdpriv->padapter->hw_init_completed, */ 320554c0a3aSHans de Goede /* pcmdpriv->cmdthd_running */ 321554c0a3aSHans de Goede /* */ 322554c0a3aSHans de Goede 323554c0a3aSHans de Goede return _FAIL; 324554c0a3aSHans de Goede } 325554c0a3aSHans de Goede return _SUCCESS; 326554c0a3aSHans de Goede } 327554c0a3aSHans de Goede 328554c0a3aSHans de Goede 329554c0a3aSHans de Goede 330e4432160SMadhumitha Prabakaran int rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) 331554c0a3aSHans de Goede { 332554c0a3aSHans de Goede int res = _FAIL; 333554c0a3aSHans de Goede struct adapter *padapter = pcmdpriv->padapter; 334554c0a3aSHans de Goede 3358f870aabSManuel Palenzuela if (cmd_obj == NULL) 336554c0a3aSHans de Goede goto exit; 337554c0a3aSHans de Goede 338554c0a3aSHans de Goede cmd_obj->padapter = padapter; 339554c0a3aSHans de Goede 340554c0a3aSHans de Goede res = rtw_cmd_filter(pcmdpriv, cmd_obj); 34192576c84SManuel Palenzuela if (res == _FAIL) { 342554c0a3aSHans de Goede rtw_free_cmd_obj(cmd_obj); 343554c0a3aSHans de Goede goto exit; 344554c0a3aSHans de Goede } 345554c0a3aSHans de Goede 346554c0a3aSHans de Goede res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj); 347554c0a3aSHans de Goede 348554c0a3aSHans de Goede if (res == _SUCCESS) 34909a8ea34SArnd Bergmann complete(&pcmdpriv->cmd_queue_comp); 350554c0a3aSHans de Goede 351554c0a3aSHans de Goede exit: 352554c0a3aSHans de Goede return res; 353554c0a3aSHans de Goede } 354554c0a3aSHans de Goede 355554c0a3aSHans de Goede struct cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv) 356554c0a3aSHans de Goede { 3571b590af9SSimran Singhal return _rtw_dequeue_cmd(&pcmdpriv->cmd_queue); 358554c0a3aSHans de Goede } 359554c0a3aSHans de Goede 360554c0a3aSHans de Goede void rtw_free_cmd_obj(struct cmd_obj *pcmd) 361554c0a3aSHans de Goede { 362554c0a3aSHans de Goede if ((pcmd->cmdcode != _JoinBss_CMD_) && 363554c0a3aSHans de Goede (pcmd->cmdcode != _CreateBss_CMD_)) { 364554c0a3aSHans de Goede /* free parmbuf in cmd_obj */ 3652dac96b3SNachammai Karuppiah kfree(pcmd->parmbuf); 366554c0a3aSHans de Goede } 367554c0a3aSHans de Goede 36834557e23SIzabela Bakollari if (pcmd->rsp) { 369554c0a3aSHans de Goede if (pcmd->rspsz != 0) { 370554c0a3aSHans de Goede /* free rsp in cmd_obj */ 3712dac96b3SNachammai Karuppiah kfree(pcmd->rsp); 372554c0a3aSHans de Goede } 373554c0a3aSHans de Goede } 374554c0a3aSHans de Goede 375554c0a3aSHans de Goede /* free cmd_obj */ 376512bbd7bSSrishti Sharma kfree(pcmd); 377554c0a3aSHans de Goede } 378554c0a3aSHans de Goede 379554c0a3aSHans de Goede 380554c0a3aSHans de Goede void rtw_stop_cmd_thread(struct adapter *adapter) 381554c0a3aSHans de Goede { 382554c0a3aSHans de Goede if (adapter->cmdThread && 383554c0a3aSHans de Goede atomic_read(&(adapter->cmdpriv.cmdthd_running)) == true && 384554c0a3aSHans de Goede adapter->cmdpriv.stop_req == 0) { 385554c0a3aSHans de Goede adapter->cmdpriv.stop_req = 1; 38609a8ea34SArnd Bergmann complete(&adapter->cmdpriv.cmd_queue_comp); 38709a8ea34SArnd Bergmann wait_for_completion(&adapter->cmdpriv.terminate_cmdthread_comp); 388554c0a3aSHans de Goede } 389554c0a3aSHans de Goede } 390554c0a3aSHans de Goede 391554c0a3aSHans de Goede int rtw_cmd_thread(void *context) 392554c0a3aSHans de Goede { 393554c0a3aSHans de Goede u8 ret; 394554c0a3aSHans de Goede struct cmd_obj *pcmd; 395d698b0a0SYueHaibing u8 *pcmdbuf; 396554c0a3aSHans de Goede unsigned long cmd_start_time; 397554c0a3aSHans de Goede unsigned long cmd_process_time; 398554c0a3aSHans de Goede u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf); 399554c0a3aSHans de Goede void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd); 400529d87b4SHimanshu Jha struct adapter *padapter = context; 401554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); 402554c0a3aSHans de Goede struct drvextra_cmd_parm *extra_parm = NULL; 403554c0a3aSHans de Goede 404554c0a3aSHans de Goede thread_enter("RTW_CMD_THREAD"); 405554c0a3aSHans de Goede 406554c0a3aSHans de Goede pcmdbuf = pcmdpriv->cmd_buf; 407554c0a3aSHans de Goede 408554c0a3aSHans de Goede pcmdpriv->stop_req = 0; 409554c0a3aSHans de Goede atomic_set(&(pcmdpriv->cmdthd_running), true); 41009a8ea34SArnd Bergmann complete(&pcmdpriv->terminate_cmdthread_comp); 411554c0a3aSHans de Goede 412554c0a3aSHans de Goede while (1) { 41309a8ea34SArnd Bergmann if (wait_for_completion_interruptible(&pcmdpriv->cmd_queue_comp)) { 41409a8ea34SArnd Bergmann DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" wait_for_completion_interruptible(&pcmdpriv->cmd_queue_comp) return != 0, break\n", FUNC_ADPT_ARG(padapter)); 415554c0a3aSHans de Goede break; 416554c0a3aSHans de Goede } 417554c0a3aSHans de Goede 418554c0a3aSHans de Goede if ((padapter->bDriverStopped == true) || (padapter->bSurpriseRemoved == true)) { 419554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n", 420554c0a3aSHans de Goede __func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__); 421554c0a3aSHans de Goede break; 422554c0a3aSHans de Goede } 423554c0a3aSHans de Goede 424554c0a3aSHans de Goede if (pcmdpriv->stop_req) { 425554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" stop_req:%u, break\n", FUNC_ADPT_ARG(padapter), pcmdpriv->stop_req); 426554c0a3aSHans de Goede break; 427554c0a3aSHans de Goede } 428554c0a3aSHans de Goede 429554c0a3aSHans de Goede if (list_empty(&(pcmdpriv->cmd_queue.queue))) { 430554c0a3aSHans de Goede /* DBG_871X("%s: cmd queue is empty!\n", __func__); */ 431554c0a3aSHans de Goede continue; 432554c0a3aSHans de Goede } 433554c0a3aSHans de Goede 43413aefa65SFabio Aiuto if (rtw_register_cmd_alive(padapter) != _SUCCESS) 435554c0a3aSHans de Goede continue; 436554c0a3aSHans de Goede 437554c0a3aSHans de Goede _next: 438554c0a3aSHans de Goede if ((padapter->bDriverStopped == true) || (padapter->bSurpriseRemoved == true)) { 439554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n", 440554c0a3aSHans de Goede __func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__); 441554c0a3aSHans de Goede break; 442554c0a3aSHans de Goede } 443554c0a3aSHans de Goede 444554c0a3aSHans de Goede pcmd = rtw_dequeue_cmd(pcmdpriv); 445554c0a3aSHans de Goede if (!pcmd) { 446554c0a3aSHans de Goede rtw_unregister_cmd_alive(padapter); 447554c0a3aSHans de Goede continue; 448554c0a3aSHans de Goede } 449554c0a3aSHans de Goede 450554c0a3aSHans de Goede cmd_start_time = jiffies; 451554c0a3aSHans de Goede 45292576c84SManuel Palenzuela if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) { 453554c0a3aSHans de Goede pcmd->res = H2C_DROPPED; 454554c0a3aSHans de Goede goto post_process; 455554c0a3aSHans de Goede } 456554c0a3aSHans de Goede 457554c0a3aSHans de Goede pcmdpriv->cmd_issued_cnt++; 458554c0a3aSHans de Goede 459046bd5c9SRoss Schmidt pcmd->cmdsz = round_up((pcmd->cmdsz), 4); 460554c0a3aSHans de Goede 461554c0a3aSHans de Goede memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz); 462554c0a3aSHans de Goede 463554c0a3aSHans de Goede if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) { 464554c0a3aSHans de Goede cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns; 465554c0a3aSHans de Goede 466554c0a3aSHans de Goede if (cmd_hdl) { 467554c0a3aSHans de Goede ret = cmd_hdl(pcmd->padapter, pcmdbuf); 468554c0a3aSHans de Goede pcmd->res = ret; 469554c0a3aSHans de Goede } 470554c0a3aSHans de Goede 471554c0a3aSHans de Goede pcmdpriv->cmd_seq++; 472554c0a3aSHans de Goede } else { 473554c0a3aSHans de Goede pcmd->res = H2C_PARAMETERS_ERROR; 474554c0a3aSHans de Goede } 475554c0a3aSHans de Goede 476554c0a3aSHans de Goede cmd_hdl = NULL; 477554c0a3aSHans de Goede 478554c0a3aSHans de Goede post_process: 479554c0a3aSHans de Goede 480554c0a3aSHans de Goede if (mutex_lock_interruptible(&(pcmd->padapter->cmdpriv.sctx_mutex)) == 0) { 481554c0a3aSHans de Goede if (pcmd->sctx) { 482554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" pcmd->sctx\n", 483554c0a3aSHans de Goede FUNC_ADPT_ARG(pcmd->padapter)); 484554c0a3aSHans de Goede 485554c0a3aSHans de Goede if (pcmd->res == H2C_SUCCESS) 486554c0a3aSHans de Goede rtw_sctx_done(&pcmd->sctx); 487554c0a3aSHans de Goede else 488554c0a3aSHans de Goede rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_ERROR); 489554c0a3aSHans de Goede } 490554c0a3aSHans de Goede mutex_unlock(&(pcmd->padapter->cmdpriv.sctx_mutex)); 491554c0a3aSHans de Goede } 492554c0a3aSHans de Goede 493554c0a3aSHans de Goede cmd_process_time = jiffies_to_msecs(jiffies - cmd_start_time); 494554c0a3aSHans de Goede if (cmd_process_time > 1000) { 495d0cc39cdSRoss Schmidt DBG_871X("%s cmd= %d process_time= %lu > 1 sec\n", 496be88dae8SAliasgar Surti ADPT_ARG(pcmd->padapter), pcmd->cmdcode, 497be88dae8SAliasgar Surti cmd_process_time); 498554c0a3aSHans de Goede } 499554c0a3aSHans de Goede 500554c0a3aSHans de Goede /* call callback function for post-processed */ 501554c0a3aSHans de Goede if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) { 502554c0a3aSHans de Goede pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback; 503554c0a3aSHans de Goede if (pcmd_callback == NULL) { 504554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 505554c0a3aSHans de Goede } else { 506554c0a3aSHans de Goede /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */ 507858ea450SR Veera Kumar pcmd_callback(pcmd->padapter, pcmd);/* need consider that free cmd_obj in rtw_cmd_callback */ 508554c0a3aSHans de Goede } 509554c0a3aSHans de Goede } else { 510554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 511554c0a3aSHans de Goede } 512554c0a3aSHans de Goede 513554c0a3aSHans de Goede flush_signals_thread(); 514554c0a3aSHans de Goede 515554c0a3aSHans de Goede goto _next; 516554c0a3aSHans de Goede 517554c0a3aSHans de Goede } 518554c0a3aSHans de Goede 519554c0a3aSHans de Goede /* free all cmd_obj resources */ 520554c0a3aSHans de Goede do { 521554c0a3aSHans de Goede pcmd = rtw_dequeue_cmd(pcmdpriv); 522554c0a3aSHans de Goede if (pcmd == NULL) { 523554c0a3aSHans de Goede rtw_unregister_cmd_alive(padapter); 524554c0a3aSHans de Goede break; 525554c0a3aSHans de Goede } 526554c0a3aSHans de Goede 527554c0a3aSHans de Goede /* DBG_871X("%s: leaving... drop cmdcode:%u size:%d\n", __func__, pcmd->cmdcode, pcmd->cmdsz); */ 528554c0a3aSHans de Goede 529554c0a3aSHans de Goede if (pcmd->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) { 530554c0a3aSHans de Goede extra_parm = (struct drvextra_cmd_parm *)pcmd->parmbuf; 5318f870aabSManuel Palenzuela if (extra_parm->pbuf && extra_parm->size > 0) 532554c0a3aSHans de Goede kfree(extra_parm->pbuf); 533554c0a3aSHans de Goede } 534554c0a3aSHans de Goede 535554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 536554c0a3aSHans de Goede } while (1); 537554c0a3aSHans de Goede 53809a8ea34SArnd Bergmann complete(&pcmdpriv->terminate_cmdthread_comp); 539554c0a3aSHans de Goede atomic_set(&(pcmdpriv->cmdthd_running), false); 540554c0a3aSHans de Goede 541554c0a3aSHans de Goede thread_exit(); 542554c0a3aSHans de Goede } 543554c0a3aSHans de Goede 544554c0a3aSHans de Goede /* 545554c0a3aSHans de Goede rtw_sitesurvey_cmd(~) 546554c0a3aSHans de Goede ### NOTE:#### (!!!!) 547554c0a3aSHans de Goede MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock 548554c0a3aSHans de Goede */ 549554c0a3aSHans de Goede u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, int ssid_num, 550554c0a3aSHans de Goede struct rtw_ieee80211_channel *ch, int ch_num) 551554c0a3aSHans de Goede { 552554c0a3aSHans de Goede u8 res = _FAIL; 553554c0a3aSHans de Goede struct cmd_obj *ph2c; 554554c0a3aSHans de Goede struct sitesurvey_parm *psurveyPara; 555554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 556554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 557554c0a3aSHans de Goede 5588f870aabSManuel Palenzuela if (check_fwstate(pmlmepriv, _FW_LINKED) == true) 559554c0a3aSHans de Goede rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1); 560554c0a3aSHans de Goede 5612ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 562554c0a3aSHans de Goede if (ph2c == NULL) 563554c0a3aSHans de Goede return _FAIL; 564554c0a3aSHans de Goede 5652ef2b7c2SJoe Perches psurveyPara = rtw_zmalloc(sizeof(struct sitesurvey_parm)); 566554c0a3aSHans de Goede if (psurveyPara == NULL) { 567512bbd7bSSrishti Sharma kfree(ph2c); 568554c0a3aSHans de Goede return _FAIL; 569554c0a3aSHans de Goede } 570554c0a3aSHans de Goede 571554c0a3aSHans de Goede rtw_free_network_queue(padapter, false); 572554c0a3aSHans de Goede 573554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey)); 574554c0a3aSHans de Goede 575554c0a3aSHans de Goede /* psurveyPara->bsslimit = 48; */ 576554c0a3aSHans de Goede psurveyPara->scan_mode = pmlmepriv->scan_mode; 577554c0a3aSHans de Goede 578554c0a3aSHans de Goede /* prepare ssid list */ 579554c0a3aSHans de Goede if (ssid) { 580554c0a3aSHans de Goede int i; 581554c0a3aSHans de Goede for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) { 582554c0a3aSHans de Goede if (ssid[i].SsidLength) { 583554c0a3aSHans de Goede memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid)); 584554c0a3aSHans de Goede psurveyPara->ssid_num++; 585554c0a3aSHans de Goede 586554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" ssid:(%s, %d)\n", FUNC_ADPT_ARG(padapter), 587554c0a3aSHans de Goede psurveyPara->ssid[i].Ssid, psurveyPara->ssid[i].SsidLength); 588554c0a3aSHans de Goede } 589554c0a3aSHans de Goede } 590554c0a3aSHans de Goede } 591554c0a3aSHans de Goede 592554c0a3aSHans de Goede /* prepare channel list */ 593554c0a3aSHans de Goede if (ch) { 594554c0a3aSHans de Goede int i; 595554c0a3aSHans de Goede for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) { 596554c0a3aSHans de Goede if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) { 597554c0a3aSHans de Goede memcpy(&psurveyPara->ch[i], &ch[i], sizeof(struct rtw_ieee80211_channel)); 598554c0a3aSHans de Goede psurveyPara->ch_num++; 599554c0a3aSHans de Goede 600554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter), 601554c0a3aSHans de Goede psurveyPara->ch[i].hw_value); 602554c0a3aSHans de Goede } 603554c0a3aSHans de Goede } 604554c0a3aSHans de Goede } 605554c0a3aSHans de Goede 606554c0a3aSHans de Goede set_fwstate(pmlmepriv, _FW_UNDER_SURVEY); 607554c0a3aSHans de Goede 608554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 609554c0a3aSHans de Goede 610554c0a3aSHans de Goede if (res == _SUCCESS) { 611554c0a3aSHans de Goede 612554c0a3aSHans de Goede pmlmepriv->scan_start_time = jiffies; 613554c0a3aSHans de Goede _set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT); 614554c0a3aSHans de Goede } else { 615554c0a3aSHans de Goede _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); 616554c0a3aSHans de Goede } 617554c0a3aSHans de Goede return res; 618554c0a3aSHans de Goede } 619554c0a3aSHans de Goede 620554c0a3aSHans de Goede u8 rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset) 621554c0a3aSHans de Goede { 622554c0a3aSHans de Goede struct cmd_obj *ph2c; 623554c0a3aSHans de Goede struct setdatarate_parm *pbsetdataratepara; 624554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 625554c0a3aSHans de Goede u8 res = _SUCCESS; 626554c0a3aSHans de Goede 6272ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 628554c0a3aSHans de Goede if (ph2c == NULL) { 629554c0a3aSHans de Goede res = _FAIL; 630554c0a3aSHans de Goede goto exit; 631554c0a3aSHans de Goede } 632554c0a3aSHans de Goede 6332ef2b7c2SJoe Perches pbsetdataratepara = rtw_zmalloc(sizeof(struct setdatarate_parm)); 634554c0a3aSHans de Goede if (pbsetdataratepara == NULL) { 635512bbd7bSSrishti Sharma kfree(ph2c); 636554c0a3aSHans de Goede res = _FAIL; 637554c0a3aSHans de Goede goto exit; 638554c0a3aSHans de Goede } 639554c0a3aSHans de Goede 640554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, GEN_CMD_CODE(_SetDataRate)); 641554c0a3aSHans de Goede pbsetdataratepara->mac_id = 5; 642554c0a3aSHans de Goede memcpy(pbsetdataratepara->datarates, rateset, NumRates); 643554c0a3aSHans de Goede 644554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 645554c0a3aSHans de Goede exit: 646554c0a3aSHans de Goede return res; 647554c0a3aSHans de Goede } 648554c0a3aSHans de Goede 649554c0a3aSHans de Goede void rtw_getbbrfreg_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) 650554c0a3aSHans de Goede { 651554c0a3aSHans de Goede /* rtw_free_cmd_obj(pcmd); */ 652512bbd7bSSrishti Sharma kfree(pcmd->parmbuf); 653512bbd7bSSrishti Sharma kfree(pcmd); 654554c0a3aSHans de Goede } 655554c0a3aSHans de Goede 656554c0a3aSHans de Goede u8 rtw_createbss_cmd(struct adapter *padapter) 657554c0a3aSHans de Goede { 658554c0a3aSHans de Goede struct cmd_obj *pcmd; 659554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 660554c0a3aSHans de Goede struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network; 661554c0a3aSHans de Goede u8 res = _SUCCESS; 662554c0a3aSHans de Goede 6632ef2b7c2SJoe Perches pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); 664554c0a3aSHans de Goede if (pcmd == NULL) { 665554c0a3aSHans de Goede res = _FAIL; 666554c0a3aSHans de Goede goto exit; 667554c0a3aSHans de Goede } 668554c0a3aSHans de Goede 669554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd->list); 670554c0a3aSHans de Goede pcmd->cmdcode = _CreateBss_CMD_; 671554c0a3aSHans de Goede pcmd->parmbuf = (unsigned char *)pdev_network; 672554c0a3aSHans de Goede pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network); 673554c0a3aSHans de Goede pcmd->rsp = NULL; 674554c0a3aSHans de Goede pcmd->rspsz = 0; 675554c0a3aSHans de Goede 676554c0a3aSHans de Goede pdev_network->Length = pcmd->cmdsz; 677554c0a3aSHans de Goede 678554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, pcmd); 679554c0a3aSHans de Goede 680554c0a3aSHans de Goede exit: 681554c0a3aSHans de Goede return res; 682554c0a3aSHans de Goede } 683554c0a3aSHans de Goede 684e4432160SMadhumitha Prabakaran int rtw_startbss_cmd(struct adapter *padapter, int flags) 685554c0a3aSHans de Goede { 686554c0a3aSHans de Goede struct cmd_obj *pcmd; 687554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 688554c0a3aSHans de Goede struct submit_ctx sctx; 689e4432160SMadhumitha Prabakaran int res = _SUCCESS; 690554c0a3aSHans de Goede 691554c0a3aSHans de Goede if (flags & RTW_CMDF_DIRECTLY) { 692554c0a3aSHans de Goede /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ 693554c0a3aSHans de Goede start_bss_network(padapter, (u8 *)&(padapter->mlmepriv.cur_network.network)); 694554c0a3aSHans de Goede } else { 695554c0a3aSHans de Goede /* need enqueue, prepare cmd_obj and enqueue */ 6962ef2b7c2SJoe Perches pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); 697554c0a3aSHans de Goede if (pcmd == NULL) { 698554c0a3aSHans de Goede res = _FAIL; 699554c0a3aSHans de Goede goto exit; 700554c0a3aSHans de Goede } 701554c0a3aSHans de Goede 702554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd->list); 703554c0a3aSHans de Goede pcmd->cmdcode = GEN_CMD_CODE(_CreateBss); 704554c0a3aSHans de Goede pcmd->parmbuf = NULL; 705554c0a3aSHans de Goede pcmd->cmdsz = 0; 706554c0a3aSHans de Goede pcmd->rsp = NULL; 707554c0a3aSHans de Goede pcmd->rspsz = 0; 708554c0a3aSHans de Goede 709554c0a3aSHans de Goede if (flags & RTW_CMDF_WAIT_ACK) { 710554c0a3aSHans de Goede pcmd->sctx = &sctx; 711554c0a3aSHans de Goede rtw_sctx_init(&sctx, 2000); 712554c0a3aSHans de Goede } 713554c0a3aSHans de Goede 714554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, pcmd); 715554c0a3aSHans de Goede 716554c0a3aSHans de Goede if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) { 717554c0a3aSHans de Goede rtw_sctx_wait(&sctx, __func__); 718554c0a3aSHans de Goede if (mutex_lock_interruptible(&pcmdpriv->sctx_mutex) == 0) { 719554c0a3aSHans de Goede if (sctx.status == RTW_SCTX_SUBMITTED) 720554c0a3aSHans de Goede pcmd->sctx = NULL; 721554c0a3aSHans de Goede mutex_unlock(&pcmdpriv->sctx_mutex); 722554c0a3aSHans de Goede } 723554c0a3aSHans de Goede } 724554c0a3aSHans de Goede } 725554c0a3aSHans de Goede 726554c0a3aSHans de Goede exit: 727554c0a3aSHans de Goede return res; 728554c0a3aSHans de Goede } 729554c0a3aSHans de Goede 730554c0a3aSHans de Goede u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) 731554c0a3aSHans de Goede { 732d698b0a0SYueHaibing u8 res = _SUCCESS; 733554c0a3aSHans de Goede uint t_len = 0; 734554c0a3aSHans de Goede struct wlan_bssid_ex *psecnetwork; 735554c0a3aSHans de Goede struct cmd_obj *pcmd; 736554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 737554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 738554c0a3aSHans de Goede struct qos_priv *pqospriv = &pmlmepriv->qospriv; 739554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 740554c0a3aSHans de Goede struct registry_priv *pregistrypriv = &padapter->registrypriv; 741554c0a3aSHans de Goede struct ht_priv *phtpriv = &pmlmepriv->htpriv; 7429e4b6c19SMarco Cesati enum ndis_802_11_network_infrastructure ndis_network_mode = pnetwork->network.InfrastructureMode; 743554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 744554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 745554c0a3aSHans de Goede u32 tmp_len; 746554c0a3aSHans de Goede u8 *ptmp = NULL; 747554c0a3aSHans de Goede 7482ef2b7c2SJoe Perches pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); 749554c0a3aSHans de Goede if (pcmd == NULL) { 750554c0a3aSHans de Goede res = _FAIL; 751554c0a3aSHans de Goede goto exit; 752554c0a3aSHans de Goede } 753554c0a3aSHans de Goede /* for IEs is fix buf size */ 754554c0a3aSHans de Goede t_len = sizeof(struct wlan_bssid_ex); 755554c0a3aSHans de Goede 756554c0a3aSHans de Goede 757554c0a3aSHans de Goede /* for hidden ap to set fw_state here */ 758554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) != true) { 759554c0a3aSHans de Goede switch (ndis_network_mode) { 760554c0a3aSHans de Goede case Ndis802_11IBSS: 761554c0a3aSHans de Goede set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); 762554c0a3aSHans de Goede break; 763554c0a3aSHans de Goede 764554c0a3aSHans de Goede case Ndis802_11Infrastructure: 765554c0a3aSHans de Goede set_fwstate(pmlmepriv, WIFI_STATION_STATE); 766554c0a3aSHans de Goede break; 767554c0a3aSHans de Goede 768554c0a3aSHans de Goede case Ndis802_11APMode: 769554c0a3aSHans de Goede case Ndis802_11AutoUnknown: 770554c0a3aSHans de Goede case Ndis802_11InfrastructureMax: 771554c0a3aSHans de Goede break; 772554c0a3aSHans de Goede 773554c0a3aSHans de Goede } 774554c0a3aSHans de Goede } 775554c0a3aSHans de Goede 776554c0a3aSHans de Goede psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss; 777554c0a3aSHans de Goede 778554c0a3aSHans de Goede memset(psecnetwork, 0, t_len); 779554c0a3aSHans de Goede 780554c0a3aSHans de Goede memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network)); 781554c0a3aSHans de Goede 782554c0a3aSHans de Goede psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength; 783554c0a3aSHans de Goede 7840ba8b68bSHyeonggonYoo if ((psecnetwork->IELength-12) < (256-1)) 785554c0a3aSHans de Goede memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength-12); 7860ba8b68bSHyeonggonYoo else 787554c0a3aSHans de Goede memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256-1)); 788554c0a3aSHans de Goede 789554c0a3aSHans de Goede psecnetwork->IELength = 0; 790554c0a3aSHans de Goede /* Added by Albert 2009/02/18 */ 791705b7c36Skyoungho koo /* If the driver wants to use the bssid to create the connection. */ 792554c0a3aSHans de Goede /* If not, we have to copy the connecting AP's MAC address to it so that */ 793554c0a3aSHans de Goede /* the driver just has the bssid information for PMKIDList searching. */ 794554c0a3aSHans de Goede 7958f870aabSManuel Palenzuela if (pmlmepriv->assoc_by_bssid == false) 796554c0a3aSHans de Goede memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN); 797554c0a3aSHans de Goede 798554c0a3aSHans de Goede psecnetwork->IELength = rtw_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength); 799554c0a3aSHans de Goede 800554c0a3aSHans de Goede 801554c0a3aSHans de Goede pqospriv->qos_option = 0; 802554c0a3aSHans de Goede 803554c0a3aSHans de Goede if (pregistrypriv->wmm_enable) { 804554c0a3aSHans de Goede tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength); 805554c0a3aSHans de Goede 806554c0a3aSHans de Goede if (psecnetwork->IELength != tmp_len) { 807554c0a3aSHans de Goede psecnetwork->IELength = tmp_len; 808554c0a3aSHans de Goede pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */ 809554c0a3aSHans de Goede } else { 810554c0a3aSHans de Goede pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */ 811554c0a3aSHans de Goede } 812554c0a3aSHans de Goede } 813554c0a3aSHans de Goede 814554c0a3aSHans de Goede phtpriv->ht_option = false; 815fc6a6528SRoss Schmidt ptmp = rtw_get_ie(&pnetwork->network.IEs[12], WLAN_EID_HT_CAPABILITY, &tmp_len, pnetwork->network.IELength-12); 816554c0a3aSHans de Goede if (pregistrypriv->ht_enable && ptmp && tmp_len > 0) { 817554c0a3aSHans de Goede /* Added by Albert 2010/06/23 */ 818554c0a3aSHans de Goede /* For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */ 819554c0a3aSHans de Goede /* Especially for Realtek 8192u SoftAP. */ 820554c0a3aSHans de Goede if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) && 821554c0a3aSHans de Goede (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) && 822554c0a3aSHans de Goede (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) { 823554c0a3aSHans de Goede rtw_ht_use_default_setting(padapter); 824554c0a3aSHans de Goede 825554c0a3aSHans de Goede rtw_build_wmm_ie_ht(padapter, &psecnetwork->IEs[12], &psecnetwork->IELength); 826554c0a3aSHans de Goede 827554c0a3aSHans de Goede /* rtw_restructure_ht_ie */ 828554c0a3aSHans de Goede rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[12], &psecnetwork->IEs[0], 829554c0a3aSHans de Goede pnetwork->network.IELength-12, &psecnetwork->IELength, 830554c0a3aSHans de Goede pnetwork->network.Configuration.DSConfig); 831554c0a3aSHans de Goede } 832554c0a3aSHans de Goede } 833554c0a3aSHans de Goede 834554c0a3aSHans de Goede rtw_append_exented_cap(padapter, &psecnetwork->IEs[0], &psecnetwork->IELength); 835554c0a3aSHans de Goede 836554c0a3aSHans de Goede pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength); 837554c0a3aSHans de Goede 838554c0a3aSHans de Goede pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */ 839554c0a3aSHans de Goede 840554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd->list); 841554c0a3aSHans de Goede pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */ 842554c0a3aSHans de Goede pcmd->parmbuf = (unsigned char *)psecnetwork; 843554c0a3aSHans de Goede pcmd->rsp = NULL; 844554c0a3aSHans de Goede pcmd->rspsz = 0; 845554c0a3aSHans de Goede 846554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, pcmd); 847554c0a3aSHans de Goede 848554c0a3aSHans de Goede exit: 849554c0a3aSHans de Goede return res; 850554c0a3aSHans de Goede } 851554c0a3aSHans de Goede 852554c0a3aSHans de Goede u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */ 853554c0a3aSHans de Goede { 854554c0a3aSHans de Goede struct cmd_obj *cmdobj = NULL; 855554c0a3aSHans de Goede struct disconnect_parm *param = NULL; 856554c0a3aSHans de Goede struct cmd_priv *cmdpriv = &padapter->cmdpriv; 857554c0a3aSHans de Goede u8 res = _SUCCESS; 858554c0a3aSHans de Goede 859554c0a3aSHans de Goede /* prepare cmd parameter */ 8602ef2b7c2SJoe Perches param = rtw_zmalloc(sizeof(*param)); 861554c0a3aSHans de Goede if (param == NULL) { 862554c0a3aSHans de Goede res = _FAIL; 863554c0a3aSHans de Goede goto exit; 864554c0a3aSHans de Goede } 865554c0a3aSHans de Goede param->deauth_timeout_ms = deauth_timeout_ms; 866554c0a3aSHans de Goede 867554c0a3aSHans de Goede if (enqueue) { 868554c0a3aSHans de Goede /* need enqueue, prepare cmd_obj and enqueue */ 8692ef2b7c2SJoe Perches cmdobj = rtw_zmalloc(sizeof(*cmdobj)); 870554c0a3aSHans de Goede if (cmdobj == NULL) { 871554c0a3aSHans de Goede res = _FAIL; 872512bbd7bSSrishti Sharma kfree(param); 873554c0a3aSHans de Goede goto exit; 874554c0a3aSHans de Goede } 875554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_); 876554c0a3aSHans de Goede res = rtw_enqueue_cmd(cmdpriv, cmdobj); 877554c0a3aSHans de Goede } else { 878554c0a3aSHans de Goede /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ 87992576c84SManuel Palenzuela if (disconnect_hdl(padapter, (u8 *)param) != H2C_SUCCESS) 880554c0a3aSHans de Goede res = _FAIL; 881512bbd7bSSrishti Sharma kfree(param); 882554c0a3aSHans de Goede } 883554c0a3aSHans de Goede 884554c0a3aSHans de Goede exit: 885554c0a3aSHans de Goede return res; 886554c0a3aSHans de Goede } 887554c0a3aSHans de Goede 8889e4b6c19SMarco Cesati u8 rtw_setopmode_cmd(struct adapter *padapter, enum ndis_802_11_network_infrastructure networktype, bool enqueue) 889554c0a3aSHans de Goede { 890554c0a3aSHans de Goede struct cmd_obj *ph2c; 891554c0a3aSHans de Goede struct setopmode_parm *psetop; 892554c0a3aSHans de Goede 893554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 894554c0a3aSHans de Goede u8 res = _SUCCESS; 895554c0a3aSHans de Goede 8962ef2b7c2SJoe Perches psetop = rtw_zmalloc(sizeof(struct setopmode_parm)); 897554c0a3aSHans de Goede 898554c0a3aSHans de Goede if (psetop == NULL) { 899554c0a3aSHans de Goede res = _FAIL; 900554c0a3aSHans de Goede goto exit; 901554c0a3aSHans de Goede } 902554c0a3aSHans de Goede psetop->mode = (u8)networktype; 903554c0a3aSHans de Goede 904554c0a3aSHans de Goede if (enqueue) { 9052ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 906554c0a3aSHans de Goede if (ph2c == NULL) { 907512bbd7bSSrishti Sharma kfree(psetop); 908554c0a3aSHans de Goede res = _FAIL; 909554c0a3aSHans de Goede goto exit; 910554c0a3aSHans de Goede } 911554c0a3aSHans de Goede 912554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_); 913554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 914554c0a3aSHans de Goede } else { 915554c0a3aSHans de Goede setopmode_hdl(padapter, (u8 *)psetop); 916512bbd7bSSrishti Sharma kfree(psetop); 917554c0a3aSHans de Goede } 918554c0a3aSHans de Goede exit: 919554c0a3aSHans de Goede return res; 920554c0a3aSHans de Goede } 921554c0a3aSHans de Goede 922554c0a3aSHans de Goede u8 rtw_setstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 unicast_key, bool enqueue) 923554c0a3aSHans de Goede { 924554c0a3aSHans de Goede struct cmd_obj *ph2c; 925554c0a3aSHans de Goede struct set_stakey_parm *psetstakey_para; 926554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 927554c0a3aSHans de Goede struct set_stakey_rsp *psetstakey_rsp = NULL; 928554c0a3aSHans de Goede 929554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 930554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 931554c0a3aSHans de Goede u8 res = _SUCCESS; 932554c0a3aSHans de Goede 9332ef2b7c2SJoe Perches psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm)); 934554c0a3aSHans de Goede if (psetstakey_para == NULL) { 935554c0a3aSHans de Goede res = _FAIL; 936554c0a3aSHans de Goede goto exit; 937554c0a3aSHans de Goede } 938554c0a3aSHans de Goede 939554c0a3aSHans de Goede memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN); 940554c0a3aSHans de Goede 9410ba8b68bSHyeonggonYoo if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) 942554c0a3aSHans de Goede psetstakey_para->algorithm = (unsigned char) psecuritypriv->dot11PrivacyAlgrthm; 9430ba8b68bSHyeonggonYoo else 944554c0a3aSHans de Goede GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false); 945554c0a3aSHans de Goede 9460ba8b68bSHyeonggonYoo if (unicast_key == true) 947554c0a3aSHans de Goede memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16); 9480ba8b68bSHyeonggonYoo else 949554c0a3aSHans de Goede memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16); 950554c0a3aSHans de Goede 951858ea450SR Veera Kumar /* jeff: set this because at least sw key is ready */ 952554c0a3aSHans de Goede padapter->securitypriv.busetkipkey = true; 953554c0a3aSHans de Goede 954554c0a3aSHans de Goede if (enqueue) { 9552ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 956554c0a3aSHans de Goede if (ph2c == NULL) { 957512bbd7bSSrishti Sharma kfree(psetstakey_para); 958554c0a3aSHans de Goede res = _FAIL; 959554c0a3aSHans de Goede goto exit; 960554c0a3aSHans de Goede } 961554c0a3aSHans de Goede 9622ef2b7c2SJoe Perches psetstakey_rsp = rtw_zmalloc(sizeof(struct set_stakey_rsp)); 963554c0a3aSHans de Goede if (psetstakey_rsp == NULL) { 964512bbd7bSSrishti Sharma kfree(ph2c); 965512bbd7bSSrishti Sharma kfree(psetstakey_para); 966554c0a3aSHans de Goede res = _FAIL; 967554c0a3aSHans de Goede goto exit; 968554c0a3aSHans de Goede } 969554c0a3aSHans de Goede 970554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); 971554c0a3aSHans de Goede ph2c->rsp = (u8 *) psetstakey_rsp; 972554c0a3aSHans de Goede ph2c->rspsz = sizeof(struct set_stakey_rsp); 973554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 974554c0a3aSHans de Goede } else { 975554c0a3aSHans de Goede set_stakey_hdl(padapter, (u8 *)psetstakey_para); 976512bbd7bSSrishti Sharma kfree(psetstakey_para); 977554c0a3aSHans de Goede } 978554c0a3aSHans de Goede exit: 979554c0a3aSHans de Goede return res; 980554c0a3aSHans de Goede } 981554c0a3aSHans de Goede 982554c0a3aSHans de Goede u8 rtw_clearstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 enqueue) 983554c0a3aSHans de Goede { 984554c0a3aSHans de Goede struct cmd_obj *ph2c; 985554c0a3aSHans de Goede struct set_stakey_parm *psetstakey_para; 986554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 987554c0a3aSHans de Goede struct set_stakey_rsp *psetstakey_rsp = NULL; 988554c0a3aSHans de Goede s16 cam_id = 0; 989554c0a3aSHans de Goede u8 res = _SUCCESS; 990554c0a3aSHans de Goede 991554c0a3aSHans de Goede if (!enqueue) { 992554c0a3aSHans de Goede while ((cam_id = rtw_camid_search(padapter, sta->hwaddr, -1)) >= 0) { 993bbda3ac4SRoss Schmidt DBG_871X_LEVEL(_drv_always_, "clear key for addr:%pM, camid:%d\n", MAC_ARG(sta->hwaddr), cam_id); 994554c0a3aSHans de Goede clear_cam_entry(padapter, cam_id); 995554c0a3aSHans de Goede rtw_camid_free(padapter, cam_id); 996554c0a3aSHans de Goede } 997554c0a3aSHans de Goede } else { 9982ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 999554c0a3aSHans de Goede if (ph2c == NULL) { 1000554c0a3aSHans de Goede res = _FAIL; 1001554c0a3aSHans de Goede goto exit; 1002554c0a3aSHans de Goede } 1003554c0a3aSHans de Goede 10042ef2b7c2SJoe Perches psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm)); 1005554c0a3aSHans de Goede if (psetstakey_para == NULL) { 1006512bbd7bSSrishti Sharma kfree(ph2c); 1007554c0a3aSHans de Goede res = _FAIL; 1008554c0a3aSHans de Goede goto exit; 1009554c0a3aSHans de Goede } 1010554c0a3aSHans de Goede 10112ef2b7c2SJoe Perches psetstakey_rsp = rtw_zmalloc(sizeof(struct set_stakey_rsp)); 1012554c0a3aSHans de Goede if (psetstakey_rsp == NULL) { 1013512bbd7bSSrishti Sharma kfree(ph2c); 1014512bbd7bSSrishti Sharma kfree(psetstakey_para); 1015554c0a3aSHans de Goede res = _FAIL; 1016554c0a3aSHans de Goede goto exit; 1017554c0a3aSHans de Goede } 1018554c0a3aSHans de Goede 1019554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); 1020554c0a3aSHans de Goede ph2c->rsp = (u8 *) psetstakey_rsp; 1021554c0a3aSHans de Goede ph2c->rspsz = sizeof(struct set_stakey_rsp); 1022554c0a3aSHans de Goede 1023554c0a3aSHans de Goede memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN); 1024554c0a3aSHans de Goede 1025554c0a3aSHans de Goede psetstakey_para->algorithm = _NO_PRIVACY_; 1026554c0a3aSHans de Goede 1027554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1028554c0a3aSHans de Goede 1029554c0a3aSHans de Goede } 1030554c0a3aSHans de Goede 1031554c0a3aSHans de Goede exit: 1032554c0a3aSHans de Goede return res; 1033554c0a3aSHans de Goede } 1034554c0a3aSHans de Goede 1035554c0a3aSHans de Goede u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr) 1036554c0a3aSHans de Goede { 1037554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1038554c0a3aSHans de Goede struct cmd_obj *ph2c; 1039554c0a3aSHans de Goede struct addBaReq_parm *paddbareq_parm; 1040554c0a3aSHans de Goede 1041554c0a3aSHans de Goede u8 res = _SUCCESS; 1042554c0a3aSHans de Goede 10432ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1044554c0a3aSHans de Goede if (ph2c == NULL) { 1045554c0a3aSHans de Goede res = _FAIL; 1046554c0a3aSHans de Goede goto exit; 1047554c0a3aSHans de Goede } 1048554c0a3aSHans de Goede 10492ef2b7c2SJoe Perches paddbareq_parm = rtw_zmalloc(sizeof(struct addBaReq_parm)); 1050554c0a3aSHans de Goede if (paddbareq_parm == NULL) { 1051512bbd7bSSrishti Sharma kfree(ph2c); 1052554c0a3aSHans de Goede res = _FAIL; 1053554c0a3aSHans de Goede goto exit; 1054554c0a3aSHans de Goede } 1055554c0a3aSHans de Goede 1056554c0a3aSHans de Goede paddbareq_parm->tid = tid; 1057554c0a3aSHans de Goede memcpy(paddbareq_parm->addr, addr, ETH_ALEN); 1058554c0a3aSHans de Goede 1059554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq)); 1060554c0a3aSHans de Goede 1061554c0a3aSHans de Goede /* DBG_871X("rtw_addbareq_cmd, tid =%d\n", tid); */ 1062554c0a3aSHans de Goede 1063554c0a3aSHans de Goede /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ 1064554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1065554c0a3aSHans de Goede 1066554c0a3aSHans de Goede exit: 1067554c0a3aSHans de Goede return res; 1068554c0a3aSHans de Goede } 1069554c0a3aSHans de Goede /* add for CONFIG_IEEE80211W, none 11w can use it */ 1070554c0a3aSHans de Goede u8 rtw_reset_securitypriv_cmd(struct adapter *padapter) 1071554c0a3aSHans de Goede { 1072554c0a3aSHans de Goede struct cmd_obj *ph2c; 1073554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1074554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1075554c0a3aSHans de Goede u8 res = _SUCCESS; 1076554c0a3aSHans de Goede 10772ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1078554c0a3aSHans de Goede if (ph2c == NULL) { 1079554c0a3aSHans de Goede res = _FAIL; 1080554c0a3aSHans de Goede goto exit; 1081554c0a3aSHans de Goede } 1082554c0a3aSHans de Goede 10832ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1084554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1085512bbd7bSSrishti Sharma kfree(ph2c); 1086554c0a3aSHans de Goede res = _FAIL; 1087554c0a3aSHans de Goede goto exit; 1088554c0a3aSHans de Goede } 1089554c0a3aSHans de Goede 1090554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = RESET_SECURITYPRIV; 1091554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1092554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1093554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1094554c0a3aSHans de Goede 1095554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1096554c0a3aSHans de Goede 1097554c0a3aSHans de Goede 1098554c0a3aSHans de Goede /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ 1099554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1100554c0a3aSHans de Goede 1101554c0a3aSHans de Goede exit: 1102554c0a3aSHans de Goede return res; 1103554c0a3aSHans de Goede } 1104554c0a3aSHans de Goede 1105554c0a3aSHans de Goede u8 rtw_free_assoc_resources_cmd(struct adapter *padapter) 1106554c0a3aSHans de Goede { 1107554c0a3aSHans de Goede struct cmd_obj *ph2c; 1108554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1109554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1110554c0a3aSHans de Goede u8 res = _SUCCESS; 1111554c0a3aSHans de Goede 11122ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1113554c0a3aSHans de Goede if (ph2c == NULL) { 1114554c0a3aSHans de Goede res = _FAIL; 1115554c0a3aSHans de Goede goto exit; 1116554c0a3aSHans de Goede } 1117554c0a3aSHans de Goede 11182ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1119554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1120512bbd7bSSrishti Sharma kfree(ph2c); 1121554c0a3aSHans de Goede res = _FAIL; 1122554c0a3aSHans de Goede goto exit; 1123554c0a3aSHans de Goede } 1124554c0a3aSHans de Goede 1125554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = FREE_ASSOC_RESOURCES; 1126554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1127554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1128554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1129554c0a3aSHans de Goede 1130554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1131554c0a3aSHans de Goede 1132554c0a3aSHans de Goede 1133554c0a3aSHans de Goede /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ 1134554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1135554c0a3aSHans de Goede 1136554c0a3aSHans de Goede exit: 1137554c0a3aSHans de Goede return res; 1138554c0a3aSHans de Goede } 1139554c0a3aSHans de Goede 1140554c0a3aSHans de Goede u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter) 1141554c0a3aSHans de Goede { 1142554c0a3aSHans de Goede struct cmd_obj *ph2c; 1143554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1144554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1145554c0a3aSHans de Goede u8 res = _SUCCESS; 1146554c0a3aSHans de Goede 1147554c0a3aSHans de Goede /* only primary padapter does this cmd */ 11482ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1149554c0a3aSHans de Goede if (ph2c == NULL) { 1150554c0a3aSHans de Goede res = _FAIL; 1151554c0a3aSHans de Goede goto exit; 1152554c0a3aSHans de Goede } 1153554c0a3aSHans de Goede 11542ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1155554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1156512bbd7bSSrishti Sharma kfree(ph2c); 1157554c0a3aSHans de Goede res = _FAIL; 1158554c0a3aSHans de Goede goto exit; 1159554c0a3aSHans de Goede } 1160554c0a3aSHans de Goede 1161554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID; 1162554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1163554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1164554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1165554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1166554c0a3aSHans de Goede 1167554c0a3aSHans de Goede 1168554c0a3aSHans de Goede /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ 1169554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1170554c0a3aSHans de Goede 1171554c0a3aSHans de Goede exit: 1172554c0a3aSHans de Goede return res; 1173554c0a3aSHans de Goede } 1174554c0a3aSHans de Goede 1175554c0a3aSHans de Goede u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue, u8 swconfig) 1176554c0a3aSHans de Goede { 1177554c0a3aSHans de Goede struct cmd_obj *pcmdobj; 1178554c0a3aSHans de Goede struct SetChannelPlan_param *setChannelPlan_param; 1179554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1180554c0a3aSHans de Goede 1181554c0a3aSHans de Goede u8 res = _SUCCESS; 1182554c0a3aSHans de Goede 1183554c0a3aSHans de Goede /* check if allow software config */ 1184554c0a3aSHans de Goede if (swconfig && rtw_hal_is_disable_sw_channel_plan(padapter) == true) { 1185554c0a3aSHans de Goede res = _FAIL; 1186554c0a3aSHans de Goede goto exit; 1187554c0a3aSHans de Goede } 1188554c0a3aSHans de Goede 1189554c0a3aSHans de Goede /* check input parameter */ 1190554c0a3aSHans de Goede if (!rtw_is_channel_plan_valid(chplan)) { 1191554c0a3aSHans de Goede res = _FAIL; 1192554c0a3aSHans de Goede goto exit; 1193554c0a3aSHans de Goede } 1194554c0a3aSHans de Goede 1195554c0a3aSHans de Goede /* prepare cmd parameter */ 11962ef2b7c2SJoe Perches setChannelPlan_param = rtw_zmalloc(sizeof(struct SetChannelPlan_param)); 1197554c0a3aSHans de Goede if (setChannelPlan_param == NULL) { 1198554c0a3aSHans de Goede res = _FAIL; 1199554c0a3aSHans de Goede goto exit; 1200554c0a3aSHans de Goede } 1201554c0a3aSHans de Goede setChannelPlan_param->channel_plan = chplan; 1202554c0a3aSHans de Goede 1203554c0a3aSHans de Goede if (enqueue) { 1204554c0a3aSHans de Goede /* need enqueue, prepare cmd_obj and enqueue */ 12052ef2b7c2SJoe Perches pcmdobj = rtw_zmalloc(sizeof(struct cmd_obj)); 1206554c0a3aSHans de Goede if (pcmdobj == NULL) { 1207512bbd7bSSrishti Sharma kfree(setChannelPlan_param); 1208554c0a3aSHans de Goede res = _FAIL; 1209554c0a3aSHans de Goede goto exit; 1210554c0a3aSHans de Goede } 1211554c0a3aSHans de Goede 1212554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, GEN_CMD_CODE(_SetChannelPlan)); 1213554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, pcmdobj); 1214554c0a3aSHans de Goede } else { 1215554c0a3aSHans de Goede /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ 121692576c84SManuel Palenzuela if (set_chplan_hdl(padapter, (unsigned char *)setChannelPlan_param) != H2C_SUCCESS) 1217554c0a3aSHans de Goede res = _FAIL; 1218554c0a3aSHans de Goede 1219512bbd7bSSrishti Sharma kfree(setChannelPlan_param); 1220554c0a3aSHans de Goede } 1221554c0a3aSHans de Goede 1222554c0a3aSHans de Goede /* do something based on res... */ 1223554c0a3aSHans de Goede if (res == _SUCCESS) 1224554c0a3aSHans de Goede padapter->mlmepriv.ChannelPlan = chplan; 1225554c0a3aSHans de Goede 1226554c0a3aSHans de Goede exit: 1227554c0a3aSHans de Goede return res; 1228554c0a3aSHans de Goede } 1229554c0a3aSHans de Goede 1230554c0a3aSHans de Goede static void collect_traffic_statistics(struct adapter *padapter) 1231554c0a3aSHans de Goede { 1232554c0a3aSHans de Goede struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); 1233554c0a3aSHans de Goede 1234554c0a3aSHans de Goede /* Tx */ 1235554c0a3aSHans de Goede pdvobjpriv->traffic_stat.tx_bytes = padapter->xmitpriv.tx_bytes; 1236554c0a3aSHans de Goede pdvobjpriv->traffic_stat.tx_pkts = padapter->xmitpriv.tx_pkts; 1237554c0a3aSHans de Goede pdvobjpriv->traffic_stat.tx_drop = padapter->xmitpriv.tx_drop; 1238554c0a3aSHans de Goede 1239554c0a3aSHans de Goede /* Rx */ 1240554c0a3aSHans de Goede pdvobjpriv->traffic_stat.rx_bytes = padapter->recvpriv.rx_bytes; 1241554c0a3aSHans de Goede pdvobjpriv->traffic_stat.rx_pkts = padapter->recvpriv.rx_pkts; 1242554c0a3aSHans de Goede pdvobjpriv->traffic_stat.rx_drop = padapter->recvpriv.rx_drop; 1243554c0a3aSHans de Goede 1244554c0a3aSHans de Goede /* Calculate throughput in last interval */ 1245554c0a3aSHans de Goede pdvobjpriv->traffic_stat.cur_tx_bytes = pdvobjpriv->traffic_stat.tx_bytes - pdvobjpriv->traffic_stat.last_tx_bytes; 1246554c0a3aSHans de Goede pdvobjpriv->traffic_stat.cur_rx_bytes = pdvobjpriv->traffic_stat.rx_bytes - pdvobjpriv->traffic_stat.last_rx_bytes; 1247554c0a3aSHans de Goede pdvobjpriv->traffic_stat.last_tx_bytes = pdvobjpriv->traffic_stat.tx_bytes; 1248554c0a3aSHans de Goede pdvobjpriv->traffic_stat.last_rx_bytes = pdvobjpriv->traffic_stat.rx_bytes; 1249554c0a3aSHans de Goede 1250554c0a3aSHans de Goede pdvobjpriv->traffic_stat.cur_tx_tp = (u32)(pdvobjpriv->traffic_stat.cur_tx_bytes * 8/2/1024/1024); 1251554c0a3aSHans de Goede pdvobjpriv->traffic_stat.cur_rx_tp = (u32)(pdvobjpriv->traffic_stat.cur_rx_bytes * 8/2/1024/1024); 1252554c0a3aSHans de Goede } 1253554c0a3aSHans de Goede 1254554c0a3aSHans de Goede u8 traffic_status_watchdog(struct adapter *padapter, u8 from_timer) 1255554c0a3aSHans de Goede { 1256554c0a3aSHans de Goede u8 bEnterPS = false; 1257554c0a3aSHans de Goede u16 BusyThresholdHigh = 25; 1258554c0a3aSHans de Goede u16 BusyThresholdLow = 10; 1259554c0a3aSHans de Goede u16 BusyThreshold = BusyThresholdHigh; 1260554c0a3aSHans de Goede u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false; 1261554c0a3aSHans de Goede u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false; 1262554c0a3aSHans de Goede 1263554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1264554c0a3aSHans de Goede 1265554c0a3aSHans de Goede collect_traffic_statistics(padapter); 1266554c0a3aSHans de Goede 1267554c0a3aSHans de Goede /* */ 1268554c0a3aSHans de Goede /* Determine if our traffic is busy now */ 1269554c0a3aSHans de Goede /* */ 1270554c0a3aSHans de Goede if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) 1271554c0a3aSHans de Goede /*&& !MgntInitAdapterInProgress(pMgntInfo)*/) { 1272554c0a3aSHans de Goede /* if we raise bBusyTraffic in last watchdog, using lower threshold. */ 1273554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.bBusyTraffic) 1274554c0a3aSHans de Goede BusyThreshold = BusyThresholdLow; 1275554c0a3aSHans de Goede 1276554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold || 1277554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold) { 1278554c0a3aSHans de Goede bBusyTraffic = true; 1279554c0a3aSHans de Goede 1280554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) 1281554c0a3aSHans de Goede bRxBusyTraffic = true; 1282554c0a3aSHans de Goede else 1283554c0a3aSHans de Goede bTxBusyTraffic = true; 1284554c0a3aSHans de Goede } 1285554c0a3aSHans de Goede 1286554c0a3aSHans de Goede /* Higher Tx/Rx data. */ 1287554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 || 1288554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) { 1289554c0a3aSHans de Goede bHigherBusyTraffic = true; 1290554c0a3aSHans de Goede 1291554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) 1292554c0a3aSHans de Goede bHigherBusyRxTraffic = true; 1293554c0a3aSHans de Goede else 1294554c0a3aSHans de Goede bHigherBusyTxTraffic = true; 1295554c0a3aSHans de Goede } 1296554c0a3aSHans de Goede 1297554c0a3aSHans de Goede /* check traffic for powersaving. */ 1298554c0a3aSHans de Goede if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) || 1299554c0a3aSHans de Goede (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2)) { 1300554c0a3aSHans de Goede /* DBG_871X("(-)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); */ 1301554c0a3aSHans de Goede bEnterPS = false; 1302554c0a3aSHans de Goede 1303554c0a3aSHans de Goede if (bBusyTraffic == true) { 1304554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount <= 4) 1305554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 4; 1306554c0a3aSHans de Goede 1307554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount++; 1308554c0a3aSHans de Goede 1309554c0a3aSHans de Goede /* DBG_871X("Set TrafficTransitionCount to %d\n", pmlmepriv->LinkDetectInfo.TrafficTransitionCount); */ 1310554c0a3aSHans de Goede 13118f870aabSManuel Palenzuela if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount > 30/*TrafficTransitionLevel*/) 1312554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 30; 1313554c0a3aSHans de Goede } 1314554c0a3aSHans de Goede } else { 1315554c0a3aSHans de Goede /* DBG_871X("(+)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); */ 1316554c0a3aSHans de Goede 1317554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount >= 2) 1318554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount -= 2; 1319554c0a3aSHans de Goede else 1320554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0; 1321554c0a3aSHans de Goede 1322554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount == 0) 1323554c0a3aSHans de Goede bEnterPS = true; 1324554c0a3aSHans de Goede } 1325554c0a3aSHans de Goede 1326554c0a3aSHans de Goede /* LeisurePS only work in infra mode. */ 1327554c0a3aSHans de Goede if (bEnterPS) { 1328554c0a3aSHans de Goede if (!from_timer) 1329554c0a3aSHans de Goede LPS_Enter(padapter, "TRAFFIC_IDLE"); 1330554c0a3aSHans de Goede } else { 1331554c0a3aSHans de Goede if (!from_timer) 1332554c0a3aSHans de Goede LPS_Leave(padapter, "TRAFFIC_BUSY"); 1333554c0a3aSHans de Goede else 1334554c0a3aSHans de Goede rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_TRAFFIC_BUSY, 1); 1335554c0a3aSHans de Goede } 1336554c0a3aSHans de Goede } else { 1337554c0a3aSHans de Goede struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); 1338554c0a3aSHans de Goede int n_assoc_iface = 0; 1339554c0a3aSHans de Goede 1340554c0a3aSHans de Goede if (check_fwstate(&(dvobj->padapters->mlmepriv), WIFI_ASOC_STATE)) 1341554c0a3aSHans de Goede n_assoc_iface++; 1342554c0a3aSHans de Goede 1343554c0a3aSHans de Goede if (!from_timer && n_assoc_iface == 0) 1344554c0a3aSHans de Goede LPS_Leave(padapter, "NON_LINKED"); 1345554c0a3aSHans de Goede } 1346554c0a3aSHans de Goede 1347554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0; 1348554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0; 1349554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0; 1350554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic; 1351554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic; 1352554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic; 1353554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic; 1354554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic; 1355554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic; 1356554c0a3aSHans de Goede 1357554c0a3aSHans de Goede return bEnterPS; 1358554c0a3aSHans de Goede 1359554c0a3aSHans de Goede } 1360554c0a3aSHans de Goede 1361554c0a3aSHans de Goede static void dynamic_chk_wk_hdl(struct adapter *padapter) 1362554c0a3aSHans de Goede { 1363554c0a3aSHans de Goede struct mlme_priv *pmlmepriv; 1364554c0a3aSHans de Goede pmlmepriv = &(padapter->mlmepriv); 1365554c0a3aSHans de Goede 13668f870aabSManuel Palenzuela if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) 1367554c0a3aSHans de Goede expire_timeout_chk(padapter); 1368554c0a3aSHans de Goede 1369554c0a3aSHans de Goede /* for debug purpose */ 1370554c0a3aSHans de Goede _linked_info_dump(padapter); 1371554c0a3aSHans de Goede 1372554c0a3aSHans de Goede 1373554c0a3aSHans de Goede /* if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING|_FW_UNDER_SURVEY) ==false) */ 1374554c0a3aSHans de Goede { 1375554c0a3aSHans de Goede linked_status_chk(padapter); 1376554c0a3aSHans de Goede traffic_status_watchdog(padapter, 0); 1377554c0a3aSHans de Goede } 1378554c0a3aSHans de Goede 1379554c0a3aSHans de Goede rtw_hal_dm_watchdog(padapter); 1380554c0a3aSHans de Goede 1381554c0a3aSHans de Goede /* check_hw_pbc(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type); */ 1382554c0a3aSHans de Goede 1383554c0a3aSHans de Goede /* */ 1384554c0a3aSHans de Goede /* BT-Coexist */ 1385554c0a3aSHans de Goede /* */ 1386a158111dSNishka Dasgupta hal_btcoex_Handler(padapter); 1387554c0a3aSHans de Goede 1388554c0a3aSHans de Goede 1389554c0a3aSHans de Goede /* always call rtw_ps_processor() at last one. */ 1390554c0a3aSHans de Goede if (is_primary_adapter(padapter)) 1391554c0a3aSHans de Goede rtw_ps_processor(padapter); 1392554c0a3aSHans de Goede } 1393554c0a3aSHans de Goede 1394554c0a3aSHans de Goede void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type); 1395554c0a3aSHans de Goede void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type) 1396554c0a3aSHans de Goede { 1397554c0a3aSHans de Goede struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); 1398554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1399554c0a3aSHans de Goede u8 mstatus; 1400554c0a3aSHans de Goede 1401554c0a3aSHans de Goede if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) 1402554c0a3aSHans de Goede || (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) { 1403554c0a3aSHans de Goede return; 1404554c0a3aSHans de Goede } 1405554c0a3aSHans de Goede 1406554c0a3aSHans de Goede switch (lps_ctrl_type) { 1407554c0a3aSHans de Goede case LPS_CTRL_SCAN: 1408554c0a3aSHans de Goede /* DBG_871X("LPS_CTRL_SCAN\n"); */ 1409a47a70c2SNishka Dasgupta hal_btcoex_ScanNotify(padapter, true); 1410554c0a3aSHans de Goede 1411554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { 1412554c0a3aSHans de Goede /* connect */ 1413554c0a3aSHans de Goede LPS_Leave(padapter, "LPS_CTRL_SCAN"); 1414554c0a3aSHans de Goede } 1415554c0a3aSHans de Goede break; 1416554c0a3aSHans de Goede case LPS_CTRL_JOINBSS: 1417554c0a3aSHans de Goede /* DBG_871X("LPS_CTRL_JOINBSS\n"); */ 1418554c0a3aSHans de Goede LPS_Leave(padapter, "LPS_CTRL_JOINBSS"); 1419554c0a3aSHans de Goede break; 1420554c0a3aSHans de Goede case LPS_CTRL_CONNECT: 1421554c0a3aSHans de Goede /* DBG_871X("LPS_CTRL_CONNECT\n"); */ 1422554c0a3aSHans de Goede mstatus = 1;/* connect */ 1423554c0a3aSHans de Goede /* Reset LPS Setting */ 1424554c0a3aSHans de Goede pwrpriv->LpsIdleCount = 0; 1425554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus)); 1426554c0a3aSHans de Goede rtw_btcoex_MediaStatusNotify(padapter, mstatus); 1427554c0a3aSHans de Goede break; 1428554c0a3aSHans de Goede case LPS_CTRL_DISCONNECT: 1429554c0a3aSHans de Goede /* DBG_871X("LPS_CTRL_DISCONNECT\n"); */ 1430554c0a3aSHans de Goede mstatus = 0;/* disconnect */ 1431554c0a3aSHans de Goede rtw_btcoex_MediaStatusNotify(padapter, mstatus); 1432554c0a3aSHans de Goede LPS_Leave(padapter, "LPS_CTRL_DISCONNECT"); 1433554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus)); 1434554c0a3aSHans de Goede break; 1435554c0a3aSHans de Goede case LPS_CTRL_SPECIAL_PACKET: 1436554c0a3aSHans de Goede /* DBG_871X("LPS_CTRL_SPECIAL_PACKET\n"); */ 1437554c0a3aSHans de Goede pwrpriv->DelayLPSLastTimeStamp = jiffies; 1438800132aaSNishka Dasgupta hal_btcoex_SpecialPacketNotify(padapter, PACKET_DHCP); 1439554c0a3aSHans de Goede LPS_Leave(padapter, "LPS_CTRL_SPECIAL_PACKET"); 1440554c0a3aSHans de Goede break; 1441554c0a3aSHans de Goede case LPS_CTRL_LEAVE: 1442554c0a3aSHans de Goede /* DBG_871X("LPS_CTRL_LEAVE\n"); */ 1443554c0a3aSHans de Goede LPS_Leave(padapter, "LPS_CTRL_LEAVE"); 1444554c0a3aSHans de Goede break; 1445554c0a3aSHans de Goede case LPS_CTRL_TRAFFIC_BUSY: 1446554c0a3aSHans de Goede LPS_Leave(padapter, "LPS_CTRL_TRAFFIC_BUSY"); 14472811861bSGustavo A. R. Silva break; 1448554c0a3aSHans de Goede default: 1449554c0a3aSHans de Goede break; 1450554c0a3aSHans de Goede } 1451554c0a3aSHans de Goede } 1452554c0a3aSHans de Goede 1453554c0a3aSHans de Goede u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue) 1454554c0a3aSHans de Goede { 1455554c0a3aSHans de Goede struct cmd_obj *ph2c; 1456554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1457554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1458554c0a3aSHans de Goede /* struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); */ 1459554c0a3aSHans de Goede u8 res = _SUCCESS; 1460554c0a3aSHans de Goede 1461554c0a3aSHans de Goede /* if (!pwrctrlpriv->bLeisurePs) */ 1462554c0a3aSHans de Goede /* return res; */ 1463554c0a3aSHans de Goede 1464554c0a3aSHans de Goede if (enqueue) { 14652ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1466554c0a3aSHans de Goede if (ph2c == NULL) { 1467554c0a3aSHans de Goede res = _FAIL; 1468554c0a3aSHans de Goede goto exit; 1469554c0a3aSHans de Goede } 1470554c0a3aSHans de Goede 14712ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1472554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1473512bbd7bSSrishti Sharma kfree(ph2c); 1474554c0a3aSHans de Goede res = _FAIL; 1475554c0a3aSHans de Goede goto exit; 1476554c0a3aSHans de Goede } 1477554c0a3aSHans de Goede 1478554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID; 1479554c0a3aSHans de Goede pdrvextra_cmd_parm->type = lps_ctrl_type; 1480554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1481554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1482554c0a3aSHans de Goede 1483554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1484554c0a3aSHans de Goede 1485554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1486554c0a3aSHans de Goede } else { 1487554c0a3aSHans de Goede lps_ctrl_wk_hdl(padapter, lps_ctrl_type); 1488554c0a3aSHans de Goede } 1489554c0a3aSHans de Goede 1490554c0a3aSHans de Goede exit: 1491554c0a3aSHans de Goede return res; 1492554c0a3aSHans de Goede } 1493554c0a3aSHans de Goede 1494554c0a3aSHans de Goede static void rtw_dm_in_lps_hdl(struct adapter *padapter) 1495554c0a3aSHans de Goede { 1496554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_DM_IN_LPS, NULL); 1497554c0a3aSHans de Goede } 1498554c0a3aSHans de Goede 1499554c0a3aSHans de Goede u8 rtw_dm_in_lps_wk_cmd(struct adapter *padapter) 1500554c0a3aSHans de Goede { 1501554c0a3aSHans de Goede struct cmd_obj *ph2c; 1502554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1503554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1504554c0a3aSHans de Goede u8 res = _SUCCESS; 1505554c0a3aSHans de Goede 1506554c0a3aSHans de Goede 15072ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1508554c0a3aSHans de Goede if (ph2c == NULL) { 1509554c0a3aSHans de Goede res = _FAIL; 1510554c0a3aSHans de Goede goto exit; 1511554c0a3aSHans de Goede } 1512554c0a3aSHans de Goede 15132ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1514554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1515512bbd7bSSrishti Sharma kfree(ph2c); 1516554c0a3aSHans de Goede res = _FAIL; 1517554c0a3aSHans de Goede goto exit; 1518554c0a3aSHans de Goede } 1519554c0a3aSHans de Goede 1520554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = DM_IN_LPS_WK_CID; 1521554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1522554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1523554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1524554c0a3aSHans de Goede 1525554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1526554c0a3aSHans de Goede 1527554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1528554c0a3aSHans de Goede 1529554c0a3aSHans de Goede exit: 1530554c0a3aSHans de Goede 1531554c0a3aSHans de Goede return res; 1532554c0a3aSHans de Goede 1533554c0a3aSHans de Goede } 1534554c0a3aSHans de Goede 1535554c0a3aSHans de Goede static void rtw_lps_change_dtim_hdl(struct adapter *padapter, u8 dtim) 1536554c0a3aSHans de Goede { 1537554c0a3aSHans de Goede struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); 1538554c0a3aSHans de Goede 1539554c0a3aSHans de Goede if (dtim <= 0 || dtim > 16) 1540554c0a3aSHans de Goede return; 1541554c0a3aSHans de Goede 1542606e33ceSNishka Dasgupta if (hal_btcoex_IsBtControlLps(padapter) == true) 1543554c0a3aSHans de Goede return; 1544554c0a3aSHans de Goede 154507e3a844SArnd Bergmann mutex_lock(&pwrpriv->lock); 1546554c0a3aSHans de Goede 1547554c0a3aSHans de Goede if (pwrpriv->dtim != dtim) { 1548554c0a3aSHans de Goede DBG_871X("change DTIM from %d to %d, bFwCurrentInPSMode =%d, ps_mode =%d\n", pwrpriv->dtim, dtim, 1549554c0a3aSHans de Goede pwrpriv->bFwCurrentInPSMode, pwrpriv->pwr_mode); 1550554c0a3aSHans de Goede 1551554c0a3aSHans de Goede pwrpriv->dtim = dtim; 1552554c0a3aSHans de Goede } 1553554c0a3aSHans de Goede 1554554c0a3aSHans de Goede if ((pwrpriv->bFwCurrentInPSMode == true) && (pwrpriv->pwr_mode > PS_MODE_ACTIVE)) { 1555554c0a3aSHans de Goede u8 ps_mode = pwrpriv->pwr_mode; 1556554c0a3aSHans de Goede 1557554c0a3aSHans de Goede /* DBG_871X("change DTIM from %d to %d, ps_mode =%d\n", pwrpriv->dtim, dtim, ps_mode); */ 1558554c0a3aSHans de Goede 1559554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode)); 1560554c0a3aSHans de Goede } 1561554c0a3aSHans de Goede 156207e3a844SArnd Bergmann mutex_unlock(&pwrpriv->lock); 1563554c0a3aSHans de Goede } 1564554c0a3aSHans de Goede 1565554c0a3aSHans de Goede static void rtw_dm_ra_mask_hdl(struct adapter *padapter, struct sta_info *psta) 1566554c0a3aSHans de Goede { 15678f870aabSManuel Palenzuela if (psta) 1568554c0a3aSHans de Goede set_sta_rate(padapter, psta); 1569554c0a3aSHans de Goede } 1570554c0a3aSHans de Goede 1571554c0a3aSHans de Goede u8 rtw_dm_ra_mask_wk_cmd(struct adapter *padapter, u8 *psta) 1572554c0a3aSHans de Goede { 1573554c0a3aSHans de Goede struct cmd_obj *ph2c; 1574554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1575554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1576554c0a3aSHans de Goede u8 res = _SUCCESS; 1577554c0a3aSHans de Goede 1578554c0a3aSHans de Goede 15792ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1580554c0a3aSHans de Goede if (ph2c == NULL) { 1581554c0a3aSHans de Goede res = _FAIL; 1582554c0a3aSHans de Goede goto exit; 1583554c0a3aSHans de Goede } 1584554c0a3aSHans de Goede 15852ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1586554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1587512bbd7bSSrishti Sharma kfree(ph2c); 1588554c0a3aSHans de Goede res = _FAIL; 1589554c0a3aSHans de Goede goto exit; 1590554c0a3aSHans de Goede } 1591554c0a3aSHans de Goede 1592554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = DM_RA_MSK_WK_CID; 1593554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1594554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1595554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = psta; 1596554c0a3aSHans de Goede 1597554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1598554c0a3aSHans de Goede 1599554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1600554c0a3aSHans de Goede 1601554c0a3aSHans de Goede exit: 1602554c0a3aSHans de Goede 1603554c0a3aSHans de Goede return res; 1604554c0a3aSHans de Goede 1605554c0a3aSHans de Goede } 1606554c0a3aSHans de Goede 1607554c0a3aSHans de Goede u8 rtw_ps_cmd(struct adapter *padapter) 1608554c0a3aSHans de Goede { 1609554c0a3aSHans de Goede struct cmd_obj *ppscmd; 1610554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1611554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1612554c0a3aSHans de Goede u8 res = _SUCCESS; 1613554c0a3aSHans de Goede 16142ef2b7c2SJoe Perches ppscmd = rtw_zmalloc(sizeof(struct cmd_obj)); 1615554c0a3aSHans de Goede if (ppscmd == NULL) { 1616554c0a3aSHans de Goede res = _FAIL; 1617554c0a3aSHans de Goede goto exit; 1618554c0a3aSHans de Goede } 1619554c0a3aSHans de Goede 16202ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1621554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1622512bbd7bSSrishti Sharma kfree(ppscmd); 1623554c0a3aSHans de Goede res = _FAIL; 1624554c0a3aSHans de Goede goto exit; 1625554c0a3aSHans de Goede } 1626554c0a3aSHans de Goede 1627554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID; 1628554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1629554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1630554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1631554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1632554c0a3aSHans de Goede 1633554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ppscmd); 1634554c0a3aSHans de Goede 1635554c0a3aSHans de Goede exit: 1636554c0a3aSHans de Goede return res; 1637554c0a3aSHans de Goede } 1638554c0a3aSHans de Goede 163964b8e685SJi-Hun Kim u32 g_wait_hiq_empty; 1640f55a6d45SArnd Bergmann 1641554c0a3aSHans de Goede static void rtw_chk_hi_queue_hdl(struct adapter *padapter) 1642554c0a3aSHans de Goede { 1643554c0a3aSHans de Goede struct sta_info *psta_bmc; 1644554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1645554c0a3aSHans de Goede unsigned long start = jiffies; 1646554c0a3aSHans de Goede u8 empty = false; 1647554c0a3aSHans de Goede 1648554c0a3aSHans de Goede psta_bmc = rtw_get_bcmc_stainfo(padapter); 1649554c0a3aSHans de Goede if (!psta_bmc) 1650554c0a3aSHans de Goede return; 1651554c0a3aSHans de Goede 1652554c0a3aSHans de Goede rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty); 1653554c0a3aSHans de Goede 1654554c0a3aSHans de Goede while (false == empty && jiffies_to_msecs(jiffies - start) < g_wait_hiq_empty) { 1655554c0a3aSHans de Goede msleep(100); 1656554c0a3aSHans de Goede rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty); 1657554c0a3aSHans de Goede } 1658554c0a3aSHans de Goede 1659554c0a3aSHans de Goede if (psta_bmc->sleepq_len == 0) { 1660554c0a3aSHans de Goede if (empty == _SUCCESS) { 1661554c0a3aSHans de Goede bool update_tim = false; 1662554c0a3aSHans de Goede 1663554c0a3aSHans de Goede if (pstapriv->tim_bitmap & BIT(0)) 1664554c0a3aSHans de Goede update_tim = true; 1665554c0a3aSHans de Goede 1666554c0a3aSHans de Goede pstapriv->tim_bitmap &= ~BIT(0); 1667554c0a3aSHans de Goede pstapriv->sta_dz_bitmap &= ~BIT(0); 1668554c0a3aSHans de Goede 166963a9c3edSJeeeun Evans if (update_tim) 1670aaa0bc19SRoss Schmidt update_beacon(padapter, WLAN_EID_TIM, NULL, true); 1671554c0a3aSHans de Goede } else {/* re check again */ 1672554c0a3aSHans de Goede rtw_chk_hi_queue_cmd(padapter); 1673554c0a3aSHans de Goede } 1674554c0a3aSHans de Goede 1675554c0a3aSHans de Goede } 1676554c0a3aSHans de Goede 1677554c0a3aSHans de Goede } 1678554c0a3aSHans de Goede 1679554c0a3aSHans de Goede u8 rtw_chk_hi_queue_cmd(struct adapter *padapter) 1680554c0a3aSHans de Goede { 1681554c0a3aSHans de Goede struct cmd_obj *ph2c; 1682554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1683554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1684554c0a3aSHans de Goede u8 res = _SUCCESS; 1685554c0a3aSHans de Goede 16862ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1687554c0a3aSHans de Goede if (ph2c == NULL) { 1688554c0a3aSHans de Goede res = _FAIL; 1689554c0a3aSHans de Goede goto exit; 1690554c0a3aSHans de Goede } 1691554c0a3aSHans de Goede 16922ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1693554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1694512bbd7bSSrishti Sharma kfree(ph2c); 1695554c0a3aSHans de Goede res = _FAIL; 1696554c0a3aSHans de Goede goto exit; 1697554c0a3aSHans de Goede } 1698554c0a3aSHans de Goede 1699554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID; 1700554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1701554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1702554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1703554c0a3aSHans de Goede 1704554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1705554c0a3aSHans de Goede 1706554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1707554c0a3aSHans de Goede 1708554c0a3aSHans de Goede exit: 1709554c0a3aSHans de Goede 1710554c0a3aSHans de Goede return res; 1711554c0a3aSHans de Goede 1712554c0a3aSHans de Goede } 1713554c0a3aSHans de Goede 1714554c0a3aSHans de Goede struct btinfo { 1715554c0a3aSHans de Goede u8 cid; 1716554c0a3aSHans de Goede u8 len; 1717554c0a3aSHans de Goede 1718554c0a3aSHans de Goede u8 bConnection:1; 1719554c0a3aSHans de Goede u8 bSCOeSCO:1; 1720554c0a3aSHans de Goede u8 bInQPage:1; 1721554c0a3aSHans de Goede u8 bACLBusy:1; 1722554c0a3aSHans de Goede u8 bSCOBusy:1; 1723554c0a3aSHans de Goede u8 bHID:1; 1724554c0a3aSHans de Goede u8 bA2DP:1; 1725554c0a3aSHans de Goede u8 bFTP:1; 1726554c0a3aSHans de Goede 1727554c0a3aSHans de Goede u8 retry_cnt:4; 1728554c0a3aSHans de Goede u8 rsvd_34:1; 1729554c0a3aSHans de Goede u8 rsvd_35:1; 1730554c0a3aSHans de Goede u8 rsvd_36:1; 1731554c0a3aSHans de Goede u8 rsvd_37:1; 1732554c0a3aSHans de Goede 1733554c0a3aSHans de Goede u8 rssi; 1734554c0a3aSHans de Goede 1735554c0a3aSHans de Goede u8 rsvd_50:1; 1736554c0a3aSHans de Goede u8 rsvd_51:1; 1737554c0a3aSHans de Goede u8 rsvd_52:1; 1738554c0a3aSHans de Goede u8 rsvd_53:1; 1739554c0a3aSHans de Goede u8 rsvd_54:1; 1740554c0a3aSHans de Goede u8 rsvd_55:1; 1741554c0a3aSHans de Goede u8 eSCO_SCO:1; 1742554c0a3aSHans de Goede u8 Master_Slave:1; 1743554c0a3aSHans de Goede 1744554c0a3aSHans de Goede u8 rsvd_6; 1745554c0a3aSHans de Goede u8 rsvd_7; 1746554c0a3aSHans de Goede }; 1747554c0a3aSHans de Goede 1748554c0a3aSHans de Goede static void rtw_btinfo_hdl(struct adapter *adapter, u8 *buf, u16 buf_len) 1749554c0a3aSHans de Goede { 1750554c0a3aSHans de Goede #define BTINFO_WIFI_FETCH 0x23 1751554c0a3aSHans de Goede #define BTINFO_BT_AUTO_RPT 0x27 1752554c0a3aSHans de Goede struct btinfo *info = (struct btinfo *)buf; 1753554c0a3aSHans de Goede u8 cmd_idx; 1754554c0a3aSHans de Goede u8 len; 1755554c0a3aSHans de Goede 1756554c0a3aSHans de Goede cmd_idx = info->cid; 1757554c0a3aSHans de Goede 1758554c0a3aSHans de Goede if (info->len > buf_len-2) { 1759554c0a3aSHans de Goede rtw_warn_on(1); 1760554c0a3aSHans de Goede len = buf_len-2; 1761554c0a3aSHans de Goede } else { 1762554c0a3aSHans de Goede len = info->len; 1763554c0a3aSHans de Goede } 1764554c0a3aSHans de Goede 1765554c0a3aSHans de Goede /* transform BT-FW btinfo to WiFI-FW C2H format and notify */ 1766554c0a3aSHans de Goede if (cmd_idx == BTINFO_WIFI_FETCH) 1767554c0a3aSHans de Goede buf[1] = 0; 1768554c0a3aSHans de Goede else if (cmd_idx == BTINFO_BT_AUTO_RPT) 1769554c0a3aSHans de Goede buf[1] = 2; 1770aa0963a1SNishka Dasgupta hal_btcoex_BtInfoNotify(adapter, len+1, &buf[1]); 1771554c0a3aSHans de Goede } 1772554c0a3aSHans de Goede 1773554c0a3aSHans de Goede u8 rtw_c2h_packet_wk_cmd(struct adapter *padapter, u8 *pbuf, u16 length) 1774554c0a3aSHans de Goede { 1775554c0a3aSHans de Goede struct cmd_obj *ph2c; 1776554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1777554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1778554c0a3aSHans de Goede u8 res = _SUCCESS; 1779554c0a3aSHans de Goede 17802ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1781554c0a3aSHans de Goede if (ph2c == NULL) { 1782554c0a3aSHans de Goede res = _FAIL; 1783554c0a3aSHans de Goede goto exit; 1784554c0a3aSHans de Goede } 1785554c0a3aSHans de Goede 17862ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1787554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1788512bbd7bSSrishti Sharma kfree(ph2c); 1789554c0a3aSHans de Goede res = _FAIL; 1790554c0a3aSHans de Goede goto exit; 1791554c0a3aSHans de Goede } 1792554c0a3aSHans de Goede 1793554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = C2H_WK_CID; 1794554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1795554c0a3aSHans de Goede pdrvextra_cmd_parm->size = length; 1796554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = pbuf; 1797554c0a3aSHans de Goede 1798554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1799554c0a3aSHans de Goede 1800554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1801554c0a3aSHans de Goede 1802554c0a3aSHans de Goede exit: 1803554c0a3aSHans de Goede return res; 1804554c0a3aSHans de Goede } 1805554c0a3aSHans de Goede 1806554c0a3aSHans de Goede /* dont call R/W in this function, beucase SDIO interrupt have claim host */ 1807554c0a3aSHans de Goede /* or deadlock will happen and cause special-systemserver-died in android */ 1808554c0a3aSHans de Goede u8 rtw_c2h_wk_cmd(struct adapter *padapter, u8 *c2h_evt) 1809554c0a3aSHans de Goede { 1810554c0a3aSHans de Goede struct cmd_obj *ph2c; 1811554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1812554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1813554c0a3aSHans de Goede u8 res = _SUCCESS; 1814554c0a3aSHans de Goede 18152ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1816554c0a3aSHans de Goede if (ph2c == NULL) { 1817554c0a3aSHans de Goede res = _FAIL; 1818554c0a3aSHans de Goede goto exit; 1819554c0a3aSHans de Goede } 1820554c0a3aSHans de Goede 18212ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1822554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1823512bbd7bSSrishti Sharma kfree(ph2c); 1824554c0a3aSHans de Goede res = _FAIL; 1825554c0a3aSHans de Goede goto exit; 1826554c0a3aSHans de Goede } 1827554c0a3aSHans de Goede 1828554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = C2H_WK_CID; 1829554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1830554c0a3aSHans de Goede pdrvextra_cmd_parm->size = c2h_evt?16:0; 1831554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = c2h_evt; 1832554c0a3aSHans de Goede 1833554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1834554c0a3aSHans de Goede 1835554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1836554c0a3aSHans de Goede 1837554c0a3aSHans de Goede exit: 1838554c0a3aSHans de Goede 1839554c0a3aSHans de Goede return res; 1840554c0a3aSHans de Goede } 1841554c0a3aSHans de Goede 184200d5865cSMarco Cesati static void c2h_wk_callback(struct work_struct *work) 1843554c0a3aSHans de Goede { 1844554c0a3aSHans de Goede struct evt_priv *evtpriv = container_of(work, struct evt_priv, c2h_wk); 1845554c0a3aSHans de Goede struct adapter *adapter = container_of(evtpriv, struct adapter, evtpriv); 1846554c0a3aSHans de Goede u8 *c2h_evt; 1847554c0a3aSHans de Goede c2h_id_filter ccx_id_filter = rtw_hal_c2h_id_filter_ccx(adapter); 1848554c0a3aSHans de Goede 1849554c0a3aSHans de Goede evtpriv->c2h_wk_alive = true; 1850554c0a3aSHans de Goede 1851554c0a3aSHans de Goede while (!rtw_cbuf_empty(evtpriv->c2h_queue)) { 1852554c0a3aSHans de Goede c2h_evt = (u8 *)rtw_cbuf_pop(evtpriv->c2h_queue); 185334557e23SIzabela Bakollari if (c2h_evt) { 1854554c0a3aSHans de Goede /* This C2H event is read, clear it */ 1855554c0a3aSHans de Goede c2h_evt_clear(adapter); 1856554c0a3aSHans de Goede } else { 18572ef2b7c2SJoe Perches c2h_evt = rtw_malloc(16); 185834557e23SIzabela Bakollari if (c2h_evt) { 1859554c0a3aSHans de Goede /* This C2H event is not read, read & clear now */ 1860414faeb1SNishka Dasgupta if (c2h_evt_read_88xx(adapter, c2h_evt) != _SUCCESS) { 1861554c0a3aSHans de Goede kfree(c2h_evt); 1862554c0a3aSHans de Goede continue; 1863554c0a3aSHans de Goede } 1864554c0a3aSHans de Goede } 1865554c0a3aSHans de Goede } 1866554c0a3aSHans de Goede 1867554c0a3aSHans de Goede /* Special pointer to trigger c2h_evt_clear only */ 1868554c0a3aSHans de Goede if ((void *)c2h_evt == (void *)evtpriv) 1869554c0a3aSHans de Goede continue; 1870554c0a3aSHans de Goede 1871554c0a3aSHans de Goede if (!rtw_hal_c2h_valid(adapter, c2h_evt)) { 1872554c0a3aSHans de Goede kfree(c2h_evt); 1873554c0a3aSHans de Goede continue; 1874554c0a3aSHans de Goede } 1875554c0a3aSHans de Goede 1876554c0a3aSHans de Goede if (ccx_id_filter(c2h_evt) == true) { 1877554c0a3aSHans de Goede /* Handle CCX report here */ 1878554c0a3aSHans de Goede rtw_hal_c2h_handler(adapter, c2h_evt); 1879554c0a3aSHans de Goede kfree(c2h_evt); 1880554c0a3aSHans de Goede } else { 1881554c0a3aSHans de Goede /* Enqueue into cmd_thread for others */ 1882554c0a3aSHans de Goede rtw_c2h_wk_cmd(adapter, c2h_evt); 1883554c0a3aSHans de Goede } 1884554c0a3aSHans de Goede } 1885554c0a3aSHans de Goede 1886554c0a3aSHans de Goede evtpriv->c2h_wk_alive = false; 1887554c0a3aSHans de Goede } 1888554c0a3aSHans de Goede 1889554c0a3aSHans de Goede u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf) 1890554c0a3aSHans de Goede { 1891554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd; 1892554c0a3aSHans de Goede 1893554c0a3aSHans de Goede if (!pbuf) 1894554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 1895554c0a3aSHans de Goede 1896554c0a3aSHans de Goede pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf; 1897554c0a3aSHans de Goede 1898554c0a3aSHans de Goede switch (pdrvextra_cmd->ec_id) { 1899554c0a3aSHans de Goede case DYNAMIC_CHK_WK_CID:/* only primary padapter go to this cmd, but execute dynamic_chk_wk_hdl() for two interfaces */ 1900554c0a3aSHans de Goede dynamic_chk_wk_hdl(padapter); 1901554c0a3aSHans de Goede break; 1902554c0a3aSHans de Goede case POWER_SAVING_CTRL_WK_CID: 1903534415d2SNishka Dasgupta rtw_ps_processor(padapter); 1904554c0a3aSHans de Goede break; 1905554c0a3aSHans de Goede case LPS_CTRL_WK_CID: 1906554c0a3aSHans de Goede lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type); 1907554c0a3aSHans de Goede break; 1908554c0a3aSHans de Goede case DM_IN_LPS_WK_CID: 1909554c0a3aSHans de Goede rtw_dm_in_lps_hdl(padapter); 1910554c0a3aSHans de Goede break; 1911554c0a3aSHans de Goede case LPS_CHANGE_DTIM_CID: 1912554c0a3aSHans de Goede rtw_lps_change_dtim_hdl(padapter, (u8)pdrvextra_cmd->type); 1913554c0a3aSHans de Goede break; 1914554c0a3aSHans de Goede case CHECK_HIQ_WK_CID: 1915554c0a3aSHans de Goede rtw_chk_hi_queue_hdl(padapter); 1916554c0a3aSHans de Goede break; 1917554c0a3aSHans de Goede /* add for CONFIG_IEEE80211W, none 11w can use it */ 1918554c0a3aSHans de Goede case RESET_SECURITYPRIV: 1919534415d2SNishka Dasgupta rtw_reset_securitypriv(padapter); 1920554c0a3aSHans de Goede break; 1921554c0a3aSHans de Goede case FREE_ASSOC_RESOURCES: 1922534415d2SNishka Dasgupta rtw_free_assoc_resources(padapter, 1); 1923554c0a3aSHans de Goede break; 1924554c0a3aSHans de Goede case C2H_WK_CID: 1925554c0a3aSHans de Goede rtw_hal_set_hwreg_with_buf(padapter, HW_VAR_C2H_HANDLE, pdrvextra_cmd->pbuf, pdrvextra_cmd->size); 1926554c0a3aSHans de Goede break; 1927554c0a3aSHans de Goede case DM_RA_MSK_WK_CID: 1928554c0a3aSHans de Goede rtw_dm_ra_mask_hdl(padapter, (struct sta_info *)pdrvextra_cmd->pbuf); 1929554c0a3aSHans de Goede break; 1930554c0a3aSHans de Goede case BTINFO_WK_CID: 1931554c0a3aSHans de Goede rtw_btinfo_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size); 1932554c0a3aSHans de Goede break; 1933554c0a3aSHans de Goede default: 1934554c0a3aSHans de Goede break; 1935554c0a3aSHans de Goede } 1936554c0a3aSHans de Goede 19378f870aabSManuel Palenzuela if (pdrvextra_cmd->pbuf && pdrvextra_cmd->size > 0) 1938554c0a3aSHans de Goede kfree(pdrvextra_cmd->pbuf); 1939554c0a3aSHans de Goede 1940554c0a3aSHans de Goede return H2C_SUCCESS; 1941554c0a3aSHans de Goede } 1942554c0a3aSHans de Goede 1943554c0a3aSHans de Goede void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 1944554c0a3aSHans de Goede { 1945554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1946554c0a3aSHans de Goede 1947554c0a3aSHans de Goede if (pcmd->res == H2C_DROPPED) { 1948554c0a3aSHans de Goede /* TODO: cancel timer and do timeout handler directly... */ 1949554c0a3aSHans de Goede /* need to make timeout handlerOS independent */ 1950554c0a3aSHans de Goede _set_timer(&pmlmepriv->scan_to_timer, 1); 1951554c0a3aSHans de Goede } else if (pcmd->res != H2C_SUCCESS) { 1952554c0a3aSHans de Goede _set_timer(&pmlmepriv->scan_to_timer, 1); 1953554c0a3aSHans de Goede } 1954554c0a3aSHans de Goede 1955554c0a3aSHans de Goede /* free cmd */ 1956554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 1957554c0a3aSHans de Goede } 1958554c0a3aSHans de Goede 1959554c0a3aSHans de Goede void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 1960554c0a3aSHans de Goede { 1961554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1962554c0a3aSHans de Goede 1963554c0a3aSHans de Goede if (pcmd->res != H2C_SUCCESS) { 1964554c0a3aSHans de Goede spin_lock_bh(&pmlmepriv->lock); 1965554c0a3aSHans de Goede set_fwstate(pmlmepriv, _FW_LINKED); 1966554c0a3aSHans de Goede spin_unlock_bh(&pmlmepriv->lock); 1967554c0a3aSHans de Goede 1968554c0a3aSHans de Goede return; 1969554c0a3aSHans de Goede } 1970554c0a3aSHans de Goede /* free cmd */ 1971554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 1972554c0a3aSHans de Goede } 1973554c0a3aSHans de Goede 1974554c0a3aSHans de Goede void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 1975554c0a3aSHans de Goede { 1976554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1977554c0a3aSHans de Goede 1978554c0a3aSHans de Goede if (pcmd->res == H2C_DROPPED) { 1979554c0a3aSHans de Goede /* TODO: cancel timer and do timeout handler directly... */ 1980554c0a3aSHans de Goede /* need to make timeout handlerOS independent */ 1981554c0a3aSHans de Goede _set_timer(&pmlmepriv->assoc_timer, 1); 1982554c0a3aSHans de Goede } else if (pcmd->res != H2C_SUCCESS) { 1983554c0a3aSHans de Goede _set_timer(&pmlmepriv->assoc_timer, 1); 1984554c0a3aSHans de Goede } 1985554c0a3aSHans de Goede 1986554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 1987554c0a3aSHans de Goede } 1988554c0a3aSHans de Goede 1989554c0a3aSHans de Goede void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 1990554c0a3aSHans de Goede { 1991554c0a3aSHans de Goede struct sta_info *psta = NULL; 1992554c0a3aSHans de Goede struct wlan_network *pwlan = NULL; 1993554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1994554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf; 1995554c0a3aSHans de Goede struct wlan_network *tgt_network = &(pmlmepriv->cur_network); 1996554c0a3aSHans de Goede 1997554c0a3aSHans de Goede if (pcmd->parmbuf == NULL) 1998554c0a3aSHans de Goede goto exit; 1999554c0a3aSHans de Goede 2000*b7fd07b6SFabio Aiuto if (pcmd->res != H2C_SUCCESS) 2001554c0a3aSHans de Goede _set_timer(&pmlmepriv->assoc_timer, 1); 2002554c0a3aSHans de Goede 2003fb127a61SRoss Schmidt del_timer_sync(&pmlmepriv->assoc_timer); 2004554c0a3aSHans de Goede 2005554c0a3aSHans de Goede spin_lock_bh(&pmlmepriv->lock); 2006554c0a3aSHans de Goede 2007554c0a3aSHans de Goede 2008554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { 2009554c0a3aSHans de Goede psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress); 2010554c0a3aSHans de Goede if (!psta) { 2011554c0a3aSHans de Goede psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress); 201261e0d092SFabio Aiuto if (!psta) 2013554c0a3aSHans de Goede goto createbss_cmd_fail; 2014554c0a3aSHans de Goede } 2015554c0a3aSHans de Goede 2016554c0a3aSHans de Goede rtw_indicate_connect(padapter); 2017554c0a3aSHans de Goede } else { 20188e97f7d8SNishka Dasgupta pwlan = rtw_alloc_network(pmlmepriv); 2019554c0a3aSHans de Goede spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 2020554c0a3aSHans de Goede if (pwlan == NULL) { 2021554c0a3aSHans de Goede pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue); 2022554c0a3aSHans de Goede if (pwlan == NULL) { 2023554c0a3aSHans de Goede spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); 2024554c0a3aSHans de Goede goto createbss_cmd_fail; 2025554c0a3aSHans de Goede } 2026554c0a3aSHans de Goede pwlan->last_scanned = jiffies; 2027554c0a3aSHans de Goede } else { 2028554c0a3aSHans de Goede list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue); 2029554c0a3aSHans de Goede } 2030554c0a3aSHans de Goede 2031554c0a3aSHans de Goede pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork); 2032554c0a3aSHans de Goede memcpy(&(pwlan->network), pnetwork, pnetwork->Length); 2033554c0a3aSHans de Goede /* pwlan->fixed = true; */ 2034554c0a3aSHans de Goede 2035554c0a3aSHans de Goede /* list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue); */ 2036554c0a3aSHans de Goede 2037554c0a3aSHans de Goede /* copy pdev_network information to pmlmepriv->cur_network */ 2038554c0a3aSHans de Goede memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork))); 2039554c0a3aSHans de Goede 2040554c0a3aSHans de Goede /* reset DSConfig */ 2041554c0a3aSHans de Goede /* tgt_network->network.Configuration.DSConfig = (u32)rtw_ch2freq(pnetwork->Configuration.DSConfig); */ 2042554c0a3aSHans de Goede 2043554c0a3aSHans de Goede _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); 2044554c0a3aSHans de Goede 2045554c0a3aSHans de Goede spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); 2046554c0a3aSHans de Goede /* we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */ 2047554c0a3aSHans de Goede 2048554c0a3aSHans de Goede } 2049554c0a3aSHans de Goede 2050554c0a3aSHans de Goede createbss_cmd_fail: 2051554c0a3aSHans de Goede 2052554c0a3aSHans de Goede spin_unlock_bh(&pmlmepriv->lock); 2053554c0a3aSHans de Goede exit: 2054554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 2055554c0a3aSHans de Goede } 2056554c0a3aSHans de Goede 2057554c0a3aSHans de Goede 2058554c0a3aSHans de Goede 2059554c0a3aSHans de Goede void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2060554c0a3aSHans de Goede { 2061554c0a3aSHans de Goede 2062554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 2063554c0a3aSHans de Goede struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *) (pcmd->rsp); 2064554c0a3aSHans de Goede struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr); 2065554c0a3aSHans de Goede 206661e0d092SFabio Aiuto if (!psta) 2067554c0a3aSHans de Goede goto exit; 206813aefa65SFabio Aiuto 2069554c0a3aSHans de Goede exit: 2070554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 2071554c0a3aSHans de Goede } 2072554c0a3aSHans de Goede 2073554c0a3aSHans de Goede void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2074554c0a3aSHans de Goede { 2075554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 2076554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2077554c0a3aSHans de Goede struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf); 2078554c0a3aSHans de Goede struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *) (pcmd->rsp); 2079554c0a3aSHans de Goede struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr); 2080554c0a3aSHans de Goede 208161e0d092SFabio Aiuto if (!psta) 2082554c0a3aSHans de Goede goto exit; 2083554c0a3aSHans de Goede 2084c42a4ac4SSimran Singhal psta->aid = passocsta_rsp->cam_id; 2085c42a4ac4SSimran Singhal psta->mac_id = passocsta_rsp->cam_id; 2086554c0a3aSHans de Goede 2087554c0a3aSHans de Goede spin_lock_bh(&pmlmepriv->lock); 2088554c0a3aSHans de Goede 2089554c0a3aSHans de Goede if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) && (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)) 2090554c0a3aSHans de Goede _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); 2091554c0a3aSHans de Goede 2092554c0a3aSHans de Goede set_fwstate(pmlmepriv, _FW_LINKED); 2093554c0a3aSHans de Goede spin_unlock_bh(&pmlmepriv->lock); 2094554c0a3aSHans de Goede 2095554c0a3aSHans de Goede exit: 2096554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 2097554c0a3aSHans de Goede } 2098