linux/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c
<<
>>
Prefs
   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}
 686