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, byte5 = 0;
426 	u8 awake_intvl;	/* DTIM = (awake_intvl - 1) */
427 	struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
428 	bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
429 			    btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
430 	bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ?
431 			  btc_ops->btc_is_bt_lps_on(rtlpriv) : false);
432 
433 	if (bt_ctrl_lps)
434 		mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE);
435 
436 	RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
437 		 mode, bt_ctrl_lps);
438 
439 	switch (mode) {
440 	case FW_PS_MIN_MODE:
441 		rlbm = 0;
442 		awake_intvl = 2;
443 		break;
444 	case FW_PS_MAX_MODE:
445 		rlbm = 1;
446 		awake_intvl = 2;
447 		break;
448 	case FW_PS_DTIM_MODE:
449 		rlbm = 2;
450 		awake_intvl = ppsc->reg_max_lps_awakeintvl;
451 		/* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
452 		 * is only used in swlps.
453 		 */
454 		break;
455 	default:
456 		rlbm = 2;
457 		awake_intvl = 4;
458 		break;
459 	}
460 
461 	if (rtlpriv->mac80211.p2p) {
462 		awake_intvl = 2;
463 		rlbm = 1;
464 	}
465 
466 	if (mode == FW_PS_ACTIVE_MODE) {
467 		byte5 = 0x40;
468 		power_state = FW_PWR_STATE_ACTIVE;
469 	} else {
470 		if (bt_ctrl_lps) {
471 			byte5 = btc_ops->btc_get_lps_val(rtlpriv);
472 			power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
473 
474 			if ((rlbm == 2) && (byte5 & BIT(4))) {
475 				/* Keep awake interval to 1 to prevent from
476 				 * decreasing coex performance
477 				 */
478 				awake_intvl = 2;
479 				rlbm = 2;
480 			}
481 		} else {
482 			byte5 = 0x40;
483 			power_state = FW_PWR_STATE_RF_OFF;
484 		}
485 	}
486 
487 	SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
488 	SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
489 	SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
490 					 bt_ctrl_lps ? 0 :
491 					 ((rtlpriv->mac80211.p2p) ?
492 					  ppsc->smart_ps : 1));
493 	SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
494 					       awake_intvl);
495 	SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
496 	SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
497 	SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
498 
499 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
500 		      "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
501 		      u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
502 	if (rtlpriv->cfg->ops->get_btc_status())
503 		btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
504 					     H2C_92E_PWEMODE_LENGTH);
505 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
506 			     u1_h2c_set_pwrmode);
507 }
508 
509 void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
510 {
511 	u8 parm[3] = { 0 , 0 , 0 };
512 	/* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
513 	 *          bit1=0-->update Media Status to MACID
514 	 *          bit1=1-->update Media Status from MACID to MACID_End
515 	 * parm[1]: MACID, if this is INFRA_STA, MacID = 0
516 	 * parm[2]: MACID_End
517 	 */
518 
519 	SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
520 	SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
521 
522 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm);
523 }
524 
525 #define BEACON_PG		0 /* ->1 */
526 #define PSPOLL_PG		2
527 #define NULL_PG			3
528 #define PROBERSP_PG		4 /* ->5 */
529 #define QOS_NULL_PG		6
530 #define BT_QOS_NULL_PG	7
531 
532 #define TOTAL_RESERVED_PKT_LEN	1024
533 
534 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
535 	/* page 0 beacon */
536 	0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
537 	0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
538 	0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
539 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
540 	0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
541 	0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
542 	0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
543 	0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
544 	0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
545 	0x09, 0x03, 0xFF, 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, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
549 	0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
550 	0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
551 	0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
552 
553 	/* page 1 beacon */
554 	0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
555 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 	0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
566 	0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 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 
571 	/* page 2  ps-poll */
572 	0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
573 	0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
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 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 	0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
584 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
585 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588 
589 	/* page 3  null */
590 	0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
591 	0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
592 	0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
593 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 	0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
602 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
603 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606 
607 	/* page 4  probe_resp */
608 	0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
609 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
610 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
611 	0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
612 	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
613 	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
614 	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
615 	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
616 	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
617 	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
618 	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621 	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
622 	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624 
625 	/* page 5  probe_resp */
626 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
628 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633 	0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
634 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
635 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 
639 	/* page 6 qos null data */
640 	0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
641 	0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
642 	0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
643 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 	0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
652 	0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
653 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 
657 	/* page 7 BT-qos null data */
658 	0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
659 	0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
660 	0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
661 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
662 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
663 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
664 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
665 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
666 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
667 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
668 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
669 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
670 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
671 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
672 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
673 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
674 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
675 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
676 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
677 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
678 };
679 
680 void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
681 {
682 	struct rtl_priv *rtlpriv = rtl_priv(hw);
683 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
684 	struct sk_buff *skb = NULL;
685 	bool rtstatus;
686 	u32 totalpacketlen;
687 	u8 u1rsvdpageloc[5] = { 0 };
688 	bool b_dlok = false;
689 
690 	u8 *beacon;
691 	u8 *p_pspoll;
692 	u8 *nullfunc;
693 	u8 *p_probersp;
694 	u8 *qosnull;
695 	u8 *btqosnull;
696 	/*---------------------------------------------------------
697 	 *			(1) beacon
698 	 *---------------------------------------------------------
699 	 */
700 	beacon = &reserved_page_packet[BEACON_PG * 128];
701 	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
702 	SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
703 
704 	/*-------------------------------------------------------
705 	 *			(2) ps-poll
706 	 *--------------------------------------------------------
707 	 */
708 	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
709 	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
710 	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
711 	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
712 
713 	SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
714 
715 	/*--------------------------------------------------------
716 	 *			(3) null data
717 	 *---------------------------------------------------------
718 	 */
719 	nullfunc = &reserved_page_packet[NULL_PG * 128];
720 	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
721 	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
722 	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
723 
724 	SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
725 
726 	/*---------------------------------------------------------
727 	 *			(4) probe response
728 	 *----------------------------------------------------------
729 	 */
730 	p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
731 	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
732 	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
733 	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
734 
735 	SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
736 
737 	/*---------------------------------------------------------
738 	 *			(5) QoS null data
739 	 *----------------------------------------------------------
740 	 */
741 	qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
742 	SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
743 	SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
744 	SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
745 
746 	SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOS_NULL_PG);
747 
748 	/*---------------------------------------------------------
749 	 *			(6) BT QoS null data
750 	 *----------------------------------------------------------
751 	 */
752 	btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
753 	SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
754 	SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
755 	SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
756 
757 	SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOS_NULL_PG);
758 
759 	totalpacketlen = TOTAL_RESERVED_PKT_LEN;
760 
761 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
762 		      "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
763 		      &reserved_page_packet[0], totalpacketlen);
764 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
765 		      "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
766 		      u1rsvdpageloc, 3);
767 
768 	skb = dev_alloc_skb(totalpacketlen);
769 	skb_put_data(skb, &reserved_page_packet, totalpacketlen);
770 
771 	rtstatus = rtl_cmd_send_packet(hw, skb);
772 	if (rtstatus)
773 		b_dlok = true;
774 
775 	if (b_dlok) {
776 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD ,
777 			 "Set RSVD page location to Fw.\n");
778 		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
779 			      "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
780 		rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE,
781 				     sizeof(u1rsvdpageloc), u1rsvdpageloc);
782 	} else {
783 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
784 			 "Set RSVD page location to Fw FAIL!!!!!!.\n");
785 	}
786 }
787 
788 /*Shoud check FW support p2p or not.*/
789 static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
790 {
791 	u8 u1_ctwindow_period[1] = {ctwindow};
792 
793 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
794 }
795 
796 void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
797 {
798 	struct rtl_priv *rtlpriv = rtl_priv(hw);
799 	struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
800 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
801 	struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
802 	struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
803 	u8 i;
804 	u16 ctwindow;
805 	u32 start_time, tsf_low;
806 
807 	switch (p2p_ps_state) {
808 	case P2P_PS_DISABLE:
809 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_DISABLE\n");
810 		memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
811 		break;
812 	case P2P_PS_ENABLE:
813 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_ENABLE\n");
814 		/* update CTWindow value. */
815 		if (p2pinfo->ctwindow > 0) {
816 			p2p_ps_offload->ctwindow_en = 1;
817 			ctwindow = p2pinfo->ctwindow;
818 			rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow);
819 		}
820 		/* hw only support 2 set of NoA */
821 		for (i = 0 ; i < p2pinfo->noa_num ; i++) {
822 			/* To control the register setting for which NOA*/
823 			rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
824 			if (i == 0)
825 				p2p_ps_offload->noa0_en = 1;
826 			else
827 				p2p_ps_offload->noa1_en = 1;
828 			/* config P2P NoA Descriptor Register */
829 			rtl_write_dword(rtlpriv, 0x5E0,
830 					p2pinfo->noa_duration[i]);
831 			rtl_write_dword(rtlpriv, 0x5E4,
832 					p2pinfo->noa_interval[i]);
833 
834 			/*Get Current TSF value */
835 			tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
836 
837 			start_time = p2pinfo->noa_start_time[i];
838 			if (p2pinfo->noa_count_type[i] != 1) {
839 				while (start_time <= (tsf_low + (50 * 1024))) {
840 					start_time += p2pinfo->noa_interval[i];
841 					if (p2pinfo->noa_count_type[i] != 255)
842 						p2pinfo->noa_count_type[i]--;
843 				}
844 			}
845 			rtl_write_dword(rtlpriv, 0x5E8, start_time);
846 			rtl_write_dword(rtlpriv, 0x5EC,
847 					p2pinfo->noa_count_type[i]);
848 		}
849 		if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
850 			/* rst p2p circuit */
851 			rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
852 			p2p_ps_offload->offload_en = 1;
853 
854 			if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
855 				p2p_ps_offload->role = 1;
856 				p2p_ps_offload->allstasleep = 0;
857 			} else {
858 				p2p_ps_offload->role = 0;
859 			}
860 			p2p_ps_offload->discovery = 0;
861 		}
862 		break;
863 	case P2P_PS_SCAN:
864 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN\n");
865 		p2p_ps_offload->discovery = 1;
866 		break;
867 	case P2P_PS_SCAN_DONE:
868 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN_DONE\n");
869 		p2p_ps_offload->discovery = 0;
870 		p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
871 		break;
872 	default:
873 		break;
874 	}
875 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1,
876 			     (u8 *)p2p_ps_offload);
877 }
878 
879 void rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw,
880 				   u8 *cmd_buf, u8 cmd_len)
881 {
882 	u8 rate = cmd_buf[0] & 0x3F;
883 	bool collision_state = cmd_buf[3] & BIT(0);
884 
885 	rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state);
886 }
887