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 35 static 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 48 static 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 pr_err("Write H2C fail because no trigger for FW INT!\n"); 101 break; 102 } 103 104 boxnum = rtlhal->last_hmeboxnum; 105 switch (boxnum) { 106 case 0: 107 box_reg = REG_HMEBOX_0; 108 box_extreg = REG_HMEBOX_EXT_0; 109 break; 110 case 1: 111 box_reg = REG_HMEBOX_1; 112 box_extreg = REG_HMEBOX_EXT_1; 113 break; 114 case 2: 115 box_reg = REG_HMEBOX_2; 116 box_extreg = REG_HMEBOX_EXT_2; 117 break; 118 case 3: 119 box_reg = REG_HMEBOX_3; 120 box_extreg = REG_HMEBOX_EXT_3; 121 break; 122 default: 123 pr_err("switch case %#x not processed\n", 124 boxnum); 125 break; 126 } 127 128 isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, boxnum); 129 while (!isfw_read) { 130 wait_h2c_limmit--; 131 if (wait_h2c_limmit == 0) { 132 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 133 "Waiting too long for FW read clear HMEBox(%d)!\n", 134 boxnum); 135 break; 136 } 137 138 udelay(10); 139 140 isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, 141 boxnum); 142 u1b_tmp = rtl_read_byte(rtlpriv, 0x130); 143 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 144 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n", 145 boxnum, u1b_tmp); 146 } 147 148 if (!isfw_read) { 149 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 150 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", 151 boxnum); 152 break; 153 } 154 155 memset(boxcontent, 0, sizeof(boxcontent)); 156 memset(boxextcontent, 0, sizeof(boxextcontent)); 157 boxcontent[0] = element_id; 158 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 159 "Write element_id box_reg(%4x) = %2x\n", 160 box_reg, element_id); 161 162 switch (cmd_len) { 163 case 1: 164 case 2: 165 case 3: 166 /*boxcontent[0] &= ~(BIT(7));*/ 167 memcpy((u8 *)(boxcontent) + 1, 168 p_cmdbuffer + buf_index, cmd_len); 169 170 for (idx = 0; idx < 4; idx++) { 171 rtl_write_byte(rtlpriv, box_reg + idx, 172 boxcontent[idx]); 173 } 174 break; 175 case 4: 176 case 5: 177 case 6: 178 case 7: 179 /*boxcontent[0] |= (BIT(7));*/ 180 memcpy((u8 *)(boxextcontent), 181 p_cmdbuffer + buf_index+3, cmd_len-3); 182 memcpy((u8 *)(boxcontent) + 1, 183 p_cmdbuffer + buf_index, 3); 184 185 for (idx = 0; idx < 4; idx++) { 186 rtl_write_byte(rtlpriv, box_extreg + idx, 187 boxextcontent[idx]); 188 } 189 190 for (idx = 0; idx < 4; idx++) { 191 rtl_write_byte(rtlpriv, box_reg + idx, 192 boxcontent[idx]); 193 } 194 break; 195 default: 196 pr_err("switch case %#x not processed\n", 197 cmd_len); 198 break; 199 } 200 201 bwrite_sucess = true; 202 203 rtlhal->last_hmeboxnum = boxnum + 1; 204 if (rtlhal->last_hmeboxnum == 4) 205 rtlhal->last_hmeboxnum = 0; 206 207 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 208 "pHalData->last_hmeboxnum = %d\n", 209 rtlhal->last_hmeboxnum); 210 } 211 212 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); 213 rtlhal->h2c_setinprogress = false; 214 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 215 216 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); 217 } 218 219 void rtl8723be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, 220 u32 cmd_len, u8 *p_cmdbuffer) 221 { 222 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 223 u32 tmp_cmdbuf[2]; 224 225 if (!rtlhal->fw_ready) { 226 WARN_ONCE(true, 227 "rtl8723be: error H2C cmd because of Fw download fail!!!\n"); 228 return; 229 } 230 231 memset(tmp_cmdbuf, 0, 8); 232 memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len); 233 _rtl8723be_fill_h2c_command(hw, element_id, cmd_len, 234 (u8 *)&tmp_cmdbuf); 235 return; 236 } 237 238 void rtl8723be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) 239 { 240 struct rtl_priv *rtlpriv = rtl_priv(hw); 241 u8 u1_h2c_set_pwrmode[H2C_PWEMODE_LENGTH] = { 0 }; 242 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 243 u8 rlbm, power_state = 0; 244 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); 245 246 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); 247 rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/ 248 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm); 249 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 250 (rtlpriv->mac80211.p2p) ? 251 ppsc->smart_ps : 1); 252 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, 253 ppsc->reg_max_lps_awakeintvl); 254 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); 255 if (mode == FW_PS_ACTIVE_MODE) 256 power_state |= FW_PWR_STATE_ACTIVE; 257 else 258 power_state |= FW_PWR_STATE_RF_OFF; 259 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); 260 261 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 262 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", 263 u1_h2c_set_pwrmode, H2C_PWEMODE_LENGTH); 264 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_SETPWRMODE, H2C_PWEMODE_LENGTH, 265 u1_h2c_set_pwrmode); 266 } 267 268 void rtl8723be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus) 269 { 270 u8 parm[3] = { 0, 0, 0 }; 271 /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect 272 * bit1=0-->update Media Status to MACID 273 * bit1=1-->update Media Status from MACID to MACID_End 274 * parm[1]: MACID, if this is INFRA_STA, MacID = 0 275 * parm[2]: MACID_End 276 */ 277 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus); 278 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0); 279 280 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_MSRRPT, 3, parm); 281 } 282 283 #define BEACON_PG 0 /* ->1 */ 284 #define PSPOLL_PG 2 285 #define NULL_PG 3 286 #define PROBERSP_PG 4 /* ->5 */ 287 #define QOS_NULL_PG 6 288 #define BT_QOS_NULL_PG 7 289 290 #define TOTAL_RESERVED_PKT_LEN 1024 /* can be up to 1280 (tx_bndy=245) */ 291 292 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { 293 /* page 0 beacon */ 294 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 295 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 296 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00, 297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 298 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65, 299 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B, 300 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06, 301 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32, 302 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 303 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 304 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 305 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 306 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C, 307 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50, 308 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 309 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00, 310 311 /* page 1 beacon */ 312 0x00, 0x50, 0xF2, 0x02, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 323 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 324 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 326 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 327 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 328 329 /* page 2 ps-poll */ 330 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B, 331 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 341 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 342 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 345 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 346 347 /* page 3 null */ 348 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B, 349 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 350 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 359 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 360 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 363 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 364 365 /* page 4 probe_resp */ 366 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, 367 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 368 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 369 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, 370 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, 371 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, 372 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, 373 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, 374 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, 375 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, 376 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 379 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, 380 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 381 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 382 383 /* page 5 probe_resp */ 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 0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 396 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 397 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 398 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 399 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 400 401 /* page 6 qos null data */ 402 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, 403 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 404 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, 405 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 406 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 407 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 408 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 409 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 410 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 413 0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 414 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 415 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 417 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 418 419 /* page 7 BT-qos null data */ 420 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, 421 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 422 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, 423 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 425 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 428 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 429 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 430 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 435 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 436 437 }; 438 439 void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, 440 bool b_dl_finished) 441 { 442 struct rtl_priv *rtlpriv = rtl_priv(hw); 443 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 444 struct sk_buff *skb = NULL; 445 446 u32 totalpacketlen; 447 bool rtstatus; 448 u8 u1rsvdpageloc[5] = { 0 }; 449 bool b_dlok = false; 450 451 u8 *beacon; 452 u8 *p_pspoll; 453 u8 *nullfunc; 454 u8 *p_probersp; 455 u8 *qosnull; 456 u8 *btqosnull; 457 /*--------------------------------------------------------- 458 * (1) beacon 459 *--------------------------------------------------------- 460 */ 461 beacon = &reserved_page_packet[BEACON_PG * 128]; 462 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); 463 SET_80211_HDR_ADDRESS3(beacon, mac->bssid); 464 465 /*------------------------------------------------------- 466 * (2) ps-poll 467 *------------------------------------------------------- 468 */ 469 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; 470 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); 471 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); 472 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); 473 474 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); 475 476 /*-------------------------------------------------------- 477 * (3) null data 478 *-------------------------------------------------------- 479 */ 480 nullfunc = &reserved_page_packet[NULL_PG * 128]; 481 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); 482 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); 483 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); 484 485 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); 486 487 /*--------------------------------------------------------- 488 * (4) probe response 489 *--------------------------------------------------------- 490 */ 491 p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; 492 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); 493 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); 494 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); 495 496 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); 497 498 /*--------------------------------------------------------- 499 * (5) QoS Null 500 *--------------------------------------------------------- 501 */ 502 qosnull = &reserved_page_packet[QOS_NULL_PG * 128]; 503 SET_80211_HDR_ADDRESS1(qosnull, mac->bssid); 504 SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr); 505 SET_80211_HDR_ADDRESS3(qosnull, mac->bssid); 506 507 SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOS_NULL_PG); 508 509 /*--------------------------------------------------------- 510 * (5) QoS Null 511 *--------------------------------------------------------- 512 */ 513 btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128]; 514 SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid); 515 SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr); 516 SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid); 517 518 SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOS_NULL_PG); 519 520 totalpacketlen = TOTAL_RESERVED_PKT_LEN; 521 522 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, 523 "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 524 &reserved_page_packet[0], totalpacketlen); 525 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 526 "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 527 u1rsvdpageloc, sizeof(u1rsvdpageloc)); 528 529 skb = dev_alloc_skb(totalpacketlen); 530 memcpy((u8 *)skb_put(skb, totalpacketlen), 531 &reserved_page_packet, totalpacketlen); 532 533 rtstatus = rtl_cmd_send_packet(hw, skb); 534 535 if (rtstatus) 536 b_dlok = true; 537 538 if (b_dlok) { 539 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, 540 "Set RSVD page location to Fw.\n"); 541 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, "H2C_RSVDPAGE:\n", 542 u1rsvdpageloc, sizeof(u1rsvdpageloc)); 543 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_RSVDPAGE, 544 sizeof(u1rsvdpageloc), u1rsvdpageloc); 545 } else 546 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, 547 "Set RSVD page location to Fw FAIL!!!!!!.\n"); 548 } 549 550 /*Should check FW support p2p or not.*/ 551 static void rtl8723be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, 552 u8 ctwindow) 553 { 554 u8 u1_ctwindow_period[1] = { ctwindow}; 555 556 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_CTW_CMD, 1, 557 u1_ctwindow_period); 558 } 559 560 void rtl8723be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, 561 u8 p2p_ps_state) 562 { 563 struct rtl_priv *rtlpriv = rtl_priv(hw); 564 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); 565 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 566 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); 567 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; 568 u8 i; 569 u16 ctwindow; 570 u32 start_time, tsf_low; 571 572 switch (p2p_ps_state) { 573 case P2P_PS_DISABLE: 574 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); 575 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); 576 break; 577 case P2P_PS_ENABLE: 578 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); 579 /* update CTWindow value. */ 580 if (p2pinfo->ctwindow > 0) { 581 p2p_ps_offload->ctwindow_en = 1; 582 ctwindow = p2pinfo->ctwindow; 583 rtl8723be_set_p2p_ctw_period_cmd(hw, ctwindow); 584 } 585 /* hw only support 2 set of NoA */ 586 for (i = 0 ; i < p2pinfo->noa_num ; i++) { 587 /* To control the register setting 588 * for which NOA 589 */ 590 rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); 591 if (i == 0) 592 p2p_ps_offload->noa0_en = 1; 593 else 594 p2p_ps_offload->noa1_en = 1; 595 596 /* config P2P NoA Descriptor Register */ 597 rtl_write_dword(rtlpriv, 0x5E0, 598 p2pinfo->noa_duration[i]); 599 rtl_write_dword(rtlpriv, 0x5E4, 600 p2pinfo->noa_interval[i]); 601 602 /*Get Current TSF value */ 603 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); 604 605 start_time = p2pinfo->noa_start_time[i]; 606 if (p2pinfo->noa_count_type[i] != 1) { 607 while (start_time <= (tsf_low + (50 * 1024))) { 608 start_time += p2pinfo->noa_interval[i]; 609 if (p2pinfo->noa_count_type[i] != 255) 610 p2pinfo->noa_count_type[i]--; 611 } 612 } 613 rtl_write_dword(rtlpriv, 0x5E8, start_time); 614 rtl_write_dword(rtlpriv, 0x5EC, 615 p2pinfo->noa_count_type[i]); 616 } 617 618 if ((p2pinfo->opp_ps == 1) || 619 (p2pinfo->noa_num > 0)) { 620 /* rst p2p circuit */ 621 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); 622 623 p2p_ps_offload->offload_en = 1; 624 625 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { 626 p2p_ps_offload->role = 1; 627 p2p_ps_offload->allstasleep = 0; 628 } else { 629 p2p_ps_offload->role = 0; 630 } 631 p2p_ps_offload->discovery = 0; 632 } 633 break; 634 case P2P_PS_SCAN: 635 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); 636 p2p_ps_offload->discovery = 1; 637 break; 638 case P2P_PS_SCAN_DONE: 639 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); 640 p2p_ps_offload->discovery = 0; 641 p2pinfo->p2p_ps_state = P2P_PS_ENABLE; 642 break; 643 default: 644 break; 645 } 646 647 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_OFFLOAD, 1, 648 (u8 *)p2p_ps_offload); 649 } 650 651 void rtl8723be_c2h_content_parsing(struct ieee80211_hw *hw, 652 u8 c2h_cmd_id, 653 u8 c2h_cmd_len, u8 *tmp_buf) 654 { 655 struct rtl_priv *rtlpriv = rtl_priv(hw); 656 657 switch (c2h_cmd_id) { 658 case C2H_8723B_DBG: 659 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 660 "[C2H], C2H_8723BE_DBG!!\n"); 661 break; 662 case C2H_8723B_TX_REPORT: 663 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 664 "[C2H], C2H_8723BE_TX_REPORT!\n"); 665 break; 666 case C2H_8723B_BT_INFO: 667 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 668 "[C2H], C2H_8723BE_BT_INFO!!\n"); 669 rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf, 670 c2h_cmd_len); 671 break; 672 case C2H_8723B_BT_MP: 673 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 674 "[C2H], C2H_8723BE_BT_MP!!\n"); 675 break; 676 default: 677 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 678 "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id); 679 break; 680 } 681 } 682 683 void rtl8723be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len) 684 { 685 struct rtl_priv *rtlpriv = rtl_priv(hw); 686 u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0; 687 u8 *tmp_buf = NULL; 688 689 c2h_cmd_id = buffer[0]; 690 c2h_cmd_seq = buffer[1]; 691 c2h_cmd_len = len - 2; 692 tmp_buf = buffer + 2; 693 694 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 695 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n", 696 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len); 697 698 RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE, 699 "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len); 700 701 switch (c2h_cmd_id) { 702 case C2H_8723B_BT_INFO: 703 case C2H_8723B_BT_MP: 704 rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf); 705 break; 706 707 default: 708 rtl8723be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, 709 tmp_buf); 710 break; 711 } 712 } 713