linux/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 2009-2012  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 _rtl8723e_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, val_mcutst_1;
  18        bool result = false;
  19
  20        val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
  21        val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
  22
  23        if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
  24                result = true;
  25        return result;
  26}
  27
  28static void _rtl8723e_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
  29                                       u32 cmd_len, u8 *cmdbuffer)
  30{
  31        struct rtl_priv *rtlpriv = rtl_priv(hw);
  32        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  33        u8 boxnum;
  34        u16 box_reg = 0, box_extreg = 0;
  35        u8 u1b_tmp;
  36        bool isfw_read = false;
  37        u8 buf_index = 0;
  38        bool bwrite_sucess = false;
  39        u8 wait_h2c_limmit = 100;
  40        u8 wait_writeh2c_limmit = 100;
  41        u8 boxcontent[4], boxextcontent[2];
  42        u32 h2c_waitcounter = 0;
  43        unsigned long flag;
  44        u8 idx;
  45
  46        rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
  47
  48        while (true) {
  49                spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
  50                if (rtlhal->h2c_setinprogress) {
  51                        rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
  52                                "H2C set in progress! Wait to set..element_id(%d).\n",
  53                                element_id);
  54
  55                        while (rtlhal->h2c_setinprogress) {
  56                                spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
  57                                                       flag);
  58                                h2c_waitcounter++;
  59                                rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
  60                                        "Wait 100 us (%d times)...\n",
  61                                        h2c_waitcounter);
  62                                udelay(100);
  63
  64                                if (h2c_waitcounter > 1000)
  65                                        return;
  66                                spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
  67                                                  flag);
  68                        }
  69                        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
  70                } else {
  71                        rtlhal->h2c_setinprogress = true;
  72                        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
  73                        break;
  74                }
  75        }
  76
  77        while (!bwrite_sucess) {
  78                wait_writeh2c_limmit--;
  79                if (wait_writeh2c_limmit == 0) {
  80                        pr_err("Write H2C fail because no trigger for FW INT!\n");
  81                        break;
  82                }
  83
  84                boxnum = rtlhal->last_hmeboxnum;
  85                switch (boxnum) {
  86                case 0:
  87                        box_reg = REG_HMEBOX_0;
  88                        box_extreg = REG_HMEBOX_EXT_0;
  89                        break;
  90                case 1:
  91                        box_reg = REG_HMEBOX_1;
  92                        box_extreg = REG_HMEBOX_EXT_1;
  93                        break;
  94                case 2:
  95                        box_reg = REG_HMEBOX_2;
  96                        box_extreg = REG_HMEBOX_EXT_2;
  97                        break;
  98                case 3:
  99                        box_reg = REG_HMEBOX_3;
 100                        box_extreg = REG_HMEBOX_EXT_3;
 101                        break;
 102                default:
 103                        pr_err("switch case %#x not processed\n",
 104                               boxnum);
 105                        break;
 106                }
 107
 108                isfw_read = _rtl8723e_check_fw_read_last_h2c(hw, boxnum);
 109                while (!isfw_read) {
 110
 111                        wait_h2c_limmit--;
 112                        if (wait_h2c_limmit == 0) {
 113                                rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 114                                        "Waiting too long for FW read clear HMEBox(%d)!\n",
 115                                        boxnum);
 116                                break;
 117                        }
 118
 119                        udelay(10);
 120
 121                        isfw_read = _rtl8723e_check_fw_read_last_h2c(hw,
 122                                                                boxnum);
 123                        u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
 124                        rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 125                                "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n",
 126                                boxnum, u1b_tmp);
 127                }
 128
 129                if (!isfw_read) {
 130                        rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 131                                "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
 132                                boxnum);
 133                        break;
 134                }
 135
 136                memset(boxcontent, 0, sizeof(boxcontent));
 137                memset(boxextcontent, 0, sizeof(boxextcontent));
 138                boxcontent[0] = element_id;
 139                rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 140                        "Write element_id box_reg(%4x) = %2x\n",
 141                        box_reg, element_id);
 142
 143                switch (cmd_len) {
 144                case 1:
 145                        boxcontent[0] &= ~(BIT(7));
 146                        memcpy((u8 *)(boxcontent) + 1,
 147                               cmdbuffer + buf_index, 1);
 148
 149                        for (idx = 0; idx < 4; idx++) {
 150                                rtl_write_byte(rtlpriv, box_reg + idx,
 151                                               boxcontent[idx]);
 152                        }
 153                        break;
 154                case 2:
 155                        boxcontent[0] &= ~(BIT(7));
 156                        memcpy((u8 *)(boxcontent) + 1,
 157                               cmdbuffer + buf_index, 2);
 158
 159                        for (idx = 0; idx < 4; idx++) {
 160                                rtl_write_byte(rtlpriv, box_reg + idx,
 161                                               boxcontent[idx]);
 162                        }
 163                        break;
 164                case 3:
 165                        boxcontent[0] &= ~(BIT(7));
 166                        memcpy((u8 *)(boxcontent) + 1,
 167                               cmdbuffer + buf_index, 3);
 168
 169                        for (idx = 0; idx < 4; idx++) {
 170                                rtl_write_byte(rtlpriv, box_reg + idx,
 171                                               boxcontent[idx]);
 172                        }
 173                        break;
 174                case 4:
 175                        boxcontent[0] |= (BIT(7));
 176                        memcpy((u8 *)(boxextcontent),
 177                               cmdbuffer + buf_index, 2);
 178                        memcpy((u8 *)(boxcontent) + 1,
 179                               cmdbuffer + buf_index + 2, 2);
 180
 181                        for (idx = 0; idx < 2; idx++) {
 182                                rtl_write_byte(rtlpriv, box_extreg + idx,
 183                                               boxextcontent[idx]);
 184                        }
 185
 186                        for (idx = 0; idx < 4; idx++) {
 187                                rtl_write_byte(rtlpriv, box_reg + idx,
 188                                               boxcontent[idx]);
 189                        }
 190                        break;
 191                case 5:
 192                        boxcontent[0] |= (BIT(7));
 193                        memcpy((u8 *)(boxextcontent),
 194                               cmdbuffer + buf_index, 2);
 195                        memcpy((u8 *)(boxcontent) + 1,
 196                               cmdbuffer + buf_index + 2, 3);
 197
 198                        for (idx = 0; idx < 2; idx++) {
 199                                rtl_write_byte(rtlpriv, box_extreg + idx,
 200                                               boxextcontent[idx]);
 201                        }
 202
 203                        for (idx = 0; idx < 4; idx++) {
 204                                rtl_write_byte(rtlpriv, box_reg + idx,
 205                                               boxcontent[idx]);
 206                        }
 207                        break;
 208                default:
 209                        pr_err("switch case %#x not processed\n",
 210                               cmd_len);
 211                        break;
 212                }
 213
 214                bwrite_sucess = true;
 215
 216                rtlhal->last_hmeboxnum = boxnum + 1;
 217                if (rtlhal->last_hmeboxnum == 4)
 218                        rtlhal->last_hmeboxnum = 0;
 219
 220                rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 221                        "pHalData->last_hmeboxnum  = %d\n",
 222                        rtlhal->last_hmeboxnum);
 223        }
 224
 225        spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
 226        rtlhal->h2c_setinprogress = false;
 227        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 228
 229        rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
 230}
 231
 232void rtl8723e_fill_h2c_cmd(struct ieee80211_hw *hw,
 233                           u8 element_id, u32 cmd_len, u8 *cmdbuffer)
 234{
 235        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 236        u32 tmp_cmdbuf[2];
 237
 238        if (!rtlhal->fw_ready) {
 239                WARN_ONCE(true,
 240                          "rtl8723ae: error H2C cmd because of Fw download fail!!!\n");
 241                return;
 242        }
 243        memset(tmp_cmdbuf, 0, 8);
 244        memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
 245        _rtl8723e_fill_h2c_command(hw, element_id, cmd_len,
 246                                   (u8 *)&tmp_cmdbuf);
 247}
 248
 249void rtl8723e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
 250{
 251        struct rtl_priv *rtlpriv = rtl_priv(hw);
 252        u8 u1_h2c_set_pwrmode[3] = { 0 };
 253        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 254
 255        rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
 256
 257        SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
 258        SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
 259                (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1);
 260        SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
 261                                              ppsc->reg_max_lps_awakeintvl);
 262
 263        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
 264                      "rtl8723e_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
 265                      u1_h2c_set_pwrmode, 3);
 266        rtl8723e_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
 267}
 268
 269#define BEACON_PG               0 /* ->1 */
 270#define PSPOLL_PG               2
 271#define NULL_PG                 3
 272#define PROBERSP_PG             4 /* ->5 */
 273
 274#define TOTAL_RESERVED_PKT_LEN  768
 275
 276static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
 277        /* page 0 beacon */
 278        0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
 279        0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 280        0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
 281        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 282        0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
 283        0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
 284        0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
 285        0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
 286        0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
 287        0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
 288        0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 289        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 290        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 291        0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
 292        0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 293        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 294
 295        /* page 1 beacon */
 296        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 297        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 298        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 299        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 300        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 301        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 302        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 303        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 304        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 305        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 306        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 307        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 308        0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
 309        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 310        0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 311        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 312
 313        /* page 2  ps-poll */
 314        0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
 315        0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 316        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 317        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 318        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 319        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 320        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 321        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 322        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 323        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 324        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 325        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 326        0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
 327        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
 328        0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 329        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 330
 331        /* page 3  null */
 332        0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
 333        0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 334        0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
 335        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 336        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 337        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 338        0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 342        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 343        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 344        0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
 345        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
 346        0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 347        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 348
 349        /* page 4  probe_resp */
 350        0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
 351        0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 352        0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
 353        0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
 354        0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
 355        0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
 356        0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
 357        0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
 358        0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
 359        0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
 360        0x03, 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        0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
 364        0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 365        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 366
 367        /* page 5  probe_resp */
 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        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 377        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 378        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 379        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 380        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 381        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 382        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 383        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 384};
 385
 386void rtl8723e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
 387{
 388        struct rtl_priv *rtlpriv = rtl_priv(hw);
 389        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 390        struct sk_buff *skb = NULL;
 391        u32 totalpacketlen;
 392        bool rtstatus;
 393        u8 u1rsvdpageloc[3] = { 0 };
 394        bool b_dlok = false;
 395        u8 *beacon;
 396        u8 *p_pspoll;
 397        u8 *nullfunc;
 398        u8 *p_probersp;
 399
 400        /*---------------------------------------------------------
 401         *                      (1) beacon
 402         *---------------------------------------------------------
 403         */
 404        beacon = &reserved_page_packet[BEACON_PG * 128];
 405        SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
 406        SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
 407
 408        /*-------------------------------------------------------
 409         *                      (2) ps-poll
 410         *--------------------------------------------------------
 411         */
 412        p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
 413        SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
 414        SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
 415        SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
 416
 417        SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
 418
 419        /*--------------------------------------------------------
 420         *                      (3) null data
 421         *---------------------------------------------------------
 422         */
 423        nullfunc = &reserved_page_packet[NULL_PG * 128];
 424        SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
 425        SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
 426        SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
 427
 428        SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
 429
 430        /*---------------------------------------------------------
 431         *                      (4) probe response
 432         *----------------------------------------------------------
 433         */
 434        p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
 435        SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
 436        SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
 437        SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
 438
 439        SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
 440
 441        totalpacketlen = TOTAL_RESERVED_PKT_LEN;
 442
 443        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
 444                      "rtl8723e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
 445                      &reserved_page_packet[0], totalpacketlen);
 446        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
 447                      "rtl8723e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
 448                      u1rsvdpageloc, 3);
 449
 450        skb = dev_alloc_skb(totalpacketlen);
 451        if (!skb)
 452                return;
 453        skb_put_data(skb, &reserved_page_packet, totalpacketlen);
 454
 455        rtstatus = rtl_cmd_send_packet(hw, skb);
 456
 457        if (rtstatus)
 458                b_dlok = true;
 459
 460        if (b_dlok) {
 461                rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
 462                        "Set RSVD page location to Fw.\n");
 463                RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
 464                              "H2C_RSVDPAGE:\n",
 465                              u1rsvdpageloc, 3);
 466                rtl8723e_fill_h2c_cmd(hw, H2C_RSVDPAGE,
 467                                      sizeof(u1rsvdpageloc), u1rsvdpageloc);
 468        } else
 469                rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
 470                        "Set RSVD page location to Fw FAIL!!!!!!.\n");
 471}
 472
 473void rtl8723e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
 474{
 475        u8 u1_joinbssrpt_parm[1] = { 0 };
 476
 477        SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
 478
 479        rtl8723e_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
 480}
 481
 482static void rtl8723e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
 483                                            u8 ctwindow)
 484{
 485        u8 u1_ctwindow_period[1] = { ctwindow};
 486
 487        rtl8723e_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
 488
 489}
 490
 491void rtl8723e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
 492{
 493        struct rtl_priv *rtlpriv = rtl_priv(hw);
 494        struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
 495        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 496        struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
 497        struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
 498        u8      i;
 499        u16     ctwindow;
 500        u32     start_time, tsf_low;
 501
 502        switch (p2p_ps_state) {
 503        case P2P_PS_DISABLE:
 504                rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
 505                memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
 506                break;
 507        case P2P_PS_ENABLE:
 508                rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
 509                /* update CTWindow value. */
 510                if (p2pinfo->ctwindow > 0) {
 511                        p2p_ps_offload->ctwindow_en = 1;
 512                        ctwindow = p2pinfo->ctwindow;
 513                        rtl8723e_set_p2p_ctw_period_cmd(hw, ctwindow);
 514                }
 515
 516                /* hw only support 2 set of NoA */
 517                for (i = 0 ; i < p2pinfo->noa_num ; i++) {
 518                        /* To control the register setting for which NOA*/
 519                        rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
 520                        if (i == 0)
 521                                p2p_ps_offload->noa0_en = 1;
 522                        else
 523                                p2p_ps_offload->noa1_en = 1;
 524
 525                        /* config P2P NoA Descriptor Register */
 526                        rtl_write_dword(rtlpriv, 0x5E0,
 527                                        p2pinfo->noa_duration[i]);
 528                        rtl_write_dword(rtlpriv, 0x5E4,
 529                                        p2pinfo->noa_interval[i]);
 530
 531                        /*Get Current TSF value */
 532                        tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
 533
 534                        start_time = p2pinfo->noa_start_time[i];
 535                        if (p2pinfo->noa_count_type[i] != 1) {
 536                                while (start_time <=
 537                                        (tsf_low+(50*1024))) {
 538                                        start_time +=
 539                                                p2pinfo->noa_interval[i];
 540                                        if (p2pinfo->noa_count_type[i] != 255)
 541                                                p2pinfo->noa_count_type[i]--;
 542                                }
 543                        }
 544                        rtl_write_dword(rtlpriv, 0x5E8, start_time);
 545                        rtl_write_dword(rtlpriv, 0x5EC,
 546                                p2pinfo->noa_count_type[i]);
 547
 548                }
 549
 550                if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
 551                        /* rst p2p circuit */
 552                        rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
 553
 554                        p2p_ps_offload->offload_en = 1;
 555
 556                        if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
 557                                p2p_ps_offload->role = 1;
 558                                p2p_ps_offload->allstasleep = 0;
 559                        } else {
 560                                p2p_ps_offload->role = 0;
 561                        }
 562
 563                        p2p_ps_offload->discovery = 0;
 564                }
 565                break;
 566        case P2P_PS_SCAN:
 567                rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
 568                p2p_ps_offload->discovery = 1;
 569                break;
 570        case P2P_PS_SCAN_DONE:
 571                rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
 572                p2p_ps_offload->discovery = 0;
 573                p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
 574                break;
 575        default:
 576                break;
 577        }
 578
 579        rtl8723e_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload);
 580
 581}
 582