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 _RTL8723B_CMD_C_ 8554c0a3aSHans de Goede 9554c0a3aSHans de Goede #include <drv_types.h> 10554c0a3aSHans de Goede #include <rtw_debug.h> 11554c0a3aSHans de Goede #include <rtl8723b_hal.h> 12554c0a3aSHans de Goede #include "hal_com_h2c.h" 13554c0a3aSHans de Goede 14554c0a3aSHans de Goede #define MAX_H2C_BOX_NUMS 4 15554c0a3aSHans de Goede #define MESSAGE_BOX_SIZE 4 16554c0a3aSHans de Goede 17554c0a3aSHans de Goede #define RTL8723B_MAX_CMD_LEN 7 18554c0a3aSHans de Goede #define RTL8723B_EX_MESSAGE_BOX_SIZE 4 19554c0a3aSHans de Goede 20554c0a3aSHans de Goede static u8 _is_fw_read_cmd_down(struct adapter *padapter, u8 msgbox_num) 21554c0a3aSHans de Goede { 22554c0a3aSHans de Goede u8 read_down = false; 23554c0a3aSHans de Goede int retry_cnts = 100; 24554c0a3aSHans de Goede 25554c0a3aSHans de Goede u8 valid; 26554c0a3aSHans de Goede 27554c0a3aSHans de Goede /* DBG_8192C(" _is_fw_read_cmd_down , reg_1cc(%x), msg_box(%d)...\n", rtw_read8(padapter, REG_HMETFR), msgbox_num); */ 28554c0a3aSHans de Goede 29554c0a3aSHans de Goede do { 30554c0a3aSHans de Goede valid = rtw_read8(padapter, REG_HMETFR) & BIT(msgbox_num); 31554c0a3aSHans de Goede if (0 == valid) { 32554c0a3aSHans de Goede read_down = true; 33554c0a3aSHans de Goede } 34554c0a3aSHans de Goede } while ((!read_down) && (retry_cnts--)); 35554c0a3aSHans de Goede 36554c0a3aSHans de Goede return read_down; 37554c0a3aSHans de Goede 38554c0a3aSHans de Goede } 39554c0a3aSHans de Goede 40554c0a3aSHans de Goede 41554c0a3aSHans de Goede /***************************************** 42554c0a3aSHans de Goede * H2C Msg format : 43554c0a3aSHans de Goede *| 31 - 8 |7-5 | 4 - 0 | 44554c0a3aSHans de Goede *| h2c_msg |Class |CMD_ID | 45554c0a3aSHans de Goede *| 31-0 | 46554c0a3aSHans de Goede *| Ext msg | 47554c0a3aSHans de Goede * 48554c0a3aSHans de Goede ******************************************/ 49554c0a3aSHans de Goede s32 FillH2CCmd8723B(struct adapter *padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer) 50554c0a3aSHans de Goede { 51554c0a3aSHans de Goede u8 h2c_box_num; 52554c0a3aSHans de Goede u32 msgbox_addr; 53554c0a3aSHans de Goede u32 msgbox_ex_addr = 0; 54554c0a3aSHans de Goede struct hal_com_data *pHalData; 55554c0a3aSHans de Goede u32 h2c_cmd = 0; 56554c0a3aSHans de Goede u32 h2c_cmd_ex = 0; 57554c0a3aSHans de Goede s32 ret = _FAIL; 58554c0a3aSHans de Goede 59554c0a3aSHans de Goede padapter = GET_PRIMARY_ADAPTER(padapter); 60554c0a3aSHans de Goede pHalData = GET_HAL_DATA(padapter); 61554c0a3aSHans de Goede if (mutex_lock_interruptible(&(adapter_to_dvobj(padapter)->h2c_fwcmd_mutex))) 62554c0a3aSHans de Goede return ret; 63554c0a3aSHans de Goede 64554c0a3aSHans de Goede if (!pCmdBuffer) { 65554c0a3aSHans de Goede goto exit; 66554c0a3aSHans de Goede } 67554c0a3aSHans de Goede 68554c0a3aSHans de Goede if (CmdLen > RTL8723B_MAX_CMD_LEN) { 69554c0a3aSHans de Goede goto exit; 70554c0a3aSHans de Goede } 71554c0a3aSHans de Goede 72f2e741cbSHariprasad Kelam if (padapter->bSurpriseRemoved) 73554c0a3aSHans de Goede goto exit; 74554c0a3aSHans de Goede 75554c0a3aSHans de Goede /* pay attention to if race condition happened in H2C cmd setting. */ 76554c0a3aSHans de Goede do { 77554c0a3aSHans de Goede h2c_box_num = pHalData->LastHMEBoxNum; 78554c0a3aSHans de Goede 79554c0a3aSHans de Goede if (!_is_fw_read_cmd_down(padapter, h2c_box_num)) { 80554c0a3aSHans de Goede DBG_8192C(" fw read cmd failed...\n"); 81554c0a3aSHans de Goede /* DBG_8192C(" 0x1c0: 0x%8x\n", rtw_read32(padapter, 0x1c0)); */ 82554c0a3aSHans de Goede /* DBG_8192C(" 0x1c4: 0x%8x\n", rtw_read32(padapter, 0x1c4)); */ 83554c0a3aSHans de Goede goto exit; 84554c0a3aSHans de Goede } 85554c0a3aSHans de Goede 86554c0a3aSHans de Goede if (CmdLen <= 3) 87554c0a3aSHans de Goede memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, CmdLen); 88554c0a3aSHans de Goede else { 89554c0a3aSHans de Goede memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, 3); 90554c0a3aSHans de Goede memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer+3, CmdLen-3); 91554c0a3aSHans de Goede /* *(u8 *)(&h2c_cmd) |= BIT(7); */ 92554c0a3aSHans de Goede } 93554c0a3aSHans de Goede 94554c0a3aSHans de Goede *(u8 *)(&h2c_cmd) |= ElementID; 95554c0a3aSHans de Goede 96554c0a3aSHans de Goede if (CmdLen > 3) { 97554c0a3aSHans de Goede msgbox_ex_addr = REG_HMEBOX_EXT0_8723B + (h2c_box_num*RTL8723B_EX_MESSAGE_BOX_SIZE); 98554c0a3aSHans de Goede rtw_write32(padapter, msgbox_ex_addr, h2c_cmd_ex); 99554c0a3aSHans de Goede } 100554c0a3aSHans de Goede msgbox_addr = REG_HMEBOX_0 + (h2c_box_num*MESSAGE_BOX_SIZE); 101554c0a3aSHans de Goede rtw_write32(padapter, msgbox_addr, h2c_cmd); 102554c0a3aSHans de Goede 103554c0a3aSHans de Goede /* DBG_8192C("MSG_BOX:%d, CmdLen(%d), CmdID(0x%x), reg:0x%x =>h2c_cmd:0x%.8x, reg:0x%x =>h2c_cmd_ex:0x%.8x\n" */ 104554c0a3aSHans de Goede /* , pHalData->LastHMEBoxNum , CmdLen, ElementID, msgbox_addr, h2c_cmd, msgbox_ex_addr, h2c_cmd_ex); */ 105554c0a3aSHans de Goede 106554c0a3aSHans de Goede pHalData->LastHMEBoxNum = (h2c_box_num+1) % MAX_H2C_BOX_NUMS; 107554c0a3aSHans de Goede 108554c0a3aSHans de Goede } while (0); 109554c0a3aSHans de Goede 110554c0a3aSHans de Goede ret = _SUCCESS; 111554c0a3aSHans de Goede 112554c0a3aSHans de Goede exit: 113554c0a3aSHans de Goede 114554c0a3aSHans de Goede mutex_unlock(&(adapter_to_dvobj(padapter)->h2c_fwcmd_mutex)); 115554c0a3aSHans de Goede return ret; 116554c0a3aSHans de Goede } 117554c0a3aSHans de Goede 118554c0a3aSHans de Goede static void ConstructBeacon(struct adapter *padapter, u8 *pframe, u32 *pLength) 119554c0a3aSHans de Goede { 120554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 121554c0a3aSHans de Goede __le16 *fctrl; 122554c0a3aSHans de Goede u32 rate_len, pktlen; 123554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 124554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 125554c0a3aSHans de Goede struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); 126554c0a3aSHans de Goede u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 127554c0a3aSHans de Goede 128554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 129554c0a3aSHans de Goede 130554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 131554c0a3aSHans de Goede *(fctrl) = 0; 132554c0a3aSHans de Goede 133554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); 134554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 135554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); 136554c0a3aSHans de Goede 137554c0a3aSHans de Goede SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); 138554c0a3aSHans de Goede /* pmlmeext->mgnt_seq++; */ 139554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_BEACON); 140554c0a3aSHans de Goede 141554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 142554c0a3aSHans de Goede pktlen = sizeof(struct ieee80211_hdr_3addr); 143554c0a3aSHans de Goede 144554c0a3aSHans de Goede /* timestamp will be inserted by hardware */ 145554c0a3aSHans de Goede pframe += 8; 146554c0a3aSHans de Goede pktlen += 8; 147554c0a3aSHans de Goede 148554c0a3aSHans de Goede /* beacon interval: 2 bytes */ 149554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); 150554c0a3aSHans de Goede 151554c0a3aSHans de Goede pframe += 2; 152554c0a3aSHans de Goede pktlen += 2; 153554c0a3aSHans de Goede 154554c0a3aSHans de Goede /* capability info: 2 bytes */ 155554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2); 156554c0a3aSHans de Goede 157554c0a3aSHans de Goede pframe += 2; 158554c0a3aSHans de Goede pktlen += 2; 159554c0a3aSHans de Goede 160554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { 161554c0a3aSHans de Goede pktlen += cur_network->IELength - sizeof(struct ndis_802_11_fix_ie); 162554c0a3aSHans de Goede memcpy(pframe, cur_network->IEs+sizeof(struct ndis_802_11_fix_ie), pktlen); 163554c0a3aSHans de Goede 164554c0a3aSHans de Goede goto _ConstructBeacon; 165554c0a3aSHans de Goede } 166554c0a3aSHans de Goede 167554c0a3aSHans de Goede /* below for ad-hoc mode */ 168554c0a3aSHans de Goede 169554c0a3aSHans de Goede /* SSID */ 1703f15277bSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen); 171554c0a3aSHans de Goede 172554c0a3aSHans de Goede /* supported rates... */ 173554c0a3aSHans de Goede rate_len = rtw_get_rateset_len(cur_network->SupportedRates); 174c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pktlen); 175554c0a3aSHans de Goede 176554c0a3aSHans de Goede /* DS parameter set */ 1778f6a9446SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen); 178554c0a3aSHans de Goede 179554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) { 180554c0a3aSHans de Goede u32 ATIMWindow; 181554c0a3aSHans de Goede /* IBSS Parameter Set... */ 182554c0a3aSHans de Goede /* ATIMWindow = cur->Configuration.ATIMWindow; */ 183554c0a3aSHans de Goede ATIMWindow = 0; 184e6038a48SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pktlen); 185554c0a3aSHans de Goede } 186554c0a3aSHans de Goede 187554c0a3aSHans de Goede 188554c0a3aSHans de Goede /* todo: ERP IE */ 189554c0a3aSHans de Goede 190554c0a3aSHans de Goede 191554c0a3aSHans de Goede /* EXTERNDED SUPPORTED RATE */ 192554c0a3aSHans de Goede if (rate_len > 8) 19300f0b682SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen); 194554c0a3aSHans de Goede 195554c0a3aSHans de Goede 196554c0a3aSHans de Goede /* todo:HT for adhoc */ 197554c0a3aSHans de Goede 198554c0a3aSHans de Goede _ConstructBeacon: 199554c0a3aSHans de Goede 200554c0a3aSHans de Goede if ((pktlen + TXDESC_SIZE) > 512) { 201554c0a3aSHans de Goede return; 202554c0a3aSHans de Goede } 203554c0a3aSHans de Goede 204554c0a3aSHans de Goede *pLength = pktlen; 205554c0a3aSHans de Goede 206554c0a3aSHans de Goede } 207554c0a3aSHans de Goede 208554c0a3aSHans de Goede static void ConstructPSPoll(struct adapter *padapter, u8 *pframe, u32 *pLength) 209554c0a3aSHans de Goede { 210554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 211554c0a3aSHans de Goede __le16 *fctrl; 212554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 213554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 214554c0a3aSHans de Goede 215554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 216554c0a3aSHans de Goede 217554c0a3aSHans de Goede /* Frame control. */ 218554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 219554c0a3aSHans de Goede *(fctrl) = 0; 220554c0a3aSHans de Goede SetPwrMgt(fctrl); 221554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_PSPOLL); 222554c0a3aSHans de Goede 223554c0a3aSHans de Goede /* AID. */ 224554c0a3aSHans de Goede SetDuration(pframe, (pmlmeinfo->aid | 0xc000)); 225554c0a3aSHans de Goede 226554c0a3aSHans de Goede /* BSSID. */ 227554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 228554c0a3aSHans de Goede 229554c0a3aSHans de Goede /* TA. */ 230554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 231554c0a3aSHans de Goede 232554c0a3aSHans de Goede *pLength = 16; 233554c0a3aSHans de Goede } 234554c0a3aSHans de Goede 235554c0a3aSHans de Goede static void ConstructNullFunctionData( 236554c0a3aSHans de Goede struct adapter *padapter, 237554c0a3aSHans de Goede u8 *pframe, 238554c0a3aSHans de Goede u32 *pLength, 239554c0a3aSHans de Goede u8 *StaAddr, 240554c0a3aSHans de Goede u8 bQoS, 241554c0a3aSHans de Goede u8 AC, 242554c0a3aSHans de Goede u8 bEosp, 243554c0a3aSHans de Goede u8 bForcePowerSave 244554c0a3aSHans de Goede ) 245554c0a3aSHans de Goede { 246554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 247554c0a3aSHans de Goede __le16 *fctrl; 248554c0a3aSHans de Goede u32 pktlen; 249554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 250554c0a3aSHans de Goede struct wlan_network *cur_network = &pmlmepriv->cur_network; 251554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 252554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 253554c0a3aSHans de Goede 254554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 255554c0a3aSHans de Goede 256554c0a3aSHans de Goede fctrl = &pwlanhdr->frame_control; 257554c0a3aSHans de Goede *(fctrl) = 0; 258554c0a3aSHans de Goede if (bForcePowerSave) 259554c0a3aSHans de Goede SetPwrMgt(fctrl); 260554c0a3aSHans de Goede 261554c0a3aSHans de Goede switch (cur_network->network.InfrastructureMode) { 262554c0a3aSHans de Goede case Ndis802_11Infrastructure: 263554c0a3aSHans de Goede SetToDs(fctrl); 264554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 265554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 266554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN); 267554c0a3aSHans de Goede break; 268554c0a3aSHans de Goede case Ndis802_11APMode: 269554c0a3aSHans de Goede SetFrDs(fctrl); 270554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); 271554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 272554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN); 273554c0a3aSHans de Goede break; 274554c0a3aSHans de Goede case Ndis802_11IBSS: 275554c0a3aSHans de Goede default: 276554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); 277554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 278554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 279554c0a3aSHans de Goede break; 280554c0a3aSHans de Goede } 281554c0a3aSHans de Goede 282554c0a3aSHans de Goede SetSeqNum(pwlanhdr, 0); 283554c0a3aSHans de Goede 284f2e741cbSHariprasad Kelam if (bQoS) { 285554c0a3aSHans de Goede struct ieee80211_qos_hdr *pwlanqoshdr; 286554c0a3aSHans de Goede 287554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_QOS_DATA_NULL); 288554c0a3aSHans de Goede 289554c0a3aSHans de Goede pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe; 290554c0a3aSHans de Goede SetPriority(&pwlanqoshdr->qos_ctrl, AC); 291554c0a3aSHans de Goede SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp); 292554c0a3aSHans de Goede 293554c0a3aSHans de Goede pktlen = sizeof(struct ieee80211_qos_hdr); 294554c0a3aSHans de Goede } else { 295554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_DATA_NULL); 296554c0a3aSHans de Goede 297554c0a3aSHans de Goede pktlen = sizeof(struct ieee80211_hdr_3addr); 298554c0a3aSHans de Goede } 299554c0a3aSHans de Goede 300554c0a3aSHans de Goede *pLength = pktlen; 301554c0a3aSHans de Goede } 302554c0a3aSHans de Goede 303e9ed75cfSR Veera Kumar /* 30456faa3c8SR Veera Kumar * To check if reserved page content is destroyed by beacon because beacon 305e9ed75cfSR Veera Kumar * is too large. 306e9ed75cfSR Veera Kumar */ 307554c0a3aSHans de Goede /* 2010.06.23. Added by tynli. */ 308554c0a3aSHans de Goede void CheckFwRsvdPageContent(struct adapter *Adapter) 309554c0a3aSHans de Goede { 310554c0a3aSHans de Goede } 311554c0a3aSHans de Goede 312dc9a4304SMarco Cesati static void rtl8723b_set_FwRsvdPage_cmd(struct adapter *padapter, struct rsvdpage_loc *rsvdpageloc) 313554c0a3aSHans de Goede { 314554c0a3aSHans de Goede u8 u1H2CRsvdPageParm[H2C_RSVDPAGE_LOC_LEN] = {0}; 315554c0a3aSHans de Goede 316554c0a3aSHans de Goede SET_8723B_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1H2CRsvdPageParm, rsvdpageloc->LocProbeRsp); 317554c0a3aSHans de Goede SET_8723B_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1H2CRsvdPageParm, rsvdpageloc->LocPsPoll); 318554c0a3aSHans de Goede SET_8723B_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocNullData); 319554c0a3aSHans de Goede SET_8723B_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocQosNull); 320554c0a3aSHans de Goede SET_8723B_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocBTQosNull); 321554c0a3aSHans de Goede 322d8365ba3SFabio Aiuto print_hex_dump_debug(DRIVER_PREFIX ": u1H2CRsvdPageParm:", DUMP_PREFIX_NONE, 323d8365ba3SFabio Aiuto 16, 1, u1H2CRsvdPageParm, H2C_RSVDPAGE_LOC_LEN, false); 324d8365ba3SFabio Aiuto 325554c0a3aSHans de Goede FillH2CCmd8723B(padapter, H2C_8723B_RSVD_PAGE, H2C_RSVDPAGE_LOC_LEN, u1H2CRsvdPageParm); 326554c0a3aSHans de Goede } 327554c0a3aSHans de Goede 328dc9a4304SMarco Cesati static void rtl8723b_set_FwAoacRsvdPage_cmd(struct adapter *padapter, struct rsvdpage_loc *rsvdpageloc) 329554c0a3aSHans de Goede { 330554c0a3aSHans de Goede } 331554c0a3aSHans de Goede 332554c0a3aSHans de Goede void rtl8723b_set_FwMediaStatusRpt_cmd(struct adapter *padapter, u8 mstatus, u8 macid) 333554c0a3aSHans de Goede { 334554c0a3aSHans de Goede u8 u1H2CMediaStatusRptParm[H2C_MEDIA_STATUS_RPT_LEN] = {0}; 335554c0a3aSHans de Goede u8 macid_end = 0; 336554c0a3aSHans de Goede 337554c0a3aSHans de Goede SET_8723B_H2CCMD_MSRRPT_PARM_OPMODE(u1H2CMediaStatusRptParm, mstatus); 338554c0a3aSHans de Goede SET_8723B_H2CCMD_MSRRPT_PARM_MACID_IND(u1H2CMediaStatusRptParm, 0); 339554c0a3aSHans de Goede SET_8723B_H2CCMD_MSRRPT_PARM_MACID(u1H2CMediaStatusRptParm, macid); 340554c0a3aSHans de Goede SET_8723B_H2CCMD_MSRRPT_PARM_MACID_END(u1H2CMediaStatusRptParm, macid_end); 341554c0a3aSHans de Goede 342d8365ba3SFabio Aiuto print_hex_dump_debug(DRIVER_PREFIX ": u1H2CMediaStatusRptParm:", DUMP_PREFIX_NONE, 343d8365ba3SFabio Aiuto 16, 1, u1H2CMediaStatusRptParm, H2C_MEDIA_STATUS_RPT_LEN, false); 344d8365ba3SFabio Aiuto 345554c0a3aSHans de Goede FillH2CCmd8723B(padapter, H2C_8723B_MEDIA_STATUS_RPT, H2C_MEDIA_STATUS_RPT_LEN, u1H2CMediaStatusRptParm); 346554c0a3aSHans de Goede } 347554c0a3aSHans de Goede 348554c0a3aSHans de Goede void rtl8723b_set_FwMacIdConfig_cmd(struct adapter *padapter, u8 mac_id, u8 raid, u8 bw, u8 sgi, u32 mask) 349554c0a3aSHans de Goede { 350554c0a3aSHans de Goede u8 u1H2CMacIdConfigParm[H2C_MACID_CFG_LEN] = {0}; 351554c0a3aSHans de Goede 352554c0a3aSHans de Goede SET_8723B_H2CCMD_MACID_CFG_MACID(u1H2CMacIdConfigParm, mac_id); 353554c0a3aSHans de Goede SET_8723B_H2CCMD_MACID_CFG_RAID(u1H2CMacIdConfigParm, raid); 354554c0a3aSHans de Goede SET_8723B_H2CCMD_MACID_CFG_SGI_EN(u1H2CMacIdConfigParm, sgi ? 1 : 0); 355554c0a3aSHans de Goede SET_8723B_H2CCMD_MACID_CFG_BW(u1H2CMacIdConfigParm, bw); 356554c0a3aSHans de Goede SET_8723B_H2CCMD_MACID_CFG_RATE_MASK0(u1H2CMacIdConfigParm, (u8)(mask & 0x000000ff)); 357554c0a3aSHans de Goede SET_8723B_H2CCMD_MACID_CFG_RATE_MASK1(u1H2CMacIdConfigParm, (u8)((mask & 0x0000ff00) >> 8)); 358554c0a3aSHans de Goede SET_8723B_H2CCMD_MACID_CFG_RATE_MASK2(u1H2CMacIdConfigParm, (u8)((mask & 0x00ff0000) >> 16)); 359554c0a3aSHans de Goede SET_8723B_H2CCMD_MACID_CFG_RATE_MASK3(u1H2CMacIdConfigParm, (u8)((mask & 0xff000000) >> 24)); 360554c0a3aSHans de Goede 361d8365ba3SFabio Aiuto print_hex_dump_debug(DRIVER_PREFIX ": u1H2CMacIdConfigParm:", DUMP_PREFIX_NONE, 362d8365ba3SFabio Aiuto 16, 1, u1H2CMacIdConfigParm, H2C_MACID_CFG_LEN, false); 363d8365ba3SFabio Aiuto 364554c0a3aSHans de Goede FillH2CCmd8723B(padapter, H2C_8723B_MACID_CFG, H2C_MACID_CFG_LEN, u1H2CMacIdConfigParm); 365554c0a3aSHans de Goede } 366554c0a3aSHans de Goede 3678fce9e28SNishka Dasgupta void rtl8723b_set_rssi_cmd(struct adapter *padapter, u8 *param) 368554c0a3aSHans de Goede { 369554c0a3aSHans de Goede u8 u1H2CRssiSettingParm[H2C_RSSI_SETTING_LEN] = {0}; 370554c0a3aSHans de Goede u8 mac_id = *param; 371554c0a3aSHans de Goede u8 rssi = *(param+2); 372554c0a3aSHans de Goede u8 uldl_state = 0; 373554c0a3aSHans de Goede 374554c0a3aSHans de Goede SET_8723B_H2CCMD_RSSI_SETTING_MACID(u1H2CRssiSettingParm, mac_id); 375554c0a3aSHans de Goede SET_8723B_H2CCMD_RSSI_SETTING_RSSI(u1H2CRssiSettingParm, rssi); 376554c0a3aSHans de Goede SET_8723B_H2CCMD_RSSI_SETTING_ULDL_STATE(u1H2CRssiSettingParm, uldl_state); 377554c0a3aSHans de Goede 378d8365ba3SFabio Aiuto print_hex_dump_debug(DRIVER_PREFIX ": u1H2CRssiSettingParm:", DUMP_PREFIX_NONE, 379d8365ba3SFabio Aiuto 16, 1, u1H2CRssiSettingParm, H2C_RSSI_SETTING_LEN, false); 380d8365ba3SFabio Aiuto 381554c0a3aSHans de Goede FillH2CCmd8723B(padapter, H2C_8723B_RSSI_SETTING, H2C_RSSI_SETTING_LEN, u1H2CRssiSettingParm); 382554c0a3aSHans de Goede } 383554c0a3aSHans de Goede 384554c0a3aSHans de Goede void rtl8723b_set_FwPwrMode_cmd(struct adapter *padapter, u8 psmode) 385554c0a3aSHans de Goede { 386554c0a3aSHans de Goede int i; 387554c0a3aSHans de Goede struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); 388554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 389554c0a3aSHans de Goede u8 u1H2CPwrModeParm[H2C_PWRMODE_LEN] = {0}; 390554c0a3aSHans de Goede u8 PowerState = 0, awake_intvl = 1, byte5 = 0, rlbm = 0; 391554c0a3aSHans de Goede 392554c0a3aSHans de Goede if (pwrpriv->dtim > 0 && pwrpriv->dtim < 16) 393554c0a3aSHans de Goede awake_intvl = pwrpriv->dtim+1;/* DTIM = (awake_intvl - 1) */ 394554c0a3aSHans de Goede else 395554c0a3aSHans de Goede awake_intvl = 3;/* DTIM =2 */ 396554c0a3aSHans de Goede 397554c0a3aSHans de Goede rlbm = 2; 398554c0a3aSHans de Goede 399554c0a3aSHans de Goede if (padapter->registrypriv.wifi_spec == 1) { 400554c0a3aSHans de Goede awake_intvl = 2; 401554c0a3aSHans de Goede rlbm = 2; 402554c0a3aSHans de Goede } 403554c0a3aSHans de Goede 404554c0a3aSHans de Goede if (psmode > 0) { 405606e33ceSNishka Dasgupta if (hal_btcoex_IsBtControlLps(padapter) == true) { 40678c5f096SNishka Dasgupta PowerState = hal_btcoex_RpwmVal(padapter); 407ee8e2ce5SNishka Dasgupta byte5 = hal_btcoex_LpsVal(padapter); 408554c0a3aSHans de Goede 409554c0a3aSHans de Goede if ((rlbm == 2) && (byte5 & BIT(4))) { 410554c0a3aSHans de Goede /* Keep awake interval to 1 to prevent from */ 411554c0a3aSHans de Goede /* decreasing coex performance */ 412554c0a3aSHans de Goede awake_intvl = 2; 413554c0a3aSHans de Goede rlbm = 2; 414554c0a3aSHans de Goede } 415554c0a3aSHans de Goede } else { 416554c0a3aSHans de Goede PowerState = 0x00;/* AllON(0x0C), RFON(0x04), RFOFF(0x00) */ 417554c0a3aSHans de Goede byte5 = 0x40; 418554c0a3aSHans de Goede } 419554c0a3aSHans de Goede } else { 420554c0a3aSHans de Goede PowerState = 0x0C;/* AllON(0x0C), RFON(0x04), RFOFF(0x00) */ 421554c0a3aSHans de Goede byte5 = 0x40; 422554c0a3aSHans de Goede } 423554c0a3aSHans de Goede 424554c0a3aSHans de Goede SET_8723B_H2CCMD_PWRMODE_PARM_MODE(u1H2CPwrModeParm, (psmode > 0) ? 1 : 0); 425554c0a3aSHans de Goede SET_8723B_H2CCMD_PWRMODE_PARM_SMART_PS(u1H2CPwrModeParm, pwrpriv->smart_ps); 426554c0a3aSHans de Goede SET_8723B_H2CCMD_PWRMODE_PARM_RLBM(u1H2CPwrModeParm, rlbm); 427554c0a3aSHans de Goede SET_8723B_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1H2CPwrModeParm, awake_intvl); 428554c0a3aSHans de Goede SET_8723B_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1H2CPwrModeParm, padapter->registrypriv.uapsd_enable); 429554c0a3aSHans de Goede SET_8723B_H2CCMD_PWRMODE_PARM_PWR_STATE(u1H2CPwrModeParm, PowerState); 430554c0a3aSHans de Goede SET_8723B_H2CCMD_PWRMODE_PARM_BYTE5(u1H2CPwrModeParm, byte5); 431554c0a3aSHans de Goede if (psmode != PS_MODE_ACTIVE) { 432f2e741cbSHariprasad Kelam if (!pmlmeext->adaptive_tsf_done && pmlmeext->bcn_cnt > 0) { 433554c0a3aSHans de Goede u8 ratio_20_delay, ratio_80_delay; 434554c0a3aSHans de Goede 435554c0a3aSHans de Goede /* byte 6 for adaptive_early_32k */ 436554c0a3aSHans de Goede /* 0:3] = DrvBcnEarly (ms) , [4:7] = DrvBcnTimeOut (ms) */ 437554c0a3aSHans de Goede /* 20% for DrvBcnEarly, 80% for DrvBcnTimeOut */ 438554c0a3aSHans de Goede ratio_20_delay = 0; 439554c0a3aSHans de Goede ratio_80_delay = 0; 440554c0a3aSHans de Goede pmlmeext->DrvBcnEarly = 0xff; 441554c0a3aSHans de Goede pmlmeext->DrvBcnTimeOut = 0xff; 442554c0a3aSHans de Goede 443554c0a3aSHans de Goede for (i = 0; i < 9; i++) { 444554c0a3aSHans de Goede pmlmeext->bcn_delay_ratio[i] = (pmlmeext->bcn_delay_cnt[i]*100)/pmlmeext->bcn_cnt; 445554c0a3aSHans de Goede 446554c0a3aSHans de Goede ratio_20_delay += pmlmeext->bcn_delay_ratio[i]; 447554c0a3aSHans de Goede ratio_80_delay += pmlmeext->bcn_delay_ratio[i]; 448554c0a3aSHans de Goede 449554c0a3aSHans de Goede if (ratio_20_delay > 20 && pmlmeext->DrvBcnEarly == 0xff) { 450554c0a3aSHans de Goede pmlmeext->DrvBcnEarly = i; 451554c0a3aSHans de Goede } 452554c0a3aSHans de Goede 453554c0a3aSHans de Goede if (ratio_80_delay > 80 && pmlmeext->DrvBcnTimeOut == 0xff) { 454554c0a3aSHans de Goede pmlmeext->DrvBcnTimeOut = i; 455554c0a3aSHans de Goede } 456554c0a3aSHans de Goede 457554c0a3aSHans de Goede /* reset adaptive_early_32k cnt */ 458554c0a3aSHans de Goede pmlmeext->bcn_delay_cnt[i] = 0; 459554c0a3aSHans de Goede pmlmeext->bcn_delay_ratio[i] = 0; 460554c0a3aSHans de Goede 461554c0a3aSHans de Goede } 462554c0a3aSHans de Goede 463554c0a3aSHans de Goede pmlmeext->bcn_cnt = 0; 464554c0a3aSHans de Goede pmlmeext->adaptive_tsf_done = true; 465554c0a3aSHans de Goede 466554c0a3aSHans de Goede } 467554c0a3aSHans de Goede 468554c0a3aSHans de Goede /* offload to FW if fw version > v15.10 469554c0a3aSHans de Goede pmlmeext->DrvBcnEarly = 0; 470554c0a3aSHans de Goede pmlmeext->DrvBcnTimeOut =7; 471554c0a3aSHans de Goede 472554c0a3aSHans de Goede if ((pmlmeext->DrvBcnEarly!= 0Xff) && (pmlmeext->DrvBcnTimeOut!= 0xff)) 473554c0a3aSHans de Goede u1H2CPwrModeParm[H2C_PWRMODE_LEN-1] = BIT(0) | ((pmlmeext->DrvBcnEarly<<1)&0x0E) |((pmlmeext->DrvBcnTimeOut<<4)&0xf0) ; 474554c0a3aSHans de Goede */ 475554c0a3aSHans de Goede 476554c0a3aSHans de Goede } 477554c0a3aSHans de Goede 478f0ef8d3eSNishka Dasgupta hal_btcoex_RecordPwrMode(padapter, u1H2CPwrModeParm, H2C_PWRMODE_LEN); 479554c0a3aSHans de Goede 480d8365ba3SFabio Aiuto print_hex_dump_debug(DRIVER_PREFIX ": u1H2CPwrModeParm:", DUMP_PREFIX_NONE, 481d8365ba3SFabio Aiuto 16, 1, u1H2CPwrModeParm, H2C_PWRMODE_LEN, false); 482554c0a3aSHans de Goede 483554c0a3aSHans de Goede FillH2CCmd8723B(padapter, H2C_8723B_SET_PWR_MODE, H2C_PWRMODE_LEN, u1H2CPwrModeParm); 484554c0a3aSHans de Goede } 485554c0a3aSHans de Goede 486554c0a3aSHans de Goede void rtl8723b_set_FwPsTuneParam_cmd(struct adapter *padapter) 487554c0a3aSHans de Goede { 488554c0a3aSHans de Goede u8 u1H2CPsTuneParm[H2C_PSTUNEPARAM_LEN] = {0}; 489554c0a3aSHans de Goede u8 bcn_to_limit = 10; /* 10 * 100 * awakeinterval (ms) */ 490554c0a3aSHans de Goede u8 dtim_timeout = 5; /* ms wait broadcast data timer */ 491554c0a3aSHans de Goede u8 ps_timeout = 20; /* ms Keep awake when tx */ 492554c0a3aSHans de Goede u8 dtim_period = 3; 493554c0a3aSHans de Goede 494554c0a3aSHans de Goede SET_8723B_H2CCMD_PSTUNE_PARM_BCN_TO_LIMIT(u1H2CPsTuneParm, bcn_to_limit); 495554c0a3aSHans de Goede SET_8723B_H2CCMD_PSTUNE_PARM_DTIM_TIMEOUT(u1H2CPsTuneParm, dtim_timeout); 496554c0a3aSHans de Goede SET_8723B_H2CCMD_PSTUNE_PARM_PS_TIMEOUT(u1H2CPsTuneParm, ps_timeout); 497554c0a3aSHans de Goede SET_8723B_H2CCMD_PSTUNE_PARM_ADOPT(u1H2CPsTuneParm, 1); 498554c0a3aSHans de Goede SET_8723B_H2CCMD_PSTUNE_PARM_DTIM_PERIOD(u1H2CPsTuneParm, dtim_period); 499554c0a3aSHans de Goede 500d8365ba3SFabio Aiuto print_hex_dump_debug(DRIVER_PREFIX ": u1H2CPsTuneParm:", DUMP_PREFIX_NONE, 501d8365ba3SFabio Aiuto 16, 1, u1H2CPsTuneParm, H2C_PSTUNEPARAM_LEN, false); 502554c0a3aSHans de Goede 503554c0a3aSHans de Goede FillH2CCmd8723B(padapter, H2C_8723B_PS_TUNING_PARA, H2C_PSTUNEPARAM_LEN, u1H2CPsTuneParm); 504554c0a3aSHans de Goede } 505554c0a3aSHans de Goede 506554c0a3aSHans de Goede void rtl8723b_set_FwPwrModeInIPS_cmd(struct adapter *padapter, u8 cmd_param) 507554c0a3aSHans de Goede { 508554c0a3aSHans de Goede 509554c0a3aSHans de Goede FillH2CCmd8723B(padapter, H2C_8723B_FWLPS_IN_IPS_, 1, &cmd_param); 510554c0a3aSHans de Goede } 511554c0a3aSHans de Goede 512e9ed75cfSR Veera Kumar /* 513e9ed75cfSR Veera Kumar * Description: Fill the reserved packets that FW will use to RSVD page. 514e9ed75cfSR Veera Kumar * Now we just send 4 types packet to rsvd page. 515e9ed75cfSR Veera Kumar * (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp. 516e9ed75cfSR Veera Kumar * 517e9ed75cfSR Veera Kumar * Input: 518e9ed75cfSR Veera Kumar * 519e9ed75cfSR Veera Kumar * bDLFinished - false: At the first time we will send all the packets as 52056faa3c8SR Veera Kumar * a large packet to Hw, so we need to set the packet length to total length. 521e9ed75cfSR Veera Kumar * 522e9ed75cfSR Veera Kumar * true: At the second time, we should send the first packet (default:beacon) 52356faa3c8SR Veera Kumar * to Hw again and set the length in descriptor to the real beacon length. 524e9ed75cfSR Veera Kumar */ 525554c0a3aSHans de Goede /* 2009.10.15 by tynli. */ 526554c0a3aSHans de Goede static void rtl8723b_set_FwRsvdPagePkt( 527554c0a3aSHans de Goede struct adapter *padapter, bool bDLFinished 528554c0a3aSHans de Goede ) 529554c0a3aSHans de Goede { 530554c0a3aSHans de Goede struct xmit_frame *pcmdframe; 531554c0a3aSHans de Goede struct pkt_attrib *pattrib; 532554c0a3aSHans de Goede struct xmit_priv *pxmitpriv; 533554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext; 534554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo; 535554c0a3aSHans de Goede struct pwrctrl_priv *pwrctl; 536554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 537554c0a3aSHans de Goede u32 BeaconLength = 0, PSPollLength = 0; 538554c0a3aSHans de Goede u32 NullDataLength = 0, QosNullLength = 0, BTQosNullLength = 0; 539554c0a3aSHans de Goede u8 *ReservedPagePacket; 540554c0a3aSHans de Goede u8 TxDescLen = TXDESC_SIZE, TxDescOffset = TXDESC_OFFSET; 541554c0a3aSHans de Goede u8 TotalPageNum = 0, CurtPktPageNum = 0, RsvdPageNum = 0; 542554c0a3aSHans de Goede u16 BufIndex, PageSize = 128; 543554c0a3aSHans de Goede u32 TotalPacketLen, MaxRsvdPageBufSize = 0; 544ada3334fSFabio Aiuto 545dc9a4304SMarco Cesati struct rsvdpage_loc RsvdPageLoc; 546554c0a3aSHans de Goede 547554c0a3aSHans de Goede pxmitpriv = &padapter->xmitpriv; 548554c0a3aSHans de Goede pmlmeext = &padapter->mlmeextpriv; 549554c0a3aSHans de Goede pmlmeinfo = &pmlmeext->mlmext_info; 550554c0a3aSHans de Goede pwrctl = adapter_to_pwrctl(padapter); 551554c0a3aSHans de Goede 552554c0a3aSHans de Goede RsvdPageNum = BCNQ_PAGE_NUM_8723B + WOWLAN_PAGE_NUM_8723B; 553554c0a3aSHans de Goede MaxRsvdPageBufSize = RsvdPageNum*PageSize; 554554c0a3aSHans de Goede 555554c0a3aSHans de Goede pcmdframe = rtw_alloc_cmdxmitframe(pxmitpriv); 5567cd6f4b0SHimadri Pandya if (!pcmdframe) { 557554c0a3aSHans de Goede return; 558554c0a3aSHans de Goede } 559554c0a3aSHans de Goede 560554c0a3aSHans de Goede ReservedPagePacket = pcmdframe->buf_addr; 561dc9a4304SMarco Cesati memset(&RsvdPageLoc, 0, sizeof(struct rsvdpage_loc)); 562554c0a3aSHans de Goede 563554c0a3aSHans de Goede /* 3 (1) beacon */ 564554c0a3aSHans de Goede BufIndex = TxDescOffset; 565554c0a3aSHans de Goede ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength); 566554c0a3aSHans de Goede 567554c0a3aSHans de Goede /* When we count the first page size, we need to reserve description size for the RSVD */ 568554c0a3aSHans de Goede /* packet, it will be filled in front of the packet in TXPKTBUF. */ 569554c0a3aSHans de Goede CurtPktPageNum = (u8)PageNum_128(TxDescLen + BeaconLength); 570554c0a3aSHans de Goede /* If we don't add 1 more page, the WOWLAN function has a problem. Baron thinks it's a bug of firmware */ 571554c0a3aSHans de Goede if (CurtPktPageNum == 1) 572554c0a3aSHans de Goede CurtPktPageNum += 1; 573554c0a3aSHans de Goede 574554c0a3aSHans de Goede TotalPageNum += CurtPktPageNum; 575554c0a3aSHans de Goede 576554c0a3aSHans de Goede BufIndex += (CurtPktPageNum*PageSize); 577554c0a3aSHans de Goede 578554c0a3aSHans de Goede /* 3 (2) ps-poll */ 579554c0a3aSHans de Goede RsvdPageLoc.LocPsPoll = TotalPageNum; 580554c0a3aSHans de Goede ConstructPSPoll(padapter, &ReservedPagePacket[BufIndex], &PSPollLength); 581554c0a3aSHans de Goede rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, true, false, false); 582554c0a3aSHans de Goede 583554c0a3aSHans de Goede CurtPktPageNum = (u8)PageNum_128(TxDescLen + PSPollLength); 584554c0a3aSHans de Goede 585554c0a3aSHans de Goede TotalPageNum += CurtPktPageNum; 586554c0a3aSHans de Goede 587554c0a3aSHans de Goede BufIndex += (CurtPktPageNum*PageSize); 588554c0a3aSHans de Goede 589554c0a3aSHans de Goede /* 3 (3) null data */ 590554c0a3aSHans de Goede RsvdPageLoc.LocNullData = TotalPageNum; 591554c0a3aSHans de Goede ConstructNullFunctionData( 592554c0a3aSHans de Goede padapter, 593554c0a3aSHans de Goede &ReservedPagePacket[BufIndex], 594554c0a3aSHans de Goede &NullDataLength, 595554c0a3aSHans de Goede get_my_bssid(&pmlmeinfo->network), 596554c0a3aSHans de Goede false, 0, 0, false 597554c0a3aSHans de Goede ); 598554c0a3aSHans de Goede rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false, false); 599554c0a3aSHans de Goede 600554c0a3aSHans de Goede CurtPktPageNum = (u8)PageNum_128(TxDescLen + NullDataLength); 601554c0a3aSHans de Goede 602554c0a3aSHans de Goede TotalPageNum += CurtPktPageNum; 603554c0a3aSHans de Goede 604554c0a3aSHans de Goede BufIndex += (CurtPktPageNum*PageSize); 605554c0a3aSHans de Goede 606554c0a3aSHans de Goede /* 3 (5) Qos null data */ 607554c0a3aSHans de Goede RsvdPageLoc.LocQosNull = TotalPageNum; 608554c0a3aSHans de Goede ConstructNullFunctionData( 609554c0a3aSHans de Goede padapter, 610554c0a3aSHans de Goede &ReservedPagePacket[BufIndex], 611554c0a3aSHans de Goede &QosNullLength, 612554c0a3aSHans de Goede get_my_bssid(&pmlmeinfo->network), 613554c0a3aSHans de Goede true, 0, 0, false 614554c0a3aSHans de Goede ); 615554c0a3aSHans de Goede rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false, false); 616554c0a3aSHans de Goede 617554c0a3aSHans de Goede CurtPktPageNum = (u8)PageNum_128(TxDescLen + QosNullLength); 618554c0a3aSHans de Goede 619554c0a3aSHans de Goede TotalPageNum += CurtPktPageNum; 620554c0a3aSHans de Goede 621554c0a3aSHans de Goede BufIndex += (CurtPktPageNum*PageSize); 622554c0a3aSHans de Goede 623554c0a3aSHans de Goede /* 3 (6) BT Qos null data */ 624554c0a3aSHans de Goede RsvdPageLoc.LocBTQosNull = TotalPageNum; 625554c0a3aSHans de Goede ConstructNullFunctionData( 626554c0a3aSHans de Goede padapter, 627554c0a3aSHans de Goede &ReservedPagePacket[BufIndex], 628554c0a3aSHans de Goede &BTQosNullLength, 629554c0a3aSHans de Goede get_my_bssid(&pmlmeinfo->network), 630554c0a3aSHans de Goede true, 0, 0, false 631554c0a3aSHans de Goede ); 632554c0a3aSHans de Goede rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true, false); 633554c0a3aSHans de Goede 634554c0a3aSHans de Goede CurtPktPageNum = (u8)PageNum_128(TxDescLen + BTQosNullLength); 635554c0a3aSHans de Goede 636554c0a3aSHans de Goede TotalPageNum += CurtPktPageNum; 637554c0a3aSHans de Goede 638554c0a3aSHans de Goede BufIndex += (CurtPktPageNum*PageSize); 639554c0a3aSHans de Goede 640554c0a3aSHans de Goede TotalPacketLen = BufIndex + BTQosNullLength; 641554c0a3aSHans de Goede 642554c0a3aSHans de Goede if (TotalPacketLen > MaxRsvdPageBufSize) { 643554c0a3aSHans de Goede goto error; 644554c0a3aSHans de Goede } else { 645554c0a3aSHans de Goede /* update attribute */ 646554c0a3aSHans de Goede pattrib = &pcmdframe->attrib; 647554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 648554c0a3aSHans de Goede pattrib->qsel = 0x10; 649554c0a3aSHans de Goede pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TxDescOffset; 650554c0a3aSHans de Goede dump_mgntframe_and_wait(padapter, pcmdframe, 100); 651554c0a3aSHans de Goede } 652554c0a3aSHans de Goede 653554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, _FW_LINKED)) { 654554c0a3aSHans de Goede rtl8723b_set_FwRsvdPage_cmd(padapter, &RsvdPageLoc); 655554c0a3aSHans de Goede rtl8723b_set_FwAoacRsvdPage_cmd(padapter, &RsvdPageLoc); 656554c0a3aSHans de Goede } else { 657554c0a3aSHans de Goede rtl8723b_set_FwAoacRsvdPage_cmd(padapter, &RsvdPageLoc); 658554c0a3aSHans de Goede } 659554c0a3aSHans de Goede return; 660554c0a3aSHans de Goede 661554c0a3aSHans de Goede error: 662554c0a3aSHans de Goede 663554c0a3aSHans de Goede rtw_free_xmitframe(pxmitpriv, pcmdframe); 664554c0a3aSHans de Goede } 665554c0a3aSHans de Goede 666554c0a3aSHans de Goede void rtl8723b_download_rsvd_page(struct adapter *padapter, u8 mstatus) 667554c0a3aSHans de Goede { 668554c0a3aSHans de Goede struct hal_com_data *pHalData = GET_HAL_DATA(padapter); 669554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 670554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 671554c0a3aSHans de Goede bool bcn_valid = false; 672554c0a3aSHans de Goede u8 DLBcnCount = 0; 673554c0a3aSHans de Goede u32 poll = 0; 674554c0a3aSHans de Goede u8 val8; 675554c0a3aSHans de Goede 676554c0a3aSHans de Goede DBG_8192C("+" FUNC_ADPT_FMT ": iface_type =%d mstatus(%x)\n", 677554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), get_iface_type(padapter), mstatus); 678554c0a3aSHans de Goede 679554c0a3aSHans de Goede if (mstatus == RT_MEDIA_CONNECT) { 680554c0a3aSHans de Goede bool bRecover = false; 681554c0a3aSHans de Goede u8 v8; 682554c0a3aSHans de Goede 683554c0a3aSHans de Goede /* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */ 684554c0a3aSHans de Goede /* Suggested by filen. Added by tynli. */ 685554c0a3aSHans de Goede rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid)); 686554c0a3aSHans de Goede 687554c0a3aSHans de Goede /* set REG_CR bit 8 */ 688554c0a3aSHans de Goede v8 = rtw_read8(padapter, REG_CR+1); 689554c0a3aSHans de Goede v8 |= BIT(0); /* ENSWBCN */ 690554c0a3aSHans de Goede rtw_write8(padapter, REG_CR+1, v8); 691554c0a3aSHans de Goede 692554c0a3aSHans de Goede /* Disable Hw protection for a time which revserd for Hw sending beacon. */ 693554c0a3aSHans de Goede /* Fix download reserved page packet fail that access collision with the protection time. */ 694554c0a3aSHans de Goede /* 2010.05.11. Added by tynli. */ 695554c0a3aSHans de Goede val8 = rtw_read8(padapter, REG_BCN_CTRL); 696554c0a3aSHans de Goede val8 &= ~EN_BCN_FUNCTION; 697554c0a3aSHans de Goede val8 |= DIS_TSF_UDT; 698554c0a3aSHans de Goede rtw_write8(padapter, REG_BCN_CTRL, val8); 699554c0a3aSHans de Goede 700554c0a3aSHans de Goede /* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */ 701554c0a3aSHans de Goede if (pHalData->RegFwHwTxQCtrl & BIT(6)) 702554c0a3aSHans de Goede bRecover = true; 703554c0a3aSHans de Goede 704554c0a3aSHans de Goede /* To tell Hw the packet is not a real beacon frame. */ 705554c0a3aSHans de Goede rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl & ~BIT(6)); 706554c0a3aSHans de Goede pHalData->RegFwHwTxQCtrl &= ~BIT(6); 707554c0a3aSHans de Goede 708554c0a3aSHans de Goede /* Clear beacon valid check bit. */ 709554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL); 710554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL); 711554c0a3aSHans de Goede 712554c0a3aSHans de Goede DLBcnCount = 0; 713554c0a3aSHans de Goede poll = 0; 714554c0a3aSHans de Goede do { 715554c0a3aSHans de Goede /* download rsvd page. */ 716554c0a3aSHans de Goede rtl8723b_set_FwRsvdPagePkt(padapter, 0); 717554c0a3aSHans de Goede DLBcnCount++; 718554c0a3aSHans de Goede do { 719554c0a3aSHans de Goede yield(); 720554c0a3aSHans de Goede /* mdelay(10); */ 721554c0a3aSHans de Goede /* check rsvd page download OK. */ 722554c0a3aSHans de Goede rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bcn_valid)); 723554c0a3aSHans de Goede poll++; 724554c0a3aSHans de Goede } while (!bcn_valid && (poll%10) != 0 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped); 725554c0a3aSHans de Goede 726554c0a3aSHans de Goede } while (!bcn_valid && DLBcnCount <= 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped); 727554c0a3aSHans de Goede 728554c0a3aSHans de Goede if (padapter->bSurpriseRemoved || padapter->bDriverStopped) { 729*21e161c3SFabio Aiuto } else { 730554c0a3aSHans de Goede struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter); 731554c0a3aSHans de Goede pwrctl->fw_psmode_iface_id = padapter->iface_id; 732554c0a3aSHans de Goede } 733554c0a3aSHans de Goede 734554c0a3aSHans de Goede /* 2010.05.11. Added by tynli. */ 735554c0a3aSHans de Goede val8 = rtw_read8(padapter, REG_BCN_CTRL); 736554c0a3aSHans de Goede val8 |= EN_BCN_FUNCTION; 737554c0a3aSHans de Goede val8 &= ~DIS_TSF_UDT; 738554c0a3aSHans de Goede rtw_write8(padapter, REG_BCN_CTRL, val8); 739554c0a3aSHans de Goede 740554c0a3aSHans de Goede /* To make sure that if there exists an adapter which would like to send beacon. */ 741554c0a3aSHans de Goede /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */ 742554c0a3aSHans de Goede /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */ 743554c0a3aSHans de Goede /* the beacon cannot be sent by HW. */ 744554c0a3aSHans de Goede /* 2010.06.23. Added by tynli. */ 745554c0a3aSHans de Goede if (bRecover) { 746554c0a3aSHans de Goede rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl | BIT(6)); 747554c0a3aSHans de Goede pHalData->RegFwHwTxQCtrl |= BIT(6); 748554c0a3aSHans de Goede } 749554c0a3aSHans de Goede 750554c0a3aSHans de Goede /* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */ 751554c0a3aSHans de Goede v8 = rtw_read8(padapter, REG_CR+1); 752554c0a3aSHans de Goede v8 &= ~BIT(0); /* ~ENSWBCN */ 753554c0a3aSHans de Goede rtw_write8(padapter, REG_CR+1, v8); 754554c0a3aSHans de Goede } 755554c0a3aSHans de Goede } 756554c0a3aSHans de Goede 757554c0a3aSHans de Goede void rtl8723b_set_FwJoinBssRpt_cmd(struct adapter *padapter, u8 mstatus) 758554c0a3aSHans de Goede { 759554c0a3aSHans de Goede if (mstatus == 1) 760554c0a3aSHans de Goede rtl8723b_download_rsvd_page(padapter, RT_MEDIA_CONNECT); 761554c0a3aSHans de Goede } 762554c0a3aSHans de Goede 763554c0a3aSHans de Goede /* arg[0] = macid */ 764554c0a3aSHans de Goede /* arg[1] = raid */ 765554c0a3aSHans de Goede /* arg[2] = shortGIrate */ 766554c0a3aSHans de Goede /* arg[3] = init_rate */ 767554c0a3aSHans de Goede void rtl8723b_Add_RateATid( 768554c0a3aSHans de Goede struct adapter *padapter, 769554c0a3aSHans de Goede u32 bitmap, 770554c0a3aSHans de Goede u8 *arg, 771554c0a3aSHans de Goede u8 rssi_level 772554c0a3aSHans de Goede ) 773554c0a3aSHans de Goede { 774554c0a3aSHans de Goede struct hal_com_data *pHalData = GET_HAL_DATA(padapter); 775554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 776554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 777554c0a3aSHans de Goede struct sta_info *psta; 778554c0a3aSHans de Goede u8 mac_id = arg[0]; 779554c0a3aSHans de Goede u8 raid = arg[1]; 780554c0a3aSHans de Goede u8 shortGI = arg[2]; 781554c0a3aSHans de Goede u8 bw; 782554c0a3aSHans de Goede u32 mask = bitmap&0x0FFFFFFF; 783554c0a3aSHans de Goede 784554c0a3aSHans de Goede psta = pmlmeinfo->FW_sta_info[mac_id].psta; 7857cd6f4b0SHimadri Pandya if (!psta) 786554c0a3aSHans de Goede return; 787554c0a3aSHans de Goede 788554c0a3aSHans de Goede bw = psta->bw_mode; 789554c0a3aSHans de Goede 790554c0a3aSHans de Goede if (rssi_level != DM_RATR_STA_INIT) 791554c0a3aSHans de Goede mask = ODM_Get_Rate_Bitmap(&pHalData->odmpriv, mac_id, mask, rssi_level); 792554c0a3aSHans de Goede 793554c0a3aSHans de Goede rtl8723b_set_FwMacIdConfig_cmd(padapter, mac_id, raid, bw, shortGI, mask); 794554c0a3aSHans de Goede } 795554c0a3aSHans de Goede 796554c0a3aSHans de Goede static void ConstructBtNullFunctionData( 797554c0a3aSHans de Goede struct adapter *padapter, 798554c0a3aSHans de Goede u8 *pframe, 799554c0a3aSHans de Goede u32 *pLength, 800554c0a3aSHans de Goede u8 *StaAddr, 801554c0a3aSHans de Goede u8 bQoS, 802554c0a3aSHans de Goede u8 AC, 803554c0a3aSHans de Goede u8 bEosp, 804554c0a3aSHans de Goede u8 bForcePowerSave 805554c0a3aSHans de Goede ) 806554c0a3aSHans de Goede { 807554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 808554c0a3aSHans de Goede __le16 *fctrl; 809554c0a3aSHans de Goede u32 pktlen; 810554c0a3aSHans de Goede u8 bssid[ETH_ALEN]; 811554c0a3aSHans de Goede 812554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 813554c0a3aSHans de Goede 8147cd6f4b0SHimadri Pandya if (!StaAddr) { 815554c0a3aSHans de Goede memcpy(bssid, myid(&padapter->eeprompriv), ETH_ALEN); 816554c0a3aSHans de Goede StaAddr = bssid; 817554c0a3aSHans de Goede } 818554c0a3aSHans de Goede 819554c0a3aSHans de Goede fctrl = &pwlanhdr->frame_control; 820554c0a3aSHans de Goede *fctrl = 0; 821554c0a3aSHans de Goede if (bForcePowerSave) 822554c0a3aSHans de Goede SetPwrMgt(fctrl); 823554c0a3aSHans de Goede 824554c0a3aSHans de Goede SetFrDs(fctrl); 825554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); 826554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); 827554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN); 828554c0a3aSHans de Goede 829554c0a3aSHans de Goede SetDuration(pwlanhdr, 0); 830554c0a3aSHans de Goede SetSeqNum(pwlanhdr, 0); 831554c0a3aSHans de Goede 832f2e741cbSHariprasad Kelam if (bQoS) { 833554c0a3aSHans de Goede struct ieee80211_qos_hdr *pwlanqoshdr; 834554c0a3aSHans de Goede 835554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_QOS_DATA_NULL); 836554c0a3aSHans de Goede 837554c0a3aSHans de Goede pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe; 838554c0a3aSHans de Goede SetPriority(&pwlanqoshdr->qos_ctrl, AC); 839554c0a3aSHans de Goede SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp); 840554c0a3aSHans de Goede 841554c0a3aSHans de Goede pktlen = sizeof(struct ieee80211_qos_hdr); 842554c0a3aSHans de Goede } else { 843554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_DATA_NULL); 844554c0a3aSHans de Goede 845554c0a3aSHans de Goede pktlen = sizeof(struct ieee80211_hdr_3addr); 846554c0a3aSHans de Goede } 847554c0a3aSHans de Goede 848554c0a3aSHans de Goede *pLength = pktlen; 849554c0a3aSHans de Goede } 850554c0a3aSHans de Goede 851554c0a3aSHans de Goede static void SetFwRsvdPagePkt_BTCoex(struct adapter *padapter) 852554c0a3aSHans de Goede { 853554c0a3aSHans de Goede struct xmit_frame *pcmdframe; 854554c0a3aSHans de Goede struct pkt_attrib *pattrib; 855554c0a3aSHans de Goede struct xmit_priv *pxmitpriv; 856554c0a3aSHans de Goede u32 BeaconLength = 0; 857554c0a3aSHans de Goede u32 BTQosNullLength = 0; 858554c0a3aSHans de Goede u8 *ReservedPagePacket; 859554c0a3aSHans de Goede u8 TxDescLen, TxDescOffset; 860554c0a3aSHans de Goede u8 TotalPageNum = 0, CurtPktPageNum = 0, RsvdPageNum = 0; 861554c0a3aSHans de Goede u16 BufIndex, PageSize; 862554c0a3aSHans de Goede u32 TotalPacketLen, MaxRsvdPageBufSize = 0; 863dc9a4304SMarco Cesati struct rsvdpage_loc RsvdPageLoc; 864554c0a3aSHans de Goede 865554c0a3aSHans de Goede 866554c0a3aSHans de Goede /* DBG_8192C("+" FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(padapter)); */ 867554c0a3aSHans de Goede 868554c0a3aSHans de Goede pxmitpriv = &padapter->xmitpriv; 869554c0a3aSHans de Goede TxDescLen = TXDESC_SIZE; 870554c0a3aSHans de Goede TxDescOffset = TXDESC_OFFSET; 871554c0a3aSHans de Goede PageSize = PAGE_SIZE_TX_8723B; 872554c0a3aSHans de Goede 873554c0a3aSHans de Goede RsvdPageNum = BCNQ_PAGE_NUM_8723B; 874554c0a3aSHans de Goede MaxRsvdPageBufSize = RsvdPageNum*PageSize; 875554c0a3aSHans de Goede 876554c0a3aSHans de Goede pcmdframe = rtw_alloc_cmdxmitframe(pxmitpriv); 8777cd6f4b0SHimadri Pandya if (!pcmdframe) { 878554c0a3aSHans de Goede DBG_8192C("%s: alloc ReservedPagePacket fail!\n", __func__); 879554c0a3aSHans de Goede return; 880554c0a3aSHans de Goede } 881554c0a3aSHans de Goede 882554c0a3aSHans de Goede ReservedPagePacket = pcmdframe->buf_addr; 883dc9a4304SMarco Cesati memset(&RsvdPageLoc, 0, sizeof(struct rsvdpage_loc)); 884554c0a3aSHans de Goede 885554c0a3aSHans de Goede /* 3 (1) beacon */ 886554c0a3aSHans de Goede BufIndex = TxDescOffset; 887554c0a3aSHans de Goede ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength); 888554c0a3aSHans de Goede 889554c0a3aSHans de Goede /* When we count the first page size, we need to reserve description size for the RSVD */ 890554c0a3aSHans de Goede /* packet, it will be filled in front of the packet in TXPKTBUF. */ 891554c0a3aSHans de Goede CurtPktPageNum = (u8)PageNum_128(TxDescLen + BeaconLength); 892554c0a3aSHans de Goede /* If we don't add 1 more page, the WOWLAN function has a problem. Baron thinks it's a bug of firmware */ 893554c0a3aSHans de Goede if (CurtPktPageNum == 1) 894554c0a3aSHans de Goede CurtPktPageNum += 1; 895554c0a3aSHans de Goede TotalPageNum += CurtPktPageNum; 896554c0a3aSHans de Goede 897554c0a3aSHans de Goede BufIndex += (CurtPktPageNum*PageSize); 898554c0a3aSHans de Goede 899554c0a3aSHans de Goede /* Jump to lastest page */ 900554c0a3aSHans de Goede if (BufIndex < (MaxRsvdPageBufSize - PageSize)) { 901554c0a3aSHans de Goede BufIndex = TxDescOffset + (MaxRsvdPageBufSize - PageSize); 902554c0a3aSHans de Goede TotalPageNum = BCNQ_PAGE_NUM_8723B - 1; 903554c0a3aSHans de Goede } 904554c0a3aSHans de Goede 905554c0a3aSHans de Goede /* 3 (6) BT Qos null data */ 906554c0a3aSHans de Goede RsvdPageLoc.LocBTQosNull = TotalPageNum; 907554c0a3aSHans de Goede ConstructBtNullFunctionData( 908554c0a3aSHans de Goede padapter, 909554c0a3aSHans de Goede &ReservedPagePacket[BufIndex], 910554c0a3aSHans de Goede &BTQosNullLength, 911554c0a3aSHans de Goede NULL, 912554c0a3aSHans de Goede true, 0, 0, false 913554c0a3aSHans de Goede ); 914554c0a3aSHans de Goede rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true, false); 915554c0a3aSHans de Goede 916554c0a3aSHans de Goede CurtPktPageNum = (u8)PageNum_128(TxDescLen + BTQosNullLength); 917554c0a3aSHans de Goede 918554c0a3aSHans de Goede TotalPageNum += CurtPktPageNum; 919554c0a3aSHans de Goede 920554c0a3aSHans de Goede TotalPacketLen = BufIndex + BTQosNullLength; 921554c0a3aSHans de Goede if (TotalPacketLen > MaxRsvdPageBufSize) { 922554c0a3aSHans de Goede DBG_8192C(FUNC_ADPT_FMT ": ERROR: The rsvd page size is not enough!!TotalPacketLen %d, MaxRsvdPageBufSize %d\n", 923554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), TotalPacketLen, MaxRsvdPageBufSize); 924554c0a3aSHans de Goede goto error; 925554c0a3aSHans de Goede } 926554c0a3aSHans de Goede 927554c0a3aSHans de Goede /* update attribute */ 928554c0a3aSHans de Goede pattrib = &pcmdframe->attrib; 929554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 930554c0a3aSHans de Goede pattrib->qsel = 0x10; 931554c0a3aSHans de Goede pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TxDescOffset; 932554c0a3aSHans de Goede dump_mgntframe_and_wait(padapter, pcmdframe, 100); 933554c0a3aSHans de Goede 934554c0a3aSHans de Goede /* DBG_8192C(FUNC_ADPT_FMT ": Set RSVD page location to Fw, TotalPacketLen(%d), TotalPageNum(%d)\n", */ 935554c0a3aSHans de Goede /* FUNC_ADPT_ARG(padapter), TotalPacketLen, TotalPageNum); */ 936554c0a3aSHans de Goede rtl8723b_set_FwRsvdPage_cmd(padapter, &RsvdPageLoc); 937554c0a3aSHans de Goede rtl8723b_set_FwAoacRsvdPage_cmd(padapter, &RsvdPageLoc); 938554c0a3aSHans de Goede 939554c0a3aSHans de Goede return; 940554c0a3aSHans de Goede 941554c0a3aSHans de Goede error: 942554c0a3aSHans de Goede rtw_free_xmitframe(pxmitpriv, pcmdframe); 943554c0a3aSHans de Goede } 944554c0a3aSHans de Goede 945554c0a3aSHans de Goede void rtl8723b_download_BTCoex_AP_mode_rsvd_page(struct adapter *padapter) 946554c0a3aSHans de Goede { 947554c0a3aSHans de Goede struct hal_com_data *pHalData; 948554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext; 949554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo; 950554c0a3aSHans de Goede u8 bRecover = false; 951554c0a3aSHans de Goede u8 bcn_valid = false; 952554c0a3aSHans de Goede u8 DLBcnCount = 0; 953554c0a3aSHans de Goede u32 poll = 0; 954554c0a3aSHans de Goede u8 val8; 955554c0a3aSHans de Goede 956554c0a3aSHans de Goede 957554c0a3aSHans de Goede DBG_8192C("+" FUNC_ADPT_FMT ": iface_type =%d fw_state = 0x%08X\n", 958554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), get_iface_type(padapter), get_fwstate(&padapter->mlmepriv)); 959554c0a3aSHans de Goede 960f55a6d45SArnd Bergmann #ifdef DEBUG 961554c0a3aSHans de Goede if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == false) { 962554c0a3aSHans de Goede DBG_8192C(FUNC_ADPT_FMT ": [WARNING] not in AP mode!!\n", 963554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter)); 964554c0a3aSHans de Goede } 965f55a6d45SArnd Bergmann #endif /* DEBUG */ 966554c0a3aSHans de Goede 967554c0a3aSHans de Goede pHalData = GET_HAL_DATA(padapter); 968554c0a3aSHans de Goede pmlmeext = &padapter->mlmeextpriv; 969554c0a3aSHans de Goede pmlmeinfo = &pmlmeext->mlmext_info; 970554c0a3aSHans de Goede 971554c0a3aSHans de Goede /* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */ 972554c0a3aSHans de Goede /* Suggested by filen. Added by tynli. */ 973554c0a3aSHans de Goede rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid)); 974554c0a3aSHans de Goede 975554c0a3aSHans de Goede /* set REG_CR bit 8 */ 976554c0a3aSHans de Goede val8 = rtw_read8(padapter, REG_CR+1); 977554c0a3aSHans de Goede val8 |= BIT(0); /* ENSWBCN */ 978554c0a3aSHans de Goede rtw_write8(padapter, REG_CR+1, val8); 979554c0a3aSHans de Goede 980554c0a3aSHans de Goede /* Disable Hw protection for a time which revserd for Hw sending beacon. */ 981554c0a3aSHans de Goede /* Fix download reserved page packet fail that access collision with the protection time. */ 982554c0a3aSHans de Goede /* 2010.05.11. Added by tynli. */ 983554c0a3aSHans de Goede val8 = rtw_read8(padapter, REG_BCN_CTRL); 984554c0a3aSHans de Goede val8 &= ~EN_BCN_FUNCTION; 985554c0a3aSHans de Goede val8 |= DIS_TSF_UDT; 986554c0a3aSHans de Goede rtw_write8(padapter, REG_BCN_CTRL, val8); 987554c0a3aSHans de Goede 988554c0a3aSHans de Goede /* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */ 989554c0a3aSHans de Goede if (pHalData->RegFwHwTxQCtrl & BIT(6)) 990554c0a3aSHans de Goede bRecover = true; 991554c0a3aSHans de Goede 992554c0a3aSHans de Goede /* To tell Hw the packet is not a real beacon frame. */ 993554c0a3aSHans de Goede pHalData->RegFwHwTxQCtrl &= ~BIT(6); 994554c0a3aSHans de Goede rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl); 995554c0a3aSHans de Goede 996554c0a3aSHans de Goede /* Clear beacon valid check bit. */ 997554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL); 998554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL); 999554c0a3aSHans de Goede 1000554c0a3aSHans de Goede DLBcnCount = 0; 1001554c0a3aSHans de Goede poll = 0; 1002554c0a3aSHans de Goede do { 1003554c0a3aSHans de Goede SetFwRsvdPagePkt_BTCoex(padapter); 1004554c0a3aSHans de Goede DLBcnCount++; 1005554c0a3aSHans de Goede do { 1006554c0a3aSHans de Goede yield(); 1007554c0a3aSHans de Goede /* mdelay(10); */ 1008554c0a3aSHans de Goede /* check rsvd page download OK. */ 1009554c0a3aSHans de Goede rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, &bcn_valid); 1010554c0a3aSHans de Goede poll++; 1011554c0a3aSHans de Goede } while (!bcn_valid && (poll%10) != 0 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped); 1012554c0a3aSHans de Goede } while (!bcn_valid && (DLBcnCount <= 100) && !padapter->bSurpriseRemoved && !padapter->bDriverStopped); 1013554c0a3aSHans de Goede 1014f2e741cbSHariprasad Kelam if (bcn_valid) { 1015554c0a3aSHans de Goede struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter); 1016554c0a3aSHans de Goede pwrctl->fw_psmode_iface_id = padapter->iface_id; 1017d0cc39cdSRoss Schmidt DBG_8192C("%s: DL RSVD page success! DLBcnCount:%d, poll:%d\n", 1018554c0a3aSHans de Goede ADPT_ARG(padapter), DLBcnCount, poll); 1019554c0a3aSHans de Goede } else { 1020d0cc39cdSRoss Schmidt DBG_8192C("%s: DL RSVD page fail! DLBcnCount:%d, poll:%d\n", 1021554c0a3aSHans de Goede ADPT_ARG(padapter), DLBcnCount, poll); 1022d0cc39cdSRoss Schmidt DBG_8192C("%s: DL RSVD page fail! bSurpriseRemoved =%d\n", 1023554c0a3aSHans de Goede ADPT_ARG(padapter), padapter->bSurpriseRemoved); 1024d0cc39cdSRoss Schmidt DBG_8192C("%s: DL RSVD page fail! bDriverStopped =%d\n", 1025554c0a3aSHans de Goede ADPT_ARG(padapter), padapter->bDriverStopped); 1026554c0a3aSHans de Goede } 1027554c0a3aSHans de Goede 1028554c0a3aSHans de Goede /* 2010.05.11. Added by tynli. */ 1029554c0a3aSHans de Goede val8 = rtw_read8(padapter, REG_BCN_CTRL); 1030554c0a3aSHans de Goede val8 |= EN_BCN_FUNCTION; 1031554c0a3aSHans de Goede val8 &= ~DIS_TSF_UDT; 1032554c0a3aSHans de Goede rtw_write8(padapter, REG_BCN_CTRL, val8); 1033554c0a3aSHans de Goede 1034554c0a3aSHans de Goede /* To make sure that if there exists an adapter which would like to send beacon. */ 1035554c0a3aSHans de Goede /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */ 1036554c0a3aSHans de Goede /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */ 1037554c0a3aSHans de Goede /* the beacon cannot be sent by HW. */ 1038554c0a3aSHans de Goede /* 2010.06.23. Added by tynli. */ 1039554c0a3aSHans de Goede if (bRecover) { 1040554c0a3aSHans de Goede pHalData->RegFwHwTxQCtrl |= BIT(6); 1041554c0a3aSHans de Goede rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl); 1042554c0a3aSHans de Goede } 1043554c0a3aSHans de Goede 1044554c0a3aSHans de Goede /* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */ 1045554c0a3aSHans de Goede val8 = rtw_read8(padapter, REG_CR+1); 1046554c0a3aSHans de Goede val8 &= ~BIT(0); /* ~ENSWBCN */ 1047554c0a3aSHans de Goede rtw_write8(padapter, REG_CR+1, val8); 1048554c0a3aSHans de Goede } 1049