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 (21567B)


      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 "reg.h"
      9#include "def.h"
     10#include "fw.h"
     11#include "../rtl8723com/fw_common.h"
     12
     13static bool _rtl8723be_check_fw_read_last_h2c(struct ieee80211_hw *hw,
     14					      u8 boxnum)
     15{
     16	struct rtl_priv *rtlpriv = rtl_priv(hw);
     17	u8 val_hmetfr;
     18	bool result = false;
     19
     20	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
     21	if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
     22		result = true;
     23	return result;
     24}
     25
     26static void _rtl8723be_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
     27					u32 cmd_len, u8 *p_cmdbuffer)
     28{
     29	struct rtl_priv *rtlpriv = rtl_priv(hw);
     30	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
     31	u8 boxnum;
     32	u16 box_reg = 0, box_extreg = 0;
     33	u8 u1b_tmp;
     34	bool isfw_read = false;
     35	u8 buf_index = 0;
     36	bool bwrite_sucess = false;
     37	u8 wait_h2c_limmit = 100;
     38	u8 wait_writeh2c_limmit = 100;
     39	u8 boxcontent[4], boxextcontent[4];
     40	u32 h2c_waitcounter = 0;
     41	unsigned long flag;
     42	u8 idx;
     43
     44	rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
     45
     46	while (true) {
     47		spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
     48		if (rtlhal->h2c_setinprogress) {
     49			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
     50				"H2C set in progress! Wait to set..element_id(%d).\n",
     51				element_id);
     52
     53			while (rtlhal->h2c_setinprogress) {
     54				spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
     55						       flag);
     56				h2c_waitcounter++;
     57				rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
     58					"Wait 100 us (%d times)...\n",
     59					h2c_waitcounter);
     60				udelay(100);
     61
     62				if (h2c_waitcounter > 1000)
     63					return;
     64				spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
     65						  flag);
     66			}
     67			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
     68		} else {
     69			rtlhal->h2c_setinprogress = true;
     70			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
     71			break;
     72		}
     73	}
     74
     75	while (!bwrite_sucess) {
     76		wait_writeh2c_limmit--;
     77		if (wait_writeh2c_limmit == 0) {
     78			pr_err("Write H2C fail because no trigger for FW INT!\n");
     79			break;
     80		}
     81
     82		boxnum = rtlhal->last_hmeboxnum;
     83		switch (boxnum) {
     84		case 0:
     85			box_reg = REG_HMEBOX_0;
     86			box_extreg = REG_HMEBOX_EXT_0;
     87			break;
     88		case 1:
     89			box_reg = REG_HMEBOX_1;
     90			box_extreg = REG_HMEBOX_EXT_1;
     91			break;
     92		case 2:
     93			box_reg = REG_HMEBOX_2;
     94			box_extreg = REG_HMEBOX_EXT_2;
     95			break;
     96		case 3:
     97			box_reg = REG_HMEBOX_3;
     98			box_extreg = REG_HMEBOX_EXT_3;
     99			break;
    100		default:
    101			pr_err("switch case %#x not processed\n",
    102			       boxnum);
    103			break;
    104		}
    105
    106		isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, boxnum);
    107		while (!isfw_read) {
    108			wait_h2c_limmit--;
    109			if (wait_h2c_limmit == 0) {
    110				rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
    111					"Waiting too long for FW read clear HMEBox(%d)!\n",
    112					boxnum);
    113				break;
    114			}
    115
    116			udelay(10);
    117
    118			isfw_read = _rtl8723be_check_fw_read_last_h2c(hw,
    119								boxnum);
    120			u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
    121			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
    122				"Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
    123				boxnum, u1b_tmp);
    124		}
    125
    126		if (!isfw_read) {
    127			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
    128				"Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
    129				boxnum);
    130			break;
    131		}
    132
    133		memset(boxcontent, 0, sizeof(boxcontent));
    134		memset(boxextcontent, 0, sizeof(boxextcontent));
    135		boxcontent[0] = element_id;
    136		rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
    137			"Write element_id box_reg(%4x) = %2x\n",
    138			box_reg, element_id);
    139
    140		switch (cmd_len) {
    141		case 1:
    142		case 2:
    143		case 3:
    144			/*boxcontent[0] &= ~(BIT(7));*/
    145			memcpy((u8 *)(boxcontent) + 1,
    146			       p_cmdbuffer + buf_index, cmd_len);
    147
    148			for (idx = 0; idx < 4; idx++) {
    149				rtl_write_byte(rtlpriv, box_reg + idx,
    150					       boxcontent[idx]);
    151			}
    152			break;
    153		case 4:
    154		case 5:
    155		case 6:
    156		case 7:
    157			/*boxcontent[0] |= (BIT(7));*/
    158			memcpy((u8 *)(boxextcontent),
    159			       p_cmdbuffer + buf_index+3, cmd_len-3);
    160			memcpy((u8 *)(boxcontent) + 1,
    161			       p_cmdbuffer + buf_index, 3);
    162
    163			for (idx = 0; idx < 4; idx++) {
    164				rtl_write_byte(rtlpriv, box_extreg + idx,
    165					       boxextcontent[idx]);
    166			}
    167
    168			for (idx = 0; idx < 4; idx++) {
    169				rtl_write_byte(rtlpriv, box_reg + idx,
    170					       boxcontent[idx]);
    171			}
    172			break;
    173		default:
    174			pr_err("switch case %#x not processed\n",
    175			       cmd_len);
    176			break;
    177		}
    178
    179		bwrite_sucess = true;
    180
    181		rtlhal->last_hmeboxnum = boxnum + 1;
    182		if (rtlhal->last_hmeboxnum == 4)
    183			rtlhal->last_hmeboxnum = 0;
    184
    185		rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
    186			"pHalData->last_hmeboxnum  = %d\n",
    187			rtlhal->last_hmeboxnum);
    188	}
    189
    190	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
    191	rtlhal->h2c_setinprogress = false;
    192	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
    193
    194	rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
    195}
    196
    197void rtl8723be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
    198			    u32 cmd_len, u8 *p_cmdbuffer)
    199{
    200	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
    201	u32 tmp_cmdbuf[2];
    202
    203	if (!rtlhal->fw_ready) {
    204		WARN_ONCE(true,
    205			  "rtl8723be: error H2C cmd because of Fw download fail!!!\n");
    206		return;
    207	}
    208
    209	memset(tmp_cmdbuf, 0, 8);
    210	memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
    211	_rtl8723be_fill_h2c_command(hw, element_id, cmd_len,
    212				    (u8 *)&tmp_cmdbuf);
    213	return;
    214}
    215
    216void rtl8723be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
    217{
    218	struct rtl_priv *rtlpriv = rtl_priv(hw);
    219	u8 u1_h2c_set_pwrmode[H2C_PWEMODE_LENGTH] = { 0 };
    220	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
    221	u8 rlbm, power_state = 0, byte5 = 0;
    222	u8 awake_intvl;	/* DTIM = (awake_intvl - 1) */
    223	struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
    224	bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
    225			    btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
    226	bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ?
    227			  btc_ops->btc_is_bt_lps_on(rtlpriv) : false);
    228
    229	if (bt_ctrl_lps)
    230		mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE);
    231
    232	rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
    233		mode, bt_ctrl_lps);
    234
    235	switch (mode) {
    236	case FW_PS_MIN_MODE:
    237		rlbm = 0;
    238		awake_intvl = 2;
    239		break;
    240	case FW_PS_MAX_MODE:
    241		rlbm = 1;
    242		awake_intvl = 2;
    243		break;
    244	case FW_PS_DTIM_MODE:
    245		rlbm = 2;
    246		awake_intvl = ppsc->reg_max_lps_awakeintvl;
    247		/* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
    248		 * is only used in swlps.
    249		 */
    250		break;
    251	default:
    252		rlbm = 2;
    253		awake_intvl = 4;
    254		break;
    255	}
    256
    257	if (rtlpriv->mac80211.p2p) {
    258		awake_intvl = 2;
    259		rlbm = 1;
    260	}
    261
    262	if (mode == FW_PS_ACTIVE_MODE) {
    263		byte5 = 0x40;
    264		power_state = FW_PWR_STATE_ACTIVE;
    265	} else {
    266		if (bt_ctrl_lps) {
    267			byte5 = btc_ops->btc_get_lps_val(rtlpriv);
    268			power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
    269
    270			if ((rlbm == 2) && (byte5 & BIT(4))) {
    271				/* Keep awake interval to 1 to prevent from
    272				 * decreasing coex performance
    273				 */
    274				awake_intvl = 2;
    275				rlbm = 2;
    276			}
    277		} else {
    278			byte5 = 0x40;
    279			power_state = FW_PWR_STATE_RF_OFF;
    280		}
    281	}
    282
    283	SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
    284	SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
    285	SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
    286					 bt_ctrl_lps ? 0 : ppsc->smart_ps);
    287	SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
    288					       awake_intvl);
    289	SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
    290	SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
    291	SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
    292
    293	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
    294		      "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
    295		      u1_h2c_set_pwrmode, H2C_PWEMODE_LENGTH);
    296	if (rtlpriv->cfg->ops->get_btc_status())
    297		btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
    298					     H2C_PWEMODE_LENGTH);
    299	rtl8723be_fill_h2c_cmd(hw, H2C_8723B_SETPWRMODE, H2C_PWEMODE_LENGTH,
    300			       u1_h2c_set_pwrmode);
    301}
    302
    303void rtl8723be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
    304{
    305	u8 parm[3] = { 0, 0, 0 };
    306	/* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
    307	 *          bit1=0-->update Media Status to MACID
    308	 *          bit1=1-->update Media Status from MACID to MACID_End
    309	 * parm[1]: MACID, if this is INFRA_STA, MacID = 0
    310	 * parm[2]: MACID_End
    311	*/
    312	SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
    313	SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
    314
    315	rtl8723be_fill_h2c_cmd(hw, H2C_8723B_MSRRPT, 3, parm);
    316}
    317
    318#define BEACON_PG		0 /* ->1 */
    319#define PSPOLL_PG		2
    320#define NULL_PG			3
    321#define PROBERSP_PG		4 /* ->5 */
    322#define QOS_NULL_PG		6
    323#define BT_QOS_NULL_PG	7
    324
    325#define TOTAL_RESERVED_PKT_LEN	1024	/* can be up to 1280 (tx_bndy=245) */
    326
    327static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
    328	/* page 0 beacon */
    329	0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
    330	0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
    331	0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
    332	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    333	0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
    334	0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
    335	0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
    336	0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
    337	0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
    338	0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
    339	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    340	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    341	0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
    342	0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
    343	0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
    344	0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
    345
    346	/* page 1 beacon */
    347	0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
    348	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    349	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    350	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    351	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    352	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    353	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    354	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    355	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    356	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    357	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    358	0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
    359	0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
    360	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    361	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    362	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    363
    364	/* page 2  ps-poll */
    365	0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
    366	0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
    367	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    368	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    369	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    370	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    371	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    372	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    373	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    374	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    375	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    376	0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
    377	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
    378	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    379	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    380	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    381
    382	/* page 3  null */
    383	0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
    384	0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
    385	0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
    386	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    387	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    388	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    389	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    390	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    391	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    392	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    393	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    394	0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
    395	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
    396	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    397	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    398	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    399
    400	/* page 4  probe_resp */
    401	0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
    402	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
    403	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
    404	0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
    405	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
    406	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
    407	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
    408	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
    409	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
    410	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
    411	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    412	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    413	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    414	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
    415	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    416	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    417
    418	/* page 5  probe_resp */
    419	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    420	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    421	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    422	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    423	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    424	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    425	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    426	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    427	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    428	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    429	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    430	0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
    431	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
    432	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    433	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    434	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    435
    436	/* page 6 qos null data */
    437	0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
    438	0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
    439	0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
    440	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    441	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    442	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    443	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    444	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    445	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    446	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    447	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    448	0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
    449	0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
    450	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    451	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    452	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    453
    454	/* page 7 BT-qos null data */
    455	0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
    456	0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
    457	0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
    458	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    459	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    460	0x00, 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	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    464	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    465	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    466	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    467	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
    472};
    473
    474void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
    475				  bool b_dl_finished)
    476{
    477	struct rtl_priv *rtlpriv = rtl_priv(hw);
    478	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
    479	struct sk_buff *skb = NULL;
    480
    481	u32 totalpacketlen;
    482	bool rtstatus;
    483	u8 u1rsvdpageloc[5] = { 0 };
    484	bool b_dlok = false;
    485
    486	u8 *beacon;
    487	u8 *p_pspoll;
    488	u8 *nullfunc;
    489	u8 *p_probersp;
    490	u8 *qosnull;
    491	u8 *btqosnull;
    492	/*---------------------------------------------------------
    493	 *			(1) beacon
    494	 *---------------------------------------------------------
    495	 */
    496	beacon = &reserved_page_packet[BEACON_PG * 128];
    497	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
    498	SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
    499
    500	/*-------------------------------------------------------
    501	 *			(2) ps-poll
    502	 *-------------------------------------------------------
    503	 */
    504	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
    505	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
    506	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
    507	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
    508
    509	SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
    510
    511	/*--------------------------------------------------------
    512	 *			(3) null data
    513	 *--------------------------------------------------------
    514	 */
    515	nullfunc = &reserved_page_packet[NULL_PG * 128];
    516	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
    517	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
    518	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
    519
    520	SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
    521
    522	/*---------------------------------------------------------
    523	 *			(4) probe response
    524	 *---------------------------------------------------------
    525	 */
    526	p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
    527	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
    528	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
    529	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
    530
    531	SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
    532
    533	/*---------------------------------------------------------
    534	 *			(5) QoS Null
    535	 *---------------------------------------------------------
    536	 */
    537	qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
    538	SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
    539	SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
    540	SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
    541
    542	SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOS_NULL_PG);
    543
    544	/*---------------------------------------------------------
    545	 *			(5) QoS Null
    546	 *---------------------------------------------------------
    547	 */
    548	btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
    549	SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
    550	SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
    551	SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
    552
    553	SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOS_NULL_PG);
    554
    555	totalpacketlen = TOTAL_RESERVED_PKT_LEN;
    556
    557	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
    558		      "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
    559		      &reserved_page_packet[0], totalpacketlen);
    560	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
    561		      "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
    562		      u1rsvdpageloc, sizeof(u1rsvdpageloc));
    563
    564	skb = dev_alloc_skb(totalpacketlen);
    565	if (!skb)
    566		return;
    567	skb_put_data(skb, &reserved_page_packet, totalpacketlen);
    568
    569	rtstatus = rtl_cmd_send_packet(hw, skb);
    570
    571	if (rtstatus)
    572		b_dlok = true;
    573
    574	if (b_dlok) {
    575		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
    576			"Set RSVD page location to Fw.\n");
    577		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, "H2C_RSVDPAGE:\n",
    578			      u1rsvdpageloc, sizeof(u1rsvdpageloc));
    579		rtl8723be_fill_h2c_cmd(hw, H2C_8723B_RSVDPAGE,
    580				       sizeof(u1rsvdpageloc), u1rsvdpageloc);
    581	} else
    582		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
    583			"Set RSVD page location to Fw FAIL!!!!!!.\n");
    584}
    585
    586/*Should check FW support p2p or not.*/
    587static void rtl8723be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
    588					     u8 ctwindow)
    589{
    590	u8 u1_ctwindow_period[1] = { ctwindow};
    591
    592	rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_CTW_CMD, 1,
    593			       u1_ctwindow_period);
    594}
    595
    596void rtl8723be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw,
    597				      u8 p2p_ps_state)
    598{
    599	struct rtl_priv *rtlpriv = rtl_priv(hw);
    600	struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
    601	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
    602	struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
    603	struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
    604	u8 i;
    605	u16 ctwindow;
    606	u32 start_time, tsf_low;
    607
    608	switch (p2p_ps_state) {
    609	case P2P_PS_DISABLE:
    610		rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
    611		memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
    612		break;
    613	case P2P_PS_ENABLE:
    614		rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
    615		/* update CTWindow value. */
    616		if (p2pinfo->ctwindow > 0) {
    617			p2p_ps_offload->ctwindow_en = 1;
    618			ctwindow = p2pinfo->ctwindow;
    619			rtl8723be_set_p2p_ctw_period_cmd(hw, ctwindow);
    620		}
    621		/* hw only support 2 set of NoA */
    622		for (i = 0 ; i < p2pinfo->noa_num ; i++) {
    623			/* To control the register setting
    624			 * for which NOA
    625			 */
    626			rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
    627			if (i == 0)
    628				p2p_ps_offload->noa0_en = 1;
    629			else
    630				p2p_ps_offload->noa1_en = 1;
    631
    632			/* config P2P NoA Descriptor Register */
    633			rtl_write_dword(rtlpriv, 0x5E0,
    634					p2pinfo->noa_duration[i]);
    635			rtl_write_dword(rtlpriv, 0x5E4,
    636					p2pinfo->noa_interval[i]);
    637
    638			/*Get Current TSF value */
    639			tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
    640
    641			start_time = p2pinfo->noa_start_time[i];
    642			if (p2pinfo->noa_count_type[i] != 1) {
    643				while (start_time <= (tsf_low + (50 * 1024))) {
    644					start_time += p2pinfo->noa_interval[i];
    645					if (p2pinfo->noa_count_type[i] != 255)
    646						p2pinfo->noa_count_type[i]--;
    647				}
    648			}
    649			rtl_write_dword(rtlpriv, 0x5E8, start_time);
    650			rtl_write_dword(rtlpriv, 0x5EC,
    651					p2pinfo->noa_count_type[i]);
    652		}
    653
    654		if ((p2pinfo->opp_ps == 1) ||
    655		    (p2pinfo->noa_num > 0)) {
    656			/* rst p2p circuit */
    657			rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
    658
    659			p2p_ps_offload->offload_en = 1;
    660
    661			if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
    662				p2p_ps_offload->role = 1;
    663				p2p_ps_offload->allstasleep = 0;
    664			} else {
    665				p2p_ps_offload->role = 0;
    666			}
    667			p2p_ps_offload->discovery = 0;
    668		}
    669		break;
    670	case P2P_PS_SCAN:
    671		rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
    672		p2p_ps_offload->discovery = 1;
    673		break;
    674	case P2P_PS_SCAN_DONE:
    675		rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
    676		p2p_ps_offload->discovery = 0;
    677		p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
    678		break;
    679	default:
    680		break;
    681	}
    682
    683	rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_OFFLOAD, 1,
    684			       (u8 *)p2p_ps_offload);
    685}