1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright(c) 2009-2014 Realtek Corporation.*/ 3 4 #include "../wifi.h" 5 #include "../pci.h" 6 #include "../base.h" 7 #include "../core.h" 8 #include "reg.h" 9 #include "def.h" 10 #include "fw.h" 11 #include "../rtl8723com/fw_common.h" 12 13 static bool _rtl8723be_check_fw_read_last_h2c(struct ieee80211_hw *hw, 14 u8 boxnum) 15 { 16 struct rtl_priv *rtlpriv = rtl_priv(hw); 17 u8 val_hmetfr; 18 bool result = false; 19 20 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); 21 if (((val_hmetfr >> boxnum) & BIT(0)) == 0) 22 result = true; 23 return result; 24 } 25 26 static void _rtl8723be_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id, 27 u32 cmd_len, u8 *p_cmdbuffer) 28 { 29 struct rtl_priv *rtlpriv = rtl_priv(hw); 30 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 31 u8 boxnum; 32 u16 box_reg = 0, box_extreg = 0; 33 u8 u1b_tmp; 34 bool isfw_read = false; 35 u8 buf_index = 0; 36 bool bwrite_sucess = false; 37 u8 wait_h2c_limmit = 100; 38 u8 wait_writeh2c_limmit = 100; 39 u8 boxcontent[4], boxextcontent[4]; 40 u32 h2c_waitcounter = 0; 41 unsigned long flag; 42 u8 idx; 43 44 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); 45 46 while (true) { 47 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); 48 if (rtlhal->h2c_setinprogress) { 49 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 50 "H2C set in progress! Wait to set..element_id(%d).\n", 51 element_id); 52 53 while (rtlhal->h2c_setinprogress) { 54 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, 55 flag); 56 h2c_waitcounter++; 57 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 58 "Wait 100 us (%d times)...\n", 59 h2c_waitcounter); 60 udelay(100); 61 62 if (h2c_waitcounter > 1000) 63 return; 64 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, 65 flag); 66 } 67 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 68 } else { 69 rtlhal->h2c_setinprogress = true; 70 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 71 break; 72 } 73 } 74 75 while (!bwrite_sucess) { 76 wait_writeh2c_limmit--; 77 if (wait_writeh2c_limmit == 0) { 78 pr_err("Write H2C fail because no trigger for FW INT!\n"); 79 break; 80 } 81 82 boxnum = rtlhal->last_hmeboxnum; 83 switch (boxnum) { 84 case 0: 85 box_reg = REG_HMEBOX_0; 86 box_extreg = REG_HMEBOX_EXT_0; 87 break; 88 case 1: 89 box_reg = REG_HMEBOX_1; 90 box_extreg = REG_HMEBOX_EXT_1; 91 break; 92 case 2: 93 box_reg = REG_HMEBOX_2; 94 box_extreg = REG_HMEBOX_EXT_2; 95 break; 96 case 3: 97 box_reg = REG_HMEBOX_3; 98 box_extreg = REG_HMEBOX_EXT_3; 99 break; 100 default: 101 pr_err("switch case %#x not processed\n", 102 boxnum); 103 break; 104 } 105 106 isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, boxnum); 107 while (!isfw_read) { 108 wait_h2c_limmit--; 109 if (wait_h2c_limmit == 0) { 110 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 111 "Waiting too long for FW read clear HMEBox(%d)!\n", 112 boxnum); 113 break; 114 } 115 116 udelay(10); 117 118 isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, 119 boxnum); 120 u1b_tmp = rtl_read_byte(rtlpriv, 0x130); 121 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 122 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n", 123 boxnum, u1b_tmp); 124 } 125 126 if (!isfw_read) { 127 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 128 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", 129 boxnum); 130 break; 131 } 132 133 memset(boxcontent, 0, sizeof(boxcontent)); 134 memset(boxextcontent, 0, sizeof(boxextcontent)); 135 boxcontent[0] = element_id; 136 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 137 "Write element_id box_reg(%4x) = %2x\n", 138 box_reg, element_id); 139 140 switch (cmd_len) { 141 case 1: 142 case 2: 143 case 3: 144 /*boxcontent[0] &= ~(BIT(7));*/ 145 memcpy((u8 *)(boxcontent) + 1, 146 p_cmdbuffer + buf_index, cmd_len); 147 148 for (idx = 0; idx < 4; idx++) { 149 rtl_write_byte(rtlpriv, box_reg + idx, 150 boxcontent[idx]); 151 } 152 break; 153 case 4: 154 case 5: 155 case 6: 156 case 7: 157 /*boxcontent[0] |= (BIT(7));*/ 158 memcpy((u8 *)(boxextcontent), 159 p_cmdbuffer + buf_index+3, cmd_len-3); 160 memcpy((u8 *)(boxcontent) + 1, 161 p_cmdbuffer + buf_index, 3); 162 163 for (idx = 0; idx < 4; idx++) { 164 rtl_write_byte(rtlpriv, box_extreg + idx, 165 boxextcontent[idx]); 166 } 167 168 for (idx = 0; idx < 4; idx++) { 169 rtl_write_byte(rtlpriv, box_reg + idx, 170 boxcontent[idx]); 171 } 172 break; 173 default: 174 pr_err("switch case %#x not processed\n", 175 cmd_len); 176 break; 177 } 178 179 bwrite_sucess = true; 180 181 rtlhal->last_hmeboxnum = boxnum + 1; 182 if (rtlhal->last_hmeboxnum == 4) 183 rtlhal->last_hmeboxnum = 0; 184 185 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 186 "pHalData->last_hmeboxnum = %d\n", 187 rtlhal->last_hmeboxnum); 188 } 189 190 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); 191 rtlhal->h2c_setinprogress = false; 192 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 193 194 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); 195 } 196 197 void rtl8723be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, 198 u32 cmd_len, u8 *p_cmdbuffer) 199 { 200 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 201 u32 tmp_cmdbuf[2]; 202 203 if (!rtlhal->fw_ready) { 204 WARN_ONCE(true, 205 "rtl8723be: error H2C cmd because of Fw download fail!!!\n"); 206 return; 207 } 208 209 memset(tmp_cmdbuf, 0, 8); 210 memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len); 211 _rtl8723be_fill_h2c_command(hw, element_id, cmd_len, 212 (u8 *)&tmp_cmdbuf); 213 return; 214 } 215 216 void rtl8723be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) 217 { 218 struct rtl_priv *rtlpriv = rtl_priv(hw); 219 u8 u1_h2c_set_pwrmode[H2C_PWEMODE_LENGTH] = { 0 }; 220 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 221 u8 rlbm, power_state = 0, byte5 = 0; 222 u8 awake_intvl; /* DTIM = (awake_intvl - 1) */ 223 struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops; 224 bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ? 225 btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false); 226 bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ? 227 btc_ops->btc_is_bt_lps_on(rtlpriv) : false); 228 229 if (bt_ctrl_lps) 230 mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE); 231 232 RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n", 233 mode, bt_ctrl_lps); 234 235 switch (mode) { 236 case FW_PS_MIN_MODE: 237 rlbm = 0; 238 awake_intvl = 2; 239 break; 240 case FW_PS_MAX_MODE: 241 rlbm = 1; 242 awake_intvl = 2; 243 break; 244 case FW_PS_DTIM_MODE: 245 rlbm = 2; 246 awake_intvl = ppsc->reg_max_lps_awakeintvl; 247 /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period 248 * is only used in swlps. 249 */ 250 break; 251 default: 252 rlbm = 2; 253 awake_intvl = 4; 254 break; 255 } 256 257 if (rtlpriv->mac80211.p2p) { 258 awake_intvl = 2; 259 rlbm = 1; 260 } 261 262 if (mode == FW_PS_ACTIVE_MODE) { 263 byte5 = 0x40; 264 power_state = FW_PWR_STATE_ACTIVE; 265 } else { 266 if (bt_ctrl_lps) { 267 byte5 = btc_ops->btc_get_lps_val(rtlpriv); 268 power_state = btc_ops->btc_get_rpwm_val(rtlpriv); 269 270 if ((rlbm == 2) && (byte5 & BIT(4))) { 271 /* Keep awake interval to 1 to prevent from 272 * decreasing coex performance 273 */ 274 awake_intvl = 2; 275 rlbm = 2; 276 } 277 } else { 278 byte5 = 0x40; 279 power_state = FW_PWR_STATE_RF_OFF; 280 } 281 } 282 283 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); 284 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm); 285 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 286 bt_ctrl_lps ? 0 : ppsc->smart_ps); 287 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, 288 awake_intvl); 289 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); 290 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); 291 SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5); 292 293 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 294 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", 295 u1_h2c_set_pwrmode, H2C_PWEMODE_LENGTH); 296 if (rtlpriv->cfg->ops->get_btc_status()) 297 btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode, 298 H2C_PWEMODE_LENGTH); 299 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_SETPWRMODE, H2C_PWEMODE_LENGTH, 300 u1_h2c_set_pwrmode); 301 } 302 303 void rtl8723be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus) 304 { 305 u8 parm[3] = { 0, 0, 0 }; 306 /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect 307 * bit1=0-->update Media Status to MACID 308 * bit1=1-->update Media Status from MACID to MACID_End 309 * parm[1]: MACID, if this is INFRA_STA, MacID = 0 310 * parm[2]: MACID_End 311 */ 312 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus); 313 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0); 314 315 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_MSRRPT, 3, parm); 316 } 317 318 #define BEACON_PG 0 /* ->1 */ 319 #define PSPOLL_PG 2 320 #define NULL_PG 3 321 #define PROBERSP_PG 4 /* ->5 */ 322 #define QOS_NULL_PG 6 323 #define BT_QOS_NULL_PG 7 324 325 #define TOTAL_RESERVED_PKT_LEN 1024 /* can be up to 1280 (tx_bndy=245) */ 326 327 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { 328 /* page 0 beacon */ 329 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 330 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 331 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00, 332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 333 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65, 334 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B, 335 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06, 336 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32, 337 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 338 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 339 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 340 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 341 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C, 342 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50, 343 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 344 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00, 345 346 /* page 1 beacon */ 347 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00, 348 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 349 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 359 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 363 364 /* page 2 ps-poll */ 365 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B, 366 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 369 0x00, 0x00, 0x00, 0x00, 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 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 377 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 380 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 381 382 /* page 3 null */ 383 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B, 384 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 385 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 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 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 395 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 397 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 398 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 399 400 /* page 4 probe_resp */ 401 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, 402 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 403 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 404 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, 405 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, 406 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, 407 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, 408 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, 409 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, 410 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, 411 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, 415 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 417 418 /* page 5 probe_resp */ 419 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 421 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 422 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 431 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 434 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 435 436 /* page 6 qos null data */ 437 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, 438 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 439 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, 440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 449 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 450 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 452 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 453 454 /* page 7 BT-qos null data */ 455 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, 456 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 457 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, 458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 460 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 461 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 471 472 }; 473 474 void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, 475 bool b_dl_finished) 476 { 477 struct rtl_priv *rtlpriv = rtl_priv(hw); 478 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 479 struct sk_buff *skb = NULL; 480 481 u32 totalpacketlen; 482 bool rtstatus; 483 u8 u1rsvdpageloc[5] = { 0 }; 484 bool b_dlok = false; 485 486 u8 *beacon; 487 u8 *p_pspoll; 488 u8 *nullfunc; 489 u8 *p_probersp; 490 u8 *qosnull; 491 u8 *btqosnull; 492 /*--------------------------------------------------------- 493 * (1) beacon 494 *--------------------------------------------------------- 495 */ 496 beacon = &reserved_page_packet[BEACON_PG * 128]; 497 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); 498 SET_80211_HDR_ADDRESS3(beacon, mac->bssid); 499 500 /*------------------------------------------------------- 501 * (2) ps-poll 502 *------------------------------------------------------- 503 */ 504 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; 505 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); 506 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); 507 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); 508 509 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); 510 511 /*-------------------------------------------------------- 512 * (3) null data 513 *-------------------------------------------------------- 514 */ 515 nullfunc = &reserved_page_packet[NULL_PG * 128]; 516 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); 517 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); 518 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); 519 520 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); 521 522 /*--------------------------------------------------------- 523 * (4) probe response 524 *--------------------------------------------------------- 525 */ 526 p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; 527 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); 528 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); 529 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); 530 531 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); 532 533 /*--------------------------------------------------------- 534 * (5) QoS Null 535 *--------------------------------------------------------- 536 */ 537 qosnull = &reserved_page_packet[QOS_NULL_PG * 128]; 538 SET_80211_HDR_ADDRESS1(qosnull, mac->bssid); 539 SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr); 540 SET_80211_HDR_ADDRESS3(qosnull, mac->bssid); 541 542 SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOS_NULL_PG); 543 544 /*--------------------------------------------------------- 545 * (5) QoS Null 546 *--------------------------------------------------------- 547 */ 548 btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128]; 549 SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid); 550 SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr); 551 SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid); 552 553 SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOS_NULL_PG); 554 555 totalpacketlen = TOTAL_RESERVED_PKT_LEN; 556 557 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, 558 "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 559 &reserved_page_packet[0], totalpacketlen); 560 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 561 "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 562 u1rsvdpageloc, sizeof(u1rsvdpageloc)); 563 564 skb = dev_alloc_skb(totalpacketlen); 565 if (!skb) 566 return; 567 skb_put_data(skb, &reserved_page_packet, totalpacketlen); 568 569 rtstatus = rtl_cmd_send_packet(hw, skb); 570 571 if (rtstatus) 572 b_dlok = true; 573 574 if (b_dlok) { 575 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, 576 "Set RSVD page location to Fw.\n"); 577 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, "H2C_RSVDPAGE:\n", 578 u1rsvdpageloc, sizeof(u1rsvdpageloc)); 579 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_RSVDPAGE, 580 sizeof(u1rsvdpageloc), u1rsvdpageloc); 581 } else 582 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, 583 "Set RSVD page location to Fw FAIL!!!!!!.\n"); 584 } 585 586 /*Should check FW support p2p or not.*/ 587 static void rtl8723be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, 588 u8 ctwindow) 589 { 590 u8 u1_ctwindow_period[1] = { ctwindow}; 591 592 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_CTW_CMD, 1, 593 u1_ctwindow_period); 594 } 595 596 void rtl8723be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, 597 u8 p2p_ps_state) 598 { 599 struct rtl_priv *rtlpriv = rtl_priv(hw); 600 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); 601 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 602 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); 603 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; 604 u8 i; 605 u16 ctwindow; 606 u32 start_time, tsf_low; 607 608 switch (p2p_ps_state) { 609 case P2P_PS_DISABLE: 610 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); 611 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); 612 break; 613 case P2P_PS_ENABLE: 614 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); 615 /* update CTWindow value. */ 616 if (p2pinfo->ctwindow > 0) { 617 p2p_ps_offload->ctwindow_en = 1; 618 ctwindow = p2pinfo->ctwindow; 619 rtl8723be_set_p2p_ctw_period_cmd(hw, ctwindow); 620 } 621 /* hw only support 2 set of NoA */ 622 for (i = 0 ; i < p2pinfo->noa_num ; i++) { 623 /* To control the register setting 624 * for which NOA 625 */ 626 rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); 627 if (i == 0) 628 p2p_ps_offload->noa0_en = 1; 629 else 630 p2p_ps_offload->noa1_en = 1; 631 632 /* config P2P NoA Descriptor Register */ 633 rtl_write_dword(rtlpriv, 0x5E0, 634 p2pinfo->noa_duration[i]); 635 rtl_write_dword(rtlpriv, 0x5E4, 636 p2pinfo->noa_interval[i]); 637 638 /*Get Current TSF value */ 639 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); 640 641 start_time = p2pinfo->noa_start_time[i]; 642 if (p2pinfo->noa_count_type[i] != 1) { 643 while (start_time <= (tsf_low + (50 * 1024))) { 644 start_time += p2pinfo->noa_interval[i]; 645 if (p2pinfo->noa_count_type[i] != 255) 646 p2pinfo->noa_count_type[i]--; 647 } 648 } 649 rtl_write_dword(rtlpriv, 0x5E8, start_time); 650 rtl_write_dword(rtlpriv, 0x5EC, 651 p2pinfo->noa_count_type[i]); 652 } 653 654 if ((p2pinfo->opp_ps == 1) || 655 (p2pinfo->noa_num > 0)) { 656 /* rst p2p circuit */ 657 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); 658 659 p2p_ps_offload->offload_en = 1; 660 661 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { 662 p2p_ps_offload->role = 1; 663 p2p_ps_offload->allstasleep = 0; 664 } else { 665 p2p_ps_offload->role = 0; 666 } 667 p2p_ps_offload->discovery = 0; 668 } 669 break; 670 case P2P_PS_SCAN: 671 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); 672 p2p_ps_offload->discovery = 1; 673 break; 674 case P2P_PS_SCAN_DONE: 675 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); 676 p2p_ps_offload->discovery = 0; 677 p2pinfo->p2p_ps_state = P2P_PS_ENABLE; 678 break; 679 default: 680 break; 681 } 682 683 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_OFFLOAD, 1, 684 (u8 *)p2p_ps_offload); 685 } 686