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