1 /******************************************************************************
3 * Copyright(c) 2009-2013 Realtek Corporation.
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.
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
14 * The full GNU General Public License is included in this distribution in the
15 * file called LICENSE.
17 * Contact Information:
18 * wlanfae <wlanfae@realtek.com>
19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20 * Hsinchu 300, Taiwan.
22 * Larry Finger <Larry.Finger@lwfinger.net>
24 *****************************************************************************/
35 static void _rtl88e_enable_fw_download(struct ieee80211_hw *hw, bool enable)
37 struct rtl_priv *rtlpriv = rtl_priv(hw);
41 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
42 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
44 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
45 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
47 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
48 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
50 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
51 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
53 rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
57 static void _rtl88e_write_fw(struct ieee80211_hw *hw,
58 enum version_8188e version, u8 *buffer, u32 size)
60 struct rtl_priv *rtlpriv = rtl_priv(hw);
61 u8 *bufferptr = (u8 *)buffer;
62 u32 pagenums, remainsize;
65 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size);
67 rtl_fill_dummy(bufferptr, &size);
69 pagenums = size / FW_8192C_PAGE_SIZE;
70 remainsize = size % FW_8192C_PAGE_SIZE;
73 pr_err("Page numbers should not greater then 8\n");
75 for (page = 0; page < pagenums; page++) {
76 offset = page * FW_8192C_PAGE_SIZE;
77 rtl_fw_page_write(hw, page, (bufferptr + offset),
82 offset = pagenums * FW_8192C_PAGE_SIZE;
84 rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize);
88 static int _rtl88e_fw_free_to_go(struct ieee80211_hw *hw)
90 struct rtl_priv *rtlpriv = rtl_priv(hw);
96 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
97 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
98 (!(value32 & FWDL_CHKSUM_RPT)));
100 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
101 pr_err("chksum report fail! REG_MCUFWDL:0x%08x .\n",
105 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
106 value32 |= MCUFWDL_RDY;
107 value32 &= ~WINTINI_RDY;
108 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
110 rtl88e_firmware_selfreset(hw);
114 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
115 if (value32 & WINTINI_RDY)
118 udelay(FW_8192C_POLLING_DELAY);
120 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
122 pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n",
129 int rtl88e_download_fw(struct ieee80211_hw *hw,
130 bool buse_wake_on_wlan_fw)
132 struct rtl_priv *rtlpriv = rtl_priv(hw);
133 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
134 struct rtlwifi_firmware_header *pfwheader;
138 enum version_8188e version = rtlhal->version;
140 if (!rtlhal->pfirmware)
143 pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
144 pfwdata = rtlhal->pfirmware;
145 fwsize = rtlhal->fwsize;
146 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
147 "normal Firmware SIZE %d\n", fwsize);
149 if (IS_FW_HEADER_EXIST(pfwheader)) {
150 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
151 "Firmware Version(%d), Signature(%#x), Size(%d)\n",
152 pfwheader->version, pfwheader->signature,
153 (int)sizeof(struct rtlwifi_firmware_header));
155 pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
156 fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
159 if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
160 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
161 rtl88e_firmware_selfreset(hw);
163 _rtl88e_enable_fw_download(hw, true);
164 _rtl88e_write_fw(hw, version, pfwdata, fwsize);
165 _rtl88e_enable_fw_download(hw, false);
167 err = _rtl88e_fw_free_to_go(hw);
169 pr_err("Firmware is not ready to run!\n");
174 static bool _rtl88e_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
176 struct rtl_priv *rtlpriv = rtl_priv(hw);
179 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
180 if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
185 static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw,
186 u8 element_id, u32 cmd_len,
189 struct rtl_priv *rtlpriv = rtl_priv(hw);
190 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
192 u16 box_reg = 0, box_extreg = 0;
194 bool isfw_read = false;
196 bool write_sucess = false;
197 u8 wait_h2c_limmit = 100;
198 u8 wait_writeh2c_limit = 100;
199 u8 boxcontent[4], boxextcontent[4];
200 u32 h2c_waitcounter = 0;
204 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
207 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
208 if (rtlhal->h2c_setinprogress) {
209 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
210 "H2C set in progress! Wait to set..element_id(%d).\n",
213 while (rtlhal->h2c_setinprogress) {
214 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
217 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
218 "Wait 100 us (%d times)...\n",
222 if (h2c_waitcounter > 1000)
224 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
227 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
229 rtlhal->h2c_setinprogress = true;
230 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
235 while (!write_sucess) {
236 wait_writeh2c_limit--;
237 if (wait_writeh2c_limit == 0) {
238 pr_err("Write H2C fail because no trigger for FW INT!\n");
242 boxnum = rtlhal->last_hmeboxnum;
245 box_reg = REG_HMEBOX_0;
246 box_extreg = REG_HMEBOX_EXT_0;
249 box_reg = REG_HMEBOX_1;
250 box_extreg = REG_HMEBOX_EXT_1;
253 box_reg = REG_HMEBOX_2;
254 box_extreg = REG_HMEBOX_EXT_2;
257 box_reg = REG_HMEBOX_3;
258 box_extreg = REG_HMEBOX_EXT_3;
261 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
262 "switch case %#x not processed\n", boxnum);
265 isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum);
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",
277 isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum);
278 u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
279 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
280 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
285 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
286 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
291 memset(boxcontent, 0, sizeof(boxcontent));
292 memset(boxextcontent, 0, sizeof(boxextcontent));
293 boxcontent[0] = element_id;
294 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
295 "Write element_id box_reg(%4x) = %2x\n",
296 box_reg, element_id);
302 /*boxcontent[0] &= ~(BIT(7));*/
303 memcpy((u8 *)(boxcontent) + 1,
304 cmd_b + buf_index, cmd_len);
306 for (idx = 0; idx < 4; idx++) {
307 rtl_write_byte(rtlpriv, box_reg + idx,
315 /*boxcontent[0] |= (BIT(7));*/
316 memcpy((u8 *)(boxextcontent),
317 cmd_b + buf_index+3, cmd_len-3);
318 memcpy((u8 *)(boxcontent) + 1,
319 cmd_b + buf_index, 3);
321 for (idx = 0; idx < 2; idx++) {
322 rtl_write_byte(rtlpriv, box_extreg + idx,
326 for (idx = 0; idx < 4; idx++) {
327 rtl_write_byte(rtlpriv, box_reg + idx,
332 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
333 "switch case %#x not processed\n", cmd_len);
339 rtlhal->last_hmeboxnum = boxnum + 1;
340 if (rtlhal->last_hmeboxnum == 4)
341 rtlhal->last_hmeboxnum = 0;
343 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
344 "pHalData->last_hmeboxnum = %d\n",
345 rtlhal->last_hmeboxnum);
348 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
349 rtlhal->h2c_setinprogress = false;
350 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
352 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
355 void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw,
356 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
358 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
361 if (!rtlhal->fw_ready) {
363 "rtl8188ee: error H2C cmd because of Fw download fail!!!\n");
367 memset(tmp_cmdbuf, 0, 8);
368 memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
369 _rtl88e_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
374 void rtl88e_firmware_selfreset(struct ieee80211_hw *hw)
377 struct rtl_priv *rtlpriv = rtl_priv(hw);
379 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1);
380 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2))));
381 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp | BIT(2)));
382 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
383 "8051Reset88E(): 8051 reset success\n");
387 void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
389 struct rtl_priv *rtlpriv = rtl_priv(hw);
390 u8 u1_h2c_set_pwrmode[H2C_88E_PWEMODE_LENGTH] = { 0 };
391 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
392 u8 rlbm, power_state = 0;
393 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
395 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
396 rlbm = 0;/*YJ, temp, 120316. FW now not support RLBM=2.*/
397 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
398 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
399 (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1);
400 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
401 ppsc->reg_max_lps_awakeintvl);
402 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
403 if (mode == FW_PS_ACTIVE_MODE)
404 power_state |= FW_PWR_STATE_ACTIVE;
406 power_state |= FW_PWR_STATE_RF_OFF;
408 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
410 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
411 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
412 u1_h2c_set_pwrmode, H2C_88E_PWEMODE_LENGTH);
413 rtl88e_fill_h2c_cmd(hw, H2C_88E_SETPWRMODE,
414 H2C_88E_PWEMODE_LENGTH, u1_h2c_set_pwrmode);
417 void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
419 u8 u1_joinbssrpt_parm[1] = { 0 };
421 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
423 rtl88e_fill_h2c_cmd(hw, H2C_88E_JOINBSSRPT, 1, u1_joinbssrpt_parm);
426 void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw,
427 u8 ap_offload_enable)
429 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
430 u8 u1_apoffload_parm[H2C_88E_AP_OFFLOAD_LENGTH] = { 0 };
432 SET_H2CCMD_AP_OFFLOAD_ON(u1_apoffload_parm, ap_offload_enable);
433 SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid);
434 SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0);
436 rtl88e_fill_h2c_cmd(hw, H2C_88E_AP_OFFLOAD,
437 H2C_88E_AP_OFFLOAD_LENGTH, u1_apoffload_parm);
441 #define BEACON_PG 0 /* ->1 */
444 #define PROBERSP_PG 4 /* ->5 */
446 #define TOTAL_RESERVED_PKT_LEN 768
448 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
450 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
451 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
452 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
455 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
456 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
457 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
458 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
459 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
460 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
461 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
463 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
464 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
476 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
480 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
486 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
487 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
488 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
492 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
493 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
494 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
496 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
498 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
500 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
501 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
504 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
505 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
506 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
516 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
518 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521 /* page 4 probe_resp */
522 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
523 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
524 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
525 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
526 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
527 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
528 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
529 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
530 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
531 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
532 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
536 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
537 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539 /* page 5 probe_resp */
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 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
549 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
550 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
551 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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,
558 void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
560 struct rtl_priv *rtlpriv = rtl_priv(hw);
561 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
562 struct sk_buff *skb = NULL;
565 u8 u1rsvdpageloc[5] = { 0 };
572 /*---------------------------------------------------------
574 *---------------------------------------------------------
576 beacon = &reserved_page_packet[BEACON_PG * 128];
577 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
578 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
580 /*-------------------------------------------------------
582 *--------------------------------------------------------
584 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
585 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
586 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
587 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
589 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
591 /*--------------------------------------------------------
593 *---------------------------------------------------------
595 nullfunc = &reserved_page_packet[NULL_PG * 128];
596 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
597 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
598 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
600 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
602 /*---------------------------------------------------------
604 *----------------------------------------------------------
606 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
607 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
608 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
609 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
611 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
613 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
615 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
616 "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
617 &reserved_page_packet[0], totalpacketlen);
618 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
619 "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
622 skb = dev_alloc_skb(totalpacketlen);
625 skb_put_data(skb, &reserved_page_packet, totalpacketlen);
627 rtstatus = rtl_cmd_send_packet(hw, skb);
633 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
634 "Set RSVD page location to Fw.\n");
635 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
636 "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
637 rtl88e_fill_h2c_cmd(hw, H2C_88E_RSVDPAGE,
638 sizeof(u1rsvdpageloc), u1rsvdpageloc);
640 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
641 "Set RSVD page location to Fw FAIL!!!!!!.\n");
644 /*Should check FW support p2p or not.*/
645 static void rtl88e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
647 u8 u1_ctwindow_period[1] = { ctwindow};
649 rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
653 void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
655 struct rtl_priv *rtlpriv = rtl_priv(hw);
656 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
657 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
658 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
659 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
662 u32 start_time, tsf_low;
664 switch (p2p_ps_state) {
666 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
667 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
670 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
671 /* update CTWindow value. */
672 if (p2pinfo->ctwindow > 0) {
673 p2p_ps_offload->ctwindow_en = 1;
674 ctwindow = p2pinfo->ctwindow;
675 rtl88e_set_p2p_ctw_period_cmd(hw, ctwindow);
678 /* hw only support 2 set of NoA */
679 for (i = 0 ; i < p2pinfo->noa_num; i++) {
680 /* To control the register setting for which NOA*/
681 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
683 p2p_ps_offload->noa0_en = 1;
685 p2p_ps_offload->noa1_en = 1;
687 /* config P2P NoA Descriptor Register */
688 rtl_write_dword(rtlpriv, 0x5E0,
689 p2pinfo->noa_duration[i]);
690 rtl_write_dword(rtlpriv, 0x5E4,
691 p2pinfo->noa_interval[i]);
693 /*Get Current TSF value */
694 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
696 start_time = p2pinfo->noa_start_time[i];
697 if (p2pinfo->noa_count_type[i] != 1) {
698 while (start_time <= (tsf_low+(50*1024))) {
699 start_time += p2pinfo->noa_interval[i];
700 if (p2pinfo->noa_count_type[i] != 255)
701 p2pinfo->noa_count_type[i]--;
704 rtl_write_dword(rtlpriv, 0x5E8, start_time);
705 rtl_write_dword(rtlpriv, 0x5EC,
706 p2pinfo->noa_count_type[i]);
709 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
710 /* rst p2p circuit */
711 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
713 p2p_ps_offload->offload_en = 1;
715 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
716 p2p_ps_offload->role = 1;
717 p2p_ps_offload->allstasleep = -1;
719 p2p_ps_offload->role = 0;
722 p2p_ps_offload->discovery = 0;
726 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
727 p2p_ps_offload->discovery = 1;
729 case P2P_PS_SCAN_DONE:
730 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
731 p2p_ps_offload->discovery = 0;
732 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
738 rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_OFFLOAD, 1,
739 (u8 *)p2p_ps_offload);