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 #define QOS_NULL_PG 6 472 #define BT_QOS_NULL_PG 7 473 474 #define TOTAL_RESERVED_PKT_LEN 1024 475 476 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { 477 /* page 0 beacon */ 478 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 479 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 480 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00, 481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 482 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65, 483 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B, 484 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06, 485 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32, 486 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 487 0x09, 0x03, 0xFF, 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, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C, 491 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50, 492 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 493 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00, 494 495 /* page 1 beacon */ 496 0x00, 0x50, 0xF2, 0x02, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 507 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 508 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 512 513 /* page 2 ps-poll */ 514 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B, 515 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 525 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 526 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 529 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 530 531 /* page 3 null */ 532 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B, 533 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 534 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 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 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 544 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 547 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 548 549 /* page 4 probe_resp */ 550 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, 551 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 552 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 553 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, 554 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, 555 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, 556 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, 557 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, 558 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, 559 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, 560 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, 564 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 566 567 /* page 5 probe_resp */ 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 0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 576 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 579 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 580 581 /* page 6 qos null data */ 582 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, 583 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 584 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, 585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 588 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 591 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 593 0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 594 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 597 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 598 599 /* page 7 BT-qos null data */ 600 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, 601 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 602 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, 603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 616 0x00, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 620 }; 621 622 void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) 623 { 624 struct rtl_priv *rtlpriv = rtl_priv(hw); 625 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 626 struct sk_buff *skb = NULL; 627 628 u32 totalpacketlen; 629 u8 u1rsvdpageloc[5] = { 0 }; 630 bool b_dlok = false; 631 632 u8 *beacon; 633 u8 *p_pspoll; 634 u8 *nullfunc; 635 u8 *p_probersp; 636 u8 *qosnull; 637 u8 *btqosnull; 638 /*--------------------------------------------------------- 639 * (1) beacon 640 *--------------------------------------------------------- 641 */ 642 beacon = &reserved_page_packet[BEACON_PG * 128]; 643 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); 644 SET_80211_HDR_ADDRESS3(beacon, mac->bssid); 645 646 /*------------------------------------------------------- 647 * (2) ps-poll 648 *-------------------------------------------------------- 649 */ 650 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; 651 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); 652 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); 653 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); 654 655 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); 656 657 /*-------------------------------------------------------- 658 * (3) null data 659 *--------------------------------------------------------- 660 */ 661 nullfunc = &reserved_page_packet[NULL_PG * 128]; 662 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); 663 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); 664 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); 665 666 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); 667 668 /*--------------------------------------------------------- 669 * (4) probe response 670 *---------------------------------------------------------- 671 */ 672 p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; 673 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); 674 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); 675 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); 676 677 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); 678 679 /*--------------------------------------------------------- 680 * (5) QoS null data 681 *---------------------------------------------------------- 682 */ 683 qosnull = &reserved_page_packet[QOS_NULL_PG * 128]; 684 SET_80211_HDR_ADDRESS1(qosnull, mac->bssid); 685 SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr); 686 SET_80211_HDR_ADDRESS3(qosnull, mac->bssid); 687 688 SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOS_NULL_PG); 689 690 /*--------------------------------------------------------- 691 * (6) BT QoS null data 692 *---------------------------------------------------------- 693 */ 694 btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128]; 695 SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid); 696 SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr); 697 SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid); 698 699 SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOS_NULL_PG); 700 701 totalpacketlen = TOTAL_RESERVED_PKT_LEN; 702 703 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD , 704 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 705 &reserved_page_packet[0], totalpacketlen); 706 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD , 707 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 708 u1rsvdpageloc, 3); 709 710 skb = dev_alloc_skb(totalpacketlen); 711 memcpy((u8 *)skb_put(skb, totalpacketlen), 712 &reserved_page_packet, totalpacketlen); 713 714 b_dlok = true; 715 716 if (b_dlok) { 717 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , 718 "Set RSVD page location to Fw.\n"); 719 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD , 720 "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3); 721 rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE, 722 sizeof(u1rsvdpageloc), u1rsvdpageloc); 723 } else { 724 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, 725 "Set RSVD page location to Fw FAIL!!!!!!.\n"); 726 } 727 } 728 729 /*Shoud check FW support p2p or not.*/ 730 static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow) 731 { 732 u8 u1_ctwindow_period[1] = {ctwindow}; 733 734 rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); 735 } 736 737 void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) 738 { 739 struct rtl_priv *rtlpriv = rtl_priv(hw); 740 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); 741 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 742 struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info; 743 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; 744 u8 i; 745 u16 ctwindow; 746 u32 start_time, tsf_low; 747 748 switch (p2p_ps_state) { 749 case P2P_PS_DISABLE: 750 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_DISABLE\n"); 751 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); 752 break; 753 case P2P_PS_ENABLE: 754 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_ENABLE\n"); 755 /* update CTWindow value. */ 756 if (p2pinfo->ctwindow > 0) { 757 p2p_ps_offload->ctwindow_en = 1; 758 ctwindow = p2pinfo->ctwindow; 759 rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow); 760 } 761 /* hw only support 2 set of NoA */ 762 for (i = 0 ; i < p2pinfo->noa_num ; i++) { 763 /* To control the register setting for which NOA*/ 764 rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); 765 if (i == 0) 766 p2p_ps_offload->noa0_en = 1; 767 else 768 p2p_ps_offload->noa1_en = 1; 769 /* config P2P NoA Descriptor Register */ 770 rtl_write_dword(rtlpriv, 0x5E0, 771 p2pinfo->noa_duration[i]); 772 rtl_write_dword(rtlpriv, 0x5E4, 773 p2pinfo->noa_interval[i]); 774 775 /*Get Current TSF value */ 776 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); 777 778 start_time = p2pinfo->noa_start_time[i]; 779 if (p2pinfo->noa_count_type[i] != 1) { 780 while (start_time <= (tsf_low + (50 * 1024))) { 781 start_time += p2pinfo->noa_interval[i]; 782 if (p2pinfo->noa_count_type[i] != 255) 783 p2pinfo->noa_count_type[i]--; 784 } 785 } 786 rtl_write_dword(rtlpriv, 0x5E8, start_time); 787 rtl_write_dword(rtlpriv, 0x5EC, 788 p2pinfo->noa_count_type[i]); 789 } 790 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { 791 /* rst p2p circuit */ 792 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); 793 p2p_ps_offload->offload_en = 1; 794 795 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { 796 p2p_ps_offload->role = 1; 797 p2p_ps_offload->allstasleep = 0; 798 } else { 799 p2p_ps_offload->role = 0; 800 } 801 p2p_ps_offload->discovery = 0; 802 } 803 break; 804 case P2P_PS_SCAN: 805 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN\n"); 806 p2p_ps_offload->discovery = 1; 807 break; 808 case P2P_PS_SCAN_DONE: 809 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN_DONE\n"); 810 p2p_ps_offload->discovery = 0; 811 p2pinfo->p2p_ps_state = P2P_PS_ENABLE; 812 break; 813 default: 814 break; 815 } 816 rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1, 817 (u8 *)p2p_ps_offload); 818 } 819 820 static void _rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw, 821 u8 *cmd_buf, u8 cmd_len) 822 { 823 u8 rate = cmd_buf[0] & 0x3F; 824 bool collision_state = cmd_buf[3] & BIT(0); 825 826 rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state); 827 } 828 829 void rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id, 830 u8 c2h_cmd_len, u8 *tmp_buf) 831 { 832 struct rtl_priv *rtlpriv = rtl_priv(hw); 833 834 switch (c2h_cmd_id) { 835 case C2H_8192E_DBG: 836 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 837 "[C2H], C2H_8723BE_DBG!!\n"); 838 break; 839 case C2H_8192E_TXBF: 840 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 841 "[C2H], C2H_8192E_TXBF!!\n"); 842 break; 843 case C2H_8192E_TX_REPORT: 844 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE , 845 "[C2H], C2H_8723BE_TX_REPORT!\n"); 846 break; 847 case C2H_8192E_BT_INFO: 848 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 849 "[C2H], C2H_8723BE_BT_INFO!!\n"); 850 rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf, 851 c2h_cmd_len); 852 break; 853 case C2H_8192E_BT_MP: 854 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 855 "[C2H], C2H_8723BE_BT_MP!!\n"); 856 break; 857 case C2H_8192E_RA_RPT: 858 _rtl92ee_c2h_ra_report_handler(hw, tmp_buf, c2h_cmd_len); 859 break; 860 default: 861 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 862 "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id); 863 break; 864 } 865 } 866 867 void rtl92ee_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len) 868 { 869 struct rtl_priv *rtlpriv = rtl_priv(hw); 870 u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0; 871 u8 *tmp_buf = NULL; 872 873 c2h_cmd_id = buffer[0]; 874 c2h_cmd_seq = buffer[1]; 875 c2h_cmd_len = len - 2; 876 tmp_buf = buffer + 2; 877 878 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 879 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n", 880 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len); 881 882 RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE, 883 "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len); 884 885 switch (c2h_cmd_id) { 886 case C2H_8192E_BT_INFO: 887 case C2H_8192E_BT_MP: 888 rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf); 889 break; 890 default: 891 rtl92ee_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, 892 tmp_buf); 893 break; 894 } 895 } 896