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 rtlhal->fw_version = le16_to_cpu(pfwheader->version);
145 rtlhal->fw_subversion = pfwheader->subversion;
146 pfwdata = rtlhal->pfirmware;
147 fwsize = rtlhal->fwsize;
148 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
149 "normal Firmware SIZE %d\n", fwsize);
151 if (IS_FW_HEADER_EXIST(pfwheader)) {
152 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
153 "Firmware Version(%d), Signature(%#x), Size(%d)\n",
154 pfwheader->version, pfwheader->signature,
155 (int)sizeof(struct rtlwifi_firmware_header));
157 pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
158 fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
161 if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
162 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
163 rtl88e_firmware_selfreset(hw);
165 _rtl88e_enable_fw_download(hw, true);
166 _rtl88e_write_fw(hw, version, pfwdata, fwsize);
167 _rtl88e_enable_fw_download(hw, false);
169 err = _rtl88e_fw_free_to_go(hw);
171 pr_err("Firmware is not ready to run!\n");
176 static bool _rtl88e_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
178 struct rtl_priv *rtlpriv = rtl_priv(hw);
181 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
182 if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
187 static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw,
188 u8 element_id, u32 cmd_len,
191 struct rtl_priv *rtlpriv = rtl_priv(hw);
192 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
194 u16 box_reg = 0, box_extreg = 0;
196 bool isfw_read = false;
198 bool write_sucess = false;
199 u8 wait_h2c_limmit = 100;
200 u8 wait_writeh2c_limit = 100;
201 u8 boxcontent[4], boxextcontent[4];
202 u32 h2c_waitcounter = 0;
206 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
209 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
210 if (rtlhal->h2c_setinprogress) {
211 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
212 "H2C set in progress! Wait to set..element_id(%d).\n",
215 while (rtlhal->h2c_setinprogress) {
216 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
219 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
220 "Wait 100 us (%d times)...\n",
224 if (h2c_waitcounter > 1000)
226 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
229 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
231 rtlhal->h2c_setinprogress = true;
232 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
237 while (!write_sucess) {
238 wait_writeh2c_limit--;
239 if (wait_writeh2c_limit == 0) {
240 pr_err("Write H2C fail because no trigger for FW INT!\n");
244 boxnum = rtlhal->last_hmeboxnum;
247 box_reg = REG_HMEBOX_0;
248 box_extreg = REG_HMEBOX_EXT_0;
251 box_reg = REG_HMEBOX_1;
252 box_extreg = REG_HMEBOX_EXT_1;
255 box_reg = REG_HMEBOX_2;
256 box_extreg = REG_HMEBOX_EXT_2;
259 box_reg = REG_HMEBOX_3;
260 box_extreg = REG_HMEBOX_EXT_3;
263 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
264 "switch case %#x not processed\n", boxnum);
267 isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum);
270 if (wait_h2c_limmit == 0) {
271 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
272 "Waiting too long for FW read clear HMEBox(%d)!\n",
279 isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum);
280 u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
281 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
282 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
287 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
288 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
293 memset(boxcontent, 0, sizeof(boxcontent));
294 memset(boxextcontent, 0, sizeof(boxextcontent));
295 boxcontent[0] = element_id;
296 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
297 "Write element_id box_reg(%4x) = %2x\n",
298 box_reg, element_id);
304 /*boxcontent[0] &= ~(BIT(7));*/
305 memcpy((u8 *)(boxcontent) + 1,
306 cmd_b + buf_index, cmd_len);
308 for (idx = 0; idx < 4; idx++) {
309 rtl_write_byte(rtlpriv, box_reg + idx,
317 /*boxcontent[0] |= (BIT(7));*/
318 memcpy((u8 *)(boxextcontent),
319 cmd_b + buf_index+3, cmd_len-3);
320 memcpy((u8 *)(boxcontent) + 1,
321 cmd_b + buf_index, 3);
323 for (idx = 0; idx < 2; idx++) {
324 rtl_write_byte(rtlpriv, box_extreg + idx,
328 for (idx = 0; idx < 4; idx++) {
329 rtl_write_byte(rtlpriv, box_reg + idx,
334 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
335 "switch case %#x not processed\n", cmd_len);
341 rtlhal->last_hmeboxnum = boxnum + 1;
342 if (rtlhal->last_hmeboxnum == 4)
343 rtlhal->last_hmeboxnum = 0;
345 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
346 "pHalData->last_hmeboxnum = %d\n",
347 rtlhal->last_hmeboxnum);
350 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
351 rtlhal->h2c_setinprogress = false;
352 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
354 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
357 void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw,
358 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
360 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
363 if (!rtlhal->fw_ready) {
365 "rtl8188ee: error H2C cmd because of Fw download fail!!!\n");
369 memset(tmp_cmdbuf, 0, 8);
370 memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
371 _rtl88e_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
376 void rtl88e_firmware_selfreset(struct ieee80211_hw *hw)
379 struct rtl_priv *rtlpriv = rtl_priv(hw);
381 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1);
382 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2))));
383 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp | BIT(2)));
384 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
385 "8051Reset88E(): 8051 reset success\n");
389 void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
391 struct rtl_priv *rtlpriv = rtl_priv(hw);
392 u8 u1_h2c_set_pwrmode[H2C_88E_PWEMODE_LENGTH] = { 0 };
393 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
394 u8 rlbm, power_state = 0;
395 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
397 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
398 rlbm = 0;/*YJ, temp, 120316. FW now not support RLBM=2.*/
399 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
400 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
401 (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1);
402 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
403 ppsc->reg_max_lps_awakeintvl);
404 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
405 if (mode == FW_PS_ACTIVE_MODE)
406 power_state |= FW_PWR_STATE_ACTIVE;
408 power_state |= FW_PWR_STATE_RF_OFF;
410 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
412 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
413 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
414 u1_h2c_set_pwrmode, H2C_88E_PWEMODE_LENGTH);
415 rtl88e_fill_h2c_cmd(hw, H2C_88E_SETPWRMODE,
416 H2C_88E_PWEMODE_LENGTH, u1_h2c_set_pwrmode);
419 void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
421 u8 u1_joinbssrpt_parm[1] = { 0 };
423 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
425 rtl88e_fill_h2c_cmd(hw, H2C_88E_JOINBSSRPT, 1, u1_joinbssrpt_parm);
428 void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw,
429 u8 ap_offload_enable)
431 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
432 u8 u1_apoffload_parm[H2C_88E_AP_OFFLOAD_LENGTH] = { 0 };
434 SET_H2CCMD_AP_OFFLOAD_ON(u1_apoffload_parm, ap_offload_enable);
435 SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid);
436 SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0);
438 rtl88e_fill_h2c_cmd(hw, H2C_88E_AP_OFFLOAD,
439 H2C_88E_AP_OFFLOAD_LENGTH, u1_apoffload_parm);
443 #define BEACON_PG 0 /* ->1 */
446 #define PROBERSP_PG 4 /* ->5 */
448 #define TOTAL_RESERVED_PKT_LEN 768
450 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
452 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
453 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
454 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
456 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
457 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
458 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
459 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
460 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
461 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
462 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
465 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
466 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
467 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
484 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
488 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
489 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
500 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
501 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
502 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
503 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
506 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
507 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
508 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
520 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
523 /* page 4 probe_resp */
524 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
525 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
526 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
527 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
528 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
529 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
530 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
531 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
532 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
533 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
534 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
538 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 /* page 5 probe_resp */
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,
556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560 void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
562 struct rtl_priv *rtlpriv = rtl_priv(hw);
563 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
564 struct sk_buff *skb = NULL;
567 u8 u1rsvdpageloc[5] = { 0 };
574 /*---------------------------------------------------------
576 *---------------------------------------------------------
578 beacon = &reserved_page_packet[BEACON_PG * 128];
579 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
580 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
582 /*-------------------------------------------------------
584 *--------------------------------------------------------
586 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
587 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
588 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
589 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
591 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
593 /*--------------------------------------------------------
595 *---------------------------------------------------------
597 nullfunc = &reserved_page_packet[NULL_PG * 128];
598 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
599 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
600 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
602 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
604 /*---------------------------------------------------------
606 *----------------------------------------------------------
608 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
609 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
610 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
611 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
613 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
615 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
617 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
618 "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
619 &reserved_page_packet[0], totalpacketlen);
620 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
621 "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
624 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);