1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright(c) 2009-2013 Realtek Corporation.*/ 3 4 #include "../wifi.h" 5 #include "../pci.h" 6 #include "../base.h" 7 #include "../core.h" 8 #include "../efuse.h" 9 #include "reg.h" 10 #include "def.h" 11 #include "fw.h" 12 13 static void _rtl88e_enable_fw_download(struct ieee80211_hw *hw, bool enable) 14 { 15 struct rtl_priv *rtlpriv = rtl_priv(hw); 16 u8 tmp; 17 18 if (enable) { 19 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 20 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04); 21 22 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); 23 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01); 24 25 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); 26 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); 27 } else { 28 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); 29 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); 30 31 rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00); 32 } 33 } 34 35 static void _rtl88e_write_fw(struct ieee80211_hw *hw, 36 enum version_8188e version, u8 *buffer, u32 size) 37 { 38 struct rtl_priv *rtlpriv = rtl_priv(hw); 39 u8 *bufferptr = (u8 *)buffer; 40 u32 pagenums, remainsize; 41 u32 page, offset; 42 43 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size); 44 45 rtl_fill_dummy(bufferptr, &size); 46 47 pagenums = size / FW_8192C_PAGE_SIZE; 48 remainsize = size % FW_8192C_PAGE_SIZE; 49 50 if (pagenums > 8) 51 pr_err("Page numbers should not greater then 8\n"); 52 53 for (page = 0; page < pagenums; page++) { 54 offset = page * FW_8192C_PAGE_SIZE; 55 rtl_fw_page_write(hw, page, (bufferptr + offset), 56 FW_8192C_PAGE_SIZE); 57 } 58 59 if (remainsize) { 60 offset = pagenums * FW_8192C_PAGE_SIZE; 61 page = pagenums; 62 rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize); 63 } 64 } 65 66 static int _rtl88e_fw_free_to_go(struct ieee80211_hw *hw) 67 { 68 struct rtl_priv *rtlpriv = rtl_priv(hw); 69 int err = -EIO; 70 u32 counter = 0; 71 u32 value32; 72 73 do { 74 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); 75 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) && 76 (!(value32 & FWDL_CHKSUM_RPT))); 77 78 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) { 79 pr_err("chksum report fail! REG_MCUFWDL:0x%08x .\n", 80 value32); 81 goto exit; 82 } 83 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); 84 value32 |= MCUFWDL_RDY; 85 value32 &= ~WINTINI_RDY; 86 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); 87 88 rtl88e_firmware_selfreset(hw); 89 counter = 0; 90 91 do { 92 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); 93 if (value32 & WINTINI_RDY) 94 return 0; 95 96 udelay(FW_8192C_POLLING_DELAY); 97 98 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT); 99 100 pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", 101 value32); 102 103 exit: 104 return err; 105 } 106 107 int rtl88e_download_fw(struct ieee80211_hw *hw, 108 bool buse_wake_on_wlan_fw) 109 { 110 struct rtl_priv *rtlpriv = rtl_priv(hw); 111 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 112 struct rtlwifi_firmware_header *pfwheader; 113 u8 *pfwdata; 114 u32 fwsize; 115 int err; 116 enum version_8188e version = rtlhal->version; 117 118 if (!rtlhal->pfirmware) 119 return 1; 120 121 pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware; 122 rtlhal->fw_version = le16_to_cpu(pfwheader->version); 123 rtlhal->fw_subversion = pfwheader->subversion; 124 pfwdata = rtlhal->pfirmware; 125 fwsize = rtlhal->fwsize; 126 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, 127 "normal Firmware SIZE %d\n", fwsize); 128 129 if (IS_FW_HEADER_EXIST(pfwheader)) { 130 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, 131 "Firmware Version(%d), Signature(%#x), Size(%d)\n", 132 pfwheader->version, pfwheader->signature, 133 (int)sizeof(struct rtlwifi_firmware_header)); 134 135 pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header); 136 fwsize = fwsize - sizeof(struct rtlwifi_firmware_header); 137 } 138 139 if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) { 140 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); 141 rtl88e_firmware_selfreset(hw); 142 } 143 _rtl88e_enable_fw_download(hw, true); 144 _rtl88e_write_fw(hw, version, pfwdata, fwsize); 145 _rtl88e_enable_fw_download(hw, false); 146 147 err = _rtl88e_fw_free_to_go(hw); 148 if (err) 149 pr_err("Firmware is not ready to run!\n"); 150 151 return 0; 152 } 153 154 static bool _rtl88e_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum) 155 { 156 struct rtl_priv *rtlpriv = rtl_priv(hw); 157 u8 val_hmetfr; 158 159 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); 160 if (((val_hmetfr >> boxnum) & BIT(0)) == 0) 161 return true; 162 return false; 163 } 164 165 static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw, 166 u8 element_id, u32 cmd_len, 167 u8 *cmd_b) 168 { 169 struct rtl_priv *rtlpriv = rtl_priv(hw); 170 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 171 u8 boxnum; 172 u16 box_reg = 0, box_extreg = 0; 173 u8 u1b_tmp; 174 bool isfw_read = false; 175 u8 buf_index = 0; 176 bool write_sucess = false; 177 u8 wait_h2c_limmit = 100; 178 u8 wait_writeh2c_limit = 100; 179 u8 boxcontent[4], boxextcontent[4]; 180 u32 h2c_waitcounter = 0; 181 unsigned long flag; 182 u8 idx; 183 184 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); 185 186 while (true) { 187 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); 188 if (rtlhal->h2c_setinprogress) { 189 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 190 "H2C set in progress! Wait to set..element_id(%d).\n", 191 element_id); 192 193 while (rtlhal->h2c_setinprogress) { 194 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, 195 flag); 196 h2c_waitcounter++; 197 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 198 "Wait 100 us (%d times)...\n", 199 h2c_waitcounter); 200 udelay(100); 201 202 if (h2c_waitcounter > 1000) 203 return; 204 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, 205 flag); 206 } 207 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 208 } else { 209 rtlhal->h2c_setinprogress = true; 210 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 211 break; 212 } 213 } 214 215 while (!write_sucess) { 216 wait_writeh2c_limit--; 217 if (wait_writeh2c_limit == 0) { 218 pr_err("Write H2C fail because no trigger for FW INT!\n"); 219 break; 220 } 221 222 boxnum = rtlhal->last_hmeboxnum; 223 switch (boxnum) { 224 case 0: 225 box_reg = REG_HMEBOX_0; 226 box_extreg = REG_HMEBOX_EXT_0; 227 break; 228 case 1: 229 box_reg = REG_HMEBOX_1; 230 box_extreg = REG_HMEBOX_EXT_1; 231 break; 232 case 2: 233 box_reg = REG_HMEBOX_2; 234 box_extreg = REG_HMEBOX_EXT_2; 235 break; 236 case 3: 237 box_reg = REG_HMEBOX_3; 238 box_extreg = REG_HMEBOX_EXT_3; 239 break; 240 default: 241 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, 242 "switch case %#x not processed\n", boxnum); 243 break; 244 } 245 isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum); 246 while (!isfw_read) { 247 wait_h2c_limmit--; 248 if (wait_h2c_limmit == 0) { 249 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 250 "Waiting too long for FW read clear HMEBox(%d)!\n", 251 boxnum); 252 break; 253 } 254 255 udelay(10); 256 257 isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum); 258 u1b_tmp = rtl_read_byte(rtlpriv, 0x130); 259 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 260 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n", 261 boxnum, u1b_tmp); 262 } 263 264 if (!isfw_read) { 265 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 266 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", 267 boxnum); 268 break; 269 } 270 271 memset(boxcontent, 0, sizeof(boxcontent)); 272 memset(boxextcontent, 0, sizeof(boxextcontent)); 273 boxcontent[0] = element_id; 274 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 275 "Write element_id box_reg(%4x) = %2x\n", 276 box_reg, element_id); 277 278 switch (cmd_len) { 279 case 1: 280 case 2: 281 case 3: 282 /*boxcontent[0] &= ~(BIT(7));*/ 283 memcpy((u8 *)(boxcontent) + 1, 284 cmd_b + buf_index, cmd_len); 285 286 for (idx = 0; idx < 4; idx++) { 287 rtl_write_byte(rtlpriv, box_reg + idx, 288 boxcontent[idx]); 289 } 290 break; 291 case 4: 292 case 5: 293 case 6: 294 case 7: 295 /*boxcontent[0] |= (BIT(7));*/ 296 memcpy((u8 *)(boxextcontent), 297 cmd_b + buf_index+3, cmd_len-3); 298 memcpy((u8 *)(boxcontent) + 1, 299 cmd_b + buf_index, 3); 300 301 for (idx = 0; idx < 2; idx++) { 302 rtl_write_byte(rtlpriv, box_extreg + idx, 303 boxextcontent[idx]); 304 } 305 306 for (idx = 0; idx < 4; idx++) { 307 rtl_write_byte(rtlpriv, box_reg + idx, 308 boxcontent[idx]); 309 } 310 break; 311 default: 312 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, 313 "switch case %#x not processed\n", cmd_len); 314 break; 315 } 316 317 write_sucess = true; 318 319 rtlhal->last_hmeboxnum = boxnum + 1; 320 if (rtlhal->last_hmeboxnum == 4) 321 rtlhal->last_hmeboxnum = 0; 322 323 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 324 "pHalData->last_hmeboxnum = %d\n", 325 rtlhal->last_hmeboxnum); 326 } 327 328 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); 329 rtlhal->h2c_setinprogress = false; 330 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 331 332 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); 333 } 334 335 void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw, 336 u8 element_id, u32 cmd_len, u8 *cmdbuffer) 337 { 338 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 339 u32 tmp_cmdbuf[2]; 340 341 if (!rtlhal->fw_ready) { 342 WARN_ONCE(true, 343 "rtl8188ee: error H2C cmd because of Fw download fail!!!\n"); 344 return; 345 } 346 347 memset(tmp_cmdbuf, 0, 8); 348 memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); 349 _rtl88e_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); 350 351 return; 352 } 353 354 void rtl88e_firmware_selfreset(struct ieee80211_hw *hw) 355 { 356 u8 u1b_tmp; 357 struct rtl_priv *rtlpriv = rtl_priv(hw); 358 359 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); 360 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2)))); 361 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp | BIT(2))); 362 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, 363 "8051Reset88E(): 8051 reset success\n"); 364 365 } 366 367 void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) 368 { 369 struct rtl_priv *rtlpriv = rtl_priv(hw); 370 u8 u1_h2c_set_pwrmode[H2C_88E_PWEMODE_LENGTH] = { 0 }; 371 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 372 u8 rlbm, power_state = 0; 373 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); 374 375 set_h2ccmd_pwrmode_parm_mode(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); 376 rlbm = 0;/*YJ, temp, 120316. FW now not support RLBM=2.*/ 377 set_h2ccmd_pwrmode_parm_rlbm(u1_h2c_set_pwrmode, rlbm); 378 set_h2ccmd_pwrmode_parm_smart_ps(u1_h2c_set_pwrmode, 379 (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1); 380 set_h2ccmd_pwrmode_parm_awake_interval(u1_h2c_set_pwrmode, 381 ppsc->reg_max_lps_awakeintvl); 382 set_h2ccmd_pwrmode_parm_all_queue_uapsd(u1_h2c_set_pwrmode, 0); 383 if (mode == FW_PS_ACTIVE_MODE) 384 power_state |= FW_PWR_STATE_ACTIVE; 385 else 386 power_state |= FW_PWR_STATE_RF_OFF; 387 388 set_h2ccmd_pwrmode_parm_pwr_state(u1_h2c_set_pwrmode, power_state); 389 390 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 391 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", 392 u1_h2c_set_pwrmode, H2C_88E_PWEMODE_LENGTH); 393 rtl88e_fill_h2c_cmd(hw, H2C_88E_SETPWRMODE, 394 H2C_88E_PWEMODE_LENGTH, u1_h2c_set_pwrmode); 395 } 396 397 void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) 398 { 399 u8 u1_joinbssrpt_parm[1] = { 0 }; 400 401 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus); 402 403 rtl88e_fill_h2c_cmd(hw, H2C_88E_JOINBSSRPT, 1, u1_joinbssrpt_parm); 404 } 405 406 void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw, 407 u8 ap_offload_enable) 408 { 409 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 410 u8 u1_apoffload_parm[H2C_88E_AP_OFFLOAD_LENGTH] = { 0 }; 411 412 SET_H2CCMD_AP_OFFLOAD_ON(u1_apoffload_parm, ap_offload_enable); 413 SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid); 414 SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0); 415 416 rtl88e_fill_h2c_cmd(hw, H2C_88E_AP_OFFLOAD, 417 H2C_88E_AP_OFFLOAD_LENGTH, u1_apoffload_parm); 418 419 } 420 421 #define BEACON_PG 0 /* ->1 */ 422 #define PSPOLL_PG 2 423 #define NULL_PG 3 424 #define PROBERSP_PG 4 /* ->5 */ 425 426 #define TOTAL_RESERVED_PKT_LEN 768 427 428 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { 429 /* page 0 beacon */ 430 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 431 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 432 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08, 433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 434 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, 435 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, 436 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, 437 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, 438 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, 439 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, 440 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, 444 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 445 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 446 447 /* page 1 beacon */ 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 460 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00, 461 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 462 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 464 465 /* page 2 ps-poll */ 466 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10, 467 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 476 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 478 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, 479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 480 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 482 483 /* page 3 null */ 484 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, 485 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 486 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 494 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 496 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, 497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 498 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 500 501 /* page 4 probe_resp */ 502 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, 503 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 504 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 505 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, 506 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, 507 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, 508 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, 509 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, 510 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, 511 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, 512 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 515 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, 516 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 518 519 /* page 5 probe_resp */ 520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 523 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 532 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 535 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 536 }; 537 538 void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) 539 { 540 struct rtl_priv *rtlpriv = rtl_priv(hw); 541 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 542 struct sk_buff *skb = NULL; 543 u32 totalpacketlen; 544 bool rtstatus; 545 u8 u1rsvdpageloc[5] = { 0 }; 546 bool b_dlok = false; 547 u8 *beacon; 548 u8 *p_pspoll; 549 u8 *nullfunc; 550 u8 *p_probersp; 551 552 /*--------------------------------------------------------- 553 * (1) beacon 554 *--------------------------------------------------------- 555 */ 556 beacon = &reserved_page_packet[BEACON_PG * 128]; 557 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); 558 SET_80211_HDR_ADDRESS3(beacon, mac->bssid); 559 560 /*------------------------------------------------------- 561 * (2) ps-poll 562 *-------------------------------------------------------- 563 */ 564 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; 565 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); 566 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); 567 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); 568 569 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); 570 571 /*-------------------------------------------------------- 572 * (3) null data 573 *--------------------------------------------------------- 574 */ 575 nullfunc = &reserved_page_packet[NULL_PG * 128]; 576 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); 577 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); 578 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); 579 580 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); 581 582 /*--------------------------------------------------------- 583 * (4) probe response 584 *---------------------------------------------------------- 585 */ 586 p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; 587 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); 588 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); 589 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); 590 591 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); 592 593 totalpacketlen = TOTAL_RESERVED_PKT_LEN; 594 595 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, 596 "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 597 &reserved_page_packet[0], totalpacketlen); 598 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 599 "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 600 u1rsvdpageloc, 3); 601 602 skb = dev_alloc_skb(totalpacketlen); 603 if (!skb) 604 return; 605 skb_put_data(skb, &reserved_page_packet, totalpacketlen); 606 607 rtstatus = rtl_cmd_send_packet(hw, skb); 608 609 if (rtstatus) 610 b_dlok = true; 611 612 if (b_dlok) { 613 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, 614 "Set RSVD page location to Fw.\n"); 615 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 616 "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3); 617 rtl88e_fill_h2c_cmd(hw, H2C_88E_RSVDPAGE, 618 sizeof(u1rsvdpageloc), u1rsvdpageloc); 619 } else 620 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, 621 "Set RSVD page location to Fw FAIL!!!!!!.\n"); 622 } 623 624 /*Should check FW support p2p or not.*/ 625 static void rtl88e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow) 626 { 627 u8 u1_ctwindow_period[1] = { ctwindow}; 628 629 rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); 630 631 } 632 633 void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) 634 { 635 struct rtl_priv *rtlpriv = rtl_priv(hw); 636 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); 637 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 638 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); 639 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; 640 u8 i; 641 u16 ctwindow; 642 u32 start_time, tsf_low; 643 644 switch (p2p_ps_state) { 645 case P2P_PS_DISABLE: 646 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); 647 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); 648 break; 649 case P2P_PS_ENABLE: 650 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); 651 /* update CTWindow value. */ 652 if (p2pinfo->ctwindow > 0) { 653 p2p_ps_offload->ctwindow_en = 1; 654 ctwindow = p2pinfo->ctwindow; 655 rtl88e_set_p2p_ctw_period_cmd(hw, ctwindow); 656 } 657 658 /* hw only support 2 set of NoA */ 659 for (i = 0 ; i < p2pinfo->noa_num; i++) { 660 /* To control the register setting for which NOA*/ 661 rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); 662 if (i == 0) 663 p2p_ps_offload->noa0_en = 1; 664 else 665 p2p_ps_offload->noa1_en = 1; 666 667 /* config P2P NoA Descriptor Register */ 668 rtl_write_dword(rtlpriv, 0x5E0, 669 p2pinfo->noa_duration[i]); 670 rtl_write_dword(rtlpriv, 0x5E4, 671 p2pinfo->noa_interval[i]); 672 673 /*Get Current TSF value */ 674 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); 675 676 start_time = p2pinfo->noa_start_time[i]; 677 if (p2pinfo->noa_count_type[i] != 1) { 678 while (start_time <= (tsf_low+(50*1024))) { 679 start_time += p2pinfo->noa_interval[i]; 680 if (p2pinfo->noa_count_type[i] != 255) 681 p2pinfo->noa_count_type[i]--; 682 } 683 } 684 rtl_write_dword(rtlpriv, 0x5E8, start_time); 685 rtl_write_dword(rtlpriv, 0x5EC, 686 p2pinfo->noa_count_type[i]); 687 } 688 689 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { 690 /* rst p2p circuit */ 691 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); 692 693 p2p_ps_offload->offload_en = 1; 694 695 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { 696 p2p_ps_offload->role = 1; 697 p2p_ps_offload->allstasleep = -1; 698 } else { 699 p2p_ps_offload->role = 0; 700 } 701 702 p2p_ps_offload->discovery = 0; 703 } 704 break; 705 case P2P_PS_SCAN: 706 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); 707 p2p_ps_offload->discovery = 1; 708 break; 709 case P2P_PS_SCAN_DONE: 710 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); 711 p2p_ps_offload->discovery = 0; 712 p2pinfo->p2p_ps_state = P2P_PS_ENABLE; 713 break; 714 default: 715 break; 716 } 717 718 rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_OFFLOAD, 1, 719 (u8 *)p2p_ps_offload); 720 721 } 722