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