1/****************************************************************************** 2 * 3 * Copyright(c) 2009-2014 Realtek Corporation. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 * The full GNU General Public License is included in this distribution in the 15 * file called LICENSE. 16 * 17 * Contact Information: 18 * wlanfae <wlanfae@realtek.com> 19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, 20 * Hsinchu 300, Taiwan. 21 * 22 * Larry Finger <Larry.Finger@lwfinger.net> 23 * 24 *****************************************************************************/ 25 26#include "../wifi.h" 27#include "../pci.h" 28#include "../base.h" 29#include "../core.h" 30#include "reg.h" 31#include "def.h" 32#include "fw.h" 33#include "../rtl8723com/fw_common.h" 34 35static bool _rtl8723be_check_fw_read_last_h2c(struct ieee80211_hw *hw, 36 u8 boxnum) 37{ 38 struct rtl_priv *rtlpriv = rtl_priv(hw); 39 u8 val_hmetfr; 40 bool result = false; 41 42 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); 43 if (((val_hmetfr >> boxnum) & BIT(0)) == 0) 44 result = true; 45 return result; 46} 47 48static void _rtl8723be_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id, 49 u32 cmd_len, u8 *p_cmdbuffer) 50{ 51 struct rtl_priv *rtlpriv = rtl_priv(hw); 52 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 53 u8 boxnum; 54 u16 box_reg = 0, box_extreg = 0; 55 u8 u1b_tmp; 56 bool isfw_read = false; 57 u8 buf_index = 0; 58 bool bwrite_sucess = false; 59 u8 wait_h2c_limmit = 100; 60 u8 wait_writeh2c_limmit = 100; 61 u8 boxcontent[4], boxextcontent[4]; 62 u32 h2c_waitcounter = 0; 63 unsigned long flag; 64 u8 idx; 65 66 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); 67 68 while (true) { 69 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); 70 if (rtlhal->h2c_setinprogress) { 71 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 72 "H2C set in progress! Wait to set..element_id(%d).\n", 73 element_id); 74 75 while (rtlhal->h2c_setinprogress) { 76 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, 77 flag); 78 h2c_waitcounter++; 79 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 80 "Wait 100 us (%d times)...\n", 81 h2c_waitcounter); 82 udelay(100); 83 84 if (h2c_waitcounter > 1000) 85 return; 86 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, 87 flag); 88 } 89 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 90 } else { 91 rtlhal->h2c_setinprogress = true; 92 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 93 break; 94 } 95 } 96 97 while (!bwrite_sucess) { 98 wait_writeh2c_limmit--; 99 if (wait_writeh2c_limmit == 0) { 100 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 101 "Write H2C fail because no trigger for FW INT!\n"); 102 break; 103 } 104 105 boxnum = rtlhal->last_hmeboxnum; 106 switch (boxnum) { 107 case 0: 108 box_reg = REG_HMEBOX_0; 109 box_extreg = REG_HMEBOX_EXT_0; 110 break; 111 case 1: 112 box_reg = REG_HMEBOX_1; 113 box_extreg = REG_HMEBOX_EXT_1; 114 break; 115 case 2: 116 box_reg = REG_HMEBOX_2; 117 box_extreg = REG_HMEBOX_EXT_2; 118 break; 119 case 3: 120 box_reg = REG_HMEBOX_3; 121 box_extreg = REG_HMEBOX_EXT_3; 122 break; 123 default: 124 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 125 "switch case not process\n"); 126 break; 127 } 128 129 isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, boxnum); 130 while (!isfw_read) { 131 wait_h2c_limmit--; 132 if (wait_h2c_limmit == 0) { 133 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 134 "Waiting too long for FW read clear HMEBox(%d)!\n", 135 boxnum); 136 break; 137 } 138 139 udelay(10); 140 141 isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, 142 boxnum); 143 u1b_tmp = rtl_read_byte(rtlpriv, 0x130); 144 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 145 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n", 146 boxnum, u1b_tmp); 147 } 148 149 if (!isfw_read) { 150 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 151 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", 152 boxnum); 153 break; 154 } 155 156 memset(boxcontent, 0, sizeof(boxcontent)); 157 memset(boxextcontent, 0, sizeof(boxextcontent)); 158 boxcontent[0] = element_id; 159 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 160 "Write element_id box_reg(%4x) = %2x\n", 161 box_reg, element_id); 162 163 switch (cmd_len) { 164 case 1: 165 case 2: 166 case 3: 167 /*boxcontent[0] &= ~(BIT(7));*/ 168 memcpy((u8 *)(boxcontent) + 1, 169 p_cmdbuffer + buf_index, cmd_len); 170 171 for (idx = 0; idx < 4; idx++) { 172 rtl_write_byte(rtlpriv, box_reg + idx, 173 boxcontent[idx]); 174 } 175 break; 176 case 4: 177 case 5: 178 case 6: 179 case 7: 180 /*boxcontent[0] |= (BIT(7));*/ 181 memcpy((u8 *)(boxextcontent), 182 p_cmdbuffer + buf_index+3, cmd_len-3); 183 memcpy((u8 *)(boxcontent) + 1, 184 p_cmdbuffer + buf_index, 3); 185 186 for (idx = 0; idx < 4; idx++) { 187 rtl_write_byte(rtlpriv, box_extreg + idx, 188 boxextcontent[idx]); 189 } 190 191 for (idx = 0; idx < 4; idx++) { 192 rtl_write_byte(rtlpriv, box_reg + idx, 193 boxcontent[idx]); 194 } 195 break; 196 default: 197 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 198 "switch case not process\n"); 199 break; 200 } 201 202 bwrite_sucess = true; 203 204 rtlhal->last_hmeboxnum = boxnum + 1; 205 if (rtlhal->last_hmeboxnum == 4) 206 rtlhal->last_hmeboxnum = 0; 207 208 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 209 "pHalData->last_hmeboxnum = %d\n", 210 rtlhal->last_hmeboxnum); 211 } 212 213 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); 214 rtlhal->h2c_setinprogress = false; 215 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 216 217 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); 218} 219 220void rtl8723be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, 221 u32 cmd_len, u8 *p_cmdbuffer) 222{ 223 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 224 u32 tmp_cmdbuf[2]; 225 226 if (!rtlhal->fw_ready) { 227 RT_ASSERT(false, 228 "return H2C cmd because of Fw download fail!!!\n"); 229 return; 230 } 231 232 memset(tmp_cmdbuf, 0, 8); 233 memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len); 234 _rtl8723be_fill_h2c_command(hw, element_id, cmd_len, 235 (u8 *)&tmp_cmdbuf); 236 return; 237} 238 239void rtl8723be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) 240{ 241 struct rtl_priv *rtlpriv = rtl_priv(hw); 242 u8 u1_h2c_set_pwrmode[H2C_PWEMODE_LENGTH] = { 0 }; 243 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 244 u8 rlbm, power_state = 0; 245 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); 246 247 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); 248 rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/ 249 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm); 250 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 251 (rtlpriv->mac80211.p2p) ? 252 ppsc->smart_ps : 1); 253 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, 254 ppsc->reg_max_lps_awakeintvl); 255 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); 256 if (mode == FW_PS_ACTIVE_MODE) 257 power_state |= FW_PWR_STATE_ACTIVE; 258 else 259 power_state |= FW_PWR_STATE_RF_OFF; 260 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); 261 262 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 263 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", 264 u1_h2c_set_pwrmode, H2C_PWEMODE_LENGTH); 265 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_SETPWRMODE, H2C_PWEMODE_LENGTH, 266 u1_h2c_set_pwrmode); 267} 268 269void rtl8723be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus) 270{ 271 u8 parm[3] = { 0, 0, 0 }; 272 /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect 273 * bit1=0-->update Media Status to MACID 274 * bit1=1-->update Media Status from MACID to MACID_End 275 * parm[1]: MACID, if this is INFRA_STA, MacID = 0 276 * parm[2]: MACID_End 277 */ 278 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus); 279 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0); 280 281 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_MSRRPT, 3, parm); 282} 283 284#define BEACON_PG 0 /* ->1 */ 285#define PSPOLL_PG 2 286#define NULL_PG 3 287#define PROBERSP_PG 4 /* ->5 */ 288 289#define TOTAL_RESERVED_PKT_LEN 768 290 291static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { 292 /* page 0 beacon */ 293 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 294 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 295 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00, 296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 297 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65, 298 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B, 299 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06, 300 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32, 301 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 302 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 304 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 305 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C, 306 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50, 307 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 308 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00, 309 310 /* page 1 beacon */ 311 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00, 312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 313 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 322 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 323 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 324 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 326 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 327 328 /* page 2 ps-poll */ 329 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B, 330 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 336 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 337 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 339 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 340 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 341 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 342 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 344 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 345 346 /* page 3 null */ 347 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B, 348 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 349 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00, 350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 351 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 352 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 358 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 359 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 362 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 363 364 /* page 4 probe_resp */ 365 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, 366 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 367 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 368 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, 369 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, 370 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, 371 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, 372 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, 373 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, 374 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, 375 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 378 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, 379 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 381 382 /* page 5 probe_resp */ 383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 386 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 387 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 390 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 391 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 392 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 393 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 394 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 395 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 397 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 398 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 399}; 400 401void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, 402 bool b_dl_finished) 403{ 404 struct rtl_priv *rtlpriv = rtl_priv(hw); 405 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 406 struct sk_buff *skb = NULL; 407 408 u32 totalpacketlen; 409 bool rtstatus; 410 u8 u1rsvdpageloc[5] = { 0 }; 411 bool b_dlok = false; 412 413 u8 *beacon; 414 u8 *p_pspoll; 415 u8 *nullfunc; 416 u8 *p_probersp; 417 /*--------------------------------------------------------- 418 * (1) beacon 419 *--------------------------------------------------------- 420 */ 421 beacon = &reserved_page_packet[BEACON_PG * 128]; 422 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); 423 SET_80211_HDR_ADDRESS3(beacon, mac->bssid); 424 425 /*------------------------------------------------------- 426 * (2) ps-poll 427 *------------------------------------------------------- 428 */ 429 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; 430 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); 431 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); 432 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); 433 434 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); 435 436 /*-------------------------------------------------------- 437 * (3) null data 438 *-------------------------------------------------------- 439 */ 440 nullfunc = &reserved_page_packet[NULL_PG * 128]; 441 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); 442 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); 443 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); 444 445 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); 446 447 /*--------------------------------------------------------- 448 * (4) probe response 449 *--------------------------------------------------------- 450 */ 451 p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; 452 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); 453 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); 454 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); 455 456 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); 457 458 totalpacketlen = TOTAL_RESERVED_PKT_LEN; 459 460 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, 461 "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 462 &reserved_page_packet[0], totalpacketlen); 463 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 464 "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 465 u1rsvdpageloc, 3); 466 467 skb = dev_alloc_skb(totalpacketlen); 468 memcpy((u8 *)skb_put(skb, totalpacketlen), 469 &reserved_page_packet, totalpacketlen); 470 471 rtstatus = rtl_cmd_send_packet(hw, skb); 472 473 if (rtstatus) 474 b_dlok = true; 475 476 if (b_dlok) { 477 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, 478 "Set RSVD page location to Fw.\n"); 479 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, "H2C_RSVDPAGE:\n", 480 u1rsvdpageloc, 3); 481 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_RSVDPAGE, 482 sizeof(u1rsvdpageloc), u1rsvdpageloc); 483 } else 484 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, 485 "Set RSVD page location to Fw FAIL!!!!!!.\n"); 486} 487 488/*Should check FW support p2p or not.*/ 489static void rtl8723be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, 490 u8 ctwindow) 491{ 492 u8 u1_ctwindow_period[1] = { ctwindow}; 493 494 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_CTW_CMD, 1, 495 u1_ctwindow_period); 496} 497 498void rtl8723be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, 499 u8 p2p_ps_state) 500{ 501 struct rtl_priv *rtlpriv = rtl_priv(hw); 502 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); 503 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 504 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); 505 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; 506 u8 i; 507 u16 ctwindow; 508 u32 start_time, tsf_low; 509 510 switch (p2p_ps_state) { 511 case P2P_PS_DISABLE: 512 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); 513 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); 514 break; 515 case P2P_PS_ENABLE: 516 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); 517 /* update CTWindow value. */ 518 if (p2pinfo->ctwindow > 0) { 519 p2p_ps_offload->ctwindow_en = 1; 520 ctwindow = p2pinfo->ctwindow; 521 rtl8723be_set_p2p_ctw_period_cmd(hw, ctwindow); 522 } 523 /* hw only support 2 set of NoA */ 524 for (i = 0 ; i < p2pinfo->noa_num ; i++) { 525 /* To control the register setting 526 * for which NOA 527 */ 528 rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); 529 if (i == 0) 530 p2p_ps_offload->noa0_en = 1; 531 else 532 p2p_ps_offload->noa1_en = 1; 533 534 /* config P2P NoA Descriptor Register */ 535 rtl_write_dword(rtlpriv, 0x5E0, 536 p2pinfo->noa_duration[i]); 537 rtl_write_dword(rtlpriv, 0x5E4, 538 p2pinfo->noa_interval[i]); 539 540 /*Get Current TSF value */ 541 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); 542 543 start_time = p2pinfo->noa_start_time[i]; 544 if (p2pinfo->noa_count_type[i] != 1) { 545 while (start_time <= (tsf_low + (50 * 1024))) { 546 start_time += p2pinfo->noa_interval[i]; 547 if (p2pinfo->noa_count_type[i] != 255) 548 p2pinfo->noa_count_type[i]--; 549 } 550 } 551 rtl_write_dword(rtlpriv, 0x5E8, start_time); 552 rtl_write_dword(rtlpriv, 0x5EC, 553 p2pinfo->noa_count_type[i]); 554 } 555 556 if ((p2pinfo->opp_ps == 1) || 557 (p2pinfo->noa_num > 0)) { 558 /* rst p2p circuit */ 559 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); 560 561 p2p_ps_offload->offload_en = 1; 562 563 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { 564 p2p_ps_offload->role = 1; 565 p2p_ps_offload->allstasleep = 0; 566 } else { 567 p2p_ps_offload->role = 0; 568 } 569 p2p_ps_offload->discovery = 0; 570 } 571 break; 572 case P2P_PS_SCAN: 573 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); 574 p2p_ps_offload->discovery = 1; 575 break; 576 case P2P_PS_SCAN_DONE: 577 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); 578 p2p_ps_offload->discovery = 0; 579 p2pinfo->p2p_ps_state = P2P_PS_ENABLE; 580 break; 581 default: 582 break; 583 } 584 585 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_OFFLOAD, 1, 586 (u8 *)p2p_ps_offload); 587} 588 589static void _rtl8723be_c2h_content_parsing(struct ieee80211_hw *hw, 590 u8 c2h_cmd_id, 591 u8 c2h_cmd_len, u8 *tmp_buf) 592{ 593 struct rtl_priv *rtlpriv = rtl_priv(hw); 594 595 switch (c2h_cmd_id) { 596 case C2H_8723B_DBG: 597 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 598 "[C2H], C2H_8723BE_DBG!!\n"); 599 break; 600 case C2H_8723B_TX_REPORT: 601 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 602 "[C2H], C2H_8723BE_TX_REPORT!\n"); 603 break; 604 case C2H_8723B_BT_INFO: 605 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 606 "[C2H], C2H_8723BE_BT_INFO!!\n"); 607 rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf, 608 c2h_cmd_len); 609 break; 610 case C2H_8723B_BT_MP: 611 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 612 "[C2H], C2H_8723BE_BT_MP!!\n"); 613 break; 614 default: 615 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 616 "[C2H], Unkown packet!! CmdId(%#X)!\n", c2h_cmd_id); 617 break; 618 } 619} 620 621void rtl8723be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len) 622{ 623 struct rtl_priv *rtlpriv = rtl_priv(hw); 624 u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0; 625 u8 *tmp_buf = NULL; 626 627 c2h_cmd_id = buffer[0]; 628 c2h_cmd_seq = buffer[1]; 629 c2h_cmd_len = len - 2; 630 tmp_buf = buffer + 2; 631 632 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 633 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n", 634 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len); 635 636 RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE, 637 "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len); 638 639 _rtl8723be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf); 640} 641