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