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 "../efuse.h" 9 #include "reg.h" 10 #include "def.h" 11 #include "fw.h" 12 #include "dm.h" 13 14 static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable) 15 { 16 struct rtl_priv *rtlpriv = rtl_priv(hw); 17 u8 tmp; 18 19 if (enable) { 20 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05); 21 22 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); 23 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); 24 } else { 25 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); 26 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); 27 } 28 } 29 30 static void _rtl92ee_write_fw(struct ieee80211_hw *hw, 31 enum version_8192e version, 32 u8 *buffer, u32 size) 33 { 34 struct rtl_priv *rtlpriv = rtl_priv(hw); 35 u8 *bufferptr = (u8 *)buffer; 36 u32 pagenums, remainsize; 37 u32 page, offset; 38 39 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "FW size is %d bytes,\n", size); 40 41 rtl_fill_dummy(bufferptr, &size); 42 43 pagenums = size / FW_8192C_PAGE_SIZE; 44 remainsize = size % FW_8192C_PAGE_SIZE; 45 46 if (pagenums > 8) 47 pr_err("Page numbers should not greater then 8\n"); 48 49 for (page = 0; page < pagenums; page++) { 50 offset = page * FW_8192C_PAGE_SIZE; 51 rtl_fw_page_write(hw, page, (bufferptr + offset), 52 FW_8192C_PAGE_SIZE); 53 udelay(2); 54 } 55 56 if (remainsize) { 57 offset = pagenums * FW_8192C_PAGE_SIZE; 58 page = pagenums; 59 rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize); 60 } 61 } 62 63 static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw) 64 { 65 struct rtl_priv *rtlpriv = rtl_priv(hw); 66 int err = -EIO; 67 u32 counter = 0; 68 u32 value32; 69 70 do { 71 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); 72 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) && 73 (!(value32 & FWDL_CHKSUM_RPT))); 74 75 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) { 76 pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n", 77 value32); 78 goto exit; 79 } 80 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); 81 value32 |= MCUFWDL_RDY; 82 value32 &= ~WINTINI_RDY; 83 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); 84 85 rtl92ee_firmware_selfreset(hw); 86 counter = 0; 87 88 do { 89 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); 90 if (value32 & WINTINI_RDY) 91 return 0; 92 93 udelay(FW_8192C_POLLING_DELAY*10); 94 95 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT); 96 97 pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n", 98 value32, counter); 99 100 exit: 101 return err; 102 } 103 104 int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw) 105 { 106 struct rtl_priv *rtlpriv = rtl_priv(hw); 107 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 108 struct rtlwifi_firmware_header *pfwheader; 109 u8 *pfwdata; 110 u32 fwsize; 111 int err; 112 enum version_8192e version = rtlhal->version; 113 114 if (!rtlhal->pfirmware) 115 return 1; 116 117 pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware; 118 rtlhal->fw_version = le16_to_cpu(pfwheader->version); 119 rtlhal->fw_subversion = pfwheader->subversion; 120 pfwdata = (u8 *)rtlhal->pfirmware; 121 fwsize = rtlhal->fwsize; 122 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, 123 "normal Firmware SIZE %d\n" , fwsize); 124 125 if (IS_FW_HEADER_EXIST(pfwheader)) { 126 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, 127 "Firmware Version(%d), Signature(%#x),Size(%d)\n", 128 pfwheader->version, pfwheader->signature, 129 (int)sizeof(struct rtlwifi_firmware_header)); 130 131 pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header); 132 fwsize = fwsize - sizeof(struct rtlwifi_firmware_header); 133 } else { 134 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, 135 "Firmware no Header, Signature(%#x)\n", 136 pfwheader->signature); 137 } 138 139 if (rtlhal->mac_func_enable) { 140 if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) { 141 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); 142 rtl92ee_firmware_selfreset(hw); 143 } 144 } 145 _rtl92ee_enable_fw_download(hw, true); 146 _rtl92ee_write_fw(hw, version, pfwdata, fwsize); 147 _rtl92ee_enable_fw_download(hw, false); 148 149 err = _rtl92ee_fw_free_to_go(hw); 150 151 return 0; 152 } 153 154 static bool _rtl92ee_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 bool result = false; 159 160 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); 161 if (((val_hmetfr >> boxnum) & BIT(0)) == 0) 162 result = true; 163 return result; 164 } 165 166 static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id, 167 u32 cmd_len, u8 *cmdbuffer) 168 { 169 struct rtl_priv *rtlpriv = rtl_priv(hw); 170 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 171 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 172 u8 boxnum; 173 u16 box_reg = 0, box_extreg = 0; 174 u8 u1b_tmp; 175 bool isfw_read = false; 176 u8 buf_index = 0; 177 bool bwrite_sucess = false; 178 u8 wait_h2c_limmit = 100; 179 u8 boxcontent[4], boxextcontent[4]; 180 u32 h2c_waitcounter = 0; 181 unsigned long flag; 182 u8 idx; 183 184 if (ppsc->dot11_psmode != EACTIVE || 185 ppsc->inactive_pwrstate == ERFOFF) { 186 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , 187 "FillH2CCommand8192E(): Return because RF is off!!!\n"); 188 return; 189 } 190 191 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "come in\n"); 192 193 /* 1. Prevent race condition in setting H2C cmd. 194 * (copy from MgntActSet_RF_State().) 195 */ 196 while (true) { 197 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); 198 if (rtlhal->h2c_setinprogress) { 199 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , 200 "H2C set in progress! Wait to set..element_id(%d).\n", 201 element_id); 202 203 while (rtlhal->h2c_setinprogress) { 204 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, 205 flag); 206 h2c_waitcounter++; 207 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , 208 "Wait 100 us (%d times)...\n", 209 h2c_waitcounter); 210 udelay(100); 211 212 if (h2c_waitcounter > 1000) 213 return; 214 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, 215 flag); 216 } 217 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 218 } else { 219 rtlhal->h2c_setinprogress = true; 220 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 221 break; 222 } 223 } 224 225 while (!bwrite_sucess) { 226 /* 2. Find the last BOX number which has been writen. */ 227 boxnum = rtlhal->last_hmeboxnum; 228 switch (boxnum) { 229 case 0: 230 box_reg = REG_HMEBOX_0; 231 box_extreg = REG_HMEBOX_EXT_0; 232 break; 233 case 1: 234 box_reg = REG_HMEBOX_1; 235 box_extreg = REG_HMEBOX_EXT_1; 236 break; 237 case 2: 238 box_reg = REG_HMEBOX_2; 239 box_extreg = REG_HMEBOX_EXT_2; 240 break; 241 case 3: 242 box_reg = REG_HMEBOX_3; 243 box_extreg = REG_HMEBOX_EXT_3; 244 break; 245 default: 246 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, 247 "switch case %#x not processed\n", boxnum); 248 break; 249 } 250 251 /* 3. Check if the box content is empty. */ 252 isfw_read = false; 253 u1b_tmp = rtl_read_byte(rtlpriv, REG_CR); 254 255 if (u1b_tmp != 0xea) { 256 isfw_read = true; 257 } else { 258 if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea || 259 rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea) 260 rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff); 261 } 262 263 if (isfw_read) { 264 wait_h2c_limmit = 100; 265 isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum); 266 while (!isfw_read) { 267 wait_h2c_limmit--; 268 if (wait_h2c_limmit == 0) { 269 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , 270 "Waiting too long for FW read clear HMEBox(%d)!!!\n", 271 boxnum); 272 break; 273 } 274 udelay(10); 275 isfw_read = 276 _rtl92ee_check_fw_read_last_h2c(hw, boxnum); 277 u1b_tmp = rtl_read_byte(rtlpriv, 0x130); 278 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , 279 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n", 280 boxnum, u1b_tmp); 281 } 282 } 283 284 /* If Fw has not read the last 285 * H2C cmd, break and give up this H2C. 286 */ 287 if (!isfw_read) { 288 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , 289 "Write H2C reg BOX[%d] fail,Fw don't read.\n", 290 boxnum); 291 break; 292 } 293 /* 4. Fill the H2C cmd into box */ 294 memset(boxcontent, 0, sizeof(boxcontent)); 295 memset(boxextcontent, 0, sizeof(boxextcontent)); 296 boxcontent[0] = element_id; 297 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , 298 "Write element_id box_reg(%4x) = %2x\n", 299 box_reg, element_id); 300 301 switch (cmd_len) { 302 case 1: 303 case 2: 304 case 3: 305 /*boxcontent[0] &= ~(BIT(7));*/ 306 memcpy((u8 *)(boxcontent) + 1, 307 cmdbuffer + buf_index, cmd_len); 308 309 for (idx = 0; idx < 4; idx++) { 310 rtl_write_byte(rtlpriv, box_reg + idx, 311 boxcontent[idx]); 312 } 313 break; 314 case 4: 315 case 5: 316 case 6: 317 case 7: 318 /*boxcontent[0] |= (BIT(7));*/ 319 memcpy((u8 *)(boxextcontent), 320 cmdbuffer + buf_index+3, cmd_len-3); 321 memcpy((u8 *)(boxcontent) + 1, 322 cmdbuffer + buf_index, 3); 323 324 for (idx = 0; idx < 4; idx++) { 325 rtl_write_byte(rtlpriv, box_extreg + idx, 326 boxextcontent[idx]); 327 } 328 329 for (idx = 0; idx < 4; idx++) { 330 rtl_write_byte(rtlpriv, box_reg + idx, 331 boxcontent[idx]); 332 } 333 break; 334 default: 335 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, 336 "switch case %#x not processed\n", cmd_len); 337 break; 338 } 339 340 bwrite_sucess = true; 341 342 rtlhal->last_hmeboxnum = boxnum + 1; 343 if (rtlhal->last_hmeboxnum == 4) 344 rtlhal->last_hmeboxnum = 0; 345 346 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , 347 "pHalData->last_hmeboxnum = %d\n", 348 rtlhal->last_hmeboxnum); 349 } 350 351 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); 352 rtlhal->h2c_setinprogress = false; 353 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 354 355 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "go out\n"); 356 } 357 358 void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw, 359 u8 element_id, u32 cmd_len, u8 *cmdbuffer) 360 { 361 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 362 u32 tmp_cmdbuf[2]; 363 364 if (!rtlhal->fw_ready) { 365 WARN_ONCE(true, 366 "rtl8192ee: error H2C cmd because of Fw download fail!!!\n"); 367 return; 368 } 369 370 memset(tmp_cmdbuf, 0, 8); 371 memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); 372 _rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); 373 } 374 375 void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw) 376 { 377 u8 u1b_tmp; 378 struct rtl_priv *rtlpriv = rtl_priv(hw); 379 380 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); 381 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0)))); 382 383 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 384 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2)))); 385 386 udelay(50); 387 388 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); 389 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0))); 390 391 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 392 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2))); 393 394 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD , 395 " _8051Reset92E(): 8051 reset success .\n"); 396 } 397 398 void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) 399 { 400 struct rtl_priv *rtlpriv = rtl_priv(hw); 401 u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 }; 402 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 403 u8 rlbm, power_state = 0, byte5 = 0; 404 u8 awake_intvl; /* DTIM = (awake_intvl - 1) */ 405 struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops; 406 bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ? 407 btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false); 408 bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ? 409 btc_ops->btc_is_bt_lps_on(rtlpriv) : false); 410 411 if (bt_ctrl_lps) 412 mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE); 413 414 RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n", 415 mode, bt_ctrl_lps); 416 417 switch (mode) { 418 case FW_PS_MIN_MODE: 419 rlbm = 0; 420 awake_intvl = 2; 421 break; 422 case FW_PS_MAX_MODE: 423 rlbm = 1; 424 awake_intvl = 2; 425 break; 426 case FW_PS_DTIM_MODE: 427 rlbm = 2; 428 awake_intvl = ppsc->reg_max_lps_awakeintvl; 429 /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period 430 * is only used in swlps. 431 */ 432 break; 433 default: 434 rlbm = 2; 435 awake_intvl = 4; 436 break; 437 } 438 439 if (rtlpriv->mac80211.p2p) { 440 awake_intvl = 2; 441 rlbm = 1; 442 } 443 444 if (mode == FW_PS_ACTIVE_MODE) { 445 byte5 = 0x40; 446 power_state = FW_PWR_STATE_ACTIVE; 447 } else { 448 if (bt_ctrl_lps) { 449 byte5 = btc_ops->btc_get_lps_val(rtlpriv); 450 power_state = btc_ops->btc_get_rpwm_val(rtlpriv); 451 452 if ((rlbm == 2) && (byte5 & BIT(4))) { 453 /* Keep awake interval to 1 to prevent from 454 * decreasing coex performance 455 */ 456 awake_intvl = 2; 457 rlbm = 2; 458 } 459 } else { 460 byte5 = 0x40; 461 power_state = FW_PWR_STATE_RF_OFF; 462 } 463 } 464 465 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); 466 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm); 467 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 468 bt_ctrl_lps ? 0 : 469 ((rtlpriv->mac80211.p2p) ? 470 ppsc->smart_ps : 1)); 471 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, 472 awake_intvl); 473 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); 474 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); 475 SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5); 476 477 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 478 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", 479 u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH); 480 if (rtlpriv->cfg->ops->get_btc_status()) 481 btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode, 482 H2C_92E_PWEMODE_LENGTH); 483 rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH, 484 u1_h2c_set_pwrmode); 485 } 486 487 void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus) 488 { 489 u8 parm[3] = { 0 , 0 , 0 }; 490 /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect 491 * bit1=0-->update Media Status to MACID 492 * bit1=1-->update Media Status from MACID to MACID_End 493 * parm[1]: MACID, if this is INFRA_STA, MacID = 0 494 * parm[2]: MACID_End 495 */ 496 497 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus); 498 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0); 499 500 rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm); 501 } 502 503 #define BEACON_PG 0 /* ->1 */ 504 #define PSPOLL_PG 2 505 #define NULL_PG 3 506 #define PROBERSP_PG 4 /* ->5 */ 507 #define QOS_NULL_PG 6 508 #define BT_QOS_NULL_PG 7 509 510 #define TOTAL_RESERVED_PKT_LEN 1024 511 512 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { 513 /* page 0 beacon */ 514 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 515 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 516 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00, 517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 518 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65, 519 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B, 520 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06, 521 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32, 522 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 523 0x09, 0x03, 0xFF, 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, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C, 527 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50, 528 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 529 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00, 530 531 /* page 1 beacon */ 532 0x00, 0x50, 0xF2, 0x02, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 537 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 538 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 539 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 540 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 541 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 543 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 544 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 548 549 /* page 2 ps-poll */ 550 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B, 551 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 553 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 561 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 562 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 565 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 566 567 /* page 3 null */ 568 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B, 569 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 570 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00, 571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 579 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 580 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 583 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 584 585 /* page 4 probe_resp */ 586 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, 587 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 588 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 589 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, 590 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, 591 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, 592 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, 593 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, 594 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, 595 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, 596 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 599 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, 600 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 602 603 /* page 5 probe_resp */ 604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 605 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 606 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 607 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 611 0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 612 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 615 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 616 617 /* page 6 qos null data */ 618 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, 619 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 620 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, 621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 625 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 628 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 629 0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 630 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 631 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 632 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 633 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 634 635 /* page 7 BT-qos null data */ 636 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, 637 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 638 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, 639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 656 }; 657 658 void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) 659 { 660 struct rtl_priv *rtlpriv = rtl_priv(hw); 661 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 662 struct sk_buff *skb = NULL; 663 bool rtstatus; 664 u32 totalpacketlen; 665 u8 u1rsvdpageloc[5] = { 0 }; 666 bool b_dlok = false; 667 668 u8 *beacon; 669 u8 *p_pspoll; 670 u8 *nullfunc; 671 u8 *p_probersp; 672 u8 *qosnull; 673 u8 *btqosnull; 674 /*--------------------------------------------------------- 675 * (1) beacon 676 *--------------------------------------------------------- 677 */ 678 beacon = &reserved_page_packet[BEACON_PG * 128]; 679 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); 680 SET_80211_HDR_ADDRESS3(beacon, mac->bssid); 681 682 /*------------------------------------------------------- 683 * (2) ps-poll 684 *-------------------------------------------------------- 685 */ 686 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; 687 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); 688 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); 689 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); 690 691 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); 692 693 /*-------------------------------------------------------- 694 * (3) null data 695 *--------------------------------------------------------- 696 */ 697 nullfunc = &reserved_page_packet[NULL_PG * 128]; 698 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); 699 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); 700 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); 701 702 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); 703 704 /*--------------------------------------------------------- 705 * (4) probe response 706 *---------------------------------------------------------- 707 */ 708 p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; 709 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); 710 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); 711 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); 712 713 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); 714 715 /*--------------------------------------------------------- 716 * (5) QoS null data 717 *---------------------------------------------------------- 718 */ 719 qosnull = &reserved_page_packet[QOS_NULL_PG * 128]; 720 SET_80211_HDR_ADDRESS1(qosnull, mac->bssid); 721 SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr); 722 SET_80211_HDR_ADDRESS3(qosnull, mac->bssid); 723 724 SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOS_NULL_PG); 725 726 /*--------------------------------------------------------- 727 * (6) BT QoS null data 728 *---------------------------------------------------------- 729 */ 730 btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128]; 731 SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid); 732 SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr); 733 SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid); 734 735 SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOS_NULL_PG); 736 737 totalpacketlen = TOTAL_RESERVED_PKT_LEN; 738 739 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD , 740 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 741 &reserved_page_packet[0], totalpacketlen); 742 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD , 743 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 744 u1rsvdpageloc, 3); 745 746 skb = dev_alloc_skb(totalpacketlen); 747 if (!skb) 748 return; 749 skb_put_data(skb, &reserved_page_packet, totalpacketlen); 750 751 rtstatus = rtl_cmd_send_packet(hw, skb); 752 if (rtstatus) 753 b_dlok = true; 754 755 if (b_dlok) { 756 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , 757 "Set RSVD page location to Fw.\n"); 758 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD , 759 "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3); 760 rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE, 761 sizeof(u1rsvdpageloc), u1rsvdpageloc); 762 } else { 763 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, 764 "Set RSVD page location to Fw FAIL!!!!!!.\n"); 765 } 766 } 767 768 /*Shoud check FW support p2p or not.*/ 769 static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow) 770 { 771 u8 u1_ctwindow_period[1] = {ctwindow}; 772 773 rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); 774 } 775 776 void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) 777 { 778 struct rtl_priv *rtlpriv = rtl_priv(hw); 779 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); 780 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 781 struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info; 782 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; 783 u8 i; 784 u16 ctwindow; 785 u32 start_time, tsf_low; 786 787 switch (p2p_ps_state) { 788 case P2P_PS_DISABLE: 789 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_DISABLE\n"); 790 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); 791 break; 792 case P2P_PS_ENABLE: 793 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_ENABLE\n"); 794 /* update CTWindow value. */ 795 if (p2pinfo->ctwindow > 0) { 796 p2p_ps_offload->ctwindow_en = 1; 797 ctwindow = p2pinfo->ctwindow; 798 rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow); 799 } 800 /* hw only support 2 set of NoA */ 801 for (i = 0 ; i < p2pinfo->noa_num ; i++) { 802 /* To control the register setting for which NOA*/ 803 rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); 804 if (i == 0) 805 p2p_ps_offload->noa0_en = 1; 806 else 807 p2p_ps_offload->noa1_en = 1; 808 /* config P2P NoA Descriptor Register */ 809 rtl_write_dword(rtlpriv, 0x5E0, 810 p2pinfo->noa_duration[i]); 811 rtl_write_dword(rtlpriv, 0x5E4, 812 p2pinfo->noa_interval[i]); 813 814 /*Get Current TSF value */ 815 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); 816 817 start_time = p2pinfo->noa_start_time[i]; 818 if (p2pinfo->noa_count_type[i] != 1) { 819 while (start_time <= (tsf_low + (50 * 1024))) { 820 start_time += p2pinfo->noa_interval[i]; 821 if (p2pinfo->noa_count_type[i] != 255) 822 p2pinfo->noa_count_type[i]--; 823 } 824 } 825 rtl_write_dword(rtlpriv, 0x5E8, start_time); 826 rtl_write_dword(rtlpriv, 0x5EC, 827 p2pinfo->noa_count_type[i]); 828 } 829 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { 830 /* rst p2p circuit */ 831 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); 832 p2p_ps_offload->offload_en = 1; 833 834 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { 835 p2p_ps_offload->role = 1; 836 p2p_ps_offload->allstasleep = 0; 837 } else { 838 p2p_ps_offload->role = 0; 839 } 840 p2p_ps_offload->discovery = 0; 841 } 842 break; 843 case P2P_PS_SCAN: 844 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN\n"); 845 p2p_ps_offload->discovery = 1; 846 break; 847 case P2P_PS_SCAN_DONE: 848 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN_DONE\n"); 849 p2p_ps_offload->discovery = 0; 850 p2pinfo->p2p_ps_state = P2P_PS_ENABLE; 851 break; 852 default: 853 break; 854 } 855 rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1, 856 (u8 *)p2p_ps_offload); 857 } 858 859 void rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw, 860 u8 *cmd_buf, u8 cmd_len) 861 { 862 u8 rate = cmd_buf[0] & 0x3F; 863 bool collision_state = cmd_buf[3] & BIT(0); 864 865 rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state); 866 } 867