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 206554c0a3aSHans de Goede static void c2h_wk_callback(_workitem * 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 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+_rtw_free_evt_priv\n")); 225554c0a3aSHans de Goede 226554c0a3aSHans de Goede _cancel_workitem_sync(&pevtpriv->c2h_wk); 227554c0a3aSHans de Goede while (pevtpriv->c2h_wk_alive) 228554c0a3aSHans de Goede msleep(10); 229554c0a3aSHans de Goede 230554c0a3aSHans de Goede while (!rtw_cbuf_empty(pevtpriv->c2h_queue)) { 231554c0a3aSHans de Goede void *c2h = rtw_cbuf_pop(pevtpriv->c2h_queue); 2328f870aabSManuel Palenzuela if (c2h && c2h != (void *)pevtpriv) 233554c0a3aSHans de Goede kfree(c2h); 234554c0a3aSHans de Goede } 235554c0a3aSHans de Goede kfree(pevtpriv->c2h_queue); 236554c0a3aSHans de Goede 237554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("-_rtw_free_evt_priv\n")); 238554c0a3aSHans de Goede } 239554c0a3aSHans de Goede 240554c0a3aSHans de Goede void _rtw_free_cmd_priv(struct cmd_priv *pcmdpriv) 241554c0a3aSHans de Goede { 242554c0a3aSHans de Goede if (pcmdpriv) { 243554c0a3aSHans de Goede kfree(pcmdpriv->cmd_allocated_buf); 244554c0a3aSHans de Goede 245554c0a3aSHans de Goede kfree(pcmdpriv->rsp_allocated_buf); 246554c0a3aSHans de Goede 247554c0a3aSHans de Goede mutex_destroy(&pcmdpriv->sctx_mutex); 248554c0a3aSHans de Goede } 249554c0a3aSHans de Goede } 250554c0a3aSHans de Goede 251554c0a3aSHans de Goede /* 252554c0a3aSHans de Goede Calling Context: 253554c0a3aSHans de Goede 254554c0a3aSHans de Goede rtw_enqueue_cmd can only be called between kernel thread, 255554c0a3aSHans de Goede since only spin_lock is used. 256554c0a3aSHans de Goede 257554c0a3aSHans de Goede ISR/Call-Back functions can't call this sub-function. 258554c0a3aSHans de Goede 259554c0a3aSHans de Goede */ 260554c0a3aSHans de Goede 261e4432160SMadhumitha Prabakaran int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj) 262554c0a3aSHans de Goede { 263554c0a3aSHans de Goede _irqL irqL; 264554c0a3aSHans de Goede 265554c0a3aSHans de Goede if (obj == NULL) 266554c0a3aSHans de Goede goto exit; 267554c0a3aSHans de Goede 268554c0a3aSHans de Goede /* spin_lock_bh(&queue->lock); */ 269554c0a3aSHans de Goede spin_lock_irqsave(&queue->lock, irqL); 270554c0a3aSHans de Goede 271554c0a3aSHans de Goede list_add_tail(&obj->list, &queue->queue); 272554c0a3aSHans de Goede 273554c0a3aSHans de Goede /* spin_unlock_bh(&queue->lock); */ 274554c0a3aSHans de Goede spin_unlock_irqrestore(&queue->lock, irqL); 275554c0a3aSHans de Goede 276554c0a3aSHans de Goede exit: 277554c0a3aSHans de Goede return _SUCCESS; 278554c0a3aSHans de Goede } 279554c0a3aSHans de Goede 280554c0a3aSHans de Goede struct cmd_obj *_rtw_dequeue_cmd(struct __queue *queue) 281554c0a3aSHans de Goede { 282554c0a3aSHans de Goede _irqL irqL; 283554c0a3aSHans de Goede struct cmd_obj *obj; 284554c0a3aSHans de Goede 285554c0a3aSHans de Goede /* spin_lock_bh(&(queue->lock)); */ 286554c0a3aSHans de Goede spin_lock_irqsave(&queue->lock, irqL); 287554c0a3aSHans de Goede if (list_empty(&(queue->queue))) 288554c0a3aSHans de Goede obj = NULL; 289554c0a3aSHans de Goede else { 290554c0a3aSHans de Goede obj = LIST_CONTAINOR(get_next(&(queue->queue)), struct cmd_obj, list); 291554c0a3aSHans de Goede list_del_init(&obj->list); 292554c0a3aSHans de Goede } 293554c0a3aSHans de Goede 294554c0a3aSHans de Goede /* spin_unlock_bh(&(queue->lock)); */ 295554c0a3aSHans de Goede spin_unlock_irqrestore(&queue->lock, irqL); 296554c0a3aSHans de Goede 297554c0a3aSHans de Goede return obj; 298554c0a3aSHans de Goede } 299554c0a3aSHans de Goede 300554c0a3aSHans de Goede void rtw_free_evt_priv(struct evt_priv *pevtpriv) 301554c0a3aSHans de Goede { 302554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("rtw_free_evt_priv\n")); 303554c0a3aSHans de Goede _rtw_free_evt_priv(pevtpriv); 304554c0a3aSHans de Goede } 305554c0a3aSHans de Goede 306554c0a3aSHans de Goede void rtw_free_cmd_priv(struct cmd_priv *pcmdpriv) 307554c0a3aSHans de Goede { 308554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("rtw_free_cmd_priv\n")); 309554c0a3aSHans de Goede _rtw_free_cmd_priv(pcmdpriv); 310554c0a3aSHans de Goede } 311554c0a3aSHans de Goede 312554c0a3aSHans de Goede int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj); 313554c0a3aSHans de Goede int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) 314554c0a3aSHans de Goede { 315554c0a3aSHans de Goede u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */ 316554c0a3aSHans de Goede 317554c0a3aSHans de Goede if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan)) 318554c0a3aSHans de Goede bAllow = true; 319554c0a3aSHans de Goede 320554c0a3aSHans de Goede if ((pcmdpriv->padapter->hw_init_completed == false && bAllow == false) 321554c0a3aSHans de Goede || atomic_read(&(pcmdpriv->cmdthd_running)) == false /* com_thread not running */ 322554c0a3aSHans de Goede ) { 323554c0a3aSHans de Goede /* DBG_871X("%s:%s: drop cmdcode:%u, hw_init_completed:%u, cmdthd_running:%u\n", caller_func, __func__, */ 324554c0a3aSHans de Goede /* cmd_obj->cmdcode, */ 325554c0a3aSHans de Goede /* pcmdpriv->padapter->hw_init_completed, */ 326554c0a3aSHans de Goede /* pcmdpriv->cmdthd_running */ 327554c0a3aSHans de Goede /* */ 328554c0a3aSHans de Goede 329554c0a3aSHans de Goede return _FAIL; 330554c0a3aSHans de Goede } 331554c0a3aSHans de Goede return _SUCCESS; 332554c0a3aSHans de Goede } 333554c0a3aSHans de Goede 334554c0a3aSHans de Goede 335554c0a3aSHans de Goede 336e4432160SMadhumitha Prabakaran int rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) 337554c0a3aSHans de Goede { 338554c0a3aSHans de Goede int res = _FAIL; 339554c0a3aSHans de Goede struct adapter *padapter = pcmdpriv->padapter; 340554c0a3aSHans de Goede 3418f870aabSManuel Palenzuela if (cmd_obj == NULL) 342554c0a3aSHans de Goede goto exit; 343554c0a3aSHans de Goede 344554c0a3aSHans de Goede cmd_obj->padapter = padapter; 345554c0a3aSHans de Goede 346554c0a3aSHans de Goede res = rtw_cmd_filter(pcmdpriv, cmd_obj); 34792576c84SManuel Palenzuela if (res == _FAIL) { 348554c0a3aSHans de Goede rtw_free_cmd_obj(cmd_obj); 349554c0a3aSHans de Goede goto exit; 350554c0a3aSHans de Goede } 351554c0a3aSHans de Goede 352554c0a3aSHans de Goede res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj); 353554c0a3aSHans de Goede 354554c0a3aSHans de Goede if (res == _SUCCESS) 35509a8ea34SArnd Bergmann complete(&pcmdpriv->cmd_queue_comp); 356554c0a3aSHans de Goede 357554c0a3aSHans de Goede exit: 358554c0a3aSHans de Goede return res; 359554c0a3aSHans de Goede } 360554c0a3aSHans de Goede 361554c0a3aSHans de Goede struct cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv) 362554c0a3aSHans de Goede { 3631b590af9SSimran Singhal return _rtw_dequeue_cmd(&pcmdpriv->cmd_queue); 364554c0a3aSHans de Goede } 365554c0a3aSHans de Goede 366554c0a3aSHans de Goede void rtw_free_cmd_obj(struct cmd_obj *pcmd) 367554c0a3aSHans de Goede { 368554c0a3aSHans de Goede if ((pcmd->cmdcode != _JoinBss_CMD_) && 369554c0a3aSHans de Goede (pcmd->cmdcode != _CreateBss_CMD_)) { 370554c0a3aSHans de Goede /* free parmbuf in cmd_obj */ 3712dac96b3SNachammai Karuppiah kfree(pcmd->parmbuf); 372554c0a3aSHans de Goede } 373554c0a3aSHans de Goede 37434557e23SIzabela Bakollari if (pcmd->rsp) { 375554c0a3aSHans de Goede if (pcmd->rspsz != 0) { 376554c0a3aSHans de Goede /* free rsp in cmd_obj */ 3772dac96b3SNachammai Karuppiah kfree(pcmd->rsp); 378554c0a3aSHans de Goede } 379554c0a3aSHans de Goede } 380554c0a3aSHans de Goede 381554c0a3aSHans de Goede /* free cmd_obj */ 382512bbd7bSSrishti Sharma kfree(pcmd); 383554c0a3aSHans de Goede } 384554c0a3aSHans de Goede 385554c0a3aSHans de Goede 386554c0a3aSHans de Goede void rtw_stop_cmd_thread(struct adapter *adapter) 387554c0a3aSHans de Goede { 388554c0a3aSHans de Goede if (adapter->cmdThread && 389554c0a3aSHans de Goede atomic_read(&(adapter->cmdpriv.cmdthd_running)) == true && 390554c0a3aSHans de Goede adapter->cmdpriv.stop_req == 0) { 391554c0a3aSHans de Goede adapter->cmdpriv.stop_req = 1; 39209a8ea34SArnd Bergmann complete(&adapter->cmdpriv.cmd_queue_comp); 39309a8ea34SArnd Bergmann wait_for_completion(&adapter->cmdpriv.terminate_cmdthread_comp); 394554c0a3aSHans de Goede } 395554c0a3aSHans de Goede } 396554c0a3aSHans de Goede 397554c0a3aSHans de Goede int rtw_cmd_thread(void *context) 398554c0a3aSHans de Goede { 399554c0a3aSHans de Goede u8 ret; 400554c0a3aSHans de Goede struct cmd_obj *pcmd; 401d698b0a0SYueHaibing u8 *pcmdbuf; 402554c0a3aSHans de Goede unsigned long cmd_start_time; 403554c0a3aSHans de Goede unsigned long cmd_process_time; 404554c0a3aSHans de Goede u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf); 405554c0a3aSHans de Goede void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd); 406529d87b4SHimanshu Jha struct adapter *padapter = context; 407554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); 408554c0a3aSHans de Goede struct drvextra_cmd_parm *extra_parm = NULL; 409554c0a3aSHans de Goede 410554c0a3aSHans de Goede thread_enter("RTW_CMD_THREAD"); 411554c0a3aSHans de Goede 412554c0a3aSHans de Goede pcmdbuf = pcmdpriv->cmd_buf; 413554c0a3aSHans de Goede 414554c0a3aSHans de Goede pcmdpriv->stop_req = 0; 415554c0a3aSHans de Goede atomic_set(&(pcmdpriv->cmdthd_running), true); 41609a8ea34SArnd Bergmann complete(&pcmdpriv->terminate_cmdthread_comp); 417554c0a3aSHans de Goede 418554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("start r871x rtw_cmd_thread !!!!\n")); 419554c0a3aSHans de Goede 420554c0a3aSHans de Goede while (1) { 42109a8ea34SArnd Bergmann if (wait_for_completion_interruptible(&pcmdpriv->cmd_queue_comp)) { 42209a8ea34SArnd 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)); 423554c0a3aSHans de Goede break; 424554c0a3aSHans de Goede } 425554c0a3aSHans de Goede 426554c0a3aSHans de Goede if ((padapter->bDriverStopped == true) || (padapter->bSurpriseRemoved == true)) { 427554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n", 428554c0a3aSHans de Goede __func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__); 429554c0a3aSHans de Goede break; 430554c0a3aSHans de Goede } 431554c0a3aSHans de Goede 432554c0a3aSHans de Goede if (pcmdpriv->stop_req) { 433554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" stop_req:%u, break\n", FUNC_ADPT_ARG(padapter), pcmdpriv->stop_req); 434554c0a3aSHans de Goede break; 435554c0a3aSHans de Goede } 436554c0a3aSHans de Goede 437554c0a3aSHans de Goede if (list_empty(&(pcmdpriv->cmd_queue.queue))) { 438554c0a3aSHans de Goede /* DBG_871X("%s: cmd queue is empty!\n", __func__); */ 439554c0a3aSHans de Goede continue; 440554c0a3aSHans de Goede } 441554c0a3aSHans de Goede 442554c0a3aSHans de Goede if (rtw_register_cmd_alive(padapter) != _SUCCESS) { 443554c0a3aSHans de Goede RT_TRACE(_module_hal_xmit_c_, _drv_notice_, 444554c0a3aSHans de Goede ("%s: wait to leave LPS_LCLK\n", __func__)); 445554c0a3aSHans de Goede continue; 446554c0a3aSHans de Goede } 447554c0a3aSHans de Goede 448554c0a3aSHans de Goede _next: 449554c0a3aSHans de Goede if ((padapter->bDriverStopped == true) || (padapter->bSurpriseRemoved == true)) { 450554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n", 451554c0a3aSHans de Goede __func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__); 452554c0a3aSHans de Goede break; 453554c0a3aSHans de Goede } 454554c0a3aSHans de Goede 455554c0a3aSHans de Goede pcmd = rtw_dequeue_cmd(pcmdpriv); 456554c0a3aSHans de Goede if (!pcmd) { 457554c0a3aSHans de Goede rtw_unregister_cmd_alive(padapter); 458554c0a3aSHans de Goede continue; 459554c0a3aSHans de Goede } 460554c0a3aSHans de Goede 461554c0a3aSHans de Goede cmd_start_time = jiffies; 462554c0a3aSHans de Goede 46392576c84SManuel Palenzuela if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) { 464554c0a3aSHans de Goede pcmd->res = H2C_DROPPED; 465554c0a3aSHans de Goede goto post_process; 466554c0a3aSHans de Goede } 467554c0a3aSHans de Goede 468554c0a3aSHans de Goede pcmdpriv->cmd_issued_cnt++; 469554c0a3aSHans de Goede 470046bd5c9SRoss Schmidt pcmd->cmdsz = round_up((pcmd->cmdsz), 4); 471554c0a3aSHans de Goede 472554c0a3aSHans de Goede memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz); 473554c0a3aSHans de Goede 474554c0a3aSHans de Goede if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) { 475554c0a3aSHans de Goede cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns; 476554c0a3aSHans de Goede 477554c0a3aSHans de Goede if (cmd_hdl) { 478554c0a3aSHans de Goede ret = cmd_hdl(pcmd->padapter, pcmdbuf); 479554c0a3aSHans de Goede pcmd->res = ret; 480554c0a3aSHans de Goede } 481554c0a3aSHans de Goede 482554c0a3aSHans de Goede pcmdpriv->cmd_seq++; 483554c0a3aSHans de Goede } else { 484554c0a3aSHans de Goede pcmd->res = H2C_PARAMETERS_ERROR; 485554c0a3aSHans de Goede } 486554c0a3aSHans de Goede 487554c0a3aSHans de Goede cmd_hdl = NULL; 488554c0a3aSHans de Goede 489554c0a3aSHans de Goede post_process: 490554c0a3aSHans de Goede 491554c0a3aSHans de Goede if (mutex_lock_interruptible(&(pcmd->padapter->cmdpriv.sctx_mutex)) == 0) { 492554c0a3aSHans de Goede if (pcmd->sctx) { 493554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" pcmd->sctx\n", 494554c0a3aSHans de Goede FUNC_ADPT_ARG(pcmd->padapter)); 495554c0a3aSHans de Goede 496554c0a3aSHans de Goede if (pcmd->res == H2C_SUCCESS) 497554c0a3aSHans de Goede rtw_sctx_done(&pcmd->sctx); 498554c0a3aSHans de Goede else 499554c0a3aSHans de Goede rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_ERROR); 500554c0a3aSHans de Goede } 501554c0a3aSHans de Goede mutex_unlock(&(pcmd->padapter->cmdpriv.sctx_mutex)); 502554c0a3aSHans de Goede } 503554c0a3aSHans de Goede 504554c0a3aSHans de Goede cmd_process_time = jiffies_to_msecs(jiffies - cmd_start_time); 505554c0a3aSHans de Goede if (cmd_process_time > 1000) { 506d0cc39cdSRoss Schmidt DBG_871X("%s cmd= %d process_time= %lu > 1 sec\n", 507be88dae8SAliasgar Surti ADPT_ARG(pcmd->padapter), pcmd->cmdcode, 508be88dae8SAliasgar Surti cmd_process_time); 509554c0a3aSHans de Goede } 510554c0a3aSHans de Goede 511554c0a3aSHans de Goede /* call callback function for post-processed */ 512554c0a3aSHans de Goede if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) { 513554c0a3aSHans de Goede pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback; 514554c0a3aSHans de Goede if (pcmd_callback == NULL) { 515554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("mlme_cmd_hdl(): pcmd_callback = 0x%p, cmdcode = 0x%x\n", pcmd_callback, pcmd->cmdcode)); 516554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 517554c0a3aSHans de Goede } else { 518554c0a3aSHans de Goede /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */ 519858ea450SR Veera Kumar pcmd_callback(pcmd->padapter, pcmd);/* need consider that free cmd_obj in rtw_cmd_callback */ 520554c0a3aSHans de Goede } 521554c0a3aSHans de Goede } else { 522554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("%s: cmdcode = 0x%x callback not defined!\n", __func__, pcmd->cmdcode)); 523554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 524554c0a3aSHans de Goede } 525554c0a3aSHans de Goede 526554c0a3aSHans de Goede flush_signals_thread(); 527554c0a3aSHans de Goede 528554c0a3aSHans de Goede goto _next; 529554c0a3aSHans de Goede 530554c0a3aSHans de Goede } 531554c0a3aSHans de Goede 532554c0a3aSHans de Goede /* free all cmd_obj resources */ 533554c0a3aSHans de Goede do { 534554c0a3aSHans de Goede pcmd = rtw_dequeue_cmd(pcmdpriv); 535554c0a3aSHans de Goede if (pcmd == NULL) { 536554c0a3aSHans de Goede rtw_unregister_cmd_alive(padapter); 537554c0a3aSHans de Goede break; 538554c0a3aSHans de Goede } 539554c0a3aSHans de Goede 540554c0a3aSHans de Goede /* DBG_871X("%s: leaving... drop cmdcode:%u size:%d\n", __func__, pcmd->cmdcode, pcmd->cmdsz); */ 541554c0a3aSHans de Goede 542554c0a3aSHans de Goede if (pcmd->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) { 543554c0a3aSHans de Goede extra_parm = (struct drvextra_cmd_parm *)pcmd->parmbuf; 5448f870aabSManuel Palenzuela if (extra_parm->pbuf && extra_parm->size > 0) 545554c0a3aSHans de Goede kfree(extra_parm->pbuf); 546554c0a3aSHans de Goede } 547554c0a3aSHans de Goede 548554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 549554c0a3aSHans de Goede } while (1); 550554c0a3aSHans de Goede 55109a8ea34SArnd Bergmann complete(&pcmdpriv->terminate_cmdthread_comp); 552554c0a3aSHans de Goede atomic_set(&(pcmdpriv->cmdthd_running), false); 553554c0a3aSHans de Goede 554554c0a3aSHans de Goede thread_exit(); 555554c0a3aSHans de Goede } 556554c0a3aSHans de Goede 557554c0a3aSHans de Goede /* 558554c0a3aSHans de Goede rtw_sitesurvey_cmd(~) 559554c0a3aSHans de Goede ### NOTE:#### (!!!!) 560554c0a3aSHans de Goede MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock 561554c0a3aSHans de Goede */ 562554c0a3aSHans de Goede u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, int ssid_num, 563554c0a3aSHans de Goede struct rtw_ieee80211_channel *ch, int ch_num) 564554c0a3aSHans de Goede { 565554c0a3aSHans de Goede u8 res = _FAIL; 566554c0a3aSHans de Goede struct cmd_obj *ph2c; 567554c0a3aSHans de Goede struct sitesurvey_parm *psurveyPara; 568554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 569554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 570554c0a3aSHans de Goede 5718f870aabSManuel Palenzuela if (check_fwstate(pmlmepriv, _FW_LINKED) == true) 572554c0a3aSHans de Goede rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1); 573554c0a3aSHans de Goede 5742ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 575554c0a3aSHans de Goede if (ph2c == NULL) 576554c0a3aSHans de Goede return _FAIL; 577554c0a3aSHans de Goede 5782ef2b7c2SJoe Perches psurveyPara = rtw_zmalloc(sizeof(struct sitesurvey_parm)); 579554c0a3aSHans de Goede if (psurveyPara == NULL) { 580512bbd7bSSrishti Sharma kfree(ph2c); 581554c0a3aSHans de Goede return _FAIL; 582554c0a3aSHans de Goede } 583554c0a3aSHans de Goede 584554c0a3aSHans de Goede rtw_free_network_queue(padapter, false); 585554c0a3aSHans de Goede 586554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("%s: flush network queue\n", __func__)); 587554c0a3aSHans de Goede 588554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey)); 589554c0a3aSHans de Goede 590554c0a3aSHans de Goede /* psurveyPara->bsslimit = 48; */ 591554c0a3aSHans de Goede psurveyPara->scan_mode = pmlmepriv->scan_mode; 592554c0a3aSHans de Goede 593554c0a3aSHans de Goede /* prepare ssid list */ 594554c0a3aSHans de Goede if (ssid) { 595554c0a3aSHans de Goede int i; 596554c0a3aSHans de Goede for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) { 597554c0a3aSHans de Goede if (ssid[i].SsidLength) { 598554c0a3aSHans de Goede memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid)); 599554c0a3aSHans de Goede psurveyPara->ssid_num++; 600554c0a3aSHans de Goede 601554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" ssid:(%s, %d)\n", FUNC_ADPT_ARG(padapter), 602554c0a3aSHans de Goede psurveyPara->ssid[i].Ssid, psurveyPara->ssid[i].SsidLength); 603554c0a3aSHans de Goede } 604554c0a3aSHans de Goede } 605554c0a3aSHans de Goede } 606554c0a3aSHans de Goede 607554c0a3aSHans de Goede /* prepare channel list */ 608554c0a3aSHans de Goede if (ch) { 609554c0a3aSHans de Goede int i; 610554c0a3aSHans de Goede for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) { 611554c0a3aSHans de Goede if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) { 612554c0a3aSHans de Goede memcpy(&psurveyPara->ch[i], &ch[i], sizeof(struct rtw_ieee80211_channel)); 613554c0a3aSHans de Goede psurveyPara->ch_num++; 614554c0a3aSHans de Goede 615554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter), 616554c0a3aSHans de Goede psurveyPara->ch[i].hw_value); 617554c0a3aSHans de Goede } 618554c0a3aSHans de Goede } 619554c0a3aSHans de Goede } 620554c0a3aSHans de Goede 621554c0a3aSHans de Goede set_fwstate(pmlmepriv, _FW_UNDER_SURVEY); 622554c0a3aSHans de Goede 623554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 624554c0a3aSHans de Goede 625554c0a3aSHans de Goede if (res == _SUCCESS) { 626554c0a3aSHans de Goede 627554c0a3aSHans de Goede pmlmepriv->scan_start_time = jiffies; 628554c0a3aSHans de Goede _set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT); 629554c0a3aSHans de Goede } else { 630554c0a3aSHans de Goede _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); 631554c0a3aSHans de Goede } 632554c0a3aSHans de Goede return res; 633554c0a3aSHans de Goede } 634554c0a3aSHans de Goede 635554c0a3aSHans de Goede u8 rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset) 636554c0a3aSHans de Goede { 637554c0a3aSHans de Goede struct cmd_obj *ph2c; 638554c0a3aSHans de Goede struct setdatarate_parm *pbsetdataratepara; 639554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 640554c0a3aSHans de Goede u8 res = _SUCCESS; 641554c0a3aSHans de Goede 6422ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 643554c0a3aSHans de Goede if (ph2c == NULL) { 644554c0a3aSHans de Goede res = _FAIL; 645554c0a3aSHans de Goede goto exit; 646554c0a3aSHans de Goede } 647554c0a3aSHans de Goede 6482ef2b7c2SJoe Perches pbsetdataratepara = rtw_zmalloc(sizeof(struct setdatarate_parm)); 649554c0a3aSHans de Goede if (pbsetdataratepara == NULL) { 650512bbd7bSSrishti Sharma kfree(ph2c); 651554c0a3aSHans de Goede res = _FAIL; 652554c0a3aSHans de Goede goto exit; 653554c0a3aSHans de Goede } 654554c0a3aSHans de Goede 655554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, GEN_CMD_CODE(_SetDataRate)); 656554c0a3aSHans de Goede pbsetdataratepara->mac_id = 5; 657554c0a3aSHans de Goede memcpy(pbsetdataratepara->datarates, rateset, NumRates); 658554c0a3aSHans de Goede 659554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 660554c0a3aSHans de Goede exit: 661554c0a3aSHans de Goede return res; 662554c0a3aSHans de Goede } 663554c0a3aSHans de Goede 664554c0a3aSHans de Goede void rtw_getbbrfreg_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) 665554c0a3aSHans de Goede { 666554c0a3aSHans de Goede /* rtw_free_cmd_obj(pcmd); */ 667512bbd7bSSrishti Sharma kfree(pcmd->parmbuf); 668512bbd7bSSrishti Sharma kfree(pcmd); 669554c0a3aSHans de Goede } 670554c0a3aSHans de Goede 671554c0a3aSHans de Goede u8 rtw_createbss_cmd(struct adapter *padapter) 672554c0a3aSHans de Goede { 673554c0a3aSHans de Goede struct cmd_obj *pcmd; 674554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 675554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 676554c0a3aSHans de Goede struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network; 677554c0a3aSHans de Goede u8 res = _SUCCESS; 678554c0a3aSHans de Goede 679554c0a3aSHans de Goede if (pmlmepriv->assoc_ssid.SsidLength == 0) { 680554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for Any SSid:%s\n", pmlmepriv->assoc_ssid.Ssid)); 681554c0a3aSHans de Goede } else { 682554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid)); 683554c0a3aSHans de Goede } 684554c0a3aSHans de Goede 6852ef2b7c2SJoe Perches pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); 686554c0a3aSHans de Goede if (pcmd == NULL) { 687554c0a3aSHans de Goede res = _FAIL; 688554c0a3aSHans de Goede goto exit; 689554c0a3aSHans de Goede } 690554c0a3aSHans de Goede 691554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd->list); 692554c0a3aSHans de Goede pcmd->cmdcode = _CreateBss_CMD_; 693554c0a3aSHans de Goede pcmd->parmbuf = (unsigned char *)pdev_network; 694554c0a3aSHans de Goede pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network); 695554c0a3aSHans de Goede pcmd->rsp = NULL; 696554c0a3aSHans de Goede pcmd->rspsz = 0; 697554c0a3aSHans de Goede 698554c0a3aSHans de Goede pdev_network->Length = pcmd->cmdsz; 699554c0a3aSHans de Goede 700554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, pcmd); 701554c0a3aSHans de Goede 702554c0a3aSHans de Goede exit: 703554c0a3aSHans de Goede return res; 704554c0a3aSHans de Goede } 705554c0a3aSHans de Goede 706e4432160SMadhumitha Prabakaran int rtw_startbss_cmd(struct adapter *padapter, int flags) 707554c0a3aSHans de Goede { 708554c0a3aSHans de Goede struct cmd_obj *pcmd; 709554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 710554c0a3aSHans de Goede struct submit_ctx sctx; 711e4432160SMadhumitha Prabakaran int res = _SUCCESS; 712554c0a3aSHans de Goede 713554c0a3aSHans de Goede if (flags & RTW_CMDF_DIRECTLY) { 714554c0a3aSHans de Goede /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ 715554c0a3aSHans de Goede start_bss_network(padapter, (u8 *)&(padapter->mlmepriv.cur_network.network)); 716554c0a3aSHans de Goede } else { 717554c0a3aSHans de Goede /* need enqueue, prepare cmd_obj and enqueue */ 7182ef2b7c2SJoe Perches pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); 719554c0a3aSHans de Goede if (pcmd == NULL) { 720554c0a3aSHans de Goede res = _FAIL; 721554c0a3aSHans de Goede goto exit; 722554c0a3aSHans de Goede } 723554c0a3aSHans de Goede 724554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd->list); 725554c0a3aSHans de Goede pcmd->cmdcode = GEN_CMD_CODE(_CreateBss); 726554c0a3aSHans de Goede pcmd->parmbuf = NULL; 727554c0a3aSHans de Goede pcmd->cmdsz = 0; 728554c0a3aSHans de Goede pcmd->rsp = NULL; 729554c0a3aSHans de Goede pcmd->rspsz = 0; 730554c0a3aSHans de Goede 731554c0a3aSHans de Goede if (flags & RTW_CMDF_WAIT_ACK) { 732554c0a3aSHans de Goede pcmd->sctx = &sctx; 733554c0a3aSHans de Goede rtw_sctx_init(&sctx, 2000); 734554c0a3aSHans de Goede } 735554c0a3aSHans de Goede 736554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, pcmd); 737554c0a3aSHans de Goede 738554c0a3aSHans de Goede if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) { 739554c0a3aSHans de Goede rtw_sctx_wait(&sctx, __func__); 740554c0a3aSHans de Goede if (mutex_lock_interruptible(&pcmdpriv->sctx_mutex) == 0) { 741554c0a3aSHans de Goede if (sctx.status == RTW_SCTX_SUBMITTED) 742554c0a3aSHans de Goede pcmd->sctx = NULL; 743554c0a3aSHans de Goede mutex_unlock(&pcmdpriv->sctx_mutex); 744554c0a3aSHans de Goede } 745554c0a3aSHans de Goede } 746554c0a3aSHans de Goede } 747554c0a3aSHans de Goede 748554c0a3aSHans de Goede exit: 749554c0a3aSHans de Goede return res; 750554c0a3aSHans de Goede } 751554c0a3aSHans de Goede 752554c0a3aSHans de Goede u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) 753554c0a3aSHans de Goede { 754d698b0a0SYueHaibing u8 res = _SUCCESS; 755554c0a3aSHans de Goede uint t_len = 0; 756554c0a3aSHans de Goede struct wlan_bssid_ex *psecnetwork; 757554c0a3aSHans de Goede struct cmd_obj *pcmd; 758554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 759554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 760554c0a3aSHans de Goede struct qos_priv *pqospriv = &pmlmepriv->qospriv; 761554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 762554c0a3aSHans de Goede struct registry_priv *pregistrypriv = &padapter->registrypriv; 763554c0a3aSHans de Goede struct ht_priv *phtpriv = &pmlmepriv->htpriv; 764554c0a3aSHans de Goede enum NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = pnetwork->network.InfrastructureMode; 765554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 766554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 767554c0a3aSHans de Goede u32 tmp_len; 768554c0a3aSHans de Goede u8 *ptmp = NULL; 769554c0a3aSHans de Goede 770554c0a3aSHans de Goede if (pmlmepriv->assoc_ssid.SsidLength == 0) { 771554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+Join cmd: Any SSid\n")); 772554c0a3aSHans de Goede } else { 773554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+Join cmd: SSid =[%s]\n", pmlmepriv->assoc_ssid.Ssid)); 774554c0a3aSHans de Goede } 775554c0a3aSHans de Goede 7762ef2b7c2SJoe Perches pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); 777554c0a3aSHans de Goede if (pcmd == NULL) { 778554c0a3aSHans de Goede res = _FAIL; 779554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd: memory allocate for cmd_obj fail!!!\n")); 780554c0a3aSHans de Goede goto exit; 781554c0a3aSHans de Goede } 782554c0a3aSHans de Goede /* for IEs is fix buf size */ 783554c0a3aSHans de Goede t_len = sizeof(struct wlan_bssid_ex); 784554c0a3aSHans de Goede 785554c0a3aSHans de Goede 786554c0a3aSHans de Goede /* for hidden ap to set fw_state here */ 787554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) != true) { 788554c0a3aSHans de Goede switch (ndis_network_mode) { 789554c0a3aSHans de Goede case Ndis802_11IBSS: 790554c0a3aSHans de Goede set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); 791554c0a3aSHans de Goede break; 792554c0a3aSHans de Goede 793554c0a3aSHans de Goede case Ndis802_11Infrastructure: 794554c0a3aSHans de Goede set_fwstate(pmlmepriv, WIFI_STATION_STATE); 795554c0a3aSHans de Goede break; 796554c0a3aSHans de Goede 797554c0a3aSHans de Goede case Ndis802_11APMode: 798554c0a3aSHans de Goede case Ndis802_11AutoUnknown: 799554c0a3aSHans de Goede case Ndis802_11InfrastructureMax: 800554c0a3aSHans de Goede break; 801554c0a3aSHans de Goede 802554c0a3aSHans de Goede } 803554c0a3aSHans de Goede } 804554c0a3aSHans de Goede 805554c0a3aSHans de Goede psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss; 806554c0a3aSHans de Goede 807554c0a3aSHans de Goede memset(psecnetwork, 0, t_len); 808554c0a3aSHans de Goede 809554c0a3aSHans de Goede memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network)); 810554c0a3aSHans de Goede 811554c0a3aSHans de Goede psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength; 812554c0a3aSHans de Goede 813554c0a3aSHans de Goede if ((psecnetwork->IELength-12) < (256-1)) { 814554c0a3aSHans de Goede memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength-12); 815554c0a3aSHans de Goede } else { 816554c0a3aSHans de Goede memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256-1)); 817554c0a3aSHans de Goede } 818554c0a3aSHans de Goede 819554c0a3aSHans de Goede psecnetwork->IELength = 0; 820554c0a3aSHans de Goede /* Added by Albert 2009/02/18 */ 821705b7c36Skyoungho koo /* If the driver wants to use the bssid to create the connection. */ 822554c0a3aSHans de Goede /* If not, we have to copy the connecting AP's MAC address to it so that */ 823554c0a3aSHans de Goede /* the driver just has the bssid information for PMKIDList searching. */ 824554c0a3aSHans de Goede 8258f870aabSManuel Palenzuela if (pmlmepriv->assoc_by_bssid == false) 826554c0a3aSHans de Goede memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN); 827554c0a3aSHans de Goede 828554c0a3aSHans de Goede psecnetwork->IELength = rtw_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength); 829554c0a3aSHans de Goede 830554c0a3aSHans de Goede 831554c0a3aSHans de Goede pqospriv->qos_option = 0; 832554c0a3aSHans de Goede 833554c0a3aSHans de Goede if (pregistrypriv->wmm_enable) { 834554c0a3aSHans de Goede tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength); 835554c0a3aSHans de Goede 836554c0a3aSHans de Goede if (psecnetwork->IELength != tmp_len) { 837554c0a3aSHans de Goede psecnetwork->IELength = tmp_len; 838554c0a3aSHans de Goede pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */ 839554c0a3aSHans de Goede } else { 840554c0a3aSHans de Goede pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */ 841554c0a3aSHans de Goede } 842554c0a3aSHans de Goede } 843554c0a3aSHans de Goede 844554c0a3aSHans de Goede phtpriv->ht_option = false; 845554c0a3aSHans de Goede ptmp = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &tmp_len, pnetwork->network.IELength-12); 846554c0a3aSHans de Goede if (pregistrypriv->ht_enable && ptmp && tmp_len > 0) { 847554c0a3aSHans de Goede /* Added by Albert 2010/06/23 */ 848554c0a3aSHans de Goede /* For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */ 849554c0a3aSHans de Goede /* Especially for Realtek 8192u SoftAP. */ 850554c0a3aSHans de Goede if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) && 851554c0a3aSHans de Goede (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) && 852554c0a3aSHans de Goede (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) { 853554c0a3aSHans de Goede rtw_ht_use_default_setting(padapter); 854554c0a3aSHans de Goede 855554c0a3aSHans de Goede rtw_build_wmm_ie_ht(padapter, &psecnetwork->IEs[12], &psecnetwork->IELength); 856554c0a3aSHans de Goede 857554c0a3aSHans de Goede /* rtw_restructure_ht_ie */ 858554c0a3aSHans de Goede rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[12], &psecnetwork->IEs[0], 859554c0a3aSHans de Goede pnetwork->network.IELength-12, &psecnetwork->IELength, 860554c0a3aSHans de Goede pnetwork->network.Configuration.DSConfig); 861554c0a3aSHans de Goede } 862554c0a3aSHans de Goede } 863554c0a3aSHans de Goede 864554c0a3aSHans de Goede rtw_append_exented_cap(padapter, &psecnetwork->IEs[0], &psecnetwork->IELength); 865554c0a3aSHans de Goede 866554c0a3aSHans de Goede pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength); 867554c0a3aSHans de Goede 868554c0a3aSHans de Goede pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */ 869554c0a3aSHans de Goede 870554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd->list); 871554c0a3aSHans de Goede pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */ 872554c0a3aSHans de Goede pcmd->parmbuf = (unsigned char *)psecnetwork; 873554c0a3aSHans de Goede pcmd->rsp = NULL; 874554c0a3aSHans de Goede pcmd->rspsz = 0; 875554c0a3aSHans de Goede 876554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, pcmd); 877554c0a3aSHans de Goede 878554c0a3aSHans de Goede exit: 879554c0a3aSHans de Goede return res; 880554c0a3aSHans de Goede } 881554c0a3aSHans de Goede 882554c0a3aSHans de Goede u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */ 883554c0a3aSHans de Goede { 884554c0a3aSHans de Goede struct cmd_obj *cmdobj = NULL; 885554c0a3aSHans de Goede struct disconnect_parm *param = NULL; 886554c0a3aSHans de Goede struct cmd_priv *cmdpriv = &padapter->cmdpriv; 887554c0a3aSHans de Goede u8 res = _SUCCESS; 888554c0a3aSHans de Goede 889554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_disassoc_cmd\n")); 890554c0a3aSHans de Goede 891554c0a3aSHans de Goede /* prepare cmd parameter */ 8922ef2b7c2SJoe Perches param = rtw_zmalloc(sizeof(*param)); 893554c0a3aSHans de Goede if (param == NULL) { 894554c0a3aSHans de Goede res = _FAIL; 895554c0a3aSHans de Goede goto exit; 896554c0a3aSHans de Goede } 897554c0a3aSHans de Goede param->deauth_timeout_ms = deauth_timeout_ms; 898554c0a3aSHans de Goede 899554c0a3aSHans de Goede if (enqueue) { 900554c0a3aSHans de Goede /* need enqueue, prepare cmd_obj and enqueue */ 9012ef2b7c2SJoe Perches cmdobj = rtw_zmalloc(sizeof(*cmdobj)); 902554c0a3aSHans de Goede if (cmdobj == NULL) { 903554c0a3aSHans de Goede res = _FAIL; 904512bbd7bSSrishti Sharma kfree(param); 905554c0a3aSHans de Goede goto exit; 906554c0a3aSHans de Goede } 907554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_); 908554c0a3aSHans de Goede res = rtw_enqueue_cmd(cmdpriv, cmdobj); 909554c0a3aSHans de Goede } else { 910554c0a3aSHans de Goede /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ 91192576c84SManuel Palenzuela if (disconnect_hdl(padapter, (u8 *)param) != H2C_SUCCESS) 912554c0a3aSHans de Goede res = _FAIL; 913512bbd7bSSrishti Sharma kfree(param); 914554c0a3aSHans de Goede } 915554c0a3aSHans de Goede 916554c0a3aSHans de Goede exit: 917554c0a3aSHans de Goede return res; 918554c0a3aSHans de Goede } 919554c0a3aSHans de Goede 920554c0a3aSHans de Goede u8 rtw_setopmode_cmd(struct adapter *padapter, enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype, bool enqueue) 921554c0a3aSHans de Goede { 922554c0a3aSHans de Goede struct cmd_obj *ph2c; 923554c0a3aSHans de Goede struct setopmode_parm *psetop; 924554c0a3aSHans de Goede 925554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 926554c0a3aSHans de Goede u8 res = _SUCCESS; 927554c0a3aSHans de Goede 9282ef2b7c2SJoe Perches psetop = rtw_zmalloc(sizeof(struct setopmode_parm)); 929554c0a3aSHans de Goede 930554c0a3aSHans de Goede if (psetop == NULL) { 931554c0a3aSHans de Goede res = _FAIL; 932554c0a3aSHans de Goede goto exit; 933554c0a3aSHans de Goede } 934554c0a3aSHans de Goede psetop->mode = (u8)networktype; 935554c0a3aSHans de Goede 936554c0a3aSHans de Goede if (enqueue) { 9372ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 938554c0a3aSHans de Goede if (ph2c == NULL) { 939512bbd7bSSrishti Sharma kfree(psetop); 940554c0a3aSHans de Goede res = _FAIL; 941554c0a3aSHans de Goede goto exit; 942554c0a3aSHans de Goede } 943554c0a3aSHans de Goede 944554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_); 945554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 946554c0a3aSHans de Goede } else { 947554c0a3aSHans de Goede setopmode_hdl(padapter, (u8 *)psetop); 948512bbd7bSSrishti Sharma kfree(psetop); 949554c0a3aSHans de Goede } 950554c0a3aSHans de Goede exit: 951554c0a3aSHans de Goede return res; 952554c0a3aSHans de Goede } 953554c0a3aSHans de Goede 954554c0a3aSHans de Goede u8 rtw_setstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 unicast_key, bool enqueue) 955554c0a3aSHans de Goede { 956554c0a3aSHans de Goede struct cmd_obj *ph2c; 957554c0a3aSHans de Goede struct set_stakey_parm *psetstakey_para; 958554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 959554c0a3aSHans de Goede struct set_stakey_rsp *psetstakey_rsp = NULL; 960554c0a3aSHans de Goede 961554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 962554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 963554c0a3aSHans de Goede u8 res = _SUCCESS; 964554c0a3aSHans de Goede 9652ef2b7c2SJoe Perches psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm)); 966554c0a3aSHans de Goede if (psetstakey_para == NULL) { 967554c0a3aSHans de Goede res = _FAIL; 968554c0a3aSHans de Goede goto exit; 969554c0a3aSHans de Goede } 970554c0a3aSHans de Goede 971554c0a3aSHans de Goede memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN); 972554c0a3aSHans de Goede 973554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { 974554c0a3aSHans de Goede psetstakey_para->algorithm = (unsigned char) psecuritypriv->dot11PrivacyAlgrthm; 975554c0a3aSHans de Goede } else { 976554c0a3aSHans de Goede GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false); 977554c0a3aSHans de Goede } 978554c0a3aSHans de Goede 979554c0a3aSHans de Goede if (unicast_key == true) { 980554c0a3aSHans de Goede memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16); 981554c0a3aSHans de Goede } else { 982554c0a3aSHans de Goede memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16); 983554c0a3aSHans de Goede } 984554c0a3aSHans de Goede 985858ea450SR Veera Kumar /* jeff: set this because at least sw key is ready */ 986554c0a3aSHans de Goede padapter->securitypriv.busetkipkey = true; 987554c0a3aSHans de Goede 988554c0a3aSHans de Goede if (enqueue) { 9892ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 990554c0a3aSHans de Goede if (ph2c == NULL) { 991512bbd7bSSrishti Sharma kfree(psetstakey_para); 992554c0a3aSHans de Goede res = _FAIL; 993554c0a3aSHans de Goede goto exit; 994554c0a3aSHans de Goede } 995554c0a3aSHans de Goede 9962ef2b7c2SJoe Perches psetstakey_rsp = rtw_zmalloc(sizeof(struct set_stakey_rsp)); 997554c0a3aSHans de Goede if (psetstakey_rsp == NULL) { 998512bbd7bSSrishti Sharma kfree(ph2c); 999512bbd7bSSrishti Sharma kfree(psetstakey_para); 1000554c0a3aSHans de Goede res = _FAIL; 1001554c0a3aSHans de Goede goto exit; 1002554c0a3aSHans de Goede } 1003554c0a3aSHans de Goede 1004554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); 1005554c0a3aSHans de Goede ph2c->rsp = (u8 *) psetstakey_rsp; 1006554c0a3aSHans de Goede ph2c->rspsz = sizeof(struct set_stakey_rsp); 1007554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1008554c0a3aSHans de Goede } else { 1009554c0a3aSHans de Goede set_stakey_hdl(padapter, (u8 *)psetstakey_para); 1010512bbd7bSSrishti Sharma kfree(psetstakey_para); 1011554c0a3aSHans de Goede } 1012554c0a3aSHans de Goede exit: 1013554c0a3aSHans de Goede return res; 1014554c0a3aSHans de Goede } 1015554c0a3aSHans de Goede 1016554c0a3aSHans de Goede u8 rtw_clearstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 enqueue) 1017554c0a3aSHans de Goede { 1018554c0a3aSHans de Goede struct cmd_obj *ph2c; 1019554c0a3aSHans de Goede struct set_stakey_parm *psetstakey_para; 1020554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1021554c0a3aSHans de Goede struct set_stakey_rsp *psetstakey_rsp = NULL; 1022554c0a3aSHans de Goede s16 cam_id = 0; 1023554c0a3aSHans de Goede u8 res = _SUCCESS; 1024554c0a3aSHans de Goede 1025554c0a3aSHans de Goede if (!enqueue) { 1026554c0a3aSHans de Goede while ((cam_id = rtw_camid_search(padapter, sta->hwaddr, -1)) >= 0) { 1027bbda3ac4SRoss Schmidt DBG_871X_LEVEL(_drv_always_, "clear key for addr:%pM, camid:%d\n", MAC_ARG(sta->hwaddr), cam_id); 1028554c0a3aSHans de Goede clear_cam_entry(padapter, cam_id); 1029554c0a3aSHans de Goede rtw_camid_free(padapter, cam_id); 1030554c0a3aSHans de Goede } 1031554c0a3aSHans de Goede } else { 10322ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1033554c0a3aSHans de Goede if (ph2c == NULL) { 1034554c0a3aSHans de Goede res = _FAIL; 1035554c0a3aSHans de Goede goto exit; 1036554c0a3aSHans de Goede } 1037554c0a3aSHans de Goede 10382ef2b7c2SJoe Perches psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm)); 1039554c0a3aSHans de Goede if (psetstakey_para == NULL) { 1040512bbd7bSSrishti Sharma kfree(ph2c); 1041554c0a3aSHans de Goede res = _FAIL; 1042554c0a3aSHans de Goede goto exit; 1043554c0a3aSHans de Goede } 1044554c0a3aSHans de Goede 10452ef2b7c2SJoe Perches psetstakey_rsp = rtw_zmalloc(sizeof(struct set_stakey_rsp)); 1046554c0a3aSHans de Goede if (psetstakey_rsp == NULL) { 1047512bbd7bSSrishti Sharma kfree(ph2c); 1048512bbd7bSSrishti Sharma kfree(psetstakey_para); 1049554c0a3aSHans de Goede res = _FAIL; 1050554c0a3aSHans de Goede goto exit; 1051554c0a3aSHans de Goede } 1052554c0a3aSHans de Goede 1053554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); 1054554c0a3aSHans de Goede ph2c->rsp = (u8 *) psetstakey_rsp; 1055554c0a3aSHans de Goede ph2c->rspsz = sizeof(struct set_stakey_rsp); 1056554c0a3aSHans de Goede 1057554c0a3aSHans de Goede memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN); 1058554c0a3aSHans de Goede 1059554c0a3aSHans de Goede psetstakey_para->algorithm = _NO_PRIVACY_; 1060554c0a3aSHans de Goede 1061554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1062554c0a3aSHans de Goede 1063554c0a3aSHans de Goede } 1064554c0a3aSHans de Goede 1065554c0a3aSHans de Goede exit: 1066554c0a3aSHans de Goede return res; 1067554c0a3aSHans de Goede } 1068554c0a3aSHans de Goede 1069554c0a3aSHans de Goede u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr) 1070554c0a3aSHans de Goede { 1071554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1072554c0a3aSHans de Goede struct cmd_obj *ph2c; 1073554c0a3aSHans de Goede struct addBaReq_parm *paddbareq_parm; 1074554c0a3aSHans de Goede 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 paddbareq_parm = rtw_zmalloc(sizeof(struct addBaReq_parm)); 1084554c0a3aSHans de Goede if (paddbareq_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 paddbareq_parm->tid = tid; 1091554c0a3aSHans de Goede memcpy(paddbareq_parm->addr, addr, ETH_ALEN); 1092554c0a3aSHans de Goede 1093554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq)); 1094554c0a3aSHans de Goede 1095554c0a3aSHans de Goede /* DBG_871X("rtw_addbareq_cmd, tid =%d\n", tid); */ 1096554c0a3aSHans de Goede 1097554c0a3aSHans de Goede /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ 1098554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1099554c0a3aSHans de Goede 1100554c0a3aSHans de Goede exit: 1101554c0a3aSHans de Goede return res; 1102554c0a3aSHans de Goede } 1103554c0a3aSHans de Goede /* add for CONFIG_IEEE80211W, none 11w can use it */ 1104554c0a3aSHans de Goede u8 rtw_reset_securitypriv_cmd(struct adapter *padapter) 1105554c0a3aSHans de Goede { 1106554c0a3aSHans de Goede struct cmd_obj *ph2c; 1107554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1108554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1109554c0a3aSHans de Goede u8 res = _SUCCESS; 1110554c0a3aSHans de Goede 11112ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1112554c0a3aSHans de Goede if (ph2c == NULL) { 1113554c0a3aSHans de Goede res = _FAIL; 1114554c0a3aSHans de Goede goto exit; 1115554c0a3aSHans de Goede } 1116554c0a3aSHans de Goede 11172ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1118554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1119512bbd7bSSrishti Sharma kfree(ph2c); 1120554c0a3aSHans de Goede res = _FAIL; 1121554c0a3aSHans de Goede goto exit; 1122554c0a3aSHans de Goede } 1123554c0a3aSHans de Goede 1124554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = RESET_SECURITYPRIV; 1125554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1126554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1127554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1128554c0a3aSHans de Goede 1129554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1130554c0a3aSHans de Goede 1131554c0a3aSHans de Goede 1132554c0a3aSHans de Goede /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ 1133554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1134554c0a3aSHans de Goede 1135554c0a3aSHans de Goede exit: 1136554c0a3aSHans de Goede return res; 1137554c0a3aSHans de Goede } 1138554c0a3aSHans de Goede 1139554c0a3aSHans de Goede u8 rtw_free_assoc_resources_cmd(struct adapter *padapter) 1140554c0a3aSHans de Goede { 1141554c0a3aSHans de Goede struct cmd_obj *ph2c; 1142554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1143554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1144554c0a3aSHans de Goede u8 res = _SUCCESS; 1145554c0a3aSHans de Goede 11462ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1147554c0a3aSHans de Goede if (ph2c == NULL) { 1148554c0a3aSHans de Goede res = _FAIL; 1149554c0a3aSHans de Goede goto exit; 1150554c0a3aSHans de Goede } 1151554c0a3aSHans de Goede 11522ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1153554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1154512bbd7bSSrishti Sharma kfree(ph2c); 1155554c0a3aSHans de Goede res = _FAIL; 1156554c0a3aSHans de Goede goto exit; 1157554c0a3aSHans de Goede } 1158554c0a3aSHans de Goede 1159554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = FREE_ASSOC_RESOURCES; 1160554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1161554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1162554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1163554c0a3aSHans de Goede 1164554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1165554c0a3aSHans de Goede 1166554c0a3aSHans de Goede 1167554c0a3aSHans de Goede /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ 1168554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1169554c0a3aSHans de Goede 1170554c0a3aSHans de Goede exit: 1171554c0a3aSHans de Goede return res; 1172554c0a3aSHans de Goede } 1173554c0a3aSHans de Goede 1174554c0a3aSHans de Goede u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter) 1175554c0a3aSHans de Goede { 1176554c0a3aSHans de Goede struct cmd_obj *ph2c; 1177554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1178554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1179554c0a3aSHans de Goede u8 res = _SUCCESS; 1180554c0a3aSHans de Goede 1181554c0a3aSHans de Goede /* only primary padapter does this cmd */ 11822ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1183554c0a3aSHans de Goede if (ph2c == NULL) { 1184554c0a3aSHans de Goede res = _FAIL; 1185554c0a3aSHans de Goede goto exit; 1186554c0a3aSHans de Goede } 1187554c0a3aSHans de Goede 11882ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1189554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1190512bbd7bSSrishti Sharma kfree(ph2c); 1191554c0a3aSHans de Goede res = _FAIL; 1192554c0a3aSHans de Goede goto exit; 1193554c0a3aSHans de Goede } 1194554c0a3aSHans de Goede 1195554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID; 1196554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1197554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1198554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1199554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1200554c0a3aSHans de Goede 1201554c0a3aSHans de Goede 1202554c0a3aSHans de Goede /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ 1203554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1204554c0a3aSHans de Goede 1205554c0a3aSHans de Goede exit: 1206554c0a3aSHans de Goede return res; 1207554c0a3aSHans de Goede } 1208554c0a3aSHans de Goede 1209554c0a3aSHans de Goede u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue, u8 swconfig) 1210554c0a3aSHans de Goede { 1211554c0a3aSHans de Goede struct cmd_obj *pcmdobj; 1212554c0a3aSHans de Goede struct SetChannelPlan_param *setChannelPlan_param; 1213554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1214554c0a3aSHans de Goede 1215554c0a3aSHans de Goede u8 res = _SUCCESS; 1216554c0a3aSHans de Goede 1217554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_chplan_cmd\n")); 1218554c0a3aSHans de Goede 1219554c0a3aSHans de Goede /* check if allow software config */ 1220554c0a3aSHans de Goede if (swconfig && rtw_hal_is_disable_sw_channel_plan(padapter) == true) { 1221554c0a3aSHans de Goede res = _FAIL; 1222554c0a3aSHans de Goede goto exit; 1223554c0a3aSHans de Goede } 1224554c0a3aSHans de Goede 1225554c0a3aSHans de Goede /* check input parameter */ 1226554c0a3aSHans de Goede if (!rtw_is_channel_plan_valid(chplan)) { 1227554c0a3aSHans de Goede res = _FAIL; 1228554c0a3aSHans de Goede goto exit; 1229554c0a3aSHans de Goede } 1230554c0a3aSHans de Goede 1231554c0a3aSHans de Goede /* prepare cmd parameter */ 12322ef2b7c2SJoe Perches setChannelPlan_param = rtw_zmalloc(sizeof(struct SetChannelPlan_param)); 1233554c0a3aSHans de Goede if (setChannelPlan_param == NULL) { 1234554c0a3aSHans de Goede res = _FAIL; 1235554c0a3aSHans de Goede goto exit; 1236554c0a3aSHans de Goede } 1237554c0a3aSHans de Goede setChannelPlan_param->channel_plan = chplan; 1238554c0a3aSHans de Goede 1239554c0a3aSHans de Goede if (enqueue) { 1240554c0a3aSHans de Goede /* need enqueue, prepare cmd_obj and enqueue */ 12412ef2b7c2SJoe Perches pcmdobj = rtw_zmalloc(sizeof(struct cmd_obj)); 1242554c0a3aSHans de Goede if (pcmdobj == NULL) { 1243512bbd7bSSrishti Sharma kfree(setChannelPlan_param); 1244554c0a3aSHans de Goede res = _FAIL; 1245554c0a3aSHans de Goede goto exit; 1246554c0a3aSHans de Goede } 1247554c0a3aSHans de Goede 1248554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, GEN_CMD_CODE(_SetChannelPlan)); 1249554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, pcmdobj); 1250554c0a3aSHans de Goede } else { 1251554c0a3aSHans de Goede /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ 125292576c84SManuel Palenzuela if (set_chplan_hdl(padapter, (unsigned char *)setChannelPlan_param) != H2C_SUCCESS) 1253554c0a3aSHans de Goede res = _FAIL; 1254554c0a3aSHans de Goede 1255512bbd7bSSrishti Sharma kfree(setChannelPlan_param); 1256554c0a3aSHans de Goede } 1257554c0a3aSHans de Goede 1258554c0a3aSHans de Goede /* do something based on res... */ 1259554c0a3aSHans de Goede if (res == _SUCCESS) 1260554c0a3aSHans de Goede padapter->mlmepriv.ChannelPlan = chplan; 1261554c0a3aSHans de Goede 1262554c0a3aSHans de Goede exit: 1263554c0a3aSHans de Goede return res; 1264554c0a3aSHans de Goede } 1265554c0a3aSHans de Goede 1266554c0a3aSHans de Goede static void collect_traffic_statistics(struct adapter *padapter) 1267554c0a3aSHans de Goede { 1268554c0a3aSHans de Goede struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); 1269554c0a3aSHans de Goede 1270554c0a3aSHans de Goede /* Tx */ 1271554c0a3aSHans de Goede pdvobjpriv->traffic_stat.tx_bytes = padapter->xmitpriv.tx_bytes; 1272554c0a3aSHans de Goede pdvobjpriv->traffic_stat.tx_pkts = padapter->xmitpriv.tx_pkts; 1273554c0a3aSHans de Goede pdvobjpriv->traffic_stat.tx_drop = padapter->xmitpriv.tx_drop; 1274554c0a3aSHans de Goede 1275554c0a3aSHans de Goede /* Rx */ 1276554c0a3aSHans de Goede pdvobjpriv->traffic_stat.rx_bytes = padapter->recvpriv.rx_bytes; 1277554c0a3aSHans de Goede pdvobjpriv->traffic_stat.rx_pkts = padapter->recvpriv.rx_pkts; 1278554c0a3aSHans de Goede pdvobjpriv->traffic_stat.rx_drop = padapter->recvpriv.rx_drop; 1279554c0a3aSHans de Goede 1280554c0a3aSHans de Goede /* Calculate throughput in last interval */ 1281554c0a3aSHans de Goede pdvobjpriv->traffic_stat.cur_tx_bytes = pdvobjpriv->traffic_stat.tx_bytes - pdvobjpriv->traffic_stat.last_tx_bytes; 1282554c0a3aSHans de Goede pdvobjpriv->traffic_stat.cur_rx_bytes = pdvobjpriv->traffic_stat.rx_bytes - pdvobjpriv->traffic_stat.last_rx_bytes; 1283554c0a3aSHans de Goede pdvobjpriv->traffic_stat.last_tx_bytes = pdvobjpriv->traffic_stat.tx_bytes; 1284554c0a3aSHans de Goede pdvobjpriv->traffic_stat.last_rx_bytes = pdvobjpriv->traffic_stat.rx_bytes; 1285554c0a3aSHans de Goede 1286554c0a3aSHans de Goede pdvobjpriv->traffic_stat.cur_tx_tp = (u32)(pdvobjpriv->traffic_stat.cur_tx_bytes * 8/2/1024/1024); 1287554c0a3aSHans de Goede pdvobjpriv->traffic_stat.cur_rx_tp = (u32)(pdvobjpriv->traffic_stat.cur_rx_bytes * 8/2/1024/1024); 1288554c0a3aSHans de Goede } 1289554c0a3aSHans de Goede 1290554c0a3aSHans de Goede u8 traffic_status_watchdog(struct adapter *padapter, u8 from_timer) 1291554c0a3aSHans de Goede { 1292554c0a3aSHans de Goede u8 bEnterPS = false; 1293554c0a3aSHans de Goede u16 BusyThresholdHigh = 25; 1294554c0a3aSHans de Goede u16 BusyThresholdLow = 10; 1295554c0a3aSHans de Goede u16 BusyThreshold = BusyThresholdHigh; 1296554c0a3aSHans de Goede u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false; 1297554c0a3aSHans de Goede u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false; 1298554c0a3aSHans de Goede 1299554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1300554c0a3aSHans de Goede 1301554c0a3aSHans de Goede collect_traffic_statistics(padapter); 1302554c0a3aSHans de Goede 1303554c0a3aSHans de Goede /* */ 1304554c0a3aSHans de Goede /* Determine if our traffic is busy now */ 1305554c0a3aSHans de Goede /* */ 1306554c0a3aSHans de Goede if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) 1307554c0a3aSHans de Goede /*&& !MgntInitAdapterInProgress(pMgntInfo)*/) { 1308554c0a3aSHans de Goede /* if we raise bBusyTraffic in last watchdog, using lower threshold. */ 1309554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.bBusyTraffic) 1310554c0a3aSHans de Goede BusyThreshold = BusyThresholdLow; 1311554c0a3aSHans de Goede 1312554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold || 1313554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold) { 1314554c0a3aSHans de Goede bBusyTraffic = true; 1315554c0a3aSHans de Goede 1316554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) 1317554c0a3aSHans de Goede bRxBusyTraffic = true; 1318554c0a3aSHans de Goede else 1319554c0a3aSHans de Goede bTxBusyTraffic = true; 1320554c0a3aSHans de Goede } 1321554c0a3aSHans de Goede 1322554c0a3aSHans de Goede /* Higher Tx/Rx data. */ 1323554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 || 1324554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) { 1325554c0a3aSHans de Goede bHigherBusyTraffic = true; 1326554c0a3aSHans de Goede 1327554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) 1328554c0a3aSHans de Goede bHigherBusyRxTraffic = true; 1329554c0a3aSHans de Goede else 1330554c0a3aSHans de Goede bHigherBusyTxTraffic = true; 1331554c0a3aSHans de Goede } 1332554c0a3aSHans de Goede 1333554c0a3aSHans de Goede /* check traffic for powersaving. */ 1334554c0a3aSHans de Goede if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) || 1335554c0a3aSHans de Goede (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2)) { 1336554c0a3aSHans de Goede /* DBG_871X("(-)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); */ 1337554c0a3aSHans de Goede bEnterPS = false; 1338554c0a3aSHans de Goede 1339554c0a3aSHans de Goede if (bBusyTraffic == true) { 1340554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount <= 4) 1341554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 4; 1342554c0a3aSHans de Goede 1343554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount++; 1344554c0a3aSHans de Goede 1345554c0a3aSHans de Goede /* DBG_871X("Set TrafficTransitionCount to %d\n", pmlmepriv->LinkDetectInfo.TrafficTransitionCount); */ 1346554c0a3aSHans de Goede 13478f870aabSManuel Palenzuela if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount > 30/*TrafficTransitionLevel*/) 1348554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 30; 1349554c0a3aSHans de Goede } 1350554c0a3aSHans de Goede } else { 1351554c0a3aSHans de Goede /* DBG_871X("(+)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); */ 1352554c0a3aSHans de Goede 1353554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount >= 2) 1354554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount -= 2; 1355554c0a3aSHans de Goede else 1356554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0; 1357554c0a3aSHans de Goede 1358554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount == 0) 1359554c0a3aSHans de Goede bEnterPS = true; 1360554c0a3aSHans de Goede } 1361554c0a3aSHans de Goede 1362554c0a3aSHans de Goede /* LeisurePS only work in infra mode. */ 1363554c0a3aSHans de Goede if (bEnterPS) { 1364554c0a3aSHans de Goede if (!from_timer) 1365554c0a3aSHans de Goede LPS_Enter(padapter, "TRAFFIC_IDLE"); 1366554c0a3aSHans de Goede } else { 1367554c0a3aSHans de Goede if (!from_timer) 1368554c0a3aSHans de Goede LPS_Leave(padapter, "TRAFFIC_BUSY"); 1369554c0a3aSHans de Goede else 1370554c0a3aSHans de Goede rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_TRAFFIC_BUSY, 1); 1371554c0a3aSHans de Goede } 1372554c0a3aSHans de Goede } else { 1373554c0a3aSHans de Goede struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); 1374554c0a3aSHans de Goede int n_assoc_iface = 0; 1375554c0a3aSHans de Goede 1376554c0a3aSHans de Goede if (check_fwstate(&(dvobj->padapters->mlmepriv), WIFI_ASOC_STATE)) 1377554c0a3aSHans de Goede n_assoc_iface++; 1378554c0a3aSHans de Goede 1379554c0a3aSHans de Goede if (!from_timer && n_assoc_iface == 0) 1380554c0a3aSHans de Goede LPS_Leave(padapter, "NON_LINKED"); 1381554c0a3aSHans de Goede } 1382554c0a3aSHans de Goede 1383554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0; 1384554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0; 1385554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0; 1386554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic; 1387554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic; 1388554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic; 1389554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic; 1390554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic; 1391554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic; 1392554c0a3aSHans de Goede 1393554c0a3aSHans de Goede return bEnterPS; 1394554c0a3aSHans de Goede 1395554c0a3aSHans de Goede } 1396554c0a3aSHans de Goede 1397554c0a3aSHans de Goede static void dynamic_chk_wk_hdl(struct adapter *padapter) 1398554c0a3aSHans de Goede { 1399554c0a3aSHans de Goede struct mlme_priv *pmlmepriv; 1400554c0a3aSHans de Goede pmlmepriv = &(padapter->mlmepriv); 1401554c0a3aSHans de Goede 14028f870aabSManuel Palenzuela if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) 1403554c0a3aSHans de Goede expire_timeout_chk(padapter); 1404554c0a3aSHans de Goede 1405554c0a3aSHans de Goede /* for debug purpose */ 1406554c0a3aSHans de Goede _linked_info_dump(padapter); 1407554c0a3aSHans de Goede 1408554c0a3aSHans de Goede 1409554c0a3aSHans de Goede /* if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING|_FW_UNDER_SURVEY) ==false) */ 1410554c0a3aSHans de Goede { 1411554c0a3aSHans de Goede linked_status_chk(padapter); 1412554c0a3aSHans de Goede traffic_status_watchdog(padapter, 0); 1413554c0a3aSHans de Goede } 1414554c0a3aSHans de Goede 1415554c0a3aSHans de Goede rtw_hal_dm_watchdog(padapter); 1416554c0a3aSHans de Goede 1417554c0a3aSHans de Goede /* check_hw_pbc(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type); */ 1418554c0a3aSHans de Goede 1419554c0a3aSHans de Goede /* */ 1420554c0a3aSHans de Goede /* BT-Coexist */ 1421554c0a3aSHans de Goede /* */ 1422a158111dSNishka Dasgupta hal_btcoex_Handler(padapter); 1423554c0a3aSHans de Goede 1424554c0a3aSHans de Goede 1425554c0a3aSHans de Goede /* always call rtw_ps_processor() at last one. */ 1426554c0a3aSHans de Goede if (is_primary_adapter(padapter)) 1427554c0a3aSHans de Goede rtw_ps_processor(padapter); 1428554c0a3aSHans de Goede } 1429554c0a3aSHans de Goede 1430554c0a3aSHans de Goede void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type); 1431554c0a3aSHans de Goede void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type) 1432554c0a3aSHans de Goede { 1433554c0a3aSHans de Goede struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); 1434554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1435554c0a3aSHans de Goede u8 mstatus; 1436554c0a3aSHans de Goede 1437554c0a3aSHans de Goede if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) 1438554c0a3aSHans de Goede || (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) { 1439554c0a3aSHans de Goede return; 1440554c0a3aSHans de Goede } 1441554c0a3aSHans de Goede 1442554c0a3aSHans de Goede switch (lps_ctrl_type) { 1443554c0a3aSHans de Goede case LPS_CTRL_SCAN: 1444554c0a3aSHans de Goede /* DBG_871X("LPS_CTRL_SCAN\n"); */ 1445a47a70c2SNishka Dasgupta hal_btcoex_ScanNotify(padapter, true); 1446554c0a3aSHans de Goede 1447554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { 1448554c0a3aSHans de Goede /* connect */ 1449554c0a3aSHans de Goede LPS_Leave(padapter, "LPS_CTRL_SCAN"); 1450554c0a3aSHans de Goede } 1451554c0a3aSHans de Goede break; 1452554c0a3aSHans de Goede case LPS_CTRL_JOINBSS: 1453554c0a3aSHans de Goede /* DBG_871X("LPS_CTRL_JOINBSS\n"); */ 1454554c0a3aSHans de Goede LPS_Leave(padapter, "LPS_CTRL_JOINBSS"); 1455554c0a3aSHans de Goede break; 1456554c0a3aSHans de Goede case LPS_CTRL_CONNECT: 1457554c0a3aSHans de Goede /* DBG_871X("LPS_CTRL_CONNECT\n"); */ 1458554c0a3aSHans de Goede mstatus = 1;/* connect */ 1459554c0a3aSHans de Goede /* Reset LPS Setting */ 1460554c0a3aSHans de Goede pwrpriv->LpsIdleCount = 0; 1461554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus)); 1462554c0a3aSHans de Goede rtw_btcoex_MediaStatusNotify(padapter, mstatus); 1463554c0a3aSHans de Goede break; 1464554c0a3aSHans de Goede case LPS_CTRL_DISCONNECT: 1465554c0a3aSHans de Goede /* DBG_871X("LPS_CTRL_DISCONNECT\n"); */ 1466554c0a3aSHans de Goede mstatus = 0;/* disconnect */ 1467554c0a3aSHans de Goede rtw_btcoex_MediaStatusNotify(padapter, mstatus); 1468554c0a3aSHans de Goede LPS_Leave(padapter, "LPS_CTRL_DISCONNECT"); 1469554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus)); 1470554c0a3aSHans de Goede break; 1471554c0a3aSHans de Goede case LPS_CTRL_SPECIAL_PACKET: 1472554c0a3aSHans de Goede /* DBG_871X("LPS_CTRL_SPECIAL_PACKET\n"); */ 1473554c0a3aSHans de Goede pwrpriv->DelayLPSLastTimeStamp = jiffies; 1474800132aaSNishka Dasgupta hal_btcoex_SpecialPacketNotify(padapter, PACKET_DHCP); 1475554c0a3aSHans de Goede LPS_Leave(padapter, "LPS_CTRL_SPECIAL_PACKET"); 1476554c0a3aSHans de Goede break; 1477554c0a3aSHans de Goede case LPS_CTRL_LEAVE: 1478554c0a3aSHans de Goede /* DBG_871X("LPS_CTRL_LEAVE\n"); */ 1479554c0a3aSHans de Goede LPS_Leave(padapter, "LPS_CTRL_LEAVE"); 1480554c0a3aSHans de Goede break; 1481554c0a3aSHans de Goede case LPS_CTRL_TRAFFIC_BUSY: 1482554c0a3aSHans de Goede LPS_Leave(padapter, "LPS_CTRL_TRAFFIC_BUSY"); 1483*2811861bSGustavo A. R. Silva break; 1484554c0a3aSHans de Goede default: 1485554c0a3aSHans de Goede break; 1486554c0a3aSHans de Goede } 1487554c0a3aSHans de Goede } 1488554c0a3aSHans de Goede 1489554c0a3aSHans de Goede u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue) 1490554c0a3aSHans de Goede { 1491554c0a3aSHans de Goede struct cmd_obj *ph2c; 1492554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1493554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1494554c0a3aSHans de Goede /* struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); */ 1495554c0a3aSHans de Goede u8 res = _SUCCESS; 1496554c0a3aSHans de Goede 1497554c0a3aSHans de Goede /* if (!pwrctrlpriv->bLeisurePs) */ 1498554c0a3aSHans de Goede /* return res; */ 1499554c0a3aSHans de Goede 1500554c0a3aSHans de Goede if (enqueue) { 15012ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1502554c0a3aSHans de Goede if (ph2c == NULL) { 1503554c0a3aSHans de Goede res = _FAIL; 1504554c0a3aSHans de Goede goto exit; 1505554c0a3aSHans de Goede } 1506554c0a3aSHans de Goede 15072ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1508554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1509512bbd7bSSrishti Sharma kfree(ph2c); 1510554c0a3aSHans de Goede res = _FAIL; 1511554c0a3aSHans de Goede goto exit; 1512554c0a3aSHans de Goede } 1513554c0a3aSHans de Goede 1514554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID; 1515554c0a3aSHans de Goede pdrvextra_cmd_parm->type = lps_ctrl_type; 1516554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1517554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1518554c0a3aSHans de Goede 1519554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1520554c0a3aSHans de Goede 1521554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1522554c0a3aSHans de Goede } else { 1523554c0a3aSHans de Goede lps_ctrl_wk_hdl(padapter, lps_ctrl_type); 1524554c0a3aSHans de Goede } 1525554c0a3aSHans de Goede 1526554c0a3aSHans de Goede exit: 1527554c0a3aSHans de Goede return res; 1528554c0a3aSHans de Goede } 1529554c0a3aSHans de Goede 1530554c0a3aSHans de Goede static void rtw_dm_in_lps_hdl(struct adapter *padapter) 1531554c0a3aSHans de Goede { 1532554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_DM_IN_LPS, NULL); 1533554c0a3aSHans de Goede } 1534554c0a3aSHans de Goede 1535554c0a3aSHans de Goede u8 rtw_dm_in_lps_wk_cmd(struct adapter *padapter) 1536554c0a3aSHans de Goede { 1537554c0a3aSHans de Goede struct cmd_obj *ph2c; 1538554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1539554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1540554c0a3aSHans de Goede u8 res = _SUCCESS; 1541554c0a3aSHans de Goede 1542554c0a3aSHans de Goede 15432ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1544554c0a3aSHans de Goede if (ph2c == NULL) { 1545554c0a3aSHans de Goede res = _FAIL; 1546554c0a3aSHans de Goede goto exit; 1547554c0a3aSHans de Goede } 1548554c0a3aSHans de Goede 15492ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1550554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1551512bbd7bSSrishti Sharma kfree(ph2c); 1552554c0a3aSHans de Goede res = _FAIL; 1553554c0a3aSHans de Goede goto exit; 1554554c0a3aSHans de Goede } 1555554c0a3aSHans de Goede 1556554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = DM_IN_LPS_WK_CID; 1557554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1558554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1559554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1560554c0a3aSHans de Goede 1561554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1562554c0a3aSHans de Goede 1563554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1564554c0a3aSHans de Goede 1565554c0a3aSHans de Goede exit: 1566554c0a3aSHans de Goede 1567554c0a3aSHans de Goede return res; 1568554c0a3aSHans de Goede 1569554c0a3aSHans de Goede } 1570554c0a3aSHans de Goede 1571554c0a3aSHans de Goede static void rtw_lps_change_dtim_hdl(struct adapter *padapter, u8 dtim) 1572554c0a3aSHans de Goede { 1573554c0a3aSHans de Goede struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); 1574554c0a3aSHans de Goede 1575554c0a3aSHans de Goede if (dtim <= 0 || dtim > 16) 1576554c0a3aSHans de Goede return; 1577554c0a3aSHans de Goede 1578606e33ceSNishka Dasgupta if (hal_btcoex_IsBtControlLps(padapter) == true) 1579554c0a3aSHans de Goede return; 1580554c0a3aSHans de Goede 158107e3a844SArnd Bergmann mutex_lock(&pwrpriv->lock); 1582554c0a3aSHans de Goede 1583554c0a3aSHans de Goede if (pwrpriv->dtim != dtim) { 1584554c0a3aSHans de Goede DBG_871X("change DTIM from %d to %d, bFwCurrentInPSMode =%d, ps_mode =%d\n", pwrpriv->dtim, dtim, 1585554c0a3aSHans de Goede pwrpriv->bFwCurrentInPSMode, pwrpriv->pwr_mode); 1586554c0a3aSHans de Goede 1587554c0a3aSHans de Goede pwrpriv->dtim = dtim; 1588554c0a3aSHans de Goede } 1589554c0a3aSHans de Goede 1590554c0a3aSHans de Goede if ((pwrpriv->bFwCurrentInPSMode == true) && (pwrpriv->pwr_mode > PS_MODE_ACTIVE)) { 1591554c0a3aSHans de Goede u8 ps_mode = pwrpriv->pwr_mode; 1592554c0a3aSHans de Goede 1593554c0a3aSHans de Goede /* DBG_871X("change DTIM from %d to %d, ps_mode =%d\n", pwrpriv->dtim, dtim, ps_mode); */ 1594554c0a3aSHans de Goede 1595554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode)); 1596554c0a3aSHans de Goede } 1597554c0a3aSHans de Goede 159807e3a844SArnd Bergmann mutex_unlock(&pwrpriv->lock); 1599554c0a3aSHans de Goede } 1600554c0a3aSHans de Goede 1601554c0a3aSHans de Goede static void rtw_dm_ra_mask_hdl(struct adapter *padapter, struct sta_info *psta) 1602554c0a3aSHans de Goede { 16038f870aabSManuel Palenzuela if (psta) 1604554c0a3aSHans de Goede set_sta_rate(padapter, psta); 1605554c0a3aSHans de Goede } 1606554c0a3aSHans de Goede 1607554c0a3aSHans de Goede u8 rtw_dm_ra_mask_wk_cmd(struct adapter *padapter, u8 *psta) 1608554c0a3aSHans de Goede { 1609554c0a3aSHans de Goede struct cmd_obj *ph2c; 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 1614554c0a3aSHans de Goede 16152ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1616554c0a3aSHans de Goede if (ph2c == NULL) { 1617554c0a3aSHans de Goede res = _FAIL; 1618554c0a3aSHans de Goede goto exit; 1619554c0a3aSHans de Goede } 1620554c0a3aSHans de Goede 16212ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1622554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1623512bbd7bSSrishti Sharma kfree(ph2c); 1624554c0a3aSHans de Goede res = _FAIL; 1625554c0a3aSHans de Goede goto exit; 1626554c0a3aSHans de Goede } 1627554c0a3aSHans de Goede 1628554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = DM_RA_MSK_WK_CID; 1629554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1630554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1631554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = psta; 1632554c0a3aSHans de Goede 1633554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1634554c0a3aSHans de Goede 1635554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1636554c0a3aSHans de Goede 1637554c0a3aSHans de Goede exit: 1638554c0a3aSHans de Goede 1639554c0a3aSHans de Goede return res; 1640554c0a3aSHans de Goede 1641554c0a3aSHans de Goede } 1642554c0a3aSHans de Goede 1643554c0a3aSHans de Goede u8 rtw_ps_cmd(struct adapter *padapter) 1644554c0a3aSHans de Goede { 1645554c0a3aSHans de Goede struct cmd_obj *ppscmd; 1646554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1647554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1648554c0a3aSHans de Goede u8 res = _SUCCESS; 1649554c0a3aSHans de Goede 16502ef2b7c2SJoe Perches ppscmd = rtw_zmalloc(sizeof(struct cmd_obj)); 1651554c0a3aSHans de Goede if (ppscmd == NULL) { 1652554c0a3aSHans de Goede res = _FAIL; 1653554c0a3aSHans de Goede goto exit; 1654554c0a3aSHans de Goede } 1655554c0a3aSHans de Goede 16562ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1657554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1658512bbd7bSSrishti Sharma kfree(ppscmd); 1659554c0a3aSHans de Goede res = _FAIL; 1660554c0a3aSHans de Goede goto exit; 1661554c0a3aSHans de Goede } 1662554c0a3aSHans de Goede 1663554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID; 1664554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1665554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1666554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1667554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1668554c0a3aSHans de Goede 1669554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ppscmd); 1670554c0a3aSHans de Goede 1671554c0a3aSHans de Goede exit: 1672554c0a3aSHans de Goede return res; 1673554c0a3aSHans de Goede } 1674554c0a3aSHans de Goede 167564b8e685SJi-Hun Kim u32 g_wait_hiq_empty; 1676f55a6d45SArnd Bergmann 1677554c0a3aSHans de Goede static void rtw_chk_hi_queue_hdl(struct adapter *padapter) 1678554c0a3aSHans de Goede { 1679554c0a3aSHans de Goede struct sta_info *psta_bmc; 1680554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1681554c0a3aSHans de Goede unsigned long start = jiffies; 1682554c0a3aSHans de Goede u8 empty = false; 1683554c0a3aSHans de Goede 1684554c0a3aSHans de Goede psta_bmc = rtw_get_bcmc_stainfo(padapter); 1685554c0a3aSHans de Goede if (!psta_bmc) 1686554c0a3aSHans de Goede return; 1687554c0a3aSHans de Goede 1688554c0a3aSHans de Goede rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty); 1689554c0a3aSHans de Goede 1690554c0a3aSHans de Goede while (false == empty && jiffies_to_msecs(jiffies - start) < g_wait_hiq_empty) { 1691554c0a3aSHans de Goede msleep(100); 1692554c0a3aSHans de Goede rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty); 1693554c0a3aSHans de Goede } 1694554c0a3aSHans de Goede 1695554c0a3aSHans de Goede if (psta_bmc->sleepq_len == 0) { 1696554c0a3aSHans de Goede if (empty == _SUCCESS) { 1697554c0a3aSHans de Goede bool update_tim = false; 1698554c0a3aSHans de Goede 1699554c0a3aSHans de Goede if (pstapriv->tim_bitmap & BIT(0)) 1700554c0a3aSHans de Goede update_tim = true; 1701554c0a3aSHans de Goede 1702554c0a3aSHans de Goede pstapriv->tim_bitmap &= ~BIT(0); 1703554c0a3aSHans de Goede pstapriv->sta_dz_bitmap &= ~BIT(0); 1704554c0a3aSHans de Goede 170563a9c3edSJeeeun Evans if (update_tim) 1706554c0a3aSHans de Goede update_beacon(padapter, _TIM_IE_, NULL, true); 1707554c0a3aSHans de Goede } else {/* re check again */ 1708554c0a3aSHans de Goede rtw_chk_hi_queue_cmd(padapter); 1709554c0a3aSHans de Goede } 1710554c0a3aSHans de Goede 1711554c0a3aSHans de Goede } 1712554c0a3aSHans de Goede 1713554c0a3aSHans de Goede } 1714554c0a3aSHans de Goede 1715554c0a3aSHans de Goede u8 rtw_chk_hi_queue_cmd(struct adapter *padapter) 1716554c0a3aSHans de Goede { 1717554c0a3aSHans de Goede struct cmd_obj *ph2c; 1718554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1719554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1720554c0a3aSHans de Goede u8 res = _SUCCESS; 1721554c0a3aSHans de Goede 17222ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1723554c0a3aSHans de Goede if (ph2c == NULL) { 1724554c0a3aSHans de Goede res = _FAIL; 1725554c0a3aSHans de Goede goto exit; 1726554c0a3aSHans de Goede } 1727554c0a3aSHans de Goede 17282ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1729554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1730512bbd7bSSrishti Sharma kfree(ph2c); 1731554c0a3aSHans de Goede res = _FAIL; 1732554c0a3aSHans de Goede goto exit; 1733554c0a3aSHans de Goede } 1734554c0a3aSHans de Goede 1735554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID; 1736554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1737554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1738554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1739554c0a3aSHans de Goede 1740554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1741554c0a3aSHans de Goede 1742554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1743554c0a3aSHans de Goede 1744554c0a3aSHans de Goede exit: 1745554c0a3aSHans de Goede 1746554c0a3aSHans de Goede return res; 1747554c0a3aSHans de Goede 1748554c0a3aSHans de Goede } 1749554c0a3aSHans de Goede 1750554c0a3aSHans de Goede struct btinfo { 1751554c0a3aSHans de Goede u8 cid; 1752554c0a3aSHans de Goede u8 len; 1753554c0a3aSHans de Goede 1754554c0a3aSHans de Goede u8 bConnection:1; 1755554c0a3aSHans de Goede u8 bSCOeSCO:1; 1756554c0a3aSHans de Goede u8 bInQPage:1; 1757554c0a3aSHans de Goede u8 bACLBusy:1; 1758554c0a3aSHans de Goede u8 bSCOBusy:1; 1759554c0a3aSHans de Goede u8 bHID:1; 1760554c0a3aSHans de Goede u8 bA2DP:1; 1761554c0a3aSHans de Goede u8 bFTP:1; 1762554c0a3aSHans de Goede 1763554c0a3aSHans de Goede u8 retry_cnt:4; 1764554c0a3aSHans de Goede u8 rsvd_34:1; 1765554c0a3aSHans de Goede u8 rsvd_35:1; 1766554c0a3aSHans de Goede u8 rsvd_36:1; 1767554c0a3aSHans de Goede u8 rsvd_37:1; 1768554c0a3aSHans de Goede 1769554c0a3aSHans de Goede u8 rssi; 1770554c0a3aSHans de Goede 1771554c0a3aSHans de Goede u8 rsvd_50:1; 1772554c0a3aSHans de Goede u8 rsvd_51:1; 1773554c0a3aSHans de Goede u8 rsvd_52:1; 1774554c0a3aSHans de Goede u8 rsvd_53:1; 1775554c0a3aSHans de Goede u8 rsvd_54:1; 1776554c0a3aSHans de Goede u8 rsvd_55:1; 1777554c0a3aSHans de Goede u8 eSCO_SCO:1; 1778554c0a3aSHans de Goede u8 Master_Slave:1; 1779554c0a3aSHans de Goede 1780554c0a3aSHans de Goede u8 rsvd_6; 1781554c0a3aSHans de Goede u8 rsvd_7; 1782554c0a3aSHans de Goede }; 1783554c0a3aSHans de Goede 1784554c0a3aSHans de Goede static void rtw_btinfo_hdl(struct adapter *adapter, u8 *buf, u16 buf_len) 1785554c0a3aSHans de Goede { 1786554c0a3aSHans de Goede #define BTINFO_WIFI_FETCH 0x23 1787554c0a3aSHans de Goede #define BTINFO_BT_AUTO_RPT 0x27 1788554c0a3aSHans de Goede struct btinfo *info = (struct btinfo *)buf; 1789554c0a3aSHans de Goede u8 cmd_idx; 1790554c0a3aSHans de Goede u8 len; 1791554c0a3aSHans de Goede 1792554c0a3aSHans de Goede cmd_idx = info->cid; 1793554c0a3aSHans de Goede 1794554c0a3aSHans de Goede if (info->len > buf_len-2) { 1795554c0a3aSHans de Goede rtw_warn_on(1); 1796554c0a3aSHans de Goede len = buf_len-2; 1797554c0a3aSHans de Goede } else { 1798554c0a3aSHans de Goede len = info->len; 1799554c0a3aSHans de Goede } 1800554c0a3aSHans de Goede 1801554c0a3aSHans de Goede /* transform BT-FW btinfo to WiFI-FW C2H format and notify */ 1802554c0a3aSHans de Goede if (cmd_idx == BTINFO_WIFI_FETCH) 1803554c0a3aSHans de Goede buf[1] = 0; 1804554c0a3aSHans de Goede else if (cmd_idx == BTINFO_BT_AUTO_RPT) 1805554c0a3aSHans de Goede buf[1] = 2; 1806aa0963a1SNishka Dasgupta hal_btcoex_BtInfoNotify(adapter, len+1, &buf[1]); 1807554c0a3aSHans de Goede } 1808554c0a3aSHans de Goede 1809554c0a3aSHans de Goede u8 rtw_c2h_packet_wk_cmd(struct adapter *padapter, u8 *pbuf, u16 length) 1810554c0a3aSHans de Goede { 1811554c0a3aSHans de Goede struct cmd_obj *ph2c; 1812554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1813554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1814554c0a3aSHans de Goede u8 res = _SUCCESS; 1815554c0a3aSHans de Goede 18162ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1817554c0a3aSHans de Goede if (ph2c == NULL) { 1818554c0a3aSHans de Goede res = _FAIL; 1819554c0a3aSHans de Goede goto exit; 1820554c0a3aSHans de Goede } 1821554c0a3aSHans de Goede 18222ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1823554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1824512bbd7bSSrishti Sharma kfree(ph2c); 1825554c0a3aSHans de Goede res = _FAIL; 1826554c0a3aSHans de Goede goto exit; 1827554c0a3aSHans de Goede } 1828554c0a3aSHans de Goede 1829554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = C2H_WK_CID; 1830554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1831554c0a3aSHans de Goede pdrvextra_cmd_parm->size = length; 1832554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = pbuf; 1833554c0a3aSHans de Goede 1834554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1835554c0a3aSHans de Goede 1836554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1837554c0a3aSHans de Goede 1838554c0a3aSHans de Goede exit: 1839554c0a3aSHans de Goede return res; 1840554c0a3aSHans de Goede } 1841554c0a3aSHans de Goede 1842554c0a3aSHans de Goede /* dont call R/W in this function, beucase SDIO interrupt have claim host */ 1843554c0a3aSHans de Goede /* or deadlock will happen and cause special-systemserver-died in android */ 1844554c0a3aSHans de Goede u8 rtw_c2h_wk_cmd(struct adapter *padapter, u8 *c2h_evt) 1845554c0a3aSHans de Goede { 1846554c0a3aSHans de Goede struct cmd_obj *ph2c; 1847554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1848554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1849554c0a3aSHans de Goede u8 res = _SUCCESS; 1850554c0a3aSHans de Goede 18512ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1852554c0a3aSHans de Goede if (ph2c == NULL) { 1853554c0a3aSHans de Goede res = _FAIL; 1854554c0a3aSHans de Goede goto exit; 1855554c0a3aSHans de Goede } 1856554c0a3aSHans de Goede 18572ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1858554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1859512bbd7bSSrishti Sharma kfree(ph2c); 1860554c0a3aSHans de Goede res = _FAIL; 1861554c0a3aSHans de Goede goto exit; 1862554c0a3aSHans de Goede } 1863554c0a3aSHans de Goede 1864554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = C2H_WK_CID; 1865554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1866554c0a3aSHans de Goede pdrvextra_cmd_parm->size = c2h_evt?16:0; 1867554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = c2h_evt; 1868554c0a3aSHans de Goede 1869554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1870554c0a3aSHans de Goede 1871554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1872554c0a3aSHans de Goede 1873554c0a3aSHans de Goede exit: 1874554c0a3aSHans de Goede 1875554c0a3aSHans de Goede return res; 1876554c0a3aSHans de Goede } 1877554c0a3aSHans de Goede 1878554c0a3aSHans de Goede static void c2h_wk_callback(_workitem *work) 1879554c0a3aSHans de Goede { 1880554c0a3aSHans de Goede struct evt_priv *evtpriv = container_of(work, struct evt_priv, c2h_wk); 1881554c0a3aSHans de Goede struct adapter *adapter = container_of(evtpriv, struct adapter, evtpriv); 1882554c0a3aSHans de Goede u8 *c2h_evt; 1883554c0a3aSHans de Goede c2h_id_filter ccx_id_filter = rtw_hal_c2h_id_filter_ccx(adapter); 1884554c0a3aSHans de Goede 1885554c0a3aSHans de Goede evtpriv->c2h_wk_alive = true; 1886554c0a3aSHans de Goede 1887554c0a3aSHans de Goede while (!rtw_cbuf_empty(evtpriv->c2h_queue)) { 1888554c0a3aSHans de Goede c2h_evt = (u8 *)rtw_cbuf_pop(evtpriv->c2h_queue); 188934557e23SIzabela Bakollari if (c2h_evt) { 1890554c0a3aSHans de Goede /* This C2H event is read, clear it */ 1891554c0a3aSHans de Goede c2h_evt_clear(adapter); 1892554c0a3aSHans de Goede } else { 18932ef2b7c2SJoe Perches c2h_evt = rtw_malloc(16); 189434557e23SIzabela Bakollari if (c2h_evt) { 1895554c0a3aSHans de Goede /* This C2H event is not read, read & clear now */ 1896414faeb1SNishka Dasgupta if (c2h_evt_read_88xx(adapter, c2h_evt) != _SUCCESS) { 1897554c0a3aSHans de Goede kfree(c2h_evt); 1898554c0a3aSHans de Goede continue; 1899554c0a3aSHans de Goede } 1900554c0a3aSHans de Goede } 1901554c0a3aSHans de Goede } 1902554c0a3aSHans de Goede 1903554c0a3aSHans de Goede /* Special pointer to trigger c2h_evt_clear only */ 1904554c0a3aSHans de Goede if ((void *)c2h_evt == (void *)evtpriv) 1905554c0a3aSHans de Goede continue; 1906554c0a3aSHans de Goede 1907554c0a3aSHans de Goede if (!rtw_hal_c2h_valid(adapter, c2h_evt)) { 1908554c0a3aSHans de Goede kfree(c2h_evt); 1909554c0a3aSHans de Goede continue; 1910554c0a3aSHans de Goede } 1911554c0a3aSHans de Goede 1912554c0a3aSHans de Goede if (ccx_id_filter(c2h_evt) == true) { 1913554c0a3aSHans de Goede /* Handle CCX report here */ 1914554c0a3aSHans de Goede rtw_hal_c2h_handler(adapter, c2h_evt); 1915554c0a3aSHans de Goede kfree(c2h_evt); 1916554c0a3aSHans de Goede } else { 1917554c0a3aSHans de Goede /* Enqueue into cmd_thread for others */ 1918554c0a3aSHans de Goede rtw_c2h_wk_cmd(adapter, c2h_evt); 1919554c0a3aSHans de Goede } 1920554c0a3aSHans de Goede } 1921554c0a3aSHans de Goede 1922554c0a3aSHans de Goede evtpriv->c2h_wk_alive = false; 1923554c0a3aSHans de Goede } 1924554c0a3aSHans de Goede 1925554c0a3aSHans de Goede u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf) 1926554c0a3aSHans de Goede { 1927554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd; 1928554c0a3aSHans de Goede 1929554c0a3aSHans de Goede if (!pbuf) 1930554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 1931554c0a3aSHans de Goede 1932554c0a3aSHans de Goede pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf; 1933554c0a3aSHans de Goede 1934554c0a3aSHans de Goede switch (pdrvextra_cmd->ec_id) { 1935554c0a3aSHans de Goede case DYNAMIC_CHK_WK_CID:/* only primary padapter go to this cmd, but execute dynamic_chk_wk_hdl() for two interfaces */ 1936554c0a3aSHans de Goede dynamic_chk_wk_hdl(padapter); 1937554c0a3aSHans de Goede break; 1938554c0a3aSHans de Goede case POWER_SAVING_CTRL_WK_CID: 1939534415d2SNishka Dasgupta rtw_ps_processor(padapter); 1940554c0a3aSHans de Goede break; 1941554c0a3aSHans de Goede case LPS_CTRL_WK_CID: 1942554c0a3aSHans de Goede lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type); 1943554c0a3aSHans de Goede break; 1944554c0a3aSHans de Goede case DM_IN_LPS_WK_CID: 1945554c0a3aSHans de Goede rtw_dm_in_lps_hdl(padapter); 1946554c0a3aSHans de Goede break; 1947554c0a3aSHans de Goede case LPS_CHANGE_DTIM_CID: 1948554c0a3aSHans de Goede rtw_lps_change_dtim_hdl(padapter, (u8)pdrvextra_cmd->type); 1949554c0a3aSHans de Goede break; 1950554c0a3aSHans de Goede case CHECK_HIQ_WK_CID: 1951554c0a3aSHans de Goede rtw_chk_hi_queue_hdl(padapter); 1952554c0a3aSHans de Goede break; 1953554c0a3aSHans de Goede /* add for CONFIG_IEEE80211W, none 11w can use it */ 1954554c0a3aSHans de Goede case RESET_SECURITYPRIV: 1955534415d2SNishka Dasgupta rtw_reset_securitypriv(padapter); 1956554c0a3aSHans de Goede break; 1957554c0a3aSHans de Goede case FREE_ASSOC_RESOURCES: 1958534415d2SNishka Dasgupta rtw_free_assoc_resources(padapter, 1); 1959554c0a3aSHans de Goede break; 1960554c0a3aSHans de Goede case C2H_WK_CID: 1961554c0a3aSHans de Goede rtw_hal_set_hwreg_with_buf(padapter, HW_VAR_C2H_HANDLE, pdrvextra_cmd->pbuf, pdrvextra_cmd->size); 1962554c0a3aSHans de Goede break; 1963554c0a3aSHans de Goede case DM_RA_MSK_WK_CID: 1964554c0a3aSHans de Goede rtw_dm_ra_mask_hdl(padapter, (struct sta_info *)pdrvextra_cmd->pbuf); 1965554c0a3aSHans de Goede break; 1966554c0a3aSHans de Goede case BTINFO_WK_CID: 1967554c0a3aSHans de Goede rtw_btinfo_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size); 1968554c0a3aSHans de Goede break; 1969554c0a3aSHans de Goede default: 1970554c0a3aSHans de Goede break; 1971554c0a3aSHans de Goede } 1972554c0a3aSHans de Goede 19738f870aabSManuel Palenzuela if (pdrvextra_cmd->pbuf && pdrvextra_cmd->size > 0) 1974554c0a3aSHans de Goede kfree(pdrvextra_cmd->pbuf); 1975554c0a3aSHans de Goede 1976554c0a3aSHans de Goede return H2C_SUCCESS; 1977554c0a3aSHans de Goede } 1978554c0a3aSHans de Goede 1979554c0a3aSHans de Goede void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 1980554c0a3aSHans de Goede { 1981554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1982554c0a3aSHans de Goede 1983554c0a3aSHans de Goede if (pcmd->res == H2C_DROPPED) { 1984554c0a3aSHans de Goede /* TODO: cancel timer and do timeout handler directly... */ 1985554c0a3aSHans de Goede /* need to make timeout handlerOS independent */ 1986554c0a3aSHans de Goede _set_timer(&pmlmepriv->scan_to_timer, 1); 1987554c0a3aSHans de Goede } else if (pcmd->res != H2C_SUCCESS) { 1988554c0a3aSHans de Goede _set_timer(&pmlmepriv->scan_to_timer, 1); 1989554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: MgntActrtw_set_802_11_bssid_LIST_SCAN Fail ************\n\n.")); 1990554c0a3aSHans de Goede } 1991554c0a3aSHans de Goede 1992554c0a3aSHans de Goede /* free cmd */ 1993554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 1994554c0a3aSHans de Goede } 1995554c0a3aSHans de Goede 1996554c0a3aSHans de Goede void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 1997554c0a3aSHans de Goede { 1998554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1999554c0a3aSHans de Goede 2000554c0a3aSHans de Goede if (pcmd->res != H2C_SUCCESS) { 2001554c0a3aSHans de Goede spin_lock_bh(&pmlmepriv->lock); 2002554c0a3aSHans de Goede set_fwstate(pmlmepriv, _FW_LINKED); 2003554c0a3aSHans de Goede spin_unlock_bh(&pmlmepriv->lock); 2004554c0a3aSHans de Goede 2005554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ***Error: disconnect_cmd_callback Fail ***\n.")); 2006554c0a3aSHans de Goede return; 2007554c0a3aSHans de Goede } 2008554c0a3aSHans de Goede /* free cmd */ 2009554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 2010554c0a3aSHans de Goede } 2011554c0a3aSHans de Goede 2012554c0a3aSHans de Goede void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2013554c0a3aSHans de Goede { 2014554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2015554c0a3aSHans de Goede 2016554c0a3aSHans de Goede if (pcmd->res == H2C_DROPPED) { 2017554c0a3aSHans de Goede /* TODO: cancel timer and do timeout handler directly... */ 2018554c0a3aSHans de Goede /* need to make timeout handlerOS independent */ 2019554c0a3aSHans de Goede _set_timer(&pmlmepriv->assoc_timer, 1); 2020554c0a3aSHans de Goede } else if (pcmd->res != H2C_SUCCESS) { 2021554c0a3aSHans de Goede _set_timer(&pmlmepriv->assoc_timer, 1); 2022554c0a3aSHans de Goede } 2023554c0a3aSHans de Goede 2024554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 2025554c0a3aSHans de Goede } 2026554c0a3aSHans de Goede 2027554c0a3aSHans de Goede void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2028554c0a3aSHans de Goede { 2029554c0a3aSHans de Goede struct sta_info *psta = NULL; 2030554c0a3aSHans de Goede struct wlan_network *pwlan = NULL; 2031554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2032554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf; 2033554c0a3aSHans de Goede struct wlan_network *tgt_network = &(pmlmepriv->cur_network); 2034554c0a3aSHans de Goede 2035554c0a3aSHans de Goede if (pcmd->parmbuf == NULL) 2036554c0a3aSHans de Goede goto exit; 2037554c0a3aSHans de Goede 2038554c0a3aSHans de Goede if ((pcmd->res != H2C_SUCCESS)) { 2039554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: rtw_createbss_cmd_callback Fail ************\n\n.")); 2040554c0a3aSHans de Goede _set_timer(&pmlmepriv->assoc_timer, 1); 2041554c0a3aSHans de Goede } 2042554c0a3aSHans de Goede 2043fb127a61SRoss Schmidt del_timer_sync(&pmlmepriv->assoc_timer); 2044554c0a3aSHans de Goede 2045554c0a3aSHans de Goede spin_lock_bh(&pmlmepriv->lock); 2046554c0a3aSHans de Goede 2047554c0a3aSHans de Goede 2048554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { 2049554c0a3aSHans de Goede psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress); 2050554c0a3aSHans de Goede if (!psta) { 2051554c0a3aSHans de Goede psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress); 2052554c0a3aSHans de Goede if (psta == NULL) { 2053554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nCan't alloc sta_info when createbss_cmd_callback\n")); 2054554c0a3aSHans de Goede goto createbss_cmd_fail; 2055554c0a3aSHans de Goede } 2056554c0a3aSHans de Goede } 2057554c0a3aSHans de Goede 2058554c0a3aSHans de Goede rtw_indicate_connect(padapter); 2059554c0a3aSHans de Goede } else { 20608e97f7d8SNishka Dasgupta pwlan = rtw_alloc_network(pmlmepriv); 2061554c0a3aSHans de Goede spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 2062554c0a3aSHans de Goede if (pwlan == NULL) { 2063554c0a3aSHans de Goede pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue); 2064554c0a3aSHans de Goede if (pwlan == NULL) { 2065554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n Error: can't get pwlan in rtw_joinbss_event_callback\n")); 2066554c0a3aSHans de Goede spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); 2067554c0a3aSHans de Goede goto createbss_cmd_fail; 2068554c0a3aSHans de Goede } 2069554c0a3aSHans de Goede pwlan->last_scanned = jiffies; 2070554c0a3aSHans de Goede } else { 2071554c0a3aSHans de Goede list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue); 2072554c0a3aSHans de Goede } 2073554c0a3aSHans de Goede 2074554c0a3aSHans de Goede pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork); 2075554c0a3aSHans de Goede memcpy(&(pwlan->network), pnetwork, pnetwork->Length); 2076554c0a3aSHans de Goede /* pwlan->fixed = true; */ 2077554c0a3aSHans de Goede 2078554c0a3aSHans de Goede /* list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue); */ 2079554c0a3aSHans de Goede 2080554c0a3aSHans de Goede /* copy pdev_network information to pmlmepriv->cur_network */ 2081554c0a3aSHans de Goede memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork))); 2082554c0a3aSHans de Goede 2083554c0a3aSHans de Goede /* reset DSConfig */ 2084554c0a3aSHans de Goede /* tgt_network->network.Configuration.DSConfig = (u32)rtw_ch2freq(pnetwork->Configuration.DSConfig); */ 2085554c0a3aSHans de Goede 2086554c0a3aSHans de Goede _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); 2087554c0a3aSHans de Goede 2088554c0a3aSHans de Goede spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); 2089554c0a3aSHans de Goede /* we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */ 2090554c0a3aSHans de Goede 2091554c0a3aSHans de Goede } 2092554c0a3aSHans de Goede 2093554c0a3aSHans de Goede createbss_cmd_fail: 2094554c0a3aSHans de Goede 2095554c0a3aSHans de Goede spin_unlock_bh(&pmlmepriv->lock); 2096554c0a3aSHans de Goede exit: 2097554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 2098554c0a3aSHans de Goede } 2099554c0a3aSHans de Goede 2100554c0a3aSHans de Goede 2101554c0a3aSHans de Goede 2102554c0a3aSHans de Goede void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2103554c0a3aSHans de Goede { 2104554c0a3aSHans de Goede 2105554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 2106554c0a3aSHans de Goede struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *) (pcmd->rsp); 2107554c0a3aSHans de Goede struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr); 2108554c0a3aSHans de Goede 2109554c0a3aSHans de Goede if (psta == NULL) { 2110554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: rtw_setstaKey_cmdrsp_callback => can't get sta_info\n\n")); 2111554c0a3aSHans de Goede goto exit; 2112554c0a3aSHans de Goede } 2113554c0a3aSHans de Goede exit: 2114554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 2115554c0a3aSHans de Goede } 2116554c0a3aSHans de Goede 2117554c0a3aSHans de Goede void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2118554c0a3aSHans de Goede { 2119554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 2120554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2121554c0a3aSHans de Goede struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf); 2122554c0a3aSHans de Goede struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *) (pcmd->rsp); 2123554c0a3aSHans de Goede struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr); 2124554c0a3aSHans de Goede 2125554c0a3aSHans de Goede if (psta == NULL) { 2126554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: setassocsta_cmdrsp_callbac => can't get sta_info\n\n")); 2127554c0a3aSHans de Goede goto exit; 2128554c0a3aSHans de Goede } 2129554c0a3aSHans de Goede 2130c42a4ac4SSimran Singhal psta->aid = passocsta_rsp->cam_id; 2131c42a4ac4SSimran Singhal psta->mac_id = passocsta_rsp->cam_id; 2132554c0a3aSHans de Goede 2133554c0a3aSHans de Goede spin_lock_bh(&pmlmepriv->lock); 2134554c0a3aSHans de Goede 2135554c0a3aSHans de Goede if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) && (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)) 2136554c0a3aSHans de Goede _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); 2137554c0a3aSHans de Goede 2138554c0a3aSHans de Goede set_fwstate(pmlmepriv, _FW_LINKED); 2139554c0a3aSHans de Goede spin_unlock_bh(&pmlmepriv->lock); 2140554c0a3aSHans de Goede 2141554c0a3aSHans de Goede exit: 2142554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 2143554c0a3aSHans de Goede } 2144