cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fw.c (26798B)


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