Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2009-2012  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 _rtl8723e_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, val_mcutst_1;
0018     bool result = false;
0019 
0020     val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
0021     val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
0022 
0023     if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
0024         result = true;
0025     return result;
0026 }
0027 
0028 static void _rtl8723e_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
0029                        u32 cmd_len, u8 *cmdbuffer)
0030 {
0031     struct rtl_priv *rtlpriv = rtl_priv(hw);
0032     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0033     u8 boxnum;
0034     u16 box_reg = 0, box_extreg = 0;
0035     u8 u1b_tmp;
0036     bool isfw_read = false;
0037     u8 buf_index = 0;
0038     bool bwrite_sucess = false;
0039     u8 wait_h2c_limmit = 100;
0040     u8 wait_writeh2c_limmit = 100;
0041     u8 boxcontent[4], boxextcontent[2];
0042     u32 h2c_waitcounter = 0;
0043     unsigned long flag;
0044     u8 idx;
0045 
0046     rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
0047 
0048     while (true) {
0049         spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
0050         if (rtlhal->h2c_setinprogress) {
0051             rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0052                 "H2C set in progress! Wait to set..element_id(%d).\n",
0053                 element_id);
0054 
0055             while (rtlhal->h2c_setinprogress) {
0056                 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
0057                                flag);
0058                 h2c_waitcounter++;
0059                 rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0060                     "Wait 100 us (%d times)...\n",
0061                     h2c_waitcounter);
0062                 udelay(100);
0063 
0064                 if (h2c_waitcounter > 1000)
0065                     return;
0066                 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
0067                           flag);
0068             }
0069             spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
0070         } else {
0071             rtlhal->h2c_setinprogress = true;
0072             spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
0073             break;
0074         }
0075     }
0076 
0077     while (!bwrite_sucess) {
0078         wait_writeh2c_limmit--;
0079         if (wait_writeh2c_limmit == 0) {
0080             pr_err("Write H2C fail because no trigger for FW INT!\n");
0081             break;
0082         }
0083 
0084         boxnum = rtlhal->last_hmeboxnum;
0085         switch (boxnum) {
0086         case 0:
0087             box_reg = REG_HMEBOX_0;
0088             box_extreg = REG_HMEBOX_EXT_0;
0089             break;
0090         case 1:
0091             box_reg = REG_HMEBOX_1;
0092             box_extreg = REG_HMEBOX_EXT_1;
0093             break;
0094         case 2:
0095             box_reg = REG_HMEBOX_2;
0096             box_extreg = REG_HMEBOX_EXT_2;
0097             break;
0098         case 3:
0099             box_reg = REG_HMEBOX_3;
0100             box_extreg = REG_HMEBOX_EXT_3;
0101             break;
0102         default:
0103             pr_err("switch case %#x not processed\n",
0104                    boxnum);
0105             break;
0106         }
0107 
0108         isfw_read = _rtl8723e_check_fw_read_last_h2c(hw, boxnum);
0109         while (!isfw_read) {
0110 
0111             wait_h2c_limmit--;
0112             if (wait_h2c_limmit == 0) {
0113                 rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0114                     "Waiting too long for FW read clear HMEBox(%d)!\n",
0115                     boxnum);
0116                 break;
0117             }
0118 
0119             udelay(10);
0120 
0121             isfw_read = _rtl8723e_check_fw_read_last_h2c(hw,
0122                                 boxnum);
0123             u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
0124             rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0125                 "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n",
0126                 boxnum, u1b_tmp);
0127         }
0128 
0129         if (!isfw_read) {
0130             rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0131                 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
0132                 boxnum);
0133             break;
0134         }
0135 
0136         memset(boxcontent, 0, sizeof(boxcontent));
0137         memset(boxextcontent, 0, sizeof(boxextcontent));
0138         boxcontent[0] = element_id;
0139         rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0140             "Write element_id box_reg(%4x) = %2x\n",
0141             box_reg, element_id);
0142 
0143         switch (cmd_len) {
0144         case 1:
0145             boxcontent[0] &= ~(BIT(7));
0146             memcpy((u8 *)(boxcontent) + 1,
0147                    cmdbuffer + buf_index, 1);
0148 
0149             for (idx = 0; idx < 4; idx++) {
0150                 rtl_write_byte(rtlpriv, box_reg + idx,
0151                            boxcontent[idx]);
0152             }
0153             break;
0154         case 2:
0155             boxcontent[0] &= ~(BIT(7));
0156             memcpy((u8 *)(boxcontent) + 1,
0157                    cmdbuffer + buf_index, 2);
0158 
0159             for (idx = 0; idx < 4; idx++) {
0160                 rtl_write_byte(rtlpriv, box_reg + idx,
0161                            boxcontent[idx]);
0162             }
0163             break;
0164         case 3:
0165             boxcontent[0] &= ~(BIT(7));
0166             memcpy((u8 *)(boxcontent) + 1,
0167                    cmdbuffer + buf_index, 3);
0168 
0169             for (idx = 0; idx < 4; idx++) {
0170                 rtl_write_byte(rtlpriv, box_reg + idx,
0171                            boxcontent[idx]);
0172             }
0173             break;
0174         case 4:
0175             boxcontent[0] |= (BIT(7));
0176             memcpy((u8 *)(boxextcontent),
0177                    cmdbuffer + buf_index, 2);
0178             memcpy((u8 *)(boxcontent) + 1,
0179                    cmdbuffer + buf_index + 2, 2);
0180 
0181             for (idx = 0; idx < 2; idx++) {
0182                 rtl_write_byte(rtlpriv, box_extreg + idx,
0183                            boxextcontent[idx]);
0184             }
0185 
0186             for (idx = 0; idx < 4; idx++) {
0187                 rtl_write_byte(rtlpriv, box_reg + idx,
0188                            boxcontent[idx]);
0189             }
0190             break;
0191         case 5:
0192             boxcontent[0] |= (BIT(7));
0193             memcpy((u8 *)(boxextcontent),
0194                    cmdbuffer + buf_index, 2);
0195             memcpy((u8 *)(boxcontent) + 1,
0196                    cmdbuffer + buf_index + 2, 3);
0197 
0198             for (idx = 0; idx < 2; idx++) {
0199                 rtl_write_byte(rtlpriv, box_extreg + idx,
0200                            boxextcontent[idx]);
0201             }
0202 
0203             for (idx = 0; idx < 4; idx++) {
0204                 rtl_write_byte(rtlpriv, box_reg + idx,
0205                            boxcontent[idx]);
0206             }
0207             break;
0208         default:
0209             pr_err("switch case %#x not processed\n",
0210                    cmd_len);
0211             break;
0212         }
0213 
0214         bwrite_sucess = true;
0215 
0216         rtlhal->last_hmeboxnum = boxnum + 1;
0217         if (rtlhal->last_hmeboxnum == 4)
0218             rtlhal->last_hmeboxnum = 0;
0219 
0220         rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
0221             "pHalData->last_hmeboxnum  = %d\n",
0222             rtlhal->last_hmeboxnum);
0223     }
0224 
0225     spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
0226     rtlhal->h2c_setinprogress = false;
0227     spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
0228 
0229     rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
0230 }
0231 
0232 void rtl8723e_fill_h2c_cmd(struct ieee80211_hw *hw,
0233                u8 element_id, u32 cmd_len, u8 *cmdbuffer)
0234 {
0235     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0236     u32 tmp_cmdbuf[2];
0237 
0238     if (!rtlhal->fw_ready) {
0239         WARN_ONCE(true,
0240               "rtl8723ae: error H2C cmd because of Fw download fail!!!\n");
0241         return;
0242     }
0243     memset(tmp_cmdbuf, 0, 8);
0244     memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
0245     _rtl8723e_fill_h2c_command(hw, element_id, cmd_len,
0246                    (u8 *)&tmp_cmdbuf);
0247 }
0248 
0249 void rtl8723e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
0250 {
0251     struct rtl_priv *rtlpriv = rtl_priv(hw);
0252     u8 u1_h2c_set_pwrmode[3] = { 0 };
0253     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
0254 
0255     rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
0256 
0257     SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
0258     SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
0259         (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1);
0260     SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
0261                           ppsc->reg_max_lps_awakeintvl);
0262 
0263     RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
0264               "rtl8723e_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
0265               u1_h2c_set_pwrmode, 3);
0266     rtl8723e_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
0267 }
0268 
0269 #define BEACON_PG       0 /* ->1 */
0270 #define PSPOLL_PG       2
0271 #define NULL_PG         3
0272 #define PROBERSP_PG     4 /* ->5 */
0273 
0274 #define TOTAL_RESERVED_PKT_LEN  768
0275 
0276 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
0277     /* page 0 beacon */
0278     0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0279     0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
0280     0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
0281     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0282     0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
0283     0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
0284     0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
0285     0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
0286     0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
0287     0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
0288     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0289     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0290     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0291     0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
0292     0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0293     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0294 
0295     /* page 1 beacon */
0296     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0297     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0298     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0299     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0300     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0301     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0302     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0303     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0304     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0305     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0306     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0307     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0308     0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
0309     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0310     0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0311     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0312 
0313     /* page 2  ps-poll */
0314     0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
0315     0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
0316     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0317     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0318     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0319     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0320     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0321     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0322     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0323     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0324     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0325     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0326     0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
0327     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0328     0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0329     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0330 
0331     /* page 3  null */
0332     0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
0333     0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
0334     0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
0335     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0336     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0337     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0338     0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0342     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0343     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0344     0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
0345     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0346     0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0347     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0348 
0349     /* page 4  probe_resp */
0350     0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
0351     0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
0352     0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
0353     0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
0354     0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
0355     0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
0356     0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
0357     0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
0358     0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
0359     0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
0360     0x03, 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     0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
0364     0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0365     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0366 
0367     /* page 5  probe_resp */
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     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0377     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0378     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0379     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0380     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0381     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0382     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0383     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0384 };
0385 
0386 void rtl8723e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
0387 {
0388     struct rtl_priv *rtlpriv = rtl_priv(hw);
0389     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0390     struct sk_buff *skb = NULL;
0391     u32 totalpacketlen;
0392     bool rtstatus;
0393     u8 u1rsvdpageloc[3] = { 0 };
0394     bool b_dlok = false;
0395     u8 *beacon;
0396     u8 *p_pspoll;
0397     u8 *nullfunc;
0398     u8 *p_probersp;
0399 
0400     /*---------------------------------------------------------
0401      *          (1) beacon
0402      *---------------------------------------------------------
0403      */
0404     beacon = &reserved_page_packet[BEACON_PG * 128];
0405     SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
0406     SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
0407 
0408     /*-------------------------------------------------------
0409      *          (2) ps-poll
0410      *--------------------------------------------------------
0411      */
0412     p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
0413     SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
0414     SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
0415     SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
0416 
0417     SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
0418 
0419     /*--------------------------------------------------------
0420      *          (3) null data
0421      *---------------------------------------------------------
0422      */
0423     nullfunc = &reserved_page_packet[NULL_PG * 128];
0424     SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
0425     SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
0426     SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
0427 
0428     SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
0429 
0430     /*---------------------------------------------------------
0431      *          (4) probe response
0432      *----------------------------------------------------------
0433      */
0434     p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
0435     SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
0436     SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
0437     SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
0438 
0439     SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
0440 
0441     totalpacketlen = TOTAL_RESERVED_PKT_LEN;
0442 
0443     RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
0444               "rtl8723e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
0445               &reserved_page_packet[0], totalpacketlen);
0446     RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
0447               "rtl8723e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
0448               u1rsvdpageloc, 3);
0449 
0450     skb = dev_alloc_skb(totalpacketlen);
0451     if (!skb)
0452         return;
0453     skb_put_data(skb, &reserved_page_packet, totalpacketlen);
0454 
0455     rtstatus = rtl_cmd_send_packet(hw, skb);
0456 
0457     if (rtstatus)
0458         b_dlok = true;
0459 
0460     if (b_dlok) {
0461         rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
0462             "Set RSVD page location to Fw.\n");
0463         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
0464                   "H2C_RSVDPAGE:\n",
0465                   u1rsvdpageloc, 3);
0466         rtl8723e_fill_h2c_cmd(hw, H2C_RSVDPAGE,
0467                       sizeof(u1rsvdpageloc), u1rsvdpageloc);
0468     } else
0469         rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
0470             "Set RSVD page location to Fw FAIL!!!!!!.\n");
0471 }
0472 
0473 void rtl8723e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
0474 {
0475     u8 u1_joinbssrpt_parm[1] = { 0 };
0476 
0477     SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
0478 
0479     rtl8723e_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
0480 }
0481 
0482 static void rtl8723e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
0483                         u8 ctwindow)
0484 {
0485     u8 u1_ctwindow_period[1] = { ctwindow};
0486 
0487     rtl8723e_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
0488 
0489 }
0490 
0491 void rtl8723e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
0492 {
0493     struct rtl_priv *rtlpriv = rtl_priv(hw);
0494     struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
0495     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0496     struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
0497     struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
0498     u8  i;
0499     u16 ctwindow;
0500     u32 start_time, tsf_low;
0501 
0502     switch (p2p_ps_state) {
0503     case P2P_PS_DISABLE:
0504         rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
0505         memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
0506         break;
0507     case P2P_PS_ENABLE:
0508         rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
0509         /* update CTWindow value. */
0510         if (p2pinfo->ctwindow > 0) {
0511             p2p_ps_offload->ctwindow_en = 1;
0512             ctwindow = p2pinfo->ctwindow;
0513             rtl8723e_set_p2p_ctw_period_cmd(hw, ctwindow);
0514         }
0515 
0516         /* hw only support 2 set of NoA */
0517         for (i = 0 ; i < p2pinfo->noa_num ; i++) {
0518             /* To control the register setting for which NOA*/
0519             rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
0520             if (i == 0)
0521                 p2p_ps_offload->noa0_en = 1;
0522             else
0523                 p2p_ps_offload->noa1_en = 1;
0524 
0525             /* config P2P NoA Descriptor Register */
0526             rtl_write_dword(rtlpriv, 0x5E0,
0527                     p2pinfo->noa_duration[i]);
0528             rtl_write_dword(rtlpriv, 0x5E4,
0529                     p2pinfo->noa_interval[i]);
0530 
0531             /*Get Current TSF value */
0532             tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
0533 
0534             start_time = p2pinfo->noa_start_time[i];
0535             if (p2pinfo->noa_count_type[i] != 1) {
0536                 while (start_time <=
0537                     (tsf_low+(50*1024))) {
0538                     start_time +=
0539                         p2pinfo->noa_interval[i];
0540                     if (p2pinfo->noa_count_type[i] != 255)
0541                         p2pinfo->noa_count_type[i]--;
0542                 }
0543             }
0544             rtl_write_dword(rtlpriv, 0x5E8, start_time);
0545             rtl_write_dword(rtlpriv, 0x5EC,
0546                 p2pinfo->noa_count_type[i]);
0547 
0548         }
0549 
0550         if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
0551             /* rst p2p circuit */
0552             rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
0553 
0554             p2p_ps_offload->offload_en = 1;
0555 
0556             if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
0557                 p2p_ps_offload->role = 1;
0558                 p2p_ps_offload->allstasleep = 0;
0559             } else {
0560                 p2p_ps_offload->role = 0;
0561             }
0562 
0563             p2p_ps_offload->discovery = 0;
0564         }
0565         break;
0566     case P2P_PS_SCAN:
0567         rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
0568         p2p_ps_offload->discovery = 1;
0569         break;
0570     case P2P_PS_SCAN_DONE:
0571         rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
0572         p2p_ps_offload->discovery = 0;
0573         p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
0574         break;
0575     default:
0576         break;
0577     }
0578 
0579     rtl8723e_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload);
0580 
0581 }