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> 11554c0a3aSHans de Goede #include <linux/jiffies.h> 12554c0a3aSHans de Goede 13554c0a3aSHans de Goede static struct _cmd_callback rtw_cmd_callback[] = { 14554c0a3aSHans de Goede {GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/ 15554c0a3aSHans de Goede {GEN_CMD_CODE(_Write_MACREG), NULL}, 16554c0a3aSHans de Goede {GEN_CMD_CODE(_Read_BBREG), &rtw_getbbrfreg_cmdrsp_callback}, 17554c0a3aSHans de Goede {GEN_CMD_CODE(_Write_BBREG), NULL}, 18554c0a3aSHans de Goede {GEN_CMD_CODE(_Read_RFREG), &rtw_getbbrfreg_cmdrsp_callback}, 19554c0a3aSHans de Goede {GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/ 20554c0a3aSHans de Goede {GEN_CMD_CODE(_Read_EEPROM), NULL}, 21554c0a3aSHans de Goede {GEN_CMD_CODE(_Write_EEPROM), NULL}, 22554c0a3aSHans de Goede {GEN_CMD_CODE(_Read_EFUSE), NULL}, 23554c0a3aSHans de Goede {GEN_CMD_CODE(_Write_EFUSE), NULL}, 24554c0a3aSHans de Goede 25554c0a3aSHans de Goede {GEN_CMD_CODE(_Read_CAM), NULL}, /*10*/ 26554c0a3aSHans de Goede {GEN_CMD_CODE(_Write_CAM), NULL}, 27554c0a3aSHans de Goede {GEN_CMD_CODE(_setBCNITV), NULL}, 28554c0a3aSHans de Goede {GEN_CMD_CODE(_setMBIDCFG), NULL}, 29554c0a3aSHans de Goede {GEN_CMD_CODE(_JoinBss), &rtw_joinbss_cmd_callback}, /*14*/ 30554c0a3aSHans de Goede {GEN_CMD_CODE(_DisConnect), &rtw_disassoc_cmd_callback}, /*15*/ 31554c0a3aSHans de Goede {GEN_CMD_CODE(_CreateBss), &rtw_createbss_cmd_callback}, 32554c0a3aSHans de Goede {GEN_CMD_CODE(_SetOpMode), NULL}, 33554c0a3aSHans de Goede {GEN_CMD_CODE(_SiteSurvey), &rtw_survey_cmd_callback}, /*18*/ 34554c0a3aSHans de Goede {GEN_CMD_CODE(_SetAuth), NULL}, 35554c0a3aSHans de Goede 36554c0a3aSHans de Goede {GEN_CMD_CODE(_SetKey), NULL}, /*20*/ 37554c0a3aSHans de Goede {GEN_CMD_CODE(_SetStaKey), &rtw_setstaKey_cmdrsp_callback}, 38554c0a3aSHans de Goede {GEN_CMD_CODE(_SetAssocSta), &rtw_setassocsta_cmdrsp_callback}, 39554c0a3aSHans de Goede {GEN_CMD_CODE(_DelAssocSta), NULL}, 40554c0a3aSHans de Goede {GEN_CMD_CODE(_SetStaPwrState), NULL}, 41554c0a3aSHans de Goede {GEN_CMD_CODE(_SetBasicRate), NULL}, /*25*/ 42554c0a3aSHans de Goede {GEN_CMD_CODE(_GetBasicRate), NULL}, 43554c0a3aSHans de Goede {GEN_CMD_CODE(_SetDataRate), NULL}, 44554c0a3aSHans de Goede {GEN_CMD_CODE(_GetDataRate), NULL}, 45554c0a3aSHans de Goede {GEN_CMD_CODE(_SetPhyInfo), NULL}, 46554c0a3aSHans de Goede 47554c0a3aSHans de Goede {GEN_CMD_CODE(_GetPhyInfo), NULL}, /*30*/ 48554c0a3aSHans de Goede {GEN_CMD_CODE(_SetPhy), NULL}, 49554c0a3aSHans de Goede {GEN_CMD_CODE(_GetPhy), NULL}, 50554c0a3aSHans de Goede {GEN_CMD_CODE(_readRssi), NULL}, 51554c0a3aSHans de Goede {GEN_CMD_CODE(_readGain), NULL}, 52554c0a3aSHans de Goede {GEN_CMD_CODE(_SetAtim), NULL}, /*35*/ 53554c0a3aSHans de Goede {GEN_CMD_CODE(_SetPwrMode), NULL}, 54554c0a3aSHans de Goede {GEN_CMD_CODE(_JoinbssRpt), NULL}, 55554c0a3aSHans de Goede {GEN_CMD_CODE(_SetRaTable), NULL}, 56554c0a3aSHans de Goede {GEN_CMD_CODE(_GetRaTable), NULL}, 57554c0a3aSHans de Goede 58554c0a3aSHans de Goede {GEN_CMD_CODE(_GetCCXReport), NULL}, /*40*/ 59554c0a3aSHans de Goede {GEN_CMD_CODE(_GetDTMReport), NULL}, 60554c0a3aSHans de Goede {GEN_CMD_CODE(_GetTXRateStatistics), NULL}, 61554c0a3aSHans de Goede {GEN_CMD_CODE(_SetUsbSuspend), NULL}, 62554c0a3aSHans de Goede {GEN_CMD_CODE(_SetH2cLbk), NULL}, 63554c0a3aSHans de Goede {GEN_CMD_CODE(_AddBAReq), NULL}, /*45*/ 64554c0a3aSHans de Goede {GEN_CMD_CODE(_SetChannel), NULL}, /*46*/ 65554c0a3aSHans de Goede {GEN_CMD_CODE(_SetTxPower), NULL}, 66554c0a3aSHans de Goede {GEN_CMD_CODE(_SwitchAntenna), NULL}, 67554c0a3aSHans de Goede {GEN_CMD_CODE(_SetCrystalCap), NULL}, 68554c0a3aSHans de Goede {GEN_CMD_CODE(_SetSingleCarrierTx), NULL}, /*50*/ 69554c0a3aSHans de Goede 70554c0a3aSHans de Goede {GEN_CMD_CODE(_SetSingleToneTx), NULL}, /*51*/ 71554c0a3aSHans de Goede {GEN_CMD_CODE(_SetCarrierSuppressionTx), NULL}, 72554c0a3aSHans de Goede {GEN_CMD_CODE(_SetContinuousTx), NULL}, 73554c0a3aSHans de Goede {GEN_CMD_CODE(_SwitchBandwidth), NULL}, /*54*/ 74554c0a3aSHans de Goede {GEN_CMD_CODE(_TX_Beacon), NULL},/*55*/ 75554c0a3aSHans de Goede 76554c0a3aSHans de Goede {GEN_CMD_CODE(_Set_MLME_EVT), NULL},/*56*/ 77554c0a3aSHans de Goede {GEN_CMD_CODE(_Set_Drv_Extra), NULL},/*57*/ 78554c0a3aSHans de Goede {GEN_CMD_CODE(_Set_H2C_MSG), NULL},/*58*/ 79554c0a3aSHans de Goede {GEN_CMD_CODE(_SetChannelPlan), NULL},/*59*/ 80554c0a3aSHans de Goede {GEN_CMD_CODE(_LedBlink), NULL},/*60*/ 81554c0a3aSHans de Goede 82554c0a3aSHans de Goede {GEN_CMD_CODE(_SetChannelSwitch), NULL},/*61*/ 83554c0a3aSHans de Goede {GEN_CMD_CODE(_TDLS), NULL},/*62*/ 84554c0a3aSHans de Goede {GEN_CMD_CODE(_ChkBMCSleepq), NULL}, /*63*/ 85554c0a3aSHans de Goede 86554c0a3aSHans de Goede {GEN_CMD_CODE(_RunInThreadCMD), NULL},/*64*/ 87554c0a3aSHans de Goede }; 88554c0a3aSHans de Goede 89554c0a3aSHans de Goede static struct cmd_hdl wlancmds[] = { 90554c0a3aSHans de Goede GEN_DRV_CMD_HANDLER(0, NULL) /*0*/ 91554c0a3aSHans de Goede GEN_DRV_CMD_HANDLER(0, NULL) 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_MLME_EXT_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) /*10*/ 101554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 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(sizeof(struct joinbss_parm), join_cmd_hdl) /*14*/ 105554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct disconnect_parm), disconnect_hdl) 106554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct createbss_parm), createbss_hdl) 107554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct setopmode_parm), setopmode_hdl) 108554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct sitesurvey_parm), sitesurvey_cmd_hdl) /*18*/ 109554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct setauth_parm), setauth_hdl) 110554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct setkey_parm), setkey_hdl) /*20*/ 111554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct set_stakey_parm), set_stakey_hdl) 112554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct set_assocsta_parm), NULL) 113554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct del_assocsta_parm), NULL) 114554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct setstapwrstate_parm), NULL) 115554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct setbasicrate_parm), NULL) 116554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct getbasicrate_parm), NULL) 117554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct setdatarate_parm), NULL) 118554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct getdatarate_parm), NULL) 119554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct setphyinfo_parm), NULL) 120554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct getphyinfo_parm), NULL) /*30*/ 121554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct setphy_parm), NULL) 122554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct getphy_parm), NULL) 123554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, 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) /*40*/ 131554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 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(sizeof(struct addBaReq_parm), add_ba_hdl) 136554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct set_ch_parm), set_ch_hdl) /* 46 */ 137554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 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) /*50*/ 141554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, NULL) 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(sizeof(struct Tx_Beacon_param), tx_beacon_hdl) /*55*/ 146554c0a3aSHans de Goede 147554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, mlme_evt_hdl) /*56*/ 148554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, rtw_drvextra_cmd_hdl) /*57*/ 149554c0a3aSHans de Goede 150554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, h2c_msg_hdl) /*58*/ 151554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelPlan_param), set_chplan_hdl) /*59*/ 152554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct LedBlink_param), led_blink_hdl) /*60*/ 153554c0a3aSHans de Goede 154554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelSwitch_param), set_csa_hdl) /*61*/ 155554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct TDLSoption_param), tdls_hdl) /*62*/ 156554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(0, chk_bmc_sleepq_hdl) /*63*/ 157554c0a3aSHans de Goede GEN_MLME_EXT_HANDLER(sizeof(struct RunInThread_param), run_in_thread_hdl) /*63*/ 158554c0a3aSHans de Goede }; 159554c0a3aSHans de Goede 160554c0a3aSHans de Goede /* 161554c0a3aSHans de Goede Caller and the rtw_cmd_thread can protect cmd_q by spin_lock. 162554c0a3aSHans de Goede No irqsave is necessary. 163554c0a3aSHans de Goede */ 164554c0a3aSHans de Goede 165b1c30bd6SMadhumitha Prabakaran int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv) 166554c0a3aSHans de Goede { 167cfd587d6SMadhumitha Prabakaran int res = 0; 168554c0a3aSHans de Goede 16909a8ea34SArnd Bergmann init_completion(&pcmdpriv->cmd_queue_comp); 17009a8ea34SArnd Bergmann init_completion(&pcmdpriv->terminate_cmdthread_comp); 171554c0a3aSHans de Goede 172554c0a3aSHans de Goede _rtw_init_queue(&(pcmdpriv->cmd_queue)); 173554c0a3aSHans de Goede 174554c0a3aSHans de Goede /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */ 175554c0a3aSHans de Goede 176554c0a3aSHans de Goede pcmdpriv->cmd_seq = 1; 177554c0a3aSHans de Goede 178554c0a3aSHans de Goede pcmdpriv->cmd_allocated_buf = rtw_zmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ); 179554c0a3aSHans de Goede 180554c0a3aSHans de Goede if (pcmdpriv->cmd_allocated_buf == NULL) { 181cfd587d6SMadhumitha Prabakaran res = -ENOMEM; 182554c0a3aSHans de Goede goto exit; 183554c0a3aSHans de Goede } 184554c0a3aSHans de Goede 185554c0a3aSHans de Goede pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ - ((SIZE_PTR)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ-1)); 186554c0a3aSHans de Goede 187554c0a3aSHans de Goede pcmdpriv->rsp_allocated_buf = rtw_zmalloc(MAX_RSPSZ + 4); 188554c0a3aSHans de Goede 189554c0a3aSHans de Goede if (pcmdpriv->rsp_allocated_buf == NULL) { 190cfd587d6SMadhumitha Prabakaran res = -ENOMEM; 191554c0a3aSHans de Goede goto exit; 192554c0a3aSHans de Goede } 193554c0a3aSHans de Goede 194554c0a3aSHans de Goede pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 - ((SIZE_PTR)(pcmdpriv->rsp_allocated_buf) & 3); 195554c0a3aSHans de Goede 196554c0a3aSHans de Goede pcmdpriv->cmd_issued_cnt = pcmdpriv->cmd_done_cnt = pcmdpriv->rsp_cnt = 0; 197554c0a3aSHans de Goede 198554c0a3aSHans de Goede mutex_init(&pcmdpriv->sctx_mutex); 199554c0a3aSHans de Goede exit: 200554c0a3aSHans de Goede return res; 201554c0a3aSHans de Goede } 202554c0a3aSHans de Goede 203554c0a3aSHans de Goede static void c2h_wk_callback(_workitem *work); 204b1c30bd6SMadhumitha Prabakaran int rtw_init_evt_priv(struct evt_priv *pevtpriv) 205554c0a3aSHans de Goede { 206554c0a3aSHans de Goede /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */ 207554c0a3aSHans de Goede atomic_set(&pevtpriv->event_seq, 0); 208554c0a3aSHans de Goede pevtpriv->evt_done_cnt = 0; 209554c0a3aSHans de Goede 210554c0a3aSHans de Goede _init_workitem(&pevtpriv->c2h_wk, c2h_wk_callback, NULL); 211554c0a3aSHans de Goede pevtpriv->c2h_wk_alive = false; 212554c0a3aSHans de Goede pevtpriv->c2h_queue = rtw_cbuf_alloc(C2H_QUEUE_MAX_LEN+1); 213554c0a3aSHans de Goede 21491734498SMadhumitha Prabakaran return 0; 215554c0a3aSHans de Goede } 216554c0a3aSHans de Goede 217554c0a3aSHans de Goede void _rtw_free_evt_priv(struct evt_priv *pevtpriv) 218554c0a3aSHans de Goede { 219554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+_rtw_free_evt_priv\n")); 220554c0a3aSHans de Goede 221554c0a3aSHans de Goede _cancel_workitem_sync(&pevtpriv->c2h_wk); 222554c0a3aSHans de Goede while (pevtpriv->c2h_wk_alive) 223554c0a3aSHans de Goede msleep(10); 224554c0a3aSHans de Goede 225554c0a3aSHans de Goede while (!rtw_cbuf_empty(pevtpriv->c2h_queue)) { 226554c0a3aSHans de Goede void *c2h = rtw_cbuf_pop(pevtpriv->c2h_queue); 227554c0a3aSHans de Goede if (c2h != NULL && c2h != (void *)pevtpriv) { 228554c0a3aSHans de Goede kfree(c2h); 229554c0a3aSHans de Goede } 230554c0a3aSHans de Goede } 231554c0a3aSHans de Goede kfree(pevtpriv->c2h_queue); 232554c0a3aSHans de Goede 233554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("-_rtw_free_evt_priv\n")); 234554c0a3aSHans de Goede } 235554c0a3aSHans de Goede 236554c0a3aSHans de Goede void _rtw_free_cmd_priv(struct cmd_priv *pcmdpriv) 237554c0a3aSHans de Goede { 238554c0a3aSHans de Goede if (pcmdpriv) { 239554c0a3aSHans de Goede kfree(pcmdpriv->cmd_allocated_buf); 240554c0a3aSHans de Goede 241554c0a3aSHans de Goede kfree(pcmdpriv->rsp_allocated_buf); 242554c0a3aSHans de Goede 243554c0a3aSHans de Goede mutex_destroy(&pcmdpriv->sctx_mutex); 244554c0a3aSHans de Goede } 245554c0a3aSHans de Goede } 246554c0a3aSHans de Goede 247554c0a3aSHans de Goede /* 248554c0a3aSHans de Goede Calling Context: 249554c0a3aSHans de Goede 250554c0a3aSHans de Goede rtw_enqueue_cmd can only be called between kernel thread, 251554c0a3aSHans de Goede since only spin_lock is used. 252554c0a3aSHans de Goede 253554c0a3aSHans de Goede ISR/Call-Back functions can't call this sub-function. 254554c0a3aSHans de Goede 255554c0a3aSHans de Goede */ 256554c0a3aSHans de Goede 257554c0a3aSHans de Goede sint _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj) 258554c0a3aSHans de Goede { 259554c0a3aSHans de Goede _irqL irqL; 260554c0a3aSHans de Goede 261554c0a3aSHans de Goede if (obj == NULL) 262554c0a3aSHans de Goede goto exit; 263554c0a3aSHans de Goede 264554c0a3aSHans de Goede /* spin_lock_bh(&queue->lock); */ 265554c0a3aSHans de Goede spin_lock_irqsave(&queue->lock, irqL); 266554c0a3aSHans de Goede 267554c0a3aSHans de Goede list_add_tail(&obj->list, &queue->queue); 268554c0a3aSHans de Goede 269554c0a3aSHans de Goede /* spin_unlock_bh(&queue->lock); */ 270554c0a3aSHans de Goede spin_unlock_irqrestore(&queue->lock, irqL); 271554c0a3aSHans de Goede 272554c0a3aSHans de Goede exit: 273554c0a3aSHans de Goede return _SUCCESS; 274554c0a3aSHans de Goede } 275554c0a3aSHans de Goede 276554c0a3aSHans de Goede struct cmd_obj *_rtw_dequeue_cmd(struct __queue *queue) 277554c0a3aSHans de Goede { 278554c0a3aSHans de Goede _irqL irqL; 279554c0a3aSHans de Goede struct cmd_obj *obj; 280554c0a3aSHans de Goede 281554c0a3aSHans de Goede /* spin_lock_bh(&(queue->lock)); */ 282554c0a3aSHans de Goede spin_lock_irqsave(&queue->lock, irqL); 283554c0a3aSHans de Goede if (list_empty(&(queue->queue))) 284554c0a3aSHans de Goede obj = NULL; 285554c0a3aSHans de Goede else { 286554c0a3aSHans de Goede obj = LIST_CONTAINOR(get_next(&(queue->queue)), struct cmd_obj, list); 287554c0a3aSHans de Goede list_del_init(&obj->list); 288554c0a3aSHans de Goede } 289554c0a3aSHans de Goede 290554c0a3aSHans de Goede /* spin_unlock_bh(&(queue->lock)); */ 291554c0a3aSHans de Goede spin_unlock_irqrestore(&queue->lock, irqL); 292554c0a3aSHans de Goede 293554c0a3aSHans de Goede return obj; 294554c0a3aSHans de Goede } 295554c0a3aSHans de Goede 296554c0a3aSHans de Goede void rtw_free_evt_priv(struct evt_priv *pevtpriv) 297554c0a3aSHans de Goede { 298554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("rtw_free_evt_priv\n")); 299554c0a3aSHans de Goede _rtw_free_evt_priv(pevtpriv); 300554c0a3aSHans de Goede } 301554c0a3aSHans de Goede 302554c0a3aSHans de Goede void rtw_free_cmd_priv(struct cmd_priv *pcmdpriv) 303554c0a3aSHans de Goede { 304554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("rtw_free_cmd_priv\n")); 305554c0a3aSHans de Goede _rtw_free_cmd_priv(pcmdpriv); 306554c0a3aSHans de Goede } 307554c0a3aSHans de Goede 308554c0a3aSHans de Goede int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj); 309554c0a3aSHans de Goede int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) 310554c0a3aSHans de Goede { 311554c0a3aSHans de Goede u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */ 312554c0a3aSHans de Goede 313554c0a3aSHans de Goede if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan)) 314554c0a3aSHans de Goede bAllow = true; 315554c0a3aSHans de Goede 316554c0a3aSHans de Goede if ((pcmdpriv->padapter->hw_init_completed == false && bAllow == false) 317554c0a3aSHans de Goede || atomic_read(&(pcmdpriv->cmdthd_running)) == false /* com_thread not running */ 318554c0a3aSHans de Goede ) { 319554c0a3aSHans de Goede /* DBG_871X("%s:%s: drop cmdcode:%u, hw_init_completed:%u, cmdthd_running:%u\n", caller_func, __func__, */ 320554c0a3aSHans de Goede /* cmd_obj->cmdcode, */ 321554c0a3aSHans de Goede /* pcmdpriv->padapter->hw_init_completed, */ 322554c0a3aSHans de Goede /* pcmdpriv->cmdthd_running */ 323554c0a3aSHans de Goede /* */ 324554c0a3aSHans de Goede 325554c0a3aSHans de Goede return _FAIL; 326554c0a3aSHans de Goede } 327554c0a3aSHans de Goede return _SUCCESS; 328554c0a3aSHans de Goede } 329554c0a3aSHans de Goede 330554c0a3aSHans de Goede 331554c0a3aSHans de Goede 332554c0a3aSHans de Goede u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) 333554c0a3aSHans de Goede { 334554c0a3aSHans de Goede int res = _FAIL; 335554c0a3aSHans de Goede struct adapter *padapter = pcmdpriv->padapter; 336554c0a3aSHans de Goede 337554c0a3aSHans de Goede if (cmd_obj == NULL) { 338554c0a3aSHans de Goede goto exit; 339554c0a3aSHans de Goede } 340554c0a3aSHans de Goede 341554c0a3aSHans de Goede cmd_obj->padapter = padapter; 342554c0a3aSHans de Goede 343554c0a3aSHans de Goede res = rtw_cmd_filter(pcmdpriv, cmd_obj); 344554c0a3aSHans de Goede if (_FAIL == res) { 345554c0a3aSHans de Goede rtw_free_cmd_obj(cmd_obj); 346554c0a3aSHans de Goede goto exit; 347554c0a3aSHans de Goede } 348554c0a3aSHans de Goede 349554c0a3aSHans de Goede res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj); 350554c0a3aSHans de Goede 351554c0a3aSHans de Goede if (res == _SUCCESS) 35209a8ea34SArnd Bergmann complete(&pcmdpriv->cmd_queue_comp); 353554c0a3aSHans de Goede 354554c0a3aSHans de Goede exit: 355554c0a3aSHans de Goede return res; 356554c0a3aSHans de Goede } 357554c0a3aSHans de Goede 358554c0a3aSHans de Goede struct cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv) 359554c0a3aSHans de Goede { 360554c0a3aSHans de Goede struct cmd_obj *cmd_obj; 361554c0a3aSHans de Goede 362554c0a3aSHans de Goede cmd_obj = _rtw_dequeue_cmd(&pcmdpriv->cmd_queue); 363554c0a3aSHans de Goede 364554c0a3aSHans de Goede return cmd_obj; 365554c0a3aSHans de Goede } 366554c0a3aSHans de Goede 367554c0a3aSHans de Goede void rtw_free_cmd_obj(struct cmd_obj *pcmd) 368554c0a3aSHans de Goede { 369554c0a3aSHans de Goede if ((pcmd->cmdcode != _JoinBss_CMD_) && 370554c0a3aSHans de Goede (pcmd->cmdcode != _CreateBss_CMD_)) { 371554c0a3aSHans de Goede /* free parmbuf in cmd_obj */ 372554c0a3aSHans de Goede kfree((unsigned char *)pcmd->parmbuf); 373554c0a3aSHans de Goede } 374554c0a3aSHans de Goede 375554c0a3aSHans de Goede if (pcmd->rsp != NULL) { 376554c0a3aSHans de Goede if (pcmd->rspsz != 0) { 377554c0a3aSHans de Goede /* free rsp in cmd_obj */ 378554c0a3aSHans de Goede kfree((unsigned char *)pcmd->rsp); 379554c0a3aSHans de Goede } 380554c0a3aSHans de Goede } 381554c0a3aSHans de Goede 382554c0a3aSHans de Goede /* free cmd_obj */ 383512bbd7bSSrishti Sharma kfree(pcmd); 384554c0a3aSHans de Goede } 385554c0a3aSHans de Goede 386554c0a3aSHans de Goede 387554c0a3aSHans de Goede void rtw_stop_cmd_thread(struct adapter *adapter) 388554c0a3aSHans de Goede { 389554c0a3aSHans de Goede if (adapter->cmdThread && 390554c0a3aSHans de Goede atomic_read(&(adapter->cmdpriv.cmdthd_running)) == true && 391554c0a3aSHans de Goede adapter->cmdpriv.stop_req == 0) { 392554c0a3aSHans de Goede adapter->cmdpriv.stop_req = 1; 39309a8ea34SArnd Bergmann complete(&adapter->cmdpriv.cmd_queue_comp); 39409a8ea34SArnd Bergmann wait_for_completion(&adapter->cmdpriv.terminate_cmdthread_comp); 395554c0a3aSHans de Goede } 396554c0a3aSHans de Goede } 397554c0a3aSHans de Goede 398554c0a3aSHans de Goede int rtw_cmd_thread(void *context) 399554c0a3aSHans de Goede { 400554c0a3aSHans de Goede u8 ret; 401554c0a3aSHans de Goede struct cmd_obj *pcmd; 402554c0a3aSHans de Goede u8 *pcmdbuf, *prspbuf; 403554c0a3aSHans de Goede unsigned long cmd_start_time; 404554c0a3aSHans de Goede unsigned long cmd_process_time; 405554c0a3aSHans de Goede u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf); 406554c0a3aSHans de Goede void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd); 407529d87b4SHimanshu Jha struct adapter *padapter = context; 408554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); 409554c0a3aSHans de Goede struct drvextra_cmd_parm *extra_parm = NULL; 410554c0a3aSHans de Goede 411554c0a3aSHans de Goede thread_enter("RTW_CMD_THREAD"); 412554c0a3aSHans de Goede 413554c0a3aSHans de Goede pcmdbuf = pcmdpriv->cmd_buf; 414554c0a3aSHans de Goede prspbuf = pcmdpriv->rsp_buf; 415554c0a3aSHans de Goede 416554c0a3aSHans de Goede pcmdpriv->stop_req = 0; 417554c0a3aSHans de Goede atomic_set(&(pcmdpriv->cmdthd_running), true); 41809a8ea34SArnd Bergmann complete(&pcmdpriv->terminate_cmdthread_comp); 419554c0a3aSHans de Goede 420554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("start r871x rtw_cmd_thread !!!!\n")); 421554c0a3aSHans de Goede 422554c0a3aSHans de Goede while (1) { 42309a8ea34SArnd Bergmann if (wait_for_completion_interruptible(&pcmdpriv->cmd_queue_comp)) { 42409a8ea34SArnd 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)); 425554c0a3aSHans de Goede break; 426554c0a3aSHans de Goede } 427554c0a3aSHans de Goede 428554c0a3aSHans de Goede if ((padapter->bDriverStopped == true) || (padapter->bSurpriseRemoved == true)) { 429554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n", 430554c0a3aSHans de Goede __func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__); 431554c0a3aSHans de Goede break; 432554c0a3aSHans de Goede } 433554c0a3aSHans de Goede 434554c0a3aSHans de Goede if (pcmdpriv->stop_req) { 435554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" stop_req:%u, break\n", FUNC_ADPT_ARG(padapter), pcmdpriv->stop_req); 436554c0a3aSHans de Goede break; 437554c0a3aSHans de Goede } 438554c0a3aSHans de Goede 439554c0a3aSHans de Goede if (list_empty(&(pcmdpriv->cmd_queue.queue))) { 440554c0a3aSHans de Goede /* DBG_871X("%s: cmd queue is empty!\n", __func__); */ 441554c0a3aSHans de Goede continue; 442554c0a3aSHans de Goede } 443554c0a3aSHans de Goede 444554c0a3aSHans de Goede if (rtw_register_cmd_alive(padapter) != _SUCCESS) { 445554c0a3aSHans de Goede RT_TRACE(_module_hal_xmit_c_, _drv_notice_, 446554c0a3aSHans de Goede ("%s: wait to leave LPS_LCLK\n", __func__)); 447554c0a3aSHans de Goede continue; 448554c0a3aSHans de Goede } 449554c0a3aSHans de Goede 450554c0a3aSHans de Goede _next: 451554c0a3aSHans de Goede if ((padapter->bDriverStopped == true) || (padapter->bSurpriseRemoved == true)) { 452554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n", 453554c0a3aSHans de Goede __func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__); 454554c0a3aSHans de Goede break; 455554c0a3aSHans de Goede } 456554c0a3aSHans de Goede 457554c0a3aSHans de Goede pcmd = rtw_dequeue_cmd(pcmdpriv); 458554c0a3aSHans de Goede if (!pcmd) { 459554c0a3aSHans de Goede rtw_unregister_cmd_alive(padapter); 460554c0a3aSHans de Goede continue; 461554c0a3aSHans de Goede } 462554c0a3aSHans de Goede 463554c0a3aSHans de Goede cmd_start_time = jiffies; 464554c0a3aSHans de Goede 465554c0a3aSHans de Goede if (_FAIL == rtw_cmd_filter(pcmdpriv, pcmd)) { 466554c0a3aSHans de Goede pcmd->res = H2C_DROPPED; 467554c0a3aSHans de Goede goto post_process; 468554c0a3aSHans de Goede } 469554c0a3aSHans de Goede 470554c0a3aSHans de Goede pcmdpriv->cmd_issued_cnt++; 471554c0a3aSHans de Goede 472554c0a3aSHans de Goede pcmd->cmdsz = _RND4((pcmd->cmdsz));/* _RND4 */ 473554c0a3aSHans de Goede 474554c0a3aSHans de Goede memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz); 475554c0a3aSHans de Goede 476554c0a3aSHans de Goede if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) { 477554c0a3aSHans de Goede cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns; 478554c0a3aSHans de Goede 479554c0a3aSHans de Goede if (cmd_hdl) { 480554c0a3aSHans de Goede ret = cmd_hdl(pcmd->padapter, pcmdbuf); 481554c0a3aSHans de Goede pcmd->res = ret; 482554c0a3aSHans de Goede } 483554c0a3aSHans de Goede 484554c0a3aSHans de Goede pcmdpriv->cmd_seq++; 485554c0a3aSHans de Goede } else { 486554c0a3aSHans de Goede pcmd->res = H2C_PARAMETERS_ERROR; 487554c0a3aSHans de Goede } 488554c0a3aSHans de Goede 489554c0a3aSHans de Goede cmd_hdl = NULL; 490554c0a3aSHans de Goede 491554c0a3aSHans de Goede post_process: 492554c0a3aSHans de Goede 493554c0a3aSHans de Goede if (mutex_lock_interruptible(&(pcmd->padapter->cmdpriv.sctx_mutex)) == 0) { 494554c0a3aSHans de Goede if (pcmd->sctx) { 495554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" pcmd->sctx\n", 496554c0a3aSHans de Goede FUNC_ADPT_ARG(pcmd->padapter)); 497554c0a3aSHans de Goede 498554c0a3aSHans de Goede if (pcmd->res == H2C_SUCCESS) 499554c0a3aSHans de Goede rtw_sctx_done(&pcmd->sctx); 500554c0a3aSHans de Goede else 501554c0a3aSHans de Goede rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_ERROR); 502554c0a3aSHans de Goede } 503554c0a3aSHans de Goede mutex_unlock(&(pcmd->padapter->cmdpriv.sctx_mutex)); 504554c0a3aSHans de Goede } 505554c0a3aSHans de Goede 506554c0a3aSHans de Goede cmd_process_time = jiffies_to_msecs(jiffies - cmd_start_time); 507554c0a3aSHans de Goede if (cmd_process_time > 1000) { 508554c0a3aSHans de Goede if (pcmd->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) { 509554c0a3aSHans de Goede DBG_871X(ADPT_FMT" cmd =%d process_time =%lu > 1 sec\n", 510554c0a3aSHans de Goede ADPT_ARG(pcmd->padapter), pcmd->cmdcode, cmd_process_time); 511554c0a3aSHans de Goede /* rtw_warn_on(1); */ 512554c0a3aSHans de Goede } else if (pcmd->cmdcode == GEN_CMD_CODE(_Set_MLME_EVT)) { 513554c0a3aSHans de Goede DBG_871X(ADPT_FMT" cmd =%d, process_time =%lu > 1 sec\n", 514554c0a3aSHans de Goede ADPT_ARG(pcmd->padapter), pcmd->cmdcode, cmd_process_time); 515554c0a3aSHans de Goede /* rtw_warn_on(1); */ 516554c0a3aSHans de Goede } else { 517554c0a3aSHans de Goede DBG_871X(ADPT_FMT" cmd =%d, process_time =%lu > 1 sec\n", 518554c0a3aSHans de Goede ADPT_ARG(pcmd->padapter), pcmd->cmdcode, cmd_process_time); 519554c0a3aSHans de Goede /* rtw_warn_on(1); */ 520554c0a3aSHans de Goede } 521554c0a3aSHans de Goede } 522554c0a3aSHans de Goede 523554c0a3aSHans de Goede /* call callback function for post-processed */ 524554c0a3aSHans de Goede if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) { 525554c0a3aSHans de Goede pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback; 526554c0a3aSHans de Goede if (pcmd_callback == NULL) { 527554c0a3aSHans 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)); 528554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 529554c0a3aSHans de Goede } else { 530554c0a3aSHans de Goede /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */ 531554c0a3aSHans de Goede pcmd_callback(pcmd->padapter, pcmd);/* need conider that free cmd_obj in rtw_cmd_callback */ 532554c0a3aSHans de Goede } 533554c0a3aSHans de Goede } else { 534554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("%s: cmdcode = 0x%x callback not defined!\n", __func__, pcmd->cmdcode)); 535554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 536554c0a3aSHans de Goede } 537554c0a3aSHans de Goede 538554c0a3aSHans de Goede flush_signals_thread(); 539554c0a3aSHans de Goede 540554c0a3aSHans de Goede goto _next; 541554c0a3aSHans de Goede 542554c0a3aSHans de Goede } 543554c0a3aSHans de Goede 544554c0a3aSHans de Goede /* free all cmd_obj resources */ 545554c0a3aSHans de Goede do { 546554c0a3aSHans de Goede pcmd = rtw_dequeue_cmd(pcmdpriv); 547554c0a3aSHans de Goede if (pcmd == NULL) { 548554c0a3aSHans de Goede rtw_unregister_cmd_alive(padapter); 549554c0a3aSHans de Goede break; 550554c0a3aSHans de Goede } 551554c0a3aSHans de Goede 552554c0a3aSHans de Goede /* DBG_871X("%s: leaving... drop cmdcode:%u size:%d\n", __func__, pcmd->cmdcode, pcmd->cmdsz); */ 553554c0a3aSHans de Goede 554554c0a3aSHans de Goede if (pcmd->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) { 555554c0a3aSHans de Goede extra_parm = (struct drvextra_cmd_parm *)pcmd->parmbuf; 556554c0a3aSHans de Goede if (extra_parm->pbuf && extra_parm->size > 0) { 557554c0a3aSHans de Goede kfree(extra_parm->pbuf); 558554c0a3aSHans de Goede } 559554c0a3aSHans de Goede } 560554c0a3aSHans de Goede 561554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 562554c0a3aSHans de Goede } while (1); 563554c0a3aSHans de Goede 56409a8ea34SArnd Bergmann complete(&pcmdpriv->terminate_cmdthread_comp); 565554c0a3aSHans de Goede atomic_set(&(pcmdpriv->cmdthd_running), false); 566554c0a3aSHans de Goede 567554c0a3aSHans de Goede thread_exit(); 568554c0a3aSHans de Goede } 569554c0a3aSHans de Goede 570554c0a3aSHans de Goede /* 571554c0a3aSHans de Goede rtw_sitesurvey_cmd(~) 572554c0a3aSHans de Goede ### NOTE:#### (!!!!) 573554c0a3aSHans de Goede MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock 574554c0a3aSHans de Goede */ 575554c0a3aSHans de Goede u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, int ssid_num, 576554c0a3aSHans de Goede struct rtw_ieee80211_channel *ch, int ch_num) 577554c0a3aSHans de Goede { 578554c0a3aSHans de Goede u8 res = _FAIL; 579554c0a3aSHans de Goede struct cmd_obj *ph2c; 580554c0a3aSHans de Goede struct sitesurvey_parm *psurveyPara; 581554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 582554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 583554c0a3aSHans de Goede 584554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { 585554c0a3aSHans de Goede rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1); 586554c0a3aSHans de Goede } 587554c0a3aSHans de Goede 5882ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 589554c0a3aSHans de Goede if (ph2c == NULL) 590554c0a3aSHans de Goede return _FAIL; 591554c0a3aSHans de Goede 5922ef2b7c2SJoe Perches psurveyPara = rtw_zmalloc(sizeof(struct sitesurvey_parm)); 593554c0a3aSHans de Goede if (psurveyPara == NULL) { 594512bbd7bSSrishti Sharma kfree(ph2c); 595554c0a3aSHans de Goede return _FAIL; 596554c0a3aSHans de Goede } 597554c0a3aSHans de Goede 598554c0a3aSHans de Goede rtw_free_network_queue(padapter, false); 599554c0a3aSHans de Goede 600554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("%s: flush network queue\n", __func__)); 601554c0a3aSHans de Goede 602554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey)); 603554c0a3aSHans de Goede 604554c0a3aSHans de Goede /* psurveyPara->bsslimit = 48; */ 605554c0a3aSHans de Goede psurveyPara->scan_mode = pmlmepriv->scan_mode; 606554c0a3aSHans de Goede 607554c0a3aSHans de Goede /* prepare ssid list */ 608554c0a3aSHans de Goede if (ssid) { 609554c0a3aSHans de Goede int i; 610554c0a3aSHans de Goede for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) { 611554c0a3aSHans de Goede if (ssid[i].SsidLength) { 612554c0a3aSHans de Goede memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid)); 613554c0a3aSHans de Goede psurveyPara->ssid_num++; 614554c0a3aSHans de Goede 615554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" ssid:(%s, %d)\n", FUNC_ADPT_ARG(padapter), 616554c0a3aSHans de Goede psurveyPara->ssid[i].Ssid, psurveyPara->ssid[i].SsidLength); 617554c0a3aSHans de Goede } 618554c0a3aSHans de Goede } 619554c0a3aSHans de Goede } 620554c0a3aSHans de Goede 621554c0a3aSHans de Goede /* prepare channel list */ 622554c0a3aSHans de Goede if (ch) { 623554c0a3aSHans de Goede int i; 624554c0a3aSHans de Goede for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) { 625554c0a3aSHans de Goede if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) { 626554c0a3aSHans de Goede memcpy(&psurveyPara->ch[i], &ch[i], sizeof(struct rtw_ieee80211_channel)); 627554c0a3aSHans de Goede psurveyPara->ch_num++; 628554c0a3aSHans de Goede 629554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter), 630554c0a3aSHans de Goede psurveyPara->ch[i].hw_value); 631554c0a3aSHans de Goede } 632554c0a3aSHans de Goede } 633554c0a3aSHans de Goede } 634554c0a3aSHans de Goede 635554c0a3aSHans de Goede set_fwstate(pmlmepriv, _FW_UNDER_SURVEY); 636554c0a3aSHans de Goede 637554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 638554c0a3aSHans de Goede 639554c0a3aSHans de Goede if (res == _SUCCESS) { 640554c0a3aSHans de Goede 641554c0a3aSHans de Goede pmlmepriv->scan_start_time = jiffies; 642554c0a3aSHans de Goede _set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT); 643554c0a3aSHans de Goede } else { 644554c0a3aSHans de Goede _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); 645554c0a3aSHans de Goede } 646554c0a3aSHans de Goede return res; 647554c0a3aSHans de Goede } 648554c0a3aSHans de Goede 649554c0a3aSHans de Goede u8 rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset) 650554c0a3aSHans de Goede { 651554c0a3aSHans de Goede struct cmd_obj *ph2c; 652554c0a3aSHans de Goede struct setdatarate_parm *pbsetdataratepara; 653554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 654554c0a3aSHans de Goede u8 res = _SUCCESS; 655554c0a3aSHans de Goede 6562ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 657554c0a3aSHans de Goede if (ph2c == NULL) { 658554c0a3aSHans de Goede res = _FAIL; 659554c0a3aSHans de Goede goto exit; 660554c0a3aSHans de Goede } 661554c0a3aSHans de Goede 6622ef2b7c2SJoe Perches pbsetdataratepara = rtw_zmalloc(sizeof(struct setdatarate_parm)); 663554c0a3aSHans de Goede if (pbsetdataratepara == NULL) { 664512bbd7bSSrishti Sharma kfree(ph2c); 665554c0a3aSHans de Goede res = _FAIL; 666554c0a3aSHans de Goede goto exit; 667554c0a3aSHans de Goede } 668554c0a3aSHans de Goede 669554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, GEN_CMD_CODE(_SetDataRate)); 670554c0a3aSHans de Goede pbsetdataratepara->mac_id = 5; 671554c0a3aSHans de Goede memcpy(pbsetdataratepara->datarates, rateset, NumRates); 672554c0a3aSHans de Goede 673554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 674554c0a3aSHans de Goede exit: 675554c0a3aSHans de Goede return res; 676554c0a3aSHans de Goede } 677554c0a3aSHans de Goede 678554c0a3aSHans de Goede void rtw_getbbrfreg_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) 679554c0a3aSHans de Goede { 680554c0a3aSHans de Goede /* rtw_free_cmd_obj(pcmd); */ 681512bbd7bSSrishti Sharma kfree(pcmd->parmbuf); 682512bbd7bSSrishti Sharma kfree(pcmd); 683554c0a3aSHans de Goede } 684554c0a3aSHans de Goede 685554c0a3aSHans de Goede u8 rtw_createbss_cmd(struct adapter *padapter) 686554c0a3aSHans de Goede { 687554c0a3aSHans de Goede struct cmd_obj *pcmd; 688554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 689554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 690554c0a3aSHans de Goede struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network; 691554c0a3aSHans de Goede u8 res = _SUCCESS; 692554c0a3aSHans de Goede 693554c0a3aSHans de Goede if (pmlmepriv->assoc_ssid.SsidLength == 0) { 694554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for Any SSid:%s\n", pmlmepriv->assoc_ssid.Ssid)); 695554c0a3aSHans de Goede } else { 696554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid)); 697554c0a3aSHans de Goede } 698554c0a3aSHans de Goede 6992ef2b7c2SJoe Perches pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); 700554c0a3aSHans de Goede if (pcmd == NULL) { 701554c0a3aSHans de Goede res = _FAIL; 702554c0a3aSHans de Goede goto exit; 703554c0a3aSHans de Goede } 704554c0a3aSHans de Goede 705554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd->list); 706554c0a3aSHans de Goede pcmd->cmdcode = _CreateBss_CMD_; 707554c0a3aSHans de Goede pcmd->parmbuf = (unsigned char *)pdev_network; 708554c0a3aSHans de Goede pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network); 709554c0a3aSHans de Goede pcmd->rsp = NULL; 710554c0a3aSHans de Goede pcmd->rspsz = 0; 711554c0a3aSHans de Goede 712554c0a3aSHans de Goede pdev_network->Length = pcmd->cmdsz; 713554c0a3aSHans de Goede 714554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, pcmd); 715554c0a3aSHans de Goede 716554c0a3aSHans de Goede exit: 717554c0a3aSHans de Goede return res; 718554c0a3aSHans de Goede } 719554c0a3aSHans de Goede 720554c0a3aSHans de Goede u8 rtw_startbss_cmd(struct adapter *padapter, int flags) 721554c0a3aSHans de Goede { 722554c0a3aSHans de Goede struct cmd_obj *pcmd; 723554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 724554c0a3aSHans de Goede struct submit_ctx sctx; 725554c0a3aSHans de Goede u8 res = _SUCCESS; 726554c0a3aSHans de Goede 727554c0a3aSHans de Goede if (flags & RTW_CMDF_DIRECTLY) { 728554c0a3aSHans de Goede /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ 729554c0a3aSHans de Goede start_bss_network(padapter, (u8 *)&(padapter->mlmepriv.cur_network.network)); 730554c0a3aSHans de Goede } else { 731554c0a3aSHans de Goede /* need enqueue, prepare cmd_obj and enqueue */ 7322ef2b7c2SJoe Perches pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); 733554c0a3aSHans de Goede if (pcmd == NULL) { 734554c0a3aSHans de Goede res = _FAIL; 735554c0a3aSHans de Goede goto exit; 736554c0a3aSHans de Goede } 737554c0a3aSHans de Goede 738554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd->list); 739554c0a3aSHans de Goede pcmd->cmdcode = GEN_CMD_CODE(_CreateBss); 740554c0a3aSHans de Goede pcmd->parmbuf = NULL; 741554c0a3aSHans de Goede pcmd->cmdsz = 0; 742554c0a3aSHans de Goede pcmd->rsp = NULL; 743554c0a3aSHans de Goede pcmd->rspsz = 0; 744554c0a3aSHans de Goede 745554c0a3aSHans de Goede if (flags & RTW_CMDF_WAIT_ACK) { 746554c0a3aSHans de Goede pcmd->sctx = &sctx; 747554c0a3aSHans de Goede rtw_sctx_init(&sctx, 2000); 748554c0a3aSHans de Goede } 749554c0a3aSHans de Goede 750554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, pcmd); 751554c0a3aSHans de Goede 752554c0a3aSHans de Goede if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) { 753554c0a3aSHans de Goede rtw_sctx_wait(&sctx, __func__); 754554c0a3aSHans de Goede if (mutex_lock_interruptible(&pcmdpriv->sctx_mutex) == 0) { 755554c0a3aSHans de Goede if (sctx.status == RTW_SCTX_SUBMITTED) 756554c0a3aSHans de Goede pcmd->sctx = NULL; 757554c0a3aSHans de Goede mutex_unlock(&pcmdpriv->sctx_mutex); 758554c0a3aSHans de Goede } 759554c0a3aSHans de Goede } 760554c0a3aSHans de Goede } 761554c0a3aSHans de Goede 762554c0a3aSHans de Goede exit: 763554c0a3aSHans de Goede return res; 764554c0a3aSHans de Goede } 765554c0a3aSHans de Goede 766554c0a3aSHans de Goede u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) 767554c0a3aSHans de Goede { 768554c0a3aSHans de Goede u8 *auth, res = _SUCCESS; 769554c0a3aSHans de Goede uint t_len = 0; 770554c0a3aSHans de Goede struct wlan_bssid_ex *psecnetwork; 771554c0a3aSHans de Goede struct cmd_obj *pcmd; 772554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 773554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 774554c0a3aSHans de Goede struct qos_priv *pqospriv = &pmlmepriv->qospriv; 775554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 776554c0a3aSHans de Goede struct registry_priv *pregistrypriv = &padapter->registrypriv; 777554c0a3aSHans de Goede struct ht_priv *phtpriv = &pmlmepriv->htpriv; 778554c0a3aSHans de Goede enum NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = pnetwork->network.InfrastructureMode; 779554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 780554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 781554c0a3aSHans de Goede u32 tmp_len; 782554c0a3aSHans de Goede u8 *ptmp = NULL; 783554c0a3aSHans de Goede 784554c0a3aSHans de Goede if (pmlmepriv->assoc_ssid.SsidLength == 0) { 785554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+Join cmd: Any SSid\n")); 786554c0a3aSHans de Goede } else { 787554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+Join cmd: SSid =[%s]\n", pmlmepriv->assoc_ssid.Ssid)); 788554c0a3aSHans de Goede } 789554c0a3aSHans de Goede 7902ef2b7c2SJoe Perches pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); 791554c0a3aSHans de Goede if (pcmd == NULL) { 792554c0a3aSHans de Goede res = _FAIL; 793554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd: memory allocate for cmd_obj fail!!!\n")); 794554c0a3aSHans de Goede goto exit; 795554c0a3aSHans de Goede } 796554c0a3aSHans de Goede /* for IEs is fix buf size */ 797554c0a3aSHans de Goede t_len = sizeof(struct wlan_bssid_ex); 798554c0a3aSHans de Goede 799554c0a3aSHans de Goede 800554c0a3aSHans de Goede /* for hidden ap to set fw_state here */ 801554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) != true) { 802554c0a3aSHans de Goede switch (ndis_network_mode) { 803554c0a3aSHans de Goede case Ndis802_11IBSS: 804554c0a3aSHans de Goede set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); 805554c0a3aSHans de Goede break; 806554c0a3aSHans de Goede 807554c0a3aSHans de Goede case Ndis802_11Infrastructure: 808554c0a3aSHans de Goede set_fwstate(pmlmepriv, WIFI_STATION_STATE); 809554c0a3aSHans de Goede break; 810554c0a3aSHans de Goede 811554c0a3aSHans de Goede case Ndis802_11APMode: 812554c0a3aSHans de Goede case Ndis802_11AutoUnknown: 813554c0a3aSHans de Goede case Ndis802_11InfrastructureMax: 814554c0a3aSHans de Goede break; 815554c0a3aSHans de Goede 816554c0a3aSHans de Goede } 817554c0a3aSHans de Goede } 818554c0a3aSHans de Goede 819554c0a3aSHans de Goede psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss; 820554c0a3aSHans de Goede 821554c0a3aSHans de Goede memset(psecnetwork, 0, t_len); 822554c0a3aSHans de Goede 823554c0a3aSHans de Goede memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network)); 824554c0a3aSHans de Goede 825554c0a3aSHans de Goede auth = &psecuritypriv->authenticator_ie[0]; 826554c0a3aSHans de Goede psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength; 827554c0a3aSHans de Goede 828554c0a3aSHans de Goede if ((psecnetwork->IELength-12) < (256-1)) { 829554c0a3aSHans de Goede memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength-12); 830554c0a3aSHans de Goede } else { 831554c0a3aSHans de Goede memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256-1)); 832554c0a3aSHans de Goede } 833554c0a3aSHans de Goede 834554c0a3aSHans de Goede psecnetwork->IELength = 0; 835554c0a3aSHans de Goede /* Added by Albert 2009/02/18 */ 836554c0a3aSHans de Goede /* If the the driver wants to use the bssid to create the connection. */ 837554c0a3aSHans de Goede /* If not, we have to copy the connecting AP's MAC address to it so that */ 838554c0a3aSHans de Goede /* the driver just has the bssid information for PMKIDList searching. */ 839554c0a3aSHans de Goede 840554c0a3aSHans de Goede if (pmlmepriv->assoc_by_bssid == false) { 841554c0a3aSHans de Goede memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN); 842554c0a3aSHans de Goede } 843554c0a3aSHans de Goede 844554c0a3aSHans de Goede psecnetwork->IELength = rtw_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength); 845554c0a3aSHans de Goede 846554c0a3aSHans de Goede 847554c0a3aSHans de Goede pqospriv->qos_option = 0; 848554c0a3aSHans de Goede 849554c0a3aSHans de Goede if (pregistrypriv->wmm_enable) { 850554c0a3aSHans de Goede tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength); 851554c0a3aSHans de Goede 852554c0a3aSHans de Goede if (psecnetwork->IELength != tmp_len) { 853554c0a3aSHans de Goede psecnetwork->IELength = tmp_len; 854554c0a3aSHans de Goede pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */ 855554c0a3aSHans de Goede } else { 856554c0a3aSHans de Goede pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */ 857554c0a3aSHans de Goede } 858554c0a3aSHans de Goede } 859554c0a3aSHans de Goede 860554c0a3aSHans de Goede phtpriv->ht_option = false; 861554c0a3aSHans de Goede ptmp = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &tmp_len, pnetwork->network.IELength-12); 862554c0a3aSHans de Goede if (pregistrypriv->ht_enable && ptmp && tmp_len > 0) { 863554c0a3aSHans de Goede /* Added by Albert 2010/06/23 */ 864554c0a3aSHans de Goede /* For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */ 865554c0a3aSHans de Goede /* Especially for Realtek 8192u SoftAP. */ 866554c0a3aSHans de Goede if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) && 867554c0a3aSHans de Goede (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) && 868554c0a3aSHans de Goede (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) { 869554c0a3aSHans de Goede rtw_ht_use_default_setting(padapter); 870554c0a3aSHans de Goede 871554c0a3aSHans de Goede rtw_build_wmm_ie_ht(padapter, &psecnetwork->IEs[12], &psecnetwork->IELength); 872554c0a3aSHans de Goede 873554c0a3aSHans de Goede /* rtw_restructure_ht_ie */ 874554c0a3aSHans de Goede rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[12], &psecnetwork->IEs[0], 875554c0a3aSHans de Goede pnetwork->network.IELength-12, &psecnetwork->IELength, 876554c0a3aSHans de Goede pnetwork->network.Configuration.DSConfig); 877554c0a3aSHans de Goede } 878554c0a3aSHans de Goede } 879554c0a3aSHans de Goede 880554c0a3aSHans de Goede rtw_append_exented_cap(padapter, &psecnetwork->IEs[0], &psecnetwork->IELength); 881554c0a3aSHans de Goede 882554c0a3aSHans de Goede pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength); 883554c0a3aSHans de Goede 884554c0a3aSHans de Goede pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */ 885554c0a3aSHans de Goede 886554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd->list); 887554c0a3aSHans de Goede pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */ 888554c0a3aSHans de Goede pcmd->parmbuf = (unsigned char *)psecnetwork; 889554c0a3aSHans de Goede pcmd->rsp = NULL; 890554c0a3aSHans de Goede pcmd->rspsz = 0; 891554c0a3aSHans de Goede 892554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, pcmd); 893554c0a3aSHans de Goede 894554c0a3aSHans de Goede exit: 895554c0a3aSHans de Goede return res; 896554c0a3aSHans de Goede } 897554c0a3aSHans de Goede 898554c0a3aSHans de Goede u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */ 899554c0a3aSHans de Goede { 900554c0a3aSHans de Goede struct cmd_obj *cmdobj = NULL; 901554c0a3aSHans de Goede struct disconnect_parm *param = NULL; 902554c0a3aSHans de Goede struct cmd_priv *cmdpriv = &padapter->cmdpriv; 903554c0a3aSHans de Goede u8 res = _SUCCESS; 904554c0a3aSHans de Goede 905554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_disassoc_cmd\n")); 906554c0a3aSHans de Goede 907554c0a3aSHans de Goede /* prepare cmd parameter */ 9082ef2b7c2SJoe Perches param = rtw_zmalloc(sizeof(*param)); 909554c0a3aSHans de Goede if (param == NULL) { 910554c0a3aSHans de Goede res = _FAIL; 911554c0a3aSHans de Goede goto exit; 912554c0a3aSHans de Goede } 913554c0a3aSHans de Goede param->deauth_timeout_ms = deauth_timeout_ms; 914554c0a3aSHans de Goede 915554c0a3aSHans de Goede if (enqueue) { 916554c0a3aSHans de Goede /* need enqueue, prepare cmd_obj and enqueue */ 9172ef2b7c2SJoe Perches cmdobj = rtw_zmalloc(sizeof(*cmdobj)); 918554c0a3aSHans de Goede if (cmdobj == NULL) { 919554c0a3aSHans de Goede res = _FAIL; 920512bbd7bSSrishti Sharma kfree(param); 921554c0a3aSHans de Goede goto exit; 922554c0a3aSHans de Goede } 923554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_); 924554c0a3aSHans de Goede res = rtw_enqueue_cmd(cmdpriv, cmdobj); 925554c0a3aSHans de Goede } else { 926554c0a3aSHans de Goede /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ 927554c0a3aSHans de Goede if (H2C_SUCCESS != disconnect_hdl(padapter, (u8 *)param)) 928554c0a3aSHans de Goede res = _FAIL; 929512bbd7bSSrishti Sharma kfree(param); 930554c0a3aSHans de Goede } 931554c0a3aSHans de Goede 932554c0a3aSHans de Goede exit: 933554c0a3aSHans de Goede return res; 934554c0a3aSHans de Goede } 935554c0a3aSHans de Goede 936554c0a3aSHans de Goede u8 rtw_setopmode_cmd(struct adapter *padapter, enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype, bool enqueue) 937554c0a3aSHans de Goede { 938554c0a3aSHans de Goede struct cmd_obj *ph2c; 939554c0a3aSHans de Goede struct setopmode_parm *psetop; 940554c0a3aSHans de Goede 941554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 942554c0a3aSHans de Goede u8 res = _SUCCESS; 943554c0a3aSHans de Goede 9442ef2b7c2SJoe Perches psetop = rtw_zmalloc(sizeof(struct setopmode_parm)); 945554c0a3aSHans de Goede 946554c0a3aSHans de Goede if (psetop == NULL) { 947554c0a3aSHans de Goede res = _FAIL; 948554c0a3aSHans de Goede goto exit; 949554c0a3aSHans de Goede } 950554c0a3aSHans de Goede psetop->mode = (u8)networktype; 951554c0a3aSHans de Goede 952554c0a3aSHans de Goede if (enqueue) { 9532ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 954554c0a3aSHans de Goede if (ph2c == NULL) { 955512bbd7bSSrishti Sharma kfree(psetop); 956554c0a3aSHans de Goede res = _FAIL; 957554c0a3aSHans de Goede goto exit; 958554c0a3aSHans de Goede } 959554c0a3aSHans de Goede 960554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_); 961554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 962554c0a3aSHans de Goede } else { 963554c0a3aSHans de Goede setopmode_hdl(padapter, (u8 *)psetop); 964512bbd7bSSrishti Sharma kfree(psetop); 965554c0a3aSHans de Goede } 966554c0a3aSHans de Goede exit: 967554c0a3aSHans de Goede return res; 968554c0a3aSHans de Goede } 969554c0a3aSHans de Goede 970554c0a3aSHans de Goede u8 rtw_setstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 unicast_key, bool enqueue) 971554c0a3aSHans de Goede { 972554c0a3aSHans de Goede struct cmd_obj *ph2c; 973554c0a3aSHans de Goede struct set_stakey_parm *psetstakey_para; 974554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 975554c0a3aSHans de Goede struct set_stakey_rsp *psetstakey_rsp = NULL; 976554c0a3aSHans de Goede 977554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 978554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 979554c0a3aSHans de Goede u8 res = _SUCCESS; 980554c0a3aSHans de Goede 9812ef2b7c2SJoe Perches psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm)); 982554c0a3aSHans de Goede if (psetstakey_para == NULL) { 983554c0a3aSHans de Goede res = _FAIL; 984554c0a3aSHans de Goede goto exit; 985554c0a3aSHans de Goede } 986554c0a3aSHans de Goede 987554c0a3aSHans de Goede memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN); 988554c0a3aSHans de Goede 989554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { 990554c0a3aSHans de Goede psetstakey_para->algorithm = (unsigned char) psecuritypriv->dot11PrivacyAlgrthm; 991554c0a3aSHans de Goede } else { 992554c0a3aSHans de Goede GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false); 993554c0a3aSHans de Goede } 994554c0a3aSHans de Goede 995554c0a3aSHans de Goede if (unicast_key == true) { 996554c0a3aSHans de Goede memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16); 997554c0a3aSHans de Goede } else { 998554c0a3aSHans de Goede memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16); 999554c0a3aSHans de Goede } 1000554c0a3aSHans de Goede 1001554c0a3aSHans de Goede /* jeff: set this becasue at least sw key is ready */ 1002554c0a3aSHans de Goede padapter->securitypriv.busetkipkey = true; 1003554c0a3aSHans de Goede 1004554c0a3aSHans de Goede if (enqueue) { 10052ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1006554c0a3aSHans de Goede if (ph2c == NULL) { 1007512bbd7bSSrishti Sharma kfree(psetstakey_para); 1008554c0a3aSHans de Goede res = _FAIL; 1009554c0a3aSHans de Goede goto exit; 1010554c0a3aSHans de Goede } 1011554c0a3aSHans de Goede 10122ef2b7c2SJoe Perches psetstakey_rsp = rtw_zmalloc(sizeof(struct set_stakey_rsp)); 1013554c0a3aSHans de Goede if (psetstakey_rsp == NULL) { 1014512bbd7bSSrishti Sharma kfree(ph2c); 1015512bbd7bSSrishti Sharma kfree(psetstakey_para); 1016554c0a3aSHans de Goede res = _FAIL; 1017554c0a3aSHans de Goede goto exit; 1018554c0a3aSHans de Goede } 1019554c0a3aSHans de Goede 1020554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); 1021554c0a3aSHans de Goede ph2c->rsp = (u8 *) psetstakey_rsp; 1022554c0a3aSHans de Goede ph2c->rspsz = sizeof(struct set_stakey_rsp); 1023554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1024554c0a3aSHans de Goede } else { 1025554c0a3aSHans de Goede set_stakey_hdl(padapter, (u8 *)psetstakey_para); 1026512bbd7bSSrishti Sharma kfree(psetstakey_para); 1027554c0a3aSHans de Goede } 1028554c0a3aSHans de Goede exit: 1029554c0a3aSHans de Goede return res; 1030554c0a3aSHans de Goede } 1031554c0a3aSHans de Goede 1032554c0a3aSHans de Goede u8 rtw_clearstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 enqueue) 1033554c0a3aSHans de Goede { 1034554c0a3aSHans de Goede struct cmd_obj *ph2c; 1035554c0a3aSHans de Goede struct set_stakey_parm *psetstakey_para; 1036554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1037554c0a3aSHans de Goede struct set_stakey_rsp *psetstakey_rsp = NULL; 1038554c0a3aSHans de Goede s16 cam_id = 0; 1039554c0a3aSHans de Goede u8 res = _SUCCESS; 1040554c0a3aSHans de Goede 1041554c0a3aSHans de Goede if (!enqueue) { 1042554c0a3aSHans de Goede while ((cam_id = rtw_camid_search(padapter, sta->hwaddr, -1)) >= 0) { 1043554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "clear key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(sta->hwaddr), cam_id); 1044554c0a3aSHans de Goede clear_cam_entry(padapter, cam_id); 1045554c0a3aSHans de Goede rtw_camid_free(padapter, cam_id); 1046554c0a3aSHans de Goede } 1047554c0a3aSHans de Goede } else { 10482ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1049554c0a3aSHans de Goede if (ph2c == NULL) { 1050554c0a3aSHans de Goede res = _FAIL; 1051554c0a3aSHans de Goede goto exit; 1052554c0a3aSHans de Goede } 1053554c0a3aSHans de Goede 10542ef2b7c2SJoe Perches psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm)); 1055554c0a3aSHans de Goede if (psetstakey_para == NULL) { 1056512bbd7bSSrishti Sharma kfree(ph2c); 1057554c0a3aSHans de Goede res = _FAIL; 1058554c0a3aSHans de Goede goto exit; 1059554c0a3aSHans de Goede } 1060554c0a3aSHans de Goede 10612ef2b7c2SJoe Perches psetstakey_rsp = rtw_zmalloc(sizeof(struct set_stakey_rsp)); 1062554c0a3aSHans de Goede if (psetstakey_rsp == NULL) { 1063512bbd7bSSrishti Sharma kfree(ph2c); 1064512bbd7bSSrishti Sharma kfree(psetstakey_para); 1065554c0a3aSHans de Goede res = _FAIL; 1066554c0a3aSHans de Goede goto exit; 1067554c0a3aSHans de Goede } 1068554c0a3aSHans de Goede 1069554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); 1070554c0a3aSHans de Goede ph2c->rsp = (u8 *) psetstakey_rsp; 1071554c0a3aSHans de Goede ph2c->rspsz = sizeof(struct set_stakey_rsp); 1072554c0a3aSHans de Goede 1073554c0a3aSHans de Goede memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN); 1074554c0a3aSHans de Goede 1075554c0a3aSHans de Goede psetstakey_para->algorithm = _NO_PRIVACY_; 1076554c0a3aSHans de Goede 1077554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1078554c0a3aSHans de Goede 1079554c0a3aSHans de Goede } 1080554c0a3aSHans de Goede 1081554c0a3aSHans de Goede exit: 1082554c0a3aSHans de Goede return res; 1083554c0a3aSHans de Goede } 1084554c0a3aSHans de Goede 1085554c0a3aSHans de Goede u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr) 1086554c0a3aSHans de Goede { 1087554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1088554c0a3aSHans de Goede struct cmd_obj *ph2c; 1089554c0a3aSHans de Goede struct addBaReq_parm *paddbareq_parm; 1090554c0a3aSHans de Goede 1091554c0a3aSHans de Goede u8 res = _SUCCESS; 1092554c0a3aSHans de Goede 10932ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1094554c0a3aSHans de Goede if (ph2c == NULL) { 1095554c0a3aSHans de Goede res = _FAIL; 1096554c0a3aSHans de Goede goto exit; 1097554c0a3aSHans de Goede } 1098554c0a3aSHans de Goede 10992ef2b7c2SJoe Perches paddbareq_parm = rtw_zmalloc(sizeof(struct addBaReq_parm)); 1100554c0a3aSHans de Goede if (paddbareq_parm == NULL) { 1101512bbd7bSSrishti Sharma kfree(ph2c); 1102554c0a3aSHans de Goede res = _FAIL; 1103554c0a3aSHans de Goede goto exit; 1104554c0a3aSHans de Goede } 1105554c0a3aSHans de Goede 1106554c0a3aSHans de Goede paddbareq_parm->tid = tid; 1107554c0a3aSHans de Goede memcpy(paddbareq_parm->addr, addr, ETH_ALEN); 1108554c0a3aSHans de Goede 1109554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq)); 1110554c0a3aSHans de Goede 1111554c0a3aSHans de Goede /* DBG_871X("rtw_addbareq_cmd, tid =%d\n", tid); */ 1112554c0a3aSHans de Goede 1113554c0a3aSHans de Goede /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ 1114554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1115554c0a3aSHans de Goede 1116554c0a3aSHans de Goede exit: 1117554c0a3aSHans de Goede return res; 1118554c0a3aSHans de Goede } 1119554c0a3aSHans de Goede /* add for CONFIG_IEEE80211W, none 11w can use it */ 1120554c0a3aSHans de Goede u8 rtw_reset_securitypriv_cmd(struct adapter *padapter) 1121554c0a3aSHans de Goede { 1122554c0a3aSHans de Goede struct cmd_obj *ph2c; 1123554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1124554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1125554c0a3aSHans de Goede u8 res = _SUCCESS; 1126554c0a3aSHans de Goede 11272ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1128554c0a3aSHans de Goede if (ph2c == NULL) { 1129554c0a3aSHans de Goede res = _FAIL; 1130554c0a3aSHans de Goede goto exit; 1131554c0a3aSHans de Goede } 1132554c0a3aSHans de Goede 11332ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1134554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1135512bbd7bSSrishti Sharma kfree(ph2c); 1136554c0a3aSHans de Goede res = _FAIL; 1137554c0a3aSHans de Goede goto exit; 1138554c0a3aSHans de Goede } 1139554c0a3aSHans de Goede 1140554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = RESET_SECURITYPRIV; 1141554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1142554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1143554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1144554c0a3aSHans de Goede 1145554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1146554c0a3aSHans de Goede 1147554c0a3aSHans de Goede 1148554c0a3aSHans de Goede /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ 1149554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1150554c0a3aSHans de Goede 1151554c0a3aSHans de Goede exit: 1152554c0a3aSHans de Goede return res; 1153554c0a3aSHans de Goede } 1154554c0a3aSHans de Goede 1155554c0a3aSHans de Goede u8 rtw_free_assoc_resources_cmd(struct adapter *padapter) 1156554c0a3aSHans de Goede { 1157554c0a3aSHans de Goede struct cmd_obj *ph2c; 1158554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1159554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1160554c0a3aSHans de Goede u8 res = _SUCCESS; 1161554c0a3aSHans de Goede 11622ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1163554c0a3aSHans de Goede if (ph2c == NULL) { 1164554c0a3aSHans de Goede res = _FAIL; 1165554c0a3aSHans de Goede goto exit; 1166554c0a3aSHans de Goede } 1167554c0a3aSHans de Goede 11682ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1169554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1170512bbd7bSSrishti Sharma kfree(ph2c); 1171554c0a3aSHans de Goede res = _FAIL; 1172554c0a3aSHans de Goede goto exit; 1173554c0a3aSHans de Goede } 1174554c0a3aSHans de Goede 1175554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = FREE_ASSOC_RESOURCES; 1176554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1177554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1178554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1179554c0a3aSHans de Goede 1180554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1181554c0a3aSHans de Goede 1182554c0a3aSHans de Goede 1183554c0a3aSHans de Goede /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ 1184554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1185554c0a3aSHans de Goede 1186554c0a3aSHans de Goede exit: 1187554c0a3aSHans de Goede return res; 1188554c0a3aSHans de Goede } 1189554c0a3aSHans de Goede 1190554c0a3aSHans de Goede u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter) 1191554c0a3aSHans de Goede { 1192554c0a3aSHans de Goede struct cmd_obj *ph2c; 1193554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1194554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1195554c0a3aSHans de Goede u8 res = _SUCCESS; 1196554c0a3aSHans de Goede 1197554c0a3aSHans de Goede /* only primary padapter does this cmd */ 11982ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1199554c0a3aSHans de Goede if (ph2c == NULL) { 1200554c0a3aSHans de Goede res = _FAIL; 1201554c0a3aSHans de Goede goto exit; 1202554c0a3aSHans de Goede } 1203554c0a3aSHans de Goede 12042ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1205554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1206512bbd7bSSrishti Sharma kfree(ph2c); 1207554c0a3aSHans de Goede res = _FAIL; 1208554c0a3aSHans de Goede goto exit; 1209554c0a3aSHans de Goede } 1210554c0a3aSHans de Goede 1211554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID; 1212554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1213554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1214554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1215554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1216554c0a3aSHans de Goede 1217554c0a3aSHans de Goede 1218554c0a3aSHans de Goede /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ 1219554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1220554c0a3aSHans de Goede 1221554c0a3aSHans de Goede exit: 1222554c0a3aSHans de Goede return res; 1223554c0a3aSHans de Goede } 1224554c0a3aSHans de Goede 1225554c0a3aSHans de Goede u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue, u8 swconfig) 1226554c0a3aSHans de Goede { 1227554c0a3aSHans de Goede struct cmd_obj *pcmdobj; 1228554c0a3aSHans de Goede struct SetChannelPlan_param *setChannelPlan_param; 1229554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1230554c0a3aSHans de Goede 1231554c0a3aSHans de Goede u8 res = _SUCCESS; 1232554c0a3aSHans de Goede 1233554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_chplan_cmd\n")); 1234554c0a3aSHans de Goede 1235554c0a3aSHans de Goede /* check if allow software config */ 1236554c0a3aSHans de Goede if (swconfig && rtw_hal_is_disable_sw_channel_plan(padapter) == true) { 1237554c0a3aSHans de Goede res = _FAIL; 1238554c0a3aSHans de Goede goto exit; 1239554c0a3aSHans de Goede } 1240554c0a3aSHans de Goede 1241554c0a3aSHans de Goede /* check input parameter */ 1242554c0a3aSHans de Goede if (!rtw_is_channel_plan_valid(chplan)) { 1243554c0a3aSHans de Goede res = _FAIL; 1244554c0a3aSHans de Goede goto exit; 1245554c0a3aSHans de Goede } 1246554c0a3aSHans de Goede 1247554c0a3aSHans de Goede /* prepare cmd parameter */ 12482ef2b7c2SJoe Perches setChannelPlan_param = rtw_zmalloc(sizeof(struct SetChannelPlan_param)); 1249554c0a3aSHans de Goede if (setChannelPlan_param == NULL) { 1250554c0a3aSHans de Goede res = _FAIL; 1251554c0a3aSHans de Goede goto exit; 1252554c0a3aSHans de Goede } 1253554c0a3aSHans de Goede setChannelPlan_param->channel_plan = chplan; 1254554c0a3aSHans de Goede 1255554c0a3aSHans de Goede if (enqueue) { 1256554c0a3aSHans de Goede /* need enqueue, prepare cmd_obj and enqueue */ 12572ef2b7c2SJoe Perches pcmdobj = rtw_zmalloc(sizeof(struct cmd_obj)); 1258554c0a3aSHans de Goede if (pcmdobj == NULL) { 1259512bbd7bSSrishti Sharma kfree(setChannelPlan_param); 1260554c0a3aSHans de Goede res = _FAIL; 1261554c0a3aSHans de Goede goto exit; 1262554c0a3aSHans de Goede } 1263554c0a3aSHans de Goede 1264554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, GEN_CMD_CODE(_SetChannelPlan)); 1265554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, pcmdobj); 1266554c0a3aSHans de Goede } else { 1267554c0a3aSHans de Goede /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ 1268554c0a3aSHans de Goede if (H2C_SUCCESS != set_chplan_hdl(padapter, (unsigned char *)setChannelPlan_param)) 1269554c0a3aSHans de Goede res = _FAIL; 1270554c0a3aSHans de Goede 1271512bbd7bSSrishti Sharma kfree(setChannelPlan_param); 1272554c0a3aSHans de Goede } 1273554c0a3aSHans de Goede 1274554c0a3aSHans de Goede /* do something based on res... */ 1275554c0a3aSHans de Goede if (res == _SUCCESS) 1276554c0a3aSHans de Goede padapter->mlmepriv.ChannelPlan = chplan; 1277554c0a3aSHans de Goede 1278554c0a3aSHans de Goede exit: 1279554c0a3aSHans de Goede return res; 1280554c0a3aSHans de Goede } 1281554c0a3aSHans de Goede 1282554c0a3aSHans de Goede static void collect_traffic_statistics(struct adapter *padapter) 1283554c0a3aSHans de Goede { 1284554c0a3aSHans de Goede struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); 1285554c0a3aSHans de Goede 1286554c0a3aSHans de Goede /* Tx */ 1287554c0a3aSHans de Goede pdvobjpriv->traffic_stat.tx_bytes = padapter->xmitpriv.tx_bytes; 1288554c0a3aSHans de Goede pdvobjpriv->traffic_stat.tx_pkts = padapter->xmitpriv.tx_pkts; 1289554c0a3aSHans de Goede pdvobjpriv->traffic_stat.tx_drop = padapter->xmitpriv.tx_drop; 1290554c0a3aSHans de Goede 1291554c0a3aSHans de Goede /* Rx */ 1292554c0a3aSHans de Goede pdvobjpriv->traffic_stat.rx_bytes = padapter->recvpriv.rx_bytes; 1293554c0a3aSHans de Goede pdvobjpriv->traffic_stat.rx_pkts = padapter->recvpriv.rx_pkts; 1294554c0a3aSHans de Goede pdvobjpriv->traffic_stat.rx_drop = padapter->recvpriv.rx_drop; 1295554c0a3aSHans de Goede 1296554c0a3aSHans de Goede /* Calculate throughput in last interval */ 1297554c0a3aSHans de Goede pdvobjpriv->traffic_stat.cur_tx_bytes = pdvobjpriv->traffic_stat.tx_bytes - pdvobjpriv->traffic_stat.last_tx_bytes; 1298554c0a3aSHans de Goede pdvobjpriv->traffic_stat.cur_rx_bytes = pdvobjpriv->traffic_stat.rx_bytes - pdvobjpriv->traffic_stat.last_rx_bytes; 1299554c0a3aSHans de Goede pdvobjpriv->traffic_stat.last_tx_bytes = pdvobjpriv->traffic_stat.tx_bytes; 1300554c0a3aSHans de Goede pdvobjpriv->traffic_stat.last_rx_bytes = pdvobjpriv->traffic_stat.rx_bytes; 1301554c0a3aSHans de Goede 1302554c0a3aSHans de Goede pdvobjpriv->traffic_stat.cur_tx_tp = (u32)(pdvobjpriv->traffic_stat.cur_tx_bytes * 8/2/1024/1024); 1303554c0a3aSHans de Goede pdvobjpriv->traffic_stat.cur_rx_tp = (u32)(pdvobjpriv->traffic_stat.cur_rx_bytes * 8/2/1024/1024); 1304554c0a3aSHans de Goede } 1305554c0a3aSHans de Goede 1306554c0a3aSHans de Goede u8 traffic_status_watchdog(struct adapter *padapter, u8 from_timer) 1307554c0a3aSHans de Goede { 1308554c0a3aSHans de Goede u8 bEnterPS = false; 1309554c0a3aSHans de Goede u16 BusyThresholdHigh = 25; 1310554c0a3aSHans de Goede u16 BusyThresholdLow = 10; 1311554c0a3aSHans de Goede u16 BusyThreshold = BusyThresholdHigh; 1312554c0a3aSHans de Goede u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false; 1313554c0a3aSHans de Goede u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false; 1314554c0a3aSHans de Goede 1315554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1316554c0a3aSHans de Goede 1317554c0a3aSHans de Goede collect_traffic_statistics(padapter); 1318554c0a3aSHans de Goede 1319554c0a3aSHans de Goede /* */ 1320554c0a3aSHans de Goede /* Determine if our traffic is busy now */ 1321554c0a3aSHans de Goede /* */ 1322554c0a3aSHans de Goede if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) 1323554c0a3aSHans de Goede /*&& !MgntInitAdapterInProgress(pMgntInfo)*/) { 1324554c0a3aSHans de Goede /* if we raise bBusyTraffic in last watchdog, using lower threshold. */ 1325554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.bBusyTraffic) 1326554c0a3aSHans de Goede BusyThreshold = BusyThresholdLow; 1327554c0a3aSHans de Goede 1328554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold || 1329554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold) { 1330554c0a3aSHans de Goede bBusyTraffic = true; 1331554c0a3aSHans de Goede 1332554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) 1333554c0a3aSHans de Goede bRxBusyTraffic = true; 1334554c0a3aSHans de Goede else 1335554c0a3aSHans de Goede bTxBusyTraffic = true; 1336554c0a3aSHans de Goede } 1337554c0a3aSHans de Goede 1338554c0a3aSHans de Goede /* Higher Tx/Rx data. */ 1339554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 || 1340554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) { 1341554c0a3aSHans de Goede bHigherBusyTraffic = true; 1342554c0a3aSHans de Goede 1343554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) 1344554c0a3aSHans de Goede bHigherBusyRxTraffic = true; 1345554c0a3aSHans de Goede else 1346554c0a3aSHans de Goede bHigherBusyTxTraffic = true; 1347554c0a3aSHans de Goede } 1348554c0a3aSHans de Goede 1349554c0a3aSHans de Goede /* check traffic for powersaving. */ 1350554c0a3aSHans de Goede if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) || 1351554c0a3aSHans de Goede (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2)) { 1352554c0a3aSHans de Goede /* DBG_871X("(-)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); */ 1353554c0a3aSHans de Goede bEnterPS = false; 1354554c0a3aSHans de Goede 1355554c0a3aSHans de Goede if (bBusyTraffic == true) { 1356554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount <= 4) 1357554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 4; 1358554c0a3aSHans de Goede 1359554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount++; 1360554c0a3aSHans de Goede 1361554c0a3aSHans de Goede /* DBG_871X("Set TrafficTransitionCount to %d\n", pmlmepriv->LinkDetectInfo.TrafficTransitionCount); */ 1362554c0a3aSHans de Goede 1363554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount > 30/*TrafficTransitionLevel*/) { 1364554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 30; 1365554c0a3aSHans de Goede } 1366554c0a3aSHans de Goede } 1367554c0a3aSHans de Goede } else { 1368554c0a3aSHans de Goede /* DBG_871X("(+)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); */ 1369554c0a3aSHans de Goede 1370554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount >= 2) 1371554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount -= 2; 1372554c0a3aSHans de Goede else 1373554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0; 1374554c0a3aSHans de Goede 1375554c0a3aSHans de Goede if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount == 0) 1376554c0a3aSHans de Goede bEnterPS = true; 1377554c0a3aSHans de Goede } 1378554c0a3aSHans de Goede 1379554c0a3aSHans de Goede /* LeisurePS only work in infra mode. */ 1380554c0a3aSHans de Goede if (bEnterPS) { 1381554c0a3aSHans de Goede if (!from_timer) 1382554c0a3aSHans de Goede LPS_Enter(padapter, "TRAFFIC_IDLE"); 1383554c0a3aSHans de Goede } else { 1384554c0a3aSHans de Goede if (!from_timer) 1385554c0a3aSHans de Goede LPS_Leave(padapter, "TRAFFIC_BUSY"); 1386554c0a3aSHans de Goede else 1387554c0a3aSHans de Goede rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_TRAFFIC_BUSY, 1); 1388554c0a3aSHans de Goede } 1389554c0a3aSHans de Goede } else { 1390554c0a3aSHans de Goede struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); 1391554c0a3aSHans de Goede int n_assoc_iface = 0; 1392554c0a3aSHans de Goede 1393554c0a3aSHans de Goede if (check_fwstate(&(dvobj->padapters->mlmepriv), WIFI_ASOC_STATE)) 1394554c0a3aSHans de Goede n_assoc_iface++; 1395554c0a3aSHans de Goede 1396554c0a3aSHans de Goede if (!from_timer && n_assoc_iface == 0) 1397554c0a3aSHans de Goede LPS_Leave(padapter, "NON_LINKED"); 1398554c0a3aSHans de Goede } 1399554c0a3aSHans de Goede 1400554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0; 1401554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0; 1402554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0; 1403554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic; 1404554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic; 1405554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic; 1406554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic; 1407554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic; 1408554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic; 1409554c0a3aSHans de Goede 1410554c0a3aSHans de Goede return bEnterPS; 1411554c0a3aSHans de Goede 1412554c0a3aSHans de Goede } 1413554c0a3aSHans de Goede 1414554c0a3aSHans de Goede static void dynamic_chk_wk_hdl(struct adapter *padapter) 1415554c0a3aSHans de Goede { 1416554c0a3aSHans de Goede struct mlme_priv *pmlmepriv; 1417554c0a3aSHans de Goede pmlmepriv = &(padapter->mlmepriv); 1418554c0a3aSHans de Goede 1419554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) { 1420554c0a3aSHans de Goede expire_timeout_chk(padapter); 1421554c0a3aSHans de Goede } 1422554c0a3aSHans de Goede 1423554c0a3aSHans de Goede /* for debug purpose */ 1424554c0a3aSHans de Goede _linked_info_dump(padapter); 1425554c0a3aSHans de Goede 1426554c0a3aSHans de Goede 1427554c0a3aSHans de Goede /* if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING|_FW_UNDER_SURVEY) ==false) */ 1428554c0a3aSHans de Goede { 1429554c0a3aSHans de Goede linked_status_chk(padapter); 1430554c0a3aSHans de Goede traffic_status_watchdog(padapter, 0); 1431554c0a3aSHans de Goede } 1432554c0a3aSHans de Goede 1433554c0a3aSHans de Goede rtw_hal_dm_watchdog(padapter); 1434554c0a3aSHans de Goede 1435554c0a3aSHans de Goede /* check_hw_pbc(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type); */ 1436554c0a3aSHans de Goede 1437554c0a3aSHans de Goede /* */ 1438554c0a3aSHans de Goede /* BT-Coexist */ 1439554c0a3aSHans de Goede /* */ 1440554c0a3aSHans de Goede rtw_btcoex_Handler(padapter); 1441554c0a3aSHans de Goede 1442554c0a3aSHans de Goede 1443554c0a3aSHans de Goede /* always call rtw_ps_processor() at last one. */ 1444554c0a3aSHans de Goede if (is_primary_adapter(padapter)) 1445554c0a3aSHans de Goede rtw_ps_processor(padapter); 1446554c0a3aSHans de Goede } 1447554c0a3aSHans de Goede 1448554c0a3aSHans de Goede void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type); 1449554c0a3aSHans de Goede void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type) 1450554c0a3aSHans de Goede { 1451554c0a3aSHans de Goede struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); 1452554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 1453554c0a3aSHans de Goede u8 mstatus; 1454554c0a3aSHans de Goede 1455554c0a3aSHans de Goede if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) 1456554c0a3aSHans de Goede || (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) { 1457554c0a3aSHans de Goede return; 1458554c0a3aSHans de Goede } 1459554c0a3aSHans de Goede 1460554c0a3aSHans de Goede switch (lps_ctrl_type) { 1461554c0a3aSHans de Goede case LPS_CTRL_SCAN: 1462554c0a3aSHans de Goede /* DBG_871X("LPS_CTRL_SCAN\n"); */ 1463554c0a3aSHans de Goede rtw_btcoex_ScanNotify(padapter, true); 1464554c0a3aSHans de Goede 1465554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { 1466554c0a3aSHans de Goede /* connect */ 1467554c0a3aSHans de Goede LPS_Leave(padapter, "LPS_CTRL_SCAN"); 1468554c0a3aSHans de Goede } 1469554c0a3aSHans de Goede break; 1470554c0a3aSHans de Goede case LPS_CTRL_JOINBSS: 1471554c0a3aSHans de Goede /* DBG_871X("LPS_CTRL_JOINBSS\n"); */ 1472554c0a3aSHans de Goede LPS_Leave(padapter, "LPS_CTRL_JOINBSS"); 1473554c0a3aSHans de Goede break; 1474554c0a3aSHans de Goede case LPS_CTRL_CONNECT: 1475554c0a3aSHans de Goede /* DBG_871X("LPS_CTRL_CONNECT\n"); */ 1476554c0a3aSHans de Goede mstatus = 1;/* connect */ 1477554c0a3aSHans de Goede /* Reset LPS Setting */ 1478554c0a3aSHans de Goede pwrpriv->LpsIdleCount = 0; 1479554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus)); 1480554c0a3aSHans de Goede rtw_btcoex_MediaStatusNotify(padapter, mstatus); 1481554c0a3aSHans de Goede break; 1482554c0a3aSHans de Goede case LPS_CTRL_DISCONNECT: 1483554c0a3aSHans de Goede /* DBG_871X("LPS_CTRL_DISCONNECT\n"); */ 1484554c0a3aSHans de Goede mstatus = 0;/* disconnect */ 1485554c0a3aSHans de Goede rtw_btcoex_MediaStatusNotify(padapter, mstatus); 1486554c0a3aSHans de Goede LPS_Leave(padapter, "LPS_CTRL_DISCONNECT"); 1487554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus)); 1488554c0a3aSHans de Goede break; 1489554c0a3aSHans de Goede case LPS_CTRL_SPECIAL_PACKET: 1490554c0a3aSHans de Goede /* DBG_871X("LPS_CTRL_SPECIAL_PACKET\n"); */ 1491554c0a3aSHans de Goede pwrpriv->DelayLPSLastTimeStamp = jiffies; 1492554c0a3aSHans de Goede rtw_btcoex_SpecialPacketNotify(padapter, PACKET_DHCP); 1493554c0a3aSHans de Goede LPS_Leave(padapter, "LPS_CTRL_SPECIAL_PACKET"); 1494554c0a3aSHans de Goede break; 1495554c0a3aSHans de Goede case LPS_CTRL_LEAVE: 1496554c0a3aSHans de Goede /* DBG_871X("LPS_CTRL_LEAVE\n"); */ 1497554c0a3aSHans de Goede LPS_Leave(padapter, "LPS_CTRL_LEAVE"); 1498554c0a3aSHans de Goede break; 1499554c0a3aSHans de Goede case LPS_CTRL_TRAFFIC_BUSY: 1500554c0a3aSHans de Goede LPS_Leave(padapter, "LPS_CTRL_TRAFFIC_BUSY"); 1501554c0a3aSHans de Goede default: 1502554c0a3aSHans de Goede break; 1503554c0a3aSHans de Goede } 1504554c0a3aSHans de Goede } 1505554c0a3aSHans de Goede 1506554c0a3aSHans de Goede u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue) 1507554c0a3aSHans de Goede { 1508554c0a3aSHans de Goede struct cmd_obj *ph2c; 1509554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1510554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1511554c0a3aSHans de Goede /* struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); */ 1512554c0a3aSHans de Goede u8 res = _SUCCESS; 1513554c0a3aSHans de Goede 1514554c0a3aSHans de Goede /* if (!pwrctrlpriv->bLeisurePs) */ 1515554c0a3aSHans de Goede /* return res; */ 1516554c0a3aSHans de Goede 1517554c0a3aSHans de Goede if (enqueue) { 15182ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1519554c0a3aSHans de Goede if (ph2c == NULL) { 1520554c0a3aSHans de Goede res = _FAIL; 1521554c0a3aSHans de Goede goto exit; 1522554c0a3aSHans de Goede } 1523554c0a3aSHans de Goede 15242ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1525554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1526512bbd7bSSrishti Sharma kfree(ph2c); 1527554c0a3aSHans de Goede res = _FAIL; 1528554c0a3aSHans de Goede goto exit; 1529554c0a3aSHans de Goede } 1530554c0a3aSHans de Goede 1531554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID; 1532554c0a3aSHans de Goede pdrvextra_cmd_parm->type = lps_ctrl_type; 1533554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1534554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1535554c0a3aSHans de Goede 1536554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1537554c0a3aSHans de Goede 1538554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1539554c0a3aSHans de Goede } else { 1540554c0a3aSHans de Goede lps_ctrl_wk_hdl(padapter, lps_ctrl_type); 1541554c0a3aSHans de Goede } 1542554c0a3aSHans de Goede 1543554c0a3aSHans de Goede exit: 1544554c0a3aSHans de Goede return res; 1545554c0a3aSHans de Goede } 1546554c0a3aSHans de Goede 1547554c0a3aSHans de Goede static void rtw_dm_in_lps_hdl(struct adapter *padapter) 1548554c0a3aSHans de Goede { 1549554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_DM_IN_LPS, NULL); 1550554c0a3aSHans de Goede } 1551554c0a3aSHans de Goede 1552554c0a3aSHans de Goede u8 rtw_dm_in_lps_wk_cmd(struct adapter *padapter) 1553554c0a3aSHans de Goede { 1554554c0a3aSHans de Goede struct cmd_obj *ph2c; 1555554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1556554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1557554c0a3aSHans de Goede u8 res = _SUCCESS; 1558554c0a3aSHans de Goede 1559554c0a3aSHans de Goede 15602ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1561554c0a3aSHans de Goede if (ph2c == NULL) { 1562554c0a3aSHans de Goede res = _FAIL; 1563554c0a3aSHans de Goede goto exit; 1564554c0a3aSHans de Goede } 1565554c0a3aSHans de Goede 15662ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1567554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1568512bbd7bSSrishti Sharma kfree(ph2c); 1569554c0a3aSHans de Goede res = _FAIL; 1570554c0a3aSHans de Goede goto exit; 1571554c0a3aSHans de Goede } 1572554c0a3aSHans de Goede 1573554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = DM_IN_LPS_WK_CID; 1574554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1575554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1576554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1577554c0a3aSHans de Goede 1578554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1579554c0a3aSHans de Goede 1580554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1581554c0a3aSHans de Goede 1582554c0a3aSHans de Goede exit: 1583554c0a3aSHans de Goede 1584554c0a3aSHans de Goede return res; 1585554c0a3aSHans de Goede 1586554c0a3aSHans de Goede } 1587554c0a3aSHans de Goede 1588554c0a3aSHans de Goede static void rtw_lps_change_dtim_hdl(struct adapter *padapter, u8 dtim) 1589554c0a3aSHans de Goede { 1590554c0a3aSHans de Goede struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); 1591554c0a3aSHans de Goede 1592554c0a3aSHans de Goede if (dtim <= 0 || dtim > 16) 1593554c0a3aSHans de Goede return; 1594554c0a3aSHans de Goede 1595554c0a3aSHans de Goede if (rtw_btcoex_IsBtControlLps(padapter) == true) 1596554c0a3aSHans de Goede return; 1597554c0a3aSHans de Goede 159807e3a844SArnd Bergmann mutex_lock(&pwrpriv->lock); 1599554c0a3aSHans de Goede 1600554c0a3aSHans de Goede if (pwrpriv->dtim != dtim) { 1601554c0a3aSHans de Goede DBG_871X("change DTIM from %d to %d, bFwCurrentInPSMode =%d, ps_mode =%d\n", pwrpriv->dtim, dtim, 1602554c0a3aSHans de Goede pwrpriv->bFwCurrentInPSMode, pwrpriv->pwr_mode); 1603554c0a3aSHans de Goede 1604554c0a3aSHans de Goede pwrpriv->dtim = dtim; 1605554c0a3aSHans de Goede } 1606554c0a3aSHans de Goede 1607554c0a3aSHans de Goede if ((pwrpriv->bFwCurrentInPSMode == true) && (pwrpriv->pwr_mode > PS_MODE_ACTIVE)) { 1608554c0a3aSHans de Goede u8 ps_mode = pwrpriv->pwr_mode; 1609554c0a3aSHans de Goede 1610554c0a3aSHans de Goede /* DBG_871X("change DTIM from %d to %d, ps_mode =%d\n", pwrpriv->dtim, dtim, ps_mode); */ 1611554c0a3aSHans de Goede 1612554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode)); 1613554c0a3aSHans de Goede } 1614554c0a3aSHans de Goede 161507e3a844SArnd Bergmann mutex_unlock(&pwrpriv->lock); 1616554c0a3aSHans de Goede } 1617554c0a3aSHans de Goede 1618554c0a3aSHans de Goede static void rtw_dm_ra_mask_hdl(struct adapter *padapter, struct sta_info *psta) 1619554c0a3aSHans de Goede { 1620554c0a3aSHans de Goede if (psta) { 1621554c0a3aSHans de Goede set_sta_rate(padapter, psta); 1622554c0a3aSHans de Goede } 1623554c0a3aSHans de Goede } 1624554c0a3aSHans de Goede 1625554c0a3aSHans de Goede u8 rtw_dm_ra_mask_wk_cmd(struct adapter *padapter, u8 *psta) 1626554c0a3aSHans de Goede { 1627554c0a3aSHans de Goede struct cmd_obj *ph2c; 1628554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1629554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1630554c0a3aSHans de Goede u8 res = _SUCCESS; 1631554c0a3aSHans de Goede 1632554c0a3aSHans de Goede 16332ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1634554c0a3aSHans de Goede if (ph2c == NULL) { 1635554c0a3aSHans de Goede res = _FAIL; 1636554c0a3aSHans de Goede goto exit; 1637554c0a3aSHans de Goede } 1638554c0a3aSHans de Goede 16392ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1640554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1641512bbd7bSSrishti Sharma kfree(ph2c); 1642554c0a3aSHans de Goede res = _FAIL; 1643554c0a3aSHans de Goede goto exit; 1644554c0a3aSHans de Goede } 1645554c0a3aSHans de Goede 1646554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = DM_RA_MSK_WK_CID; 1647554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1648554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1649554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = psta; 1650554c0a3aSHans de Goede 1651554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1652554c0a3aSHans de Goede 1653554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1654554c0a3aSHans de Goede 1655554c0a3aSHans de Goede exit: 1656554c0a3aSHans de Goede 1657554c0a3aSHans de Goede return res; 1658554c0a3aSHans de Goede 1659554c0a3aSHans de Goede } 1660554c0a3aSHans de Goede 1661554c0a3aSHans de Goede static void power_saving_wk_hdl(struct adapter *padapter) 1662554c0a3aSHans de Goede { 1663554c0a3aSHans de Goede rtw_ps_processor(padapter); 1664554c0a3aSHans de Goede } 1665554c0a3aSHans de Goede 1666554c0a3aSHans de Goede /* add for CONFIG_IEEE80211W, none 11w can use it */ 1667554c0a3aSHans de Goede static void reset_securitypriv_hdl(struct adapter *padapter) 1668554c0a3aSHans de Goede { 1669554c0a3aSHans de Goede rtw_reset_securitypriv(padapter); 1670554c0a3aSHans de Goede } 1671554c0a3aSHans de Goede 1672554c0a3aSHans de Goede static void free_assoc_resources_hdl(struct adapter *padapter) 1673554c0a3aSHans de Goede { 1674554c0a3aSHans de Goede rtw_free_assoc_resources(padapter, 1); 1675554c0a3aSHans de Goede } 1676554c0a3aSHans de Goede 1677554c0a3aSHans de Goede u8 rtw_ps_cmd(struct adapter *padapter) 1678554c0a3aSHans de Goede { 1679554c0a3aSHans de Goede struct cmd_obj *ppscmd; 1680554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1681554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1682554c0a3aSHans de Goede u8 res = _SUCCESS; 1683554c0a3aSHans de Goede 16842ef2b7c2SJoe Perches ppscmd = rtw_zmalloc(sizeof(struct cmd_obj)); 1685554c0a3aSHans de Goede if (ppscmd == NULL) { 1686554c0a3aSHans de Goede res = _FAIL; 1687554c0a3aSHans de Goede goto exit; 1688554c0a3aSHans de Goede } 1689554c0a3aSHans de Goede 16902ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1691554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1692512bbd7bSSrishti Sharma kfree(ppscmd); 1693554c0a3aSHans de Goede res = _FAIL; 1694554c0a3aSHans de Goede goto exit; 1695554c0a3aSHans de Goede } 1696554c0a3aSHans de Goede 1697554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID; 1698554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1699554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1700554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1701554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1702554c0a3aSHans de Goede 1703554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ppscmd); 1704554c0a3aSHans de Goede 1705554c0a3aSHans de Goede exit: 1706554c0a3aSHans de Goede return res; 1707554c0a3aSHans de Goede } 1708554c0a3aSHans de Goede 170964b8e685SJi-Hun Kim u32 g_wait_hiq_empty; 1710f55a6d45SArnd Bergmann 1711554c0a3aSHans de Goede static void rtw_chk_hi_queue_hdl(struct adapter *padapter) 1712554c0a3aSHans de Goede { 1713554c0a3aSHans de Goede struct sta_info *psta_bmc; 1714554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1715554c0a3aSHans de Goede unsigned long start = jiffies; 1716554c0a3aSHans de Goede u8 empty = false; 1717554c0a3aSHans de Goede 1718554c0a3aSHans de Goede psta_bmc = rtw_get_bcmc_stainfo(padapter); 1719554c0a3aSHans de Goede if (!psta_bmc) 1720554c0a3aSHans de Goede return; 1721554c0a3aSHans de Goede 1722554c0a3aSHans de Goede rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty); 1723554c0a3aSHans de Goede 1724554c0a3aSHans de Goede while (false == empty && jiffies_to_msecs(jiffies - start) < g_wait_hiq_empty) { 1725554c0a3aSHans de Goede msleep(100); 1726554c0a3aSHans de Goede rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty); 1727554c0a3aSHans de Goede } 1728554c0a3aSHans de Goede 1729554c0a3aSHans de Goede if (psta_bmc->sleepq_len == 0) { 1730554c0a3aSHans de Goede if (empty == _SUCCESS) { 1731554c0a3aSHans de Goede bool update_tim = false; 1732554c0a3aSHans de Goede 1733554c0a3aSHans de Goede if (pstapriv->tim_bitmap & BIT(0)) 1734554c0a3aSHans de Goede update_tim = true; 1735554c0a3aSHans de Goede 1736554c0a3aSHans de Goede pstapriv->tim_bitmap &= ~BIT(0); 1737554c0a3aSHans de Goede pstapriv->sta_dz_bitmap &= ~BIT(0); 1738554c0a3aSHans de Goede 1739554c0a3aSHans de Goede if (update_tim == true) 1740554c0a3aSHans de Goede update_beacon(padapter, _TIM_IE_, NULL, true); 1741554c0a3aSHans de Goede } else {/* re check again */ 1742554c0a3aSHans de Goede rtw_chk_hi_queue_cmd(padapter); 1743554c0a3aSHans de Goede } 1744554c0a3aSHans de Goede 1745554c0a3aSHans de Goede } 1746554c0a3aSHans de Goede 1747554c0a3aSHans de Goede } 1748554c0a3aSHans de Goede 1749554c0a3aSHans de Goede u8 rtw_chk_hi_queue_cmd(struct adapter *padapter) 1750554c0a3aSHans de Goede { 1751554c0a3aSHans de Goede struct cmd_obj *ph2c; 1752554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1753554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1754554c0a3aSHans de Goede u8 res = _SUCCESS; 1755554c0a3aSHans de Goede 17562ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1757554c0a3aSHans de Goede if (ph2c == NULL) { 1758554c0a3aSHans de Goede res = _FAIL; 1759554c0a3aSHans de Goede goto exit; 1760554c0a3aSHans de Goede } 1761554c0a3aSHans de Goede 17622ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1763554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1764512bbd7bSSrishti Sharma kfree(ph2c); 1765554c0a3aSHans de Goede res = _FAIL; 1766554c0a3aSHans de Goede goto exit; 1767554c0a3aSHans de Goede } 1768554c0a3aSHans de Goede 1769554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID; 1770554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1771554c0a3aSHans de Goede pdrvextra_cmd_parm->size = 0; 1772554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = NULL; 1773554c0a3aSHans de Goede 1774554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1775554c0a3aSHans de Goede 1776554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1777554c0a3aSHans de Goede 1778554c0a3aSHans de Goede exit: 1779554c0a3aSHans de Goede 1780554c0a3aSHans de Goede return res; 1781554c0a3aSHans de Goede 1782554c0a3aSHans de Goede } 1783554c0a3aSHans de Goede 1784554c0a3aSHans de Goede struct btinfo { 1785554c0a3aSHans de Goede u8 cid; 1786554c0a3aSHans de Goede u8 len; 1787554c0a3aSHans de Goede 1788554c0a3aSHans de Goede u8 bConnection:1; 1789554c0a3aSHans de Goede u8 bSCOeSCO:1; 1790554c0a3aSHans de Goede u8 bInQPage:1; 1791554c0a3aSHans de Goede u8 bACLBusy:1; 1792554c0a3aSHans de Goede u8 bSCOBusy:1; 1793554c0a3aSHans de Goede u8 bHID:1; 1794554c0a3aSHans de Goede u8 bA2DP:1; 1795554c0a3aSHans de Goede u8 bFTP:1; 1796554c0a3aSHans de Goede 1797554c0a3aSHans de Goede u8 retry_cnt:4; 1798554c0a3aSHans de Goede u8 rsvd_34:1; 1799554c0a3aSHans de Goede u8 rsvd_35:1; 1800554c0a3aSHans de Goede u8 rsvd_36:1; 1801554c0a3aSHans de Goede u8 rsvd_37:1; 1802554c0a3aSHans de Goede 1803554c0a3aSHans de Goede u8 rssi; 1804554c0a3aSHans de Goede 1805554c0a3aSHans de Goede u8 rsvd_50:1; 1806554c0a3aSHans de Goede u8 rsvd_51:1; 1807554c0a3aSHans de Goede u8 rsvd_52:1; 1808554c0a3aSHans de Goede u8 rsvd_53:1; 1809554c0a3aSHans de Goede u8 rsvd_54:1; 1810554c0a3aSHans de Goede u8 rsvd_55:1; 1811554c0a3aSHans de Goede u8 eSCO_SCO:1; 1812554c0a3aSHans de Goede u8 Master_Slave:1; 1813554c0a3aSHans de Goede 1814554c0a3aSHans de Goede u8 rsvd_6; 1815554c0a3aSHans de Goede u8 rsvd_7; 1816554c0a3aSHans de Goede }; 1817554c0a3aSHans de Goede 1818554c0a3aSHans de Goede static void rtw_btinfo_hdl(struct adapter *adapter, u8 *buf, u16 buf_len) 1819554c0a3aSHans de Goede { 1820554c0a3aSHans de Goede #define BTINFO_WIFI_FETCH 0x23 1821554c0a3aSHans de Goede #define BTINFO_BT_AUTO_RPT 0x27 1822554c0a3aSHans de Goede struct btinfo *info = (struct btinfo *)buf; 1823554c0a3aSHans de Goede u8 cmd_idx; 1824554c0a3aSHans de Goede u8 len; 1825554c0a3aSHans de Goede 1826554c0a3aSHans de Goede cmd_idx = info->cid; 1827554c0a3aSHans de Goede 1828554c0a3aSHans de Goede if (info->len > buf_len-2) { 1829554c0a3aSHans de Goede rtw_warn_on(1); 1830554c0a3aSHans de Goede len = buf_len-2; 1831554c0a3aSHans de Goede } else { 1832554c0a3aSHans de Goede len = info->len; 1833554c0a3aSHans de Goede } 1834554c0a3aSHans de Goede 1835554c0a3aSHans de Goede /* define DBG_PROC_SET_BTINFO_EVT */ 1836554c0a3aSHans de Goede #ifdef DBG_PROC_SET_BTINFO_EVT 1837554c0a3aSHans de Goede btinfo_evt_dump(RTW_DBGDUMP, info); 1838554c0a3aSHans de Goede #endif 1839554c0a3aSHans de Goede 1840554c0a3aSHans de Goede /* transform BT-FW btinfo to WiFI-FW C2H format and notify */ 1841554c0a3aSHans de Goede if (cmd_idx == BTINFO_WIFI_FETCH) 1842554c0a3aSHans de Goede buf[1] = 0; 1843554c0a3aSHans de Goede else if (cmd_idx == BTINFO_BT_AUTO_RPT) 1844554c0a3aSHans de Goede buf[1] = 2; 1845554c0a3aSHans de Goede rtw_btcoex_BtInfoNotify(adapter, len+1, &buf[1]); 1846554c0a3aSHans de Goede } 1847554c0a3aSHans de Goede 1848554c0a3aSHans de Goede u8 rtw_c2h_packet_wk_cmd(struct adapter *padapter, u8 *pbuf, u16 length) 1849554c0a3aSHans de Goede { 1850554c0a3aSHans de Goede struct cmd_obj *ph2c; 1851554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1852554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1853554c0a3aSHans de Goede u8 res = _SUCCESS; 1854554c0a3aSHans de Goede 18552ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1856554c0a3aSHans de Goede if (ph2c == NULL) { 1857554c0a3aSHans de Goede res = _FAIL; 1858554c0a3aSHans de Goede goto exit; 1859554c0a3aSHans de Goede } 1860554c0a3aSHans de Goede 18612ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1862554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1863512bbd7bSSrishti Sharma kfree(ph2c); 1864554c0a3aSHans de Goede res = _FAIL; 1865554c0a3aSHans de Goede goto exit; 1866554c0a3aSHans de Goede } 1867554c0a3aSHans de Goede 1868554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = C2H_WK_CID; 1869554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1870554c0a3aSHans de Goede pdrvextra_cmd_parm->size = length; 1871554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = pbuf; 1872554c0a3aSHans de Goede 1873554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1874554c0a3aSHans de Goede 1875554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1876554c0a3aSHans de Goede 1877554c0a3aSHans de Goede exit: 1878554c0a3aSHans de Goede return res; 1879554c0a3aSHans de Goede } 1880554c0a3aSHans de Goede 1881554c0a3aSHans de Goede /* dont call R/W in this function, beucase SDIO interrupt have claim host */ 1882554c0a3aSHans de Goede /* or deadlock will happen and cause special-systemserver-died in android */ 1883554c0a3aSHans de Goede u8 rtw_c2h_wk_cmd(struct adapter *padapter, u8 *c2h_evt) 1884554c0a3aSHans de Goede { 1885554c0a3aSHans de Goede struct cmd_obj *ph2c; 1886554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd_parm; 1887554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 1888554c0a3aSHans de Goede u8 res = _SUCCESS; 1889554c0a3aSHans de Goede 18902ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 1891554c0a3aSHans de Goede if (ph2c == NULL) { 1892554c0a3aSHans de Goede res = _FAIL; 1893554c0a3aSHans de Goede goto exit; 1894554c0a3aSHans de Goede } 1895554c0a3aSHans de Goede 18962ef2b7c2SJoe Perches pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 1897554c0a3aSHans de Goede if (pdrvextra_cmd_parm == NULL) { 1898512bbd7bSSrishti Sharma kfree(ph2c); 1899554c0a3aSHans de Goede res = _FAIL; 1900554c0a3aSHans de Goede goto exit; 1901554c0a3aSHans de Goede } 1902554c0a3aSHans de Goede 1903554c0a3aSHans de Goede pdrvextra_cmd_parm->ec_id = C2H_WK_CID; 1904554c0a3aSHans de Goede pdrvextra_cmd_parm->type = 0; 1905554c0a3aSHans de Goede pdrvextra_cmd_parm->size = c2h_evt?16:0; 1906554c0a3aSHans de Goede pdrvextra_cmd_parm->pbuf = c2h_evt; 1907554c0a3aSHans de Goede 1908554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); 1909554c0a3aSHans de Goede 1910554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 1911554c0a3aSHans de Goede 1912554c0a3aSHans de Goede exit: 1913554c0a3aSHans de Goede 1914554c0a3aSHans de Goede return res; 1915554c0a3aSHans de Goede } 1916554c0a3aSHans de Goede 1917554c0a3aSHans de Goede static void c2h_wk_callback(_workitem *work) 1918554c0a3aSHans de Goede { 1919554c0a3aSHans de Goede struct evt_priv *evtpriv = container_of(work, struct evt_priv, c2h_wk); 1920554c0a3aSHans de Goede struct adapter *adapter = container_of(evtpriv, struct adapter, evtpriv); 1921554c0a3aSHans de Goede u8 *c2h_evt; 1922554c0a3aSHans de Goede c2h_id_filter ccx_id_filter = rtw_hal_c2h_id_filter_ccx(adapter); 1923554c0a3aSHans de Goede 1924554c0a3aSHans de Goede evtpriv->c2h_wk_alive = true; 1925554c0a3aSHans de Goede 1926554c0a3aSHans de Goede while (!rtw_cbuf_empty(evtpriv->c2h_queue)) { 1927554c0a3aSHans de Goede c2h_evt = (u8 *)rtw_cbuf_pop(evtpriv->c2h_queue); 1928554c0a3aSHans de Goede if (c2h_evt != NULL) { 1929554c0a3aSHans de Goede /* This C2H event is read, clear it */ 1930554c0a3aSHans de Goede c2h_evt_clear(adapter); 1931554c0a3aSHans de Goede } else { 19322ef2b7c2SJoe Perches c2h_evt = rtw_malloc(16); 1933554c0a3aSHans de Goede if (c2h_evt != NULL) { 1934554c0a3aSHans de Goede /* This C2H event is not read, read & clear now */ 1935554c0a3aSHans de Goede if (rtw_hal_c2h_evt_read(adapter, c2h_evt) != _SUCCESS) { 1936554c0a3aSHans de Goede kfree(c2h_evt); 1937554c0a3aSHans de Goede continue; 1938554c0a3aSHans de Goede } 1939554c0a3aSHans de Goede } 1940554c0a3aSHans de Goede } 1941554c0a3aSHans de Goede 1942554c0a3aSHans de Goede /* Special pointer to trigger c2h_evt_clear only */ 1943554c0a3aSHans de Goede if ((void *)c2h_evt == (void *)evtpriv) 1944554c0a3aSHans de Goede continue; 1945554c0a3aSHans de Goede 1946554c0a3aSHans de Goede if (!rtw_hal_c2h_valid(adapter, c2h_evt)) { 1947554c0a3aSHans de Goede kfree(c2h_evt); 1948554c0a3aSHans de Goede continue; 1949554c0a3aSHans de Goede } 1950554c0a3aSHans de Goede 1951554c0a3aSHans de Goede if (ccx_id_filter(c2h_evt) == true) { 1952554c0a3aSHans de Goede /* Handle CCX report here */ 1953554c0a3aSHans de Goede rtw_hal_c2h_handler(adapter, c2h_evt); 1954554c0a3aSHans de Goede kfree(c2h_evt); 1955554c0a3aSHans de Goede } else { 1956554c0a3aSHans de Goede /* Enqueue into cmd_thread for others */ 1957554c0a3aSHans de Goede rtw_c2h_wk_cmd(adapter, c2h_evt); 1958554c0a3aSHans de Goede } 1959554c0a3aSHans de Goede } 1960554c0a3aSHans de Goede 1961554c0a3aSHans de Goede evtpriv->c2h_wk_alive = false; 1962554c0a3aSHans de Goede } 1963554c0a3aSHans de Goede 1964554c0a3aSHans de Goede u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf) 1965554c0a3aSHans de Goede { 1966554c0a3aSHans de Goede struct drvextra_cmd_parm *pdrvextra_cmd; 1967554c0a3aSHans de Goede 1968554c0a3aSHans de Goede if (!pbuf) 1969554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 1970554c0a3aSHans de Goede 1971554c0a3aSHans de Goede pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf; 1972554c0a3aSHans de Goede 1973554c0a3aSHans de Goede switch (pdrvextra_cmd->ec_id) { 1974554c0a3aSHans de Goede case DYNAMIC_CHK_WK_CID:/* only primary padapter go to this cmd, but execute dynamic_chk_wk_hdl() for two interfaces */ 1975554c0a3aSHans de Goede dynamic_chk_wk_hdl(padapter); 1976554c0a3aSHans de Goede break; 1977554c0a3aSHans de Goede case POWER_SAVING_CTRL_WK_CID: 1978554c0a3aSHans de Goede power_saving_wk_hdl(padapter); 1979554c0a3aSHans de Goede break; 1980554c0a3aSHans de Goede case LPS_CTRL_WK_CID: 1981554c0a3aSHans de Goede lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type); 1982554c0a3aSHans de Goede break; 1983554c0a3aSHans de Goede case DM_IN_LPS_WK_CID: 1984554c0a3aSHans de Goede rtw_dm_in_lps_hdl(padapter); 1985554c0a3aSHans de Goede break; 1986554c0a3aSHans de Goede case LPS_CHANGE_DTIM_CID: 1987554c0a3aSHans de Goede rtw_lps_change_dtim_hdl(padapter, (u8)pdrvextra_cmd->type); 1988554c0a3aSHans de Goede break; 1989554c0a3aSHans de Goede case CHECK_HIQ_WK_CID: 1990554c0a3aSHans de Goede rtw_chk_hi_queue_hdl(padapter); 1991554c0a3aSHans de Goede break; 1992554c0a3aSHans de Goede /* add for CONFIG_IEEE80211W, none 11w can use it */ 1993554c0a3aSHans de Goede case RESET_SECURITYPRIV: 1994554c0a3aSHans de Goede reset_securitypriv_hdl(padapter); 1995554c0a3aSHans de Goede break; 1996554c0a3aSHans de Goede case FREE_ASSOC_RESOURCES: 1997554c0a3aSHans de Goede free_assoc_resources_hdl(padapter); 1998554c0a3aSHans de Goede break; 1999554c0a3aSHans de Goede case C2H_WK_CID: 2000554c0a3aSHans de Goede rtw_hal_set_hwreg_with_buf(padapter, HW_VAR_C2H_HANDLE, pdrvextra_cmd->pbuf, pdrvextra_cmd->size); 2001554c0a3aSHans de Goede break; 2002554c0a3aSHans de Goede case DM_RA_MSK_WK_CID: 2003554c0a3aSHans de Goede rtw_dm_ra_mask_hdl(padapter, (struct sta_info *)pdrvextra_cmd->pbuf); 2004554c0a3aSHans de Goede break; 2005554c0a3aSHans de Goede case BTINFO_WK_CID: 2006554c0a3aSHans de Goede rtw_btinfo_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size); 2007554c0a3aSHans de Goede break; 2008554c0a3aSHans de Goede default: 2009554c0a3aSHans de Goede break; 2010554c0a3aSHans de Goede } 2011554c0a3aSHans de Goede 2012554c0a3aSHans de Goede if (pdrvextra_cmd->pbuf && pdrvextra_cmd->size > 0) { 2013554c0a3aSHans de Goede kfree(pdrvextra_cmd->pbuf); 2014554c0a3aSHans de Goede } 2015554c0a3aSHans de Goede 2016554c0a3aSHans de Goede return H2C_SUCCESS; 2017554c0a3aSHans de Goede } 2018554c0a3aSHans de Goede 2019554c0a3aSHans de Goede void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2020554c0a3aSHans de Goede { 2021554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2022554c0a3aSHans de Goede 2023554c0a3aSHans de Goede if (pcmd->res == H2C_DROPPED) { 2024554c0a3aSHans de Goede /* TODO: cancel timer and do timeout handler directly... */ 2025554c0a3aSHans de Goede /* need to make timeout handlerOS independent */ 2026554c0a3aSHans de Goede _set_timer(&pmlmepriv->scan_to_timer, 1); 2027554c0a3aSHans de Goede } else if (pcmd->res != H2C_SUCCESS) { 2028554c0a3aSHans de Goede _set_timer(&pmlmepriv->scan_to_timer, 1); 2029554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: MgntActrtw_set_802_11_bssid_LIST_SCAN Fail ************\n\n.")); 2030554c0a3aSHans de Goede } 2031554c0a3aSHans de Goede 2032554c0a3aSHans de Goede /* free cmd */ 2033554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 2034554c0a3aSHans de Goede } 2035554c0a3aSHans de Goede 2036554c0a3aSHans de Goede void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2037554c0a3aSHans de Goede { 2038554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2039554c0a3aSHans de Goede 2040554c0a3aSHans de Goede if (pcmd->res != H2C_SUCCESS) { 2041554c0a3aSHans de Goede spin_lock_bh(&pmlmepriv->lock); 2042554c0a3aSHans de Goede set_fwstate(pmlmepriv, _FW_LINKED); 2043554c0a3aSHans de Goede spin_unlock_bh(&pmlmepriv->lock); 2044554c0a3aSHans de Goede 2045554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ***Error: disconnect_cmd_callback Fail ***\n.")); 2046554c0a3aSHans de Goede return; 2047554c0a3aSHans de Goede } 2048554c0a3aSHans de Goede /* free cmd */ 2049554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 2050554c0a3aSHans de Goede } 2051554c0a3aSHans de Goede 2052554c0a3aSHans de Goede void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2053554c0a3aSHans de Goede { 2054554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2055554c0a3aSHans de Goede 2056554c0a3aSHans de Goede if (pcmd->res == H2C_DROPPED) { 2057554c0a3aSHans de Goede /* TODO: cancel timer and do timeout handler directly... */ 2058554c0a3aSHans de Goede /* need to make timeout handlerOS independent */ 2059554c0a3aSHans de Goede _set_timer(&pmlmepriv->assoc_timer, 1); 2060554c0a3aSHans de Goede } else if (pcmd->res != H2C_SUCCESS) { 2061554c0a3aSHans de Goede _set_timer(&pmlmepriv->assoc_timer, 1); 2062554c0a3aSHans de Goede } 2063554c0a3aSHans de Goede 2064554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 2065554c0a3aSHans de Goede } 2066554c0a3aSHans de Goede 2067554c0a3aSHans de Goede void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2068554c0a3aSHans de Goede { 2069554c0a3aSHans de Goede u8 timer_cancelled; 2070554c0a3aSHans de Goede struct sta_info *psta = NULL; 2071554c0a3aSHans de Goede struct wlan_network *pwlan = NULL; 2072554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2073554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf; 2074554c0a3aSHans de Goede struct wlan_network *tgt_network = &(pmlmepriv->cur_network); 2075554c0a3aSHans de Goede 2076554c0a3aSHans de Goede if (pcmd->parmbuf == NULL) 2077554c0a3aSHans de Goede goto exit; 2078554c0a3aSHans de Goede 2079554c0a3aSHans de Goede if ((pcmd->res != H2C_SUCCESS)) { 2080554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: rtw_createbss_cmd_callback Fail ************\n\n.")); 2081554c0a3aSHans de Goede _set_timer(&pmlmepriv->assoc_timer, 1); 2082554c0a3aSHans de Goede } 2083554c0a3aSHans de Goede 2084554c0a3aSHans de Goede _cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled); 2085554c0a3aSHans de Goede 2086554c0a3aSHans de Goede spin_lock_bh(&pmlmepriv->lock); 2087554c0a3aSHans de Goede 2088554c0a3aSHans de Goede 2089554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { 2090554c0a3aSHans de Goede psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress); 2091554c0a3aSHans de Goede if (!psta) { 2092554c0a3aSHans de Goede psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress); 2093554c0a3aSHans de Goede if (psta == NULL) { 2094554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nCan't alloc sta_info when createbss_cmd_callback\n")); 2095554c0a3aSHans de Goede goto createbss_cmd_fail; 2096554c0a3aSHans de Goede } 2097554c0a3aSHans de Goede } 2098554c0a3aSHans de Goede 2099554c0a3aSHans de Goede rtw_indicate_connect(padapter); 2100554c0a3aSHans de Goede } else { 2101554c0a3aSHans de Goede pwlan = _rtw_alloc_network(pmlmepriv); 2102554c0a3aSHans de Goede spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 2103554c0a3aSHans de Goede if (pwlan == NULL) { 2104554c0a3aSHans de Goede pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue); 2105554c0a3aSHans de Goede if (pwlan == NULL) { 2106554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n Error: can't get pwlan in rtw_joinbss_event_callback\n")); 2107554c0a3aSHans de Goede spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); 2108554c0a3aSHans de Goede goto createbss_cmd_fail; 2109554c0a3aSHans de Goede } 2110554c0a3aSHans de Goede pwlan->last_scanned = jiffies; 2111554c0a3aSHans de Goede } else { 2112554c0a3aSHans de Goede list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue); 2113554c0a3aSHans de Goede } 2114554c0a3aSHans de Goede 2115554c0a3aSHans de Goede pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork); 2116554c0a3aSHans de Goede memcpy(&(pwlan->network), pnetwork, pnetwork->Length); 2117554c0a3aSHans de Goede /* pwlan->fixed = true; */ 2118554c0a3aSHans de Goede 2119554c0a3aSHans de Goede /* list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue); */ 2120554c0a3aSHans de Goede 2121554c0a3aSHans de Goede /* copy pdev_network information to pmlmepriv->cur_network */ 2122554c0a3aSHans de Goede memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork))); 2123554c0a3aSHans de Goede 2124554c0a3aSHans de Goede /* reset DSConfig */ 2125554c0a3aSHans de Goede /* tgt_network->network.Configuration.DSConfig = (u32)rtw_ch2freq(pnetwork->Configuration.DSConfig); */ 2126554c0a3aSHans de Goede 2127554c0a3aSHans de Goede _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); 2128554c0a3aSHans de Goede 2129554c0a3aSHans de Goede spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); 2130554c0a3aSHans de Goede /* we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */ 2131554c0a3aSHans de Goede 2132554c0a3aSHans de Goede } 2133554c0a3aSHans de Goede 2134554c0a3aSHans de Goede createbss_cmd_fail: 2135554c0a3aSHans de Goede 2136554c0a3aSHans de Goede spin_unlock_bh(&pmlmepriv->lock); 2137554c0a3aSHans de Goede exit: 2138554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 2139554c0a3aSHans de Goede } 2140554c0a3aSHans de Goede 2141554c0a3aSHans de Goede 2142554c0a3aSHans de Goede 2143554c0a3aSHans de Goede void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2144554c0a3aSHans de Goede { 2145554c0a3aSHans de Goede 2146554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 2147554c0a3aSHans de Goede struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *) (pcmd->rsp); 2148554c0a3aSHans de Goede struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr); 2149554c0a3aSHans de Goede 2150554c0a3aSHans de Goede if (psta == NULL) { 2151554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: rtw_setstaKey_cmdrsp_callback => can't get sta_info\n\n")); 2152554c0a3aSHans de Goede goto exit; 2153554c0a3aSHans de Goede } 2154554c0a3aSHans de Goede exit: 2155554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 2156554c0a3aSHans de Goede } 2157554c0a3aSHans de Goede 2158554c0a3aSHans de Goede void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) 2159554c0a3aSHans de Goede { 2160554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 2161554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2162554c0a3aSHans de Goede struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf); 2163554c0a3aSHans de Goede struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *) (pcmd->rsp); 2164554c0a3aSHans de Goede struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr); 2165554c0a3aSHans de Goede 2166554c0a3aSHans de Goede if (psta == NULL) { 2167554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: setassocsta_cmdrsp_callbac => can't get sta_info\n\n")); 2168554c0a3aSHans de Goede goto exit; 2169554c0a3aSHans de Goede } 2170554c0a3aSHans de Goede 2171554c0a3aSHans de Goede psta->aid = psta->mac_id = passocsta_rsp->cam_id; 2172554c0a3aSHans de Goede 2173554c0a3aSHans de Goede spin_lock_bh(&pmlmepriv->lock); 2174554c0a3aSHans de Goede 2175554c0a3aSHans de Goede if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) && (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)) 2176554c0a3aSHans de Goede _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); 2177554c0a3aSHans de Goede 2178554c0a3aSHans de Goede set_fwstate(pmlmepriv, _FW_LINKED); 2179554c0a3aSHans de Goede spin_unlock_bh(&pmlmepriv->lock); 2180554c0a3aSHans de Goede 2181554c0a3aSHans de Goede exit: 2182554c0a3aSHans de Goede rtw_free_cmd_obj(pcmd); 2183554c0a3aSHans de Goede } 2184