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