Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2009-2014  Realtek Corporation.*/
0003 
0004 #include "../wifi.h"
0005 #include "../pci.h"
0006 #include "../base.h"
0007 #include "../core.h"
0008 #include "reg.h"
0009 #include "def.h"
0010 #include "fw.h"
0011 #include "../rtl8723com/fw_common.h"
0012 
0013 static bool _rtl8723be_check_fw_read_last_h2c(struct ieee80211_hw *hw,
0014                           u8 boxnum)
0015 {
0016     struct rtl_priv *rtlpriv = rtl_priv(hw);
0017     u8 val_hmetfr;
0018     bool result = false;
0019 
0020     val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
0021     if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
0022         result = true;
0023     return result;
0024 }
0025 
0026 static void _rtl8723be_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
0027                     u32 cmd_len, u8 *p_cmdbuffer)
0028 {
0029     struct rtl_priv *rtlpriv = rtl_priv(hw);
0030     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0031     u8 boxnum;
0032     u16 box_reg = 0, box_extreg = 0;
0033     u8 u1b_tmp;
0034     bool isfw_read = false;
0035     u8 buf_index = 0;
0036     bool bwrite_sucess = false;
0037     u8 wait_h2c_limmit = 100;
0038     u8 wait_writeh2c_limmit = 100;
0039     u8 boxcontent[4], boxextcontent[4];
0040     u32 h2c_waitcounter = 0;
0041     unsigned long flag;
0042     u8 idx;
0043 
0044     rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
0045 
0046     while (true) {
0047         spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
0048         if (rtlhal->h2c_setinprogress) {
0049             rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0050                 "H2C set in progress! Wait to set..element_id(%d).\n",
0051                 element_id);
0052 
0053             while (rtlhal->h2c_setinprogress) {
0054                 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
0055                                flag);
0056                 h2c_waitcounter++;
0057                 rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0058                     "Wait 100 us (%d times)...\n",
0059                     h2c_waitcounter);
0060                 udelay(100);
0061 
0062                 if (h2c_waitcounter > 1000)
0063                     return;
0064                 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
0065                           flag);
0066             }
0067             spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
0068         } else {
0069             rtlhal->h2c_setinprogress = true;
0070             spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
0071             break;
0072         }
0073     }
0074 
0075     while (!bwrite_sucess) {
0076         wait_writeh2c_limmit--;
0077         if (wait_writeh2c_limmit == 0) {
0078             pr_err("Write H2C fail because no trigger for FW INT!\n");
0079             break;
0080         }
0081 
0082         boxnum = rtlhal->last_hmeboxnum;
0083         switch (boxnum) {
0084         case 0:
0085             box_reg = REG_HMEBOX_0;
0086             box_extreg = REG_HMEBOX_EXT_0;
0087             break;
0088         case 1:
0089             box_reg = REG_HMEBOX_1;
0090             box_extreg = REG_HMEBOX_EXT_1;
0091             break;
0092         case 2:
0093             box_reg = REG_HMEBOX_2;
0094             box_extreg = REG_HMEBOX_EXT_2;
0095             break;
0096         case 3:
0097             box_reg = REG_HMEBOX_3;
0098             box_extreg = REG_HMEBOX_EXT_3;
0099             break;
0100         default:
0101             pr_err("switch case %#x not processed\n",
0102                    boxnum);
0103             break;
0104         }
0105 
0106         isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, boxnum);
0107         while (!isfw_read) {
0108             wait_h2c_limmit--;
0109             if (wait_h2c_limmit == 0) {
0110                 rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0111                     "Waiting too long for FW read clear HMEBox(%d)!\n",
0112                     boxnum);
0113                 break;
0114             }
0115 
0116             udelay(10);
0117 
0118             isfw_read = _rtl8723be_check_fw_read_last_h2c(hw,
0119                                 boxnum);
0120             u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
0121             rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0122                 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
0123                 boxnum, u1b_tmp);
0124         }
0125 
0126         if (!isfw_read) {
0127             rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0128                 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
0129                 boxnum);
0130             break;
0131         }
0132 
0133         memset(boxcontent, 0, sizeof(boxcontent));
0134         memset(boxextcontent, 0, sizeof(boxextcontent));
0135         boxcontent[0] = element_id;
0136         rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0137             "Write element_id box_reg(%4x) = %2x\n",
0138             box_reg, element_id);
0139 
0140         switch (cmd_len) {
0141         case 1:
0142         case 2:
0143         case 3:
0144             /*boxcontent[0] &= ~(BIT(7));*/
0145             memcpy((u8 *)(boxcontent) + 1,
0146                    p_cmdbuffer + buf_index, cmd_len);
0147 
0148             for (idx = 0; idx < 4; idx++) {
0149                 rtl_write_byte(rtlpriv, box_reg + idx,
0150                            boxcontent[idx]);
0151             }
0152             break;
0153         case 4:
0154         case 5:
0155         case 6:
0156         case 7:
0157             /*boxcontent[0] |= (BIT(7));*/
0158             memcpy((u8 *)(boxextcontent),
0159                    p_cmdbuffer + buf_index+3, cmd_len-3);
0160             memcpy((u8 *)(boxcontent) + 1,
0161                    p_cmdbuffer + buf_index, 3);
0162 
0163             for (idx = 0; idx < 4; idx++) {
0164                 rtl_write_byte(rtlpriv, box_extreg + idx,
0165                            boxextcontent[idx]);
0166             }
0167 
0168             for (idx = 0; idx < 4; idx++) {
0169                 rtl_write_byte(rtlpriv, box_reg + idx,
0170                            boxcontent[idx]);
0171             }
0172             break;
0173         default:
0174             pr_err("switch case %#x not processed\n",
0175                    cmd_len);
0176             break;
0177         }
0178 
0179         bwrite_sucess = true;
0180 
0181         rtlhal->last_hmeboxnum = boxnum + 1;
0182         if (rtlhal->last_hmeboxnum == 4)
0183             rtlhal->last_hmeboxnum = 0;
0184 
0185         rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0186             "pHalData->last_hmeboxnum  = %d\n",
0187             rtlhal->last_hmeboxnum);
0188     }
0189 
0190     spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
0191     rtlhal->h2c_setinprogress = false;
0192     spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
0193 
0194     rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
0195 }
0196 
0197 void rtl8723be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
0198                 u32 cmd_len, u8 *p_cmdbuffer)
0199 {
0200     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0201     u32 tmp_cmdbuf[2];
0202 
0203     if (!rtlhal->fw_ready) {
0204         WARN_ONCE(true,
0205               "rtl8723be: error H2C cmd because of Fw download fail!!!\n");
0206         return;
0207     }
0208 
0209     memset(tmp_cmdbuf, 0, 8);
0210     memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
0211     _rtl8723be_fill_h2c_command(hw, element_id, cmd_len,
0212                     (u8 *)&tmp_cmdbuf);
0213     return;
0214 }
0215 
0216 void rtl8723be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
0217 {
0218     struct rtl_priv *rtlpriv = rtl_priv(hw);
0219     u8 u1_h2c_set_pwrmode[H2C_PWEMODE_LENGTH] = { 0 };
0220     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
0221     u8 rlbm, power_state = 0, byte5 = 0;
0222     u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
0223     struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
0224     bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
0225                 btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
0226     bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ?
0227               btc_ops->btc_is_bt_lps_on(rtlpriv) : false);
0228 
0229     if (bt_ctrl_lps)
0230         mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE);
0231 
0232     rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
0233         mode, bt_ctrl_lps);
0234 
0235     switch (mode) {
0236     case FW_PS_MIN_MODE:
0237         rlbm = 0;
0238         awake_intvl = 2;
0239         break;
0240     case FW_PS_MAX_MODE:
0241         rlbm = 1;
0242         awake_intvl = 2;
0243         break;
0244     case FW_PS_DTIM_MODE:
0245         rlbm = 2;
0246         awake_intvl = ppsc->reg_max_lps_awakeintvl;
0247         /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
0248          * is only used in swlps.
0249          */
0250         break;
0251     default:
0252         rlbm = 2;
0253         awake_intvl = 4;
0254         break;
0255     }
0256 
0257     if (rtlpriv->mac80211.p2p) {
0258         awake_intvl = 2;
0259         rlbm = 1;
0260     }
0261 
0262     if (mode == FW_PS_ACTIVE_MODE) {
0263         byte5 = 0x40;
0264         power_state = FW_PWR_STATE_ACTIVE;
0265     } else {
0266         if (bt_ctrl_lps) {
0267             byte5 = btc_ops->btc_get_lps_val(rtlpriv);
0268             power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
0269 
0270             if ((rlbm == 2) && (byte5 & BIT(4))) {
0271                 /* Keep awake interval to 1 to prevent from
0272                  * decreasing coex performance
0273                  */
0274                 awake_intvl = 2;
0275                 rlbm = 2;
0276             }
0277         } else {
0278             byte5 = 0x40;
0279             power_state = FW_PWR_STATE_RF_OFF;
0280         }
0281     }
0282 
0283     SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
0284     SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
0285     SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
0286                      bt_ctrl_lps ? 0 : ppsc->smart_ps);
0287     SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
0288                            awake_intvl);
0289     SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
0290     SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
0291     SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
0292 
0293     RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
0294               "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
0295               u1_h2c_set_pwrmode, H2C_PWEMODE_LENGTH);
0296     if (rtlpriv->cfg->ops->get_btc_status())
0297         btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
0298                          H2C_PWEMODE_LENGTH);
0299     rtl8723be_fill_h2c_cmd(hw, H2C_8723B_SETPWRMODE, H2C_PWEMODE_LENGTH,
0300                    u1_h2c_set_pwrmode);
0301 }
0302 
0303 void rtl8723be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
0304 {
0305     u8 parm[3] = { 0, 0, 0 };
0306     /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
0307      *          bit1=0-->update Media Status to MACID
0308      *          bit1=1-->update Media Status from MACID to MACID_End
0309      * parm[1]: MACID, if this is INFRA_STA, MacID = 0
0310      * parm[2]: MACID_End
0311     */
0312     SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
0313     SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
0314 
0315     rtl8723be_fill_h2c_cmd(hw, H2C_8723B_MSRRPT, 3, parm);
0316 }
0317 
0318 #define BEACON_PG       0 /* ->1 */
0319 #define PSPOLL_PG       2
0320 #define NULL_PG         3
0321 #define PROBERSP_PG     4 /* ->5 */
0322 #define QOS_NULL_PG     6
0323 #define BT_QOS_NULL_PG  7
0324 
0325 #define TOTAL_RESERVED_PKT_LEN  1024    /* can be up to 1280 (tx_bndy=245) */
0326 
0327 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
0328     /* page 0 beacon */
0329     0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0330     0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
0331     0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
0332     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0333     0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
0334     0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
0335     0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
0336     0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
0337     0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
0338     0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0339     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0340     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0341     0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
0342     0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
0343     0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
0344     0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
0345 
0346     /* page 1 beacon */
0347     0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
0348     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0349     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0350     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0351     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0352     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0353     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0354     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0355     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0356     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0357     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0358     0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
0359     0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
0360     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0361     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0362     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0363 
0364     /* page 2  ps-poll */
0365     0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
0366     0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
0367     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0368     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0369     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0370     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0371     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0372     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0373     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0374     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0375     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0376     0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
0377     0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0378     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0379     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0380     0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0381 
0382     /* page 3  null */
0383     0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
0384     0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
0385     0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
0386     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0387     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0388     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0389     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0390     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0391     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0392     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0393     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0394     0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
0395     0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0396     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0397     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0398     0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0399 
0400     /* page 4  probe_resp */
0401     0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
0402     0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
0403     0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
0404     0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
0405     0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
0406     0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
0407     0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
0408     0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
0409     0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
0410     0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
0411     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0412     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0413     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0414     0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
0415     0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0416     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0417 
0418     /* page 5  probe_resp */
0419     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0420     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0421     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0422     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0423     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0424     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0425     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0426     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0427     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0428     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0429     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0430     0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
0431     0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0432     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0433     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0434     0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0435 
0436     /* page 6 qos null data */
0437     0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
0438     0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
0439     0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
0440     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0441     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0442     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0443     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0444     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0445     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0446     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0447     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0448     0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
0449     0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
0450     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0451     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0452     0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0453 
0454     /* page 7 BT-qos null data */
0455     0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
0456     0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
0457     0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
0458     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0459     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0460     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0461     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0462     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0463     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0464     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0465     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0466     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0467     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0468     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0469     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0470     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0471 
0472 };
0473 
0474 void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
0475                   bool b_dl_finished)
0476 {
0477     struct rtl_priv *rtlpriv = rtl_priv(hw);
0478     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0479     struct sk_buff *skb = NULL;
0480 
0481     u32 totalpacketlen;
0482     bool rtstatus;
0483     u8 u1rsvdpageloc[5] = { 0 };
0484     bool b_dlok = false;
0485 
0486     u8 *beacon;
0487     u8 *p_pspoll;
0488     u8 *nullfunc;
0489     u8 *p_probersp;
0490     u8 *qosnull;
0491     u8 *btqosnull;
0492     /*---------------------------------------------------------
0493      *          (1) beacon
0494      *---------------------------------------------------------
0495      */
0496     beacon = &reserved_page_packet[BEACON_PG * 128];
0497     SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
0498     SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
0499 
0500     /*-------------------------------------------------------
0501      *          (2) ps-poll
0502      *-------------------------------------------------------
0503      */
0504     p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
0505     SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
0506     SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
0507     SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
0508 
0509     SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
0510 
0511     /*--------------------------------------------------------
0512      *          (3) null data
0513      *--------------------------------------------------------
0514      */
0515     nullfunc = &reserved_page_packet[NULL_PG * 128];
0516     SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
0517     SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
0518     SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
0519 
0520     SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
0521 
0522     /*---------------------------------------------------------
0523      *          (4) probe response
0524      *---------------------------------------------------------
0525      */
0526     p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
0527     SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
0528     SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
0529     SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
0530 
0531     SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
0532 
0533     /*---------------------------------------------------------
0534      *          (5) QoS Null
0535      *---------------------------------------------------------
0536      */
0537     qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
0538     SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
0539     SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
0540     SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
0541 
0542     SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOS_NULL_PG);
0543 
0544     /*---------------------------------------------------------
0545      *          (5) QoS Null
0546      *---------------------------------------------------------
0547      */
0548     btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
0549     SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
0550     SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
0551     SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
0552 
0553     SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOS_NULL_PG);
0554 
0555     totalpacketlen = TOTAL_RESERVED_PKT_LEN;
0556 
0557     RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
0558               "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
0559               &reserved_page_packet[0], totalpacketlen);
0560     RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
0561               "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
0562               u1rsvdpageloc, sizeof(u1rsvdpageloc));
0563 
0564     skb = dev_alloc_skb(totalpacketlen);
0565     if (!skb)
0566         return;
0567     skb_put_data(skb, &reserved_page_packet, totalpacketlen);
0568 
0569     rtstatus = rtl_cmd_send_packet(hw, skb);
0570 
0571     if (rtstatus)
0572         b_dlok = true;
0573 
0574     if (b_dlok) {
0575         rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
0576             "Set RSVD page location to Fw.\n");
0577         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, "H2C_RSVDPAGE:\n",
0578                   u1rsvdpageloc, sizeof(u1rsvdpageloc));
0579         rtl8723be_fill_h2c_cmd(hw, H2C_8723B_RSVDPAGE,
0580                        sizeof(u1rsvdpageloc), u1rsvdpageloc);
0581     } else
0582         rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
0583             "Set RSVD page location to Fw FAIL!!!!!!.\n");
0584 }
0585 
0586 /*Should check FW support p2p or not.*/
0587 static void rtl8723be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
0588                          u8 ctwindow)
0589 {
0590     u8 u1_ctwindow_period[1] = { ctwindow};
0591 
0592     rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_CTW_CMD, 1,
0593                    u1_ctwindow_period);
0594 }
0595 
0596 void rtl8723be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw,
0597                       u8 p2p_ps_state)
0598 {
0599     struct rtl_priv *rtlpriv = rtl_priv(hw);
0600     struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
0601     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0602     struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
0603     struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
0604     u8 i;
0605     u16 ctwindow;
0606     u32 start_time, tsf_low;
0607 
0608     switch (p2p_ps_state) {
0609     case P2P_PS_DISABLE:
0610         rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
0611         memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
0612         break;
0613     case P2P_PS_ENABLE:
0614         rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
0615         /* update CTWindow value. */
0616         if (p2pinfo->ctwindow > 0) {
0617             p2p_ps_offload->ctwindow_en = 1;
0618             ctwindow = p2pinfo->ctwindow;
0619             rtl8723be_set_p2p_ctw_period_cmd(hw, ctwindow);
0620         }
0621         /* hw only support 2 set of NoA */
0622         for (i = 0 ; i < p2pinfo->noa_num ; i++) {
0623             /* To control the register setting
0624              * for which NOA
0625              */
0626             rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
0627             if (i == 0)
0628                 p2p_ps_offload->noa0_en = 1;
0629             else
0630                 p2p_ps_offload->noa1_en = 1;
0631 
0632             /* config P2P NoA Descriptor Register */
0633             rtl_write_dword(rtlpriv, 0x5E0,
0634                     p2pinfo->noa_duration[i]);
0635             rtl_write_dword(rtlpriv, 0x5E4,
0636                     p2pinfo->noa_interval[i]);
0637 
0638             /*Get Current TSF value */
0639             tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
0640 
0641             start_time = p2pinfo->noa_start_time[i];
0642             if (p2pinfo->noa_count_type[i] != 1) {
0643                 while (start_time <= (tsf_low + (50 * 1024))) {
0644                     start_time += p2pinfo->noa_interval[i];
0645                     if (p2pinfo->noa_count_type[i] != 255)
0646                         p2pinfo->noa_count_type[i]--;
0647                 }
0648             }
0649             rtl_write_dword(rtlpriv, 0x5E8, start_time);
0650             rtl_write_dword(rtlpriv, 0x5EC,
0651                     p2pinfo->noa_count_type[i]);
0652         }
0653 
0654         if ((p2pinfo->opp_ps == 1) ||
0655             (p2pinfo->noa_num > 0)) {
0656             /* rst p2p circuit */
0657             rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
0658 
0659             p2p_ps_offload->offload_en = 1;
0660 
0661             if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
0662                 p2p_ps_offload->role = 1;
0663                 p2p_ps_offload->allstasleep = 0;
0664             } else {
0665                 p2p_ps_offload->role = 0;
0666             }
0667             p2p_ps_offload->discovery = 0;
0668         }
0669         break;
0670     case P2P_PS_SCAN:
0671         rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
0672         p2p_ps_offload->discovery = 1;
0673         break;
0674     case P2P_PS_SCAN_DONE:
0675         rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
0676         p2p_ps_offload->discovery = 0;
0677         p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
0678         break;
0679     default:
0680         break;
0681     }
0682 
0683     rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_OFFLOAD, 1,
0684                    (u8 *)p2p_ps_offload);
0685 }