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, byte5 = 0; 244 u8 awake_intvl; /* DTIM = (awake_intvl - 1) */ 245 struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops; 246 bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ? 247 btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false); 248 bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ? 249 btc_ops->btc_is_bt_lps_on(rtlpriv) : false); 250 251 if (bt_ctrl_lps) 252 mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE); 253 254 RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n", 255 mode, bt_ctrl_lps); 256 257 switch (mode) { 258 case FW_PS_MIN_MODE: 259 rlbm = 0; 260 awake_intvl = 2; 261 break; 262 case FW_PS_MAX_MODE: 263 rlbm = 1; 264 awake_intvl = 2; 265 break; 266 case FW_PS_DTIM_MODE: 267 rlbm = 2; 268 awake_intvl = ppsc->reg_max_lps_awakeintvl; 269 /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period 270 * is only used in swlps. 271 */ 272 break; 273 default: 274 rlbm = 2; 275 awake_intvl = 4; 276 break; 277 } 278 279 if (rtlpriv->mac80211.p2p) { 280 awake_intvl = 2; 281 rlbm = 1; 282 } 283 284 if (mode == FW_PS_ACTIVE_MODE) { 285 byte5 = 0x40; 286 power_state = FW_PWR_STATE_ACTIVE; 287 } else { 288 if (bt_ctrl_lps) { 289 byte5 = btc_ops->btc_get_lps_val(rtlpriv); 290 power_state = btc_ops->btc_get_rpwm_val(rtlpriv); 291 292 if ((rlbm == 2) && (byte5 & BIT(4))) { 293 /* Keep awake interval to 1 to prevent from 294 * decreasing coex performance 295 */ 296 awake_intvl = 2; 297 rlbm = 2; 298 } 299 } else { 300 byte5 = 0x40; 301 power_state = FW_PWR_STATE_RF_OFF; 302 } 303 } 304 305 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); 306 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm); 307 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 308 bt_ctrl_lps ? 0 : ppsc->smart_ps); 309 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, 310 awake_intvl); 311 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); 312 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); 313 SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5); 314 315 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 316 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", 317 u1_h2c_set_pwrmode, H2C_PWEMODE_LENGTH); 318 if (rtlpriv->cfg->ops->get_btc_status()) 319 btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode, 320 H2C_PWEMODE_LENGTH); 321 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_SETPWRMODE, H2C_PWEMODE_LENGTH, 322 u1_h2c_set_pwrmode); 323 } 324 325 void rtl8723be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus) 326 { 327 u8 parm[3] = { 0, 0, 0 }; 328 /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect 329 * bit1=0-->update Media Status to MACID 330 * bit1=1-->update Media Status from MACID to MACID_End 331 * parm[1]: MACID, if this is INFRA_STA, MacID = 0 332 * parm[2]: MACID_End 333 */ 334 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus); 335 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0); 336 337 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_MSRRPT, 3, parm); 338 } 339 340 #define BEACON_PG 0 /* ->1 */ 341 #define PSPOLL_PG 2 342 #define NULL_PG 3 343 #define PROBERSP_PG 4 /* ->5 */ 344 #define QOS_NULL_PG 6 345 #define BT_QOS_NULL_PG 7 346 347 #define TOTAL_RESERVED_PKT_LEN 1024 /* can be up to 1280 (tx_bndy=245) */ 348 349 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { 350 /* page 0 beacon */ 351 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 352 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 353 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00, 354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 355 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65, 356 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B, 357 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06, 358 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32, 359 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 360 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 363 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C, 364 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50, 365 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 366 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00, 367 368 /* page 1 beacon */ 369 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00, 370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 373 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 374 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 375 0x00, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 380 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 381 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 382 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 385 386 /* page 2 ps-poll */ 387 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B, 388 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 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 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 399 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 400 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 401 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 402 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 403 404 /* page 3 null */ 405 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B, 406 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 407 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 415 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 416 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 417 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 418 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 419 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 420 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 421 422 /* page 4 probe_resp */ 423 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, 424 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 425 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 426 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, 427 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, 428 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, 429 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, 430 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, 431 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, 432 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, 433 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, 437 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 438 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 439 440 /* page 5 probe_resp */ 441 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 443 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 444 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 445 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 447 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 448 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 450 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 452 0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 453 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 456 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 457 458 /* page 6 qos null data */ 459 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, 460 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 461 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, 462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 466 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 467 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 470 0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 471 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 474 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 475 476 /* page 7 BT-qos null data */ 477 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, 478 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 479 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, 480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 487 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 488 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 492 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 493 494 }; 495 496 void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, 497 bool b_dl_finished) 498 { 499 struct rtl_priv *rtlpriv = rtl_priv(hw); 500 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 501 struct sk_buff *skb = NULL; 502 503 u32 totalpacketlen; 504 bool rtstatus; 505 u8 u1rsvdpageloc[5] = { 0 }; 506 bool b_dlok = false; 507 508 u8 *beacon; 509 u8 *p_pspoll; 510 u8 *nullfunc; 511 u8 *p_probersp; 512 u8 *qosnull; 513 u8 *btqosnull; 514 /*--------------------------------------------------------- 515 * (1) beacon 516 *--------------------------------------------------------- 517 */ 518 beacon = &reserved_page_packet[BEACON_PG * 128]; 519 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); 520 SET_80211_HDR_ADDRESS3(beacon, mac->bssid); 521 522 /*------------------------------------------------------- 523 * (2) ps-poll 524 *------------------------------------------------------- 525 */ 526 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; 527 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); 528 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); 529 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); 530 531 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); 532 533 /*-------------------------------------------------------- 534 * (3) null data 535 *-------------------------------------------------------- 536 */ 537 nullfunc = &reserved_page_packet[NULL_PG * 128]; 538 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); 539 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); 540 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); 541 542 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); 543 544 /*--------------------------------------------------------- 545 * (4) probe response 546 *--------------------------------------------------------- 547 */ 548 p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; 549 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); 550 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); 551 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); 552 553 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); 554 555 /*--------------------------------------------------------- 556 * (5) QoS Null 557 *--------------------------------------------------------- 558 */ 559 qosnull = &reserved_page_packet[QOS_NULL_PG * 128]; 560 SET_80211_HDR_ADDRESS1(qosnull, mac->bssid); 561 SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr); 562 SET_80211_HDR_ADDRESS3(qosnull, mac->bssid); 563 564 SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOS_NULL_PG); 565 566 /*--------------------------------------------------------- 567 * (5) QoS Null 568 *--------------------------------------------------------- 569 */ 570 btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128]; 571 SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid); 572 SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr); 573 SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid); 574 575 SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOS_NULL_PG); 576 577 totalpacketlen = TOTAL_RESERVED_PKT_LEN; 578 579 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, 580 "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 581 &reserved_page_packet[0], totalpacketlen); 582 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 583 "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 584 u1rsvdpageloc, sizeof(u1rsvdpageloc)); 585 586 skb = dev_alloc_skb(totalpacketlen); 587 skb_put_data(skb, &reserved_page_packet, totalpacketlen); 588 589 rtstatus = rtl_cmd_send_packet(hw, skb); 590 591 if (rtstatus) 592 b_dlok = true; 593 594 if (b_dlok) { 595 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, 596 "Set RSVD page location to Fw.\n"); 597 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, "H2C_RSVDPAGE:\n", 598 u1rsvdpageloc, sizeof(u1rsvdpageloc)); 599 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_RSVDPAGE, 600 sizeof(u1rsvdpageloc), u1rsvdpageloc); 601 } else 602 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, 603 "Set RSVD page location to Fw FAIL!!!!!!.\n"); 604 } 605 606 /*Should check FW support p2p or not.*/ 607 static void rtl8723be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, 608 u8 ctwindow) 609 { 610 u8 u1_ctwindow_period[1] = { ctwindow}; 611 612 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_CTW_CMD, 1, 613 u1_ctwindow_period); 614 } 615 616 void rtl8723be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, 617 u8 p2p_ps_state) 618 { 619 struct rtl_priv *rtlpriv = rtl_priv(hw); 620 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); 621 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 622 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); 623 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; 624 u8 i; 625 u16 ctwindow; 626 u32 start_time, tsf_low; 627 628 switch (p2p_ps_state) { 629 case P2P_PS_DISABLE: 630 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); 631 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); 632 break; 633 case P2P_PS_ENABLE: 634 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); 635 /* update CTWindow value. */ 636 if (p2pinfo->ctwindow > 0) { 637 p2p_ps_offload->ctwindow_en = 1; 638 ctwindow = p2pinfo->ctwindow; 639 rtl8723be_set_p2p_ctw_period_cmd(hw, ctwindow); 640 } 641 /* hw only support 2 set of NoA */ 642 for (i = 0 ; i < p2pinfo->noa_num ; i++) { 643 /* To control the register setting 644 * for which NOA 645 */ 646 rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); 647 if (i == 0) 648 p2p_ps_offload->noa0_en = 1; 649 else 650 p2p_ps_offload->noa1_en = 1; 651 652 /* config P2P NoA Descriptor Register */ 653 rtl_write_dword(rtlpriv, 0x5E0, 654 p2pinfo->noa_duration[i]); 655 rtl_write_dword(rtlpriv, 0x5E4, 656 p2pinfo->noa_interval[i]); 657 658 /*Get Current TSF value */ 659 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); 660 661 start_time = p2pinfo->noa_start_time[i]; 662 if (p2pinfo->noa_count_type[i] != 1) { 663 while (start_time <= (tsf_low + (50 * 1024))) { 664 start_time += p2pinfo->noa_interval[i]; 665 if (p2pinfo->noa_count_type[i] != 255) 666 p2pinfo->noa_count_type[i]--; 667 } 668 } 669 rtl_write_dword(rtlpriv, 0x5E8, start_time); 670 rtl_write_dword(rtlpriv, 0x5EC, 671 p2pinfo->noa_count_type[i]); 672 } 673 674 if ((p2pinfo->opp_ps == 1) || 675 (p2pinfo->noa_num > 0)) { 676 /* rst p2p circuit */ 677 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); 678 679 p2p_ps_offload->offload_en = 1; 680 681 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { 682 p2p_ps_offload->role = 1; 683 p2p_ps_offload->allstasleep = 0; 684 } else { 685 p2p_ps_offload->role = 0; 686 } 687 p2p_ps_offload->discovery = 0; 688 } 689 break; 690 case P2P_PS_SCAN: 691 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); 692 p2p_ps_offload->discovery = 1; 693 break; 694 case P2P_PS_SCAN_DONE: 695 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); 696 p2p_ps_offload->discovery = 0; 697 p2pinfo->p2p_ps_state = P2P_PS_ENABLE; 698 break; 699 default: 700 break; 701 } 702 703 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_OFFLOAD, 1, 704 (u8 *)p2p_ps_offload); 705 } 706 707 void rtl8723be_c2h_content_parsing(struct ieee80211_hw *hw, 708 u8 c2h_cmd_id, 709 u8 c2h_cmd_len, u8 *tmp_buf) 710 { 711 struct rtl_priv *rtlpriv = rtl_priv(hw); 712 713 switch (c2h_cmd_id) { 714 case C2H_8723B_DBG: 715 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 716 "[C2H], C2H_8723BE_DBG!!\n"); 717 break; 718 case C2H_8723B_TX_REPORT: 719 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 720 "[C2H], C2H_8723BE_TX_REPORT!\n"); 721 rtl_tx_report_handler(hw, tmp_buf, c2h_cmd_len); 722 break; 723 case C2H_8723B_BT_INFO: 724 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 725 "[C2H], C2H_8723BE_BT_INFO!!\n"); 726 rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf, 727 c2h_cmd_len); 728 break; 729 case C2H_8723B_BT_MP: 730 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 731 "[C2H], C2H_8723BE_BT_MP!!\n"); 732 break; 733 default: 734 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 735 "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id); 736 break; 737 } 738 } 739 740 void rtl8723be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len) 741 { 742 struct rtl_priv *rtlpriv = rtl_priv(hw); 743 u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0; 744 u8 *tmp_buf = NULL; 745 746 c2h_cmd_id = buffer[0]; 747 c2h_cmd_seq = buffer[1]; 748 c2h_cmd_len = len - 2; 749 tmp_buf = buffer + 2; 750 751 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 752 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n", 753 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len); 754 755 RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE, 756 "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len); 757 758 switch (c2h_cmd_id) { 759 case C2H_8723B_BT_INFO: 760 case C2H_8723B_BT_MP: 761 rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf); 762 break; 763 764 default: 765 rtl8723be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, 766 tmp_buf); 767 break; 768 } 769 } 770