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                        pr_err("Write H2C fail because no trigger for FW INT!\n");
 103                        break;
 104                }
 105
 106                boxnum = rtlhal->last_hmeboxnum;
 107                switch (boxnum) {
 108                case 0:
 109                        box_reg = REG_HMEBOX_0;
 110                        box_extreg = REG_HMEBOX_EXT_0;
 111                        break;
 112                case 1:
 113                        box_reg = REG_HMEBOX_1;
 114                        box_extreg = REG_HMEBOX_EXT_1;
 115                        break;
 116                case 2:
 117                        box_reg = REG_HMEBOX_2;
 118                        box_extreg = REG_HMEBOX_EXT_2;
 119                        break;
 120                case 3:
 121                        box_reg = REG_HMEBOX_3;
 122                        box_extreg = REG_HMEBOX_EXT_3;
 123                        break;
 124                default:
 125                        pr_err("switch case %#x not processed\n",
 126                               boxnum);
 127                        break;
 128                }
 129
 130                isfw_read = _rtl8723e_check_fw_read_last_h2c(hw, boxnum);
 131                while (!isfw_read) {
 132
 133                        wait_h2c_limmit--;
 134                        if (wait_h2c_limmit == 0) {
 135                                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 136                                         "Waiting too long for FW read clear HMEBox(%d)!\n",
 137                                         boxnum);
 138                                break;
 139                        }
 140
 141                        udelay(10);
 142
 143                        isfw_read = _rtl8723e_check_fw_read_last_h2c(hw,
 144                                                                boxnum);
 145                        u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
 146                        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 147                                 "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n",
 148                                 boxnum, u1b_tmp);
 149                }
 150
 151                if (!isfw_read) {
 152                        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 153                                 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
 154                                 boxnum);
 155                        break;
 156                }
 157
 158                memset(boxcontent, 0, sizeof(boxcontent));
 159                memset(boxextcontent, 0, sizeof(boxextcontent));
 160                boxcontent[0] = element_id;
 161                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 162                         "Write element_id box_reg(%4x) = %2x\n",
 163                          box_reg, element_id);
 164
 165                switch (cmd_len) {
 166                case 1:
 167                        boxcontent[0] &= ~(BIT(7));
 168                        memcpy((u8 *)(boxcontent) + 1,
 169                               cmdbuffer + buf_index, 1);
 170
 171                        for (idx = 0; idx < 4; idx++) {
 172                                rtl_write_byte(rtlpriv, box_reg + idx,
 173                                               boxcontent[idx]);
 174                        }
 175                        break;
 176                case 2:
 177                        boxcontent[0] &= ~(BIT(7));
 178                        memcpy((u8 *)(boxcontent) + 1,
 179                               cmdbuffer + buf_index, 2);
 180
 181                        for (idx = 0; idx < 4; idx++) {
 182                                rtl_write_byte(rtlpriv, box_reg + idx,
 183                                               boxcontent[idx]);
 184                        }
 185                        break;
 186                case 3:
 187                        boxcontent[0] &= ~(BIT(7));
 188                        memcpy((u8 *)(boxcontent) + 1,
 189                               cmdbuffer + buf_index, 3);
 190
 191                        for (idx = 0; idx < 4; idx++) {
 192                                rtl_write_byte(rtlpriv, box_reg + idx,
 193                                               boxcontent[idx]);
 194                        }
 195                        break;
 196                case 4:
 197                        boxcontent[0] |= (BIT(7));
 198                        memcpy((u8 *)(boxextcontent),
 199                               cmdbuffer + buf_index, 2);
 200                        memcpy((u8 *)(boxcontent) + 1,
 201                               cmdbuffer + buf_index + 2, 2);
 202
 203                        for (idx = 0; idx < 2; idx++) {
 204                                rtl_write_byte(rtlpriv, box_extreg + idx,
 205                                               boxextcontent[idx]);
 206                        }
 207
 208                        for (idx = 0; idx < 4; idx++) {
 209                                rtl_write_byte(rtlpriv, box_reg + idx,
 210                                               boxcontent[idx]);
 211                        }
 212                        break;
 213                case 5:
 214                        boxcontent[0] |= (BIT(7));
 215                        memcpy((u8 *)(boxextcontent),
 216                               cmdbuffer + buf_index, 2);
 217                        memcpy((u8 *)(boxcontent) + 1,
 218                               cmdbuffer + buf_index + 2, 3);
 219
 220                        for (idx = 0; idx < 2; idx++) {
 221                                rtl_write_byte(rtlpriv, box_extreg + idx,
 222                                               boxextcontent[idx]);
 223                        }
 224
 225                        for (idx = 0; idx < 4; idx++) {
 226                                rtl_write_byte(rtlpriv, box_reg + idx,
 227                                               boxcontent[idx]);
 228                        }
 229                        break;
 230                default:
 231                        pr_err("switch case %#x not processed\n",
 232                               cmd_len);
 233                        break;
 234                }
 235
 236                bwrite_sucess = true;
 237
 238                rtlhal->last_hmeboxnum = boxnum + 1;
 239                if (rtlhal->last_hmeboxnum == 4)
 240                        rtlhal->last_hmeboxnum = 0;
 241
 242                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 243                         "pHalData->last_hmeboxnum  = %d\n",
 244                          rtlhal->last_hmeboxnum);
 245        }
 246
 247        spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
 248        rtlhal->h2c_setinprogress = false;
 249        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 250
 251        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
 252}
 253
 254void rtl8723e_fill_h2c_cmd(struct ieee80211_hw *hw,
 255                           u8 element_id, u32 cmd_len, u8 *cmdbuffer)
 256{
 257        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 258        u32 tmp_cmdbuf[2];
 259
 260        if (!rtlhal->fw_ready) {
 261                WARN_ONCE(true,
 262                          "rtl8723ae: error H2C cmd because of Fw download fail!!!\n");
 263                return;
 264        }
 265        memset(tmp_cmdbuf, 0, 8);
 266        memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
 267        _rtl8723e_fill_h2c_command(hw, element_id, cmd_len,
 268                                   (u8 *)&tmp_cmdbuf);
 269}
 270
 271void rtl8723e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
 272{
 273        struct rtl_priv *rtlpriv = rtl_priv(hw);
 274        u8 u1_h2c_set_pwrmode[3] = { 0 };
 275        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 276
 277        RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
 278
 279        SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
 280        SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
 281                (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1);
 282        SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
 283                                              ppsc->reg_max_lps_awakeintvl);
 284
 285        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
 286                      "rtl8723e_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
 287                      u1_h2c_set_pwrmode, 3);
 288        rtl8723e_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
 289}
 290
 291#define BEACON_PG               0 /* ->1 */
 292#define PSPOLL_PG               2
 293#define NULL_PG                 3
 294#define PROBERSP_PG             4 /* ->5 */
 295
 296#define TOTAL_RESERVED_PKT_LEN  768
 297
 298static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
 299        /* page 0 beacon */
 300        0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
 301        0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 302        0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
 303        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 304        0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
 305        0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
 306        0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
 307        0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
 308        0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
 309        0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
 310        0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 311        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 312        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 313        0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
 314        0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 315        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 316
 317        /* page 1 beacon */
 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        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        0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
 331        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 332        0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 333        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 334
 335        /* page 2  ps-poll */
 336        0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
 337        0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 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        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        0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
 349        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
 350        0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 351        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 352
 353        /* page 3  null */
 354        0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
 355        0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 356        0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
 357        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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        0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
 367        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
 368        0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 369        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 370
 371        /* page 4  probe_resp */
 372        0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
 373        0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 374        0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
 375        0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
 376        0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
 377        0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
 378        0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
 379        0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
 380        0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
 381        0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
 382        0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 383        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 384        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 385        0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
 386        0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 387        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 388
 389        /* page 5  probe_resp */
 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        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};
 407
 408void rtl8723e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
 409{
 410        struct rtl_priv *rtlpriv = rtl_priv(hw);
 411        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 412        struct sk_buff *skb = NULL;
 413        u32 totalpacketlen;
 414        bool rtstatus;
 415        u8 u1rsvdpageloc[3] = { 0 };
 416        bool b_dlok = false;
 417        u8 *beacon;
 418        u8 *p_pspoll;
 419        u8 *nullfunc;
 420        u8 *p_probersp;
 421
 422        /*---------------------------------------------------------
 423         *                      (1) beacon
 424         *---------------------------------------------------------
 425         */
 426        beacon = &reserved_page_packet[BEACON_PG * 128];
 427        SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
 428        SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
 429
 430        /*-------------------------------------------------------
 431         *                      (2) ps-poll
 432         *--------------------------------------------------------
 433         */
 434        p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
 435        SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
 436        SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
 437        SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
 438
 439        SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
 440
 441        /*--------------------------------------------------------
 442         *                      (3) null data
 443         *---------------------------------------------------------
 444         */
 445        nullfunc = &reserved_page_packet[NULL_PG * 128];
 446        SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
 447        SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
 448        SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
 449
 450        SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
 451
 452        /*---------------------------------------------------------
 453         *                      (4) probe response
 454         *----------------------------------------------------------
 455         */
 456        p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
 457        SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
 458        SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
 459        SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
 460
 461        SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
 462
 463        totalpacketlen = TOTAL_RESERVED_PKT_LEN;
 464
 465        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
 466                      "rtl8723e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
 467                      &reserved_page_packet[0], totalpacketlen);
 468        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
 469                      "rtl8723e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
 470                      u1rsvdpageloc, 3);
 471
 472        skb = dev_alloc_skb(totalpacketlen);
 473        skb_put_data(skb, &reserved_page_packet, totalpacketlen);
 474
 475        rtstatus = rtl_cmd_send_packet(hw, skb);
 476
 477        if (rtstatus)
 478                b_dlok = true;
 479
 480        if (b_dlok) {
 481                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 482                         "Set RSVD page location to Fw.\n");
 483                RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
 484                              "H2C_RSVDPAGE:\n",
 485                              u1rsvdpageloc, 3);
 486                rtl8723e_fill_h2c_cmd(hw, H2C_RSVDPAGE,
 487                                      sizeof(u1rsvdpageloc), u1rsvdpageloc);
 488        } else
 489                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 490                         "Set RSVD page location to Fw FAIL!!!!!!.\n");
 491}
 492
 493void rtl8723e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
 494{
 495        u8 u1_joinbssrpt_parm[1] = { 0 };
 496
 497        SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
 498
 499        rtl8723e_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
 500}
 501
 502static void rtl8723e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
 503                                            u8 ctwindow)
 504{
 505        u8 u1_ctwindow_period[1] = { ctwindow};
 506
 507        rtl8723e_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
 508
 509}
 510
 511void rtl8723e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
 512{
 513        struct rtl_priv *rtlpriv = rtl_priv(hw);
 514        struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
 515        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 516        struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
 517        struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
 518        u8      i;
 519        u16     ctwindow;
 520        u32     start_time, tsf_low;
 521
 522        switch (p2p_ps_state) {
 523        case P2P_PS_DISABLE:
 524                RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
 525                memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
 526                break;
 527        case P2P_PS_ENABLE:
 528                RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
 529                /* update CTWindow value. */
 530                if (p2pinfo->ctwindow > 0) {
 531                        p2p_ps_offload->ctwindow_en = 1;
 532                        ctwindow = p2pinfo->ctwindow;
 533                        rtl8723e_set_p2p_ctw_period_cmd(hw, ctwindow);
 534                }
 535
 536                /* hw only support 2 set of NoA */
 537                for (i = 0 ; i < p2pinfo->noa_num ; i++) {
 538                        /* To control the register setting for which NOA*/
 539                        rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
 540                        if (i == 0)
 541                                p2p_ps_offload->noa0_en = 1;
 542                        else
 543                                p2p_ps_offload->noa1_en = 1;
 544
 545                        /* config P2P NoA Descriptor Register */
 546                        rtl_write_dword(rtlpriv, 0x5E0,
 547                                        p2pinfo->noa_duration[i]);
 548                        rtl_write_dword(rtlpriv, 0x5E4,
 549                                        p2pinfo->noa_interval[i]);
 550
 551                        /*Get Current TSF value */
 552                        tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
 553
 554                        start_time = p2pinfo->noa_start_time[i];
 555                        if (p2pinfo->noa_count_type[i] != 1) {
 556                                while (start_time <=
 557                                        (tsf_low+(50*1024))) {
 558                                        start_time +=
 559                                                p2pinfo->noa_interval[i];
 560                                        if (p2pinfo->noa_count_type[i] != 255)
 561                                                p2pinfo->noa_count_type[i]--;
 562                                }
 563                        }
 564                        rtl_write_dword(rtlpriv, 0x5E8, start_time);
 565                        rtl_write_dword(rtlpriv, 0x5EC,
 566                                p2pinfo->noa_count_type[i]);
 567
 568                }
 569
 570                if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
 571                        /* rst p2p circuit */
 572                        rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
 573
 574                        p2p_ps_offload->offload_en = 1;
 575
 576                        if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
 577                                p2p_ps_offload->role = 1;
 578                                p2p_ps_offload->allstasleep = 0;
 579                        } else {
 580                                p2p_ps_offload->role = 0;
 581                        }
 582
 583                        p2p_ps_offload->discovery = 0;
 584                }
 585                break;
 586        case P2P_PS_SCAN:
 587                RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
 588                p2p_ps_offload->discovery = 1;
 589                break;
 590        case P2P_PS_SCAN_DONE:
 591                RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
 592                p2p_ps_offload->discovery = 0;
 593                p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
 594                break;
 595        default:
 596                break;
 597        }
 598
 599        rtl8723e_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload);
 600
 601}
 602