linux/drivers/net/wireless/rtlwifi/rtl8723be/fw.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2009-2014  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 _rtl8723be_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;
  40        bool result = false;
  41
  42        val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
  43        if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
  44                result = true;
  45        return result;
  46}
  47
  48static void _rtl8723be_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
  49                                        u32 cmd_len, u8 *p_cmdbuffer)
  50{
  51        struct rtl_priv *rtlpriv = rtl_priv(hw);
  52        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  53        u8 boxnum;
  54        u16 box_reg = 0, box_extreg = 0;
  55        u8 u1b_tmp;
  56        bool isfw_read = false;
  57        u8 buf_index = 0;
  58        bool bwrite_sucess = false;
  59        u8 wait_h2c_limmit = 100;
  60        u8 wait_writeh2c_limmit = 100;
  61        u8 boxcontent[4], boxextcontent[4];
  62        u32 h2c_waitcounter = 0;
  63        unsigned long flag;
  64        u8 idx;
  65
  66        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
  67
  68        while (true) {
  69                spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
  70                if (rtlhal->h2c_setinprogress) {
  71                        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
  72                                 "H2C set in progress! Wait to set..element_id(%d).\n",
  73                                 element_id);
  74
  75                        while (rtlhal->h2c_setinprogress) {
  76                                spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
  77                                                       flag);
  78                                h2c_waitcounter++;
  79                                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
  80                                         "Wait 100 us (%d times)...\n",
  81                                         h2c_waitcounter);
  82                                udelay(100);
  83
  84                                if (h2c_waitcounter > 1000)
  85                                        return;
  86                                spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
  87                                                  flag);
  88                        }
  89                        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
  90                } else {
  91                        rtlhal->h2c_setinprogress = true;
  92                        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
  93                        break;
  94                }
  95        }
  96
  97        while (!bwrite_sucess) {
  98                wait_writeh2c_limmit--;
  99                if (wait_writeh2c_limmit == 0) {
 100                        RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 101                                 "Write H2C fail because no trigger for FW INT!\n");
 102                        break;
 103                }
 104
 105                boxnum = rtlhal->last_hmeboxnum;
 106                switch (boxnum) {
 107                case 0:
 108                        box_reg = REG_HMEBOX_0;
 109                        box_extreg = REG_HMEBOX_EXT_0;
 110                        break;
 111                case 1:
 112                        box_reg = REG_HMEBOX_1;
 113                        box_extreg = REG_HMEBOX_EXT_1;
 114                        break;
 115                case 2:
 116                        box_reg = REG_HMEBOX_2;
 117                        box_extreg = REG_HMEBOX_EXT_2;
 118                        break;
 119                case 3:
 120                        box_reg = REG_HMEBOX_3;
 121                        box_extreg = REG_HMEBOX_EXT_3;
 122                        break;
 123                default:
 124                        RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 125                                 "switch case not process\n");
 126                        break;
 127                }
 128
 129                isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, boxnum);
 130                while (!isfw_read) {
 131                        wait_h2c_limmit--;
 132                        if (wait_h2c_limmit == 0) {
 133                                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 134                                         "Waiting too long for FW read clear HMEBox(%d)!\n",
 135                                         boxnum);
 136                                break;
 137                        }
 138
 139                        udelay(10);
 140
 141                        isfw_read = _rtl8723be_check_fw_read_last_h2c(hw,
 142                                                                boxnum);
 143                        u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
 144                        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 145                                 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
 146                                 boxnum, u1b_tmp);
 147                }
 148
 149                if (!isfw_read) {
 150                        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 151                                 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
 152                                 boxnum);
 153                        break;
 154                }
 155
 156                memset(boxcontent, 0, sizeof(boxcontent));
 157                memset(boxextcontent, 0, sizeof(boxextcontent));
 158                boxcontent[0] = element_id;
 159                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 160                         "Write element_id box_reg(%4x) = %2x\n",
 161                          box_reg, element_id);
 162
 163                switch (cmd_len) {
 164                case 1:
 165                case 2:
 166                case 3:
 167                        /*boxcontent[0] &= ~(BIT(7));*/
 168                        memcpy((u8 *)(boxcontent) + 1,
 169                               p_cmdbuffer + buf_index, cmd_len);
 170
 171                        for (idx = 0; idx < 4; idx++) {
 172                                rtl_write_byte(rtlpriv, box_reg + idx,
 173                                               boxcontent[idx]);
 174                        }
 175                        break;
 176                case 4:
 177                case 5:
 178                case 6:
 179                case 7:
 180                        /*boxcontent[0] |= (BIT(7));*/
 181                        memcpy((u8 *)(boxextcontent),
 182                               p_cmdbuffer + buf_index+3, cmd_len-3);
 183                        memcpy((u8 *)(boxcontent) + 1,
 184                               p_cmdbuffer + buf_index, 3);
 185
 186                        for (idx = 0; idx < 4; idx++) {
 187                                rtl_write_byte(rtlpriv, box_extreg + idx,
 188                                               boxextcontent[idx]);
 189                        }
 190
 191                        for (idx = 0; idx < 4; idx++) {
 192                                rtl_write_byte(rtlpriv, box_reg + idx,
 193                                               boxcontent[idx]);
 194                        }
 195                        break;
 196                default:
 197                        RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 198                                 "switch case not process\n");
 199                        break;
 200                }
 201
 202                bwrite_sucess = true;
 203
 204                rtlhal->last_hmeboxnum = boxnum + 1;
 205                if (rtlhal->last_hmeboxnum == 4)
 206                        rtlhal->last_hmeboxnum = 0;
 207
 208                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 209                         "pHalData->last_hmeboxnum  = %d\n",
 210                          rtlhal->last_hmeboxnum);
 211        }
 212
 213        spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
 214        rtlhal->h2c_setinprogress = false;
 215        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 216
 217        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
 218}
 219
 220void rtl8723be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
 221                            u32 cmd_len, u8 *p_cmdbuffer)
 222{
 223        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 224        u32 tmp_cmdbuf[2];
 225
 226        if (!rtlhal->fw_ready) {
 227                RT_ASSERT(false,
 228                          "return H2C cmd because of Fw download fail!!!\n");
 229                return;
 230        }
 231
 232        memset(tmp_cmdbuf, 0, 8);
 233        memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
 234        _rtl8723be_fill_h2c_command(hw, element_id, cmd_len,
 235                                    (u8 *)&tmp_cmdbuf);
 236        return;
 237}
 238
 239void rtl8723be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
 240{
 241        struct rtl_priv *rtlpriv = rtl_priv(hw);
 242        u8 u1_h2c_set_pwrmode[H2C_PWEMODE_LENGTH] = { 0 };
 243        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 244        u8 rlbm, power_state = 0;
 245        RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
 246
 247        SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
 248        rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/
 249        SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
 250        SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
 251                                         (rtlpriv->mac80211.p2p) ?
 252                                          ppsc->smart_ps : 1);
 253        SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
 254                                               ppsc->reg_max_lps_awakeintvl);
 255        SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
 256        if (mode == FW_PS_ACTIVE_MODE)
 257                power_state |= FW_PWR_STATE_ACTIVE;
 258        else
 259                power_state |= FW_PWR_STATE_RF_OFF;
 260        SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
 261
 262        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
 263                      "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
 264                      u1_h2c_set_pwrmode, H2C_PWEMODE_LENGTH);
 265        rtl8723be_fill_h2c_cmd(hw, H2C_8723B_SETPWRMODE, H2C_PWEMODE_LENGTH,
 266                               u1_h2c_set_pwrmode);
 267}
 268
 269void rtl8723be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
 270{
 271        u8 parm[3] = { 0, 0, 0 };
 272        /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
 273         *          bit1=0-->update Media Status to MACID
 274         *          bit1=1-->update Media Status from MACID to MACID_End
 275         * parm[1]: MACID, if this is INFRA_STA, MacID = 0
 276         * parm[2]: MACID_End
 277        */
 278        SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
 279        SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
 280
 281        rtl8723be_fill_h2c_cmd(hw, H2C_8723B_MSRRPT, 3, parm);
 282}
 283
 284#define BEACON_PG               0 /* ->1 */
 285#define PSPOLL_PG               2
 286#define NULL_PG                 3
 287#define PROBERSP_PG             4 /* ->5 */
 288
 289#define TOTAL_RESERVED_PKT_LEN  768
 290
 291static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
 292        /* page 0 beacon */
 293        0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
 294        0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
 295        0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
 296        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 297        0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
 298        0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
 299        0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
 300        0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
 301        0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
 302        0x09, 0x03, 0xFF, 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, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
 306        0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
 307        0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
 308        0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
 309
 310        /* page 1 beacon */
 311        0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
 312        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 313        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 314        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 315        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 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        0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
 323        0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 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
 328        /* page 2  ps-poll */
 329        0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
 330        0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
 331        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 332        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 333        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 334        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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        0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
 341        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
 342        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 343        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 344        0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 345
 346        /* page 3  null */
 347        0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
 348        0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
 349        0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 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        0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
 359        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
 360        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 361        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 362        0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 363
 364        /* page 4  probe_resp */
 365        0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
 366        0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 367        0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
 368        0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
 369        0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
 370        0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
 371        0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
 372        0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
 373        0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
 374        0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
 375        0x03, 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        0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
 379        0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 380        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 381
 382        /* page 5  probe_resp */
 383        0x00, 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        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        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};
 400
 401void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
 402                                  bool b_dl_finished)
 403{
 404        struct rtl_priv *rtlpriv = rtl_priv(hw);
 405        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 406        struct sk_buff *skb = NULL;
 407
 408        u32 totalpacketlen;
 409        bool rtstatus;
 410        u8 u1rsvdpageloc[5] = { 0 };
 411        bool b_dlok = false;
 412
 413        u8 *beacon;
 414        u8 *p_pspoll;
 415        u8 *nullfunc;
 416        u8 *p_probersp;
 417        /*---------------------------------------------------------
 418         *                      (1) beacon
 419         *---------------------------------------------------------
 420         */
 421        beacon = &reserved_page_packet[BEACON_PG * 128];
 422        SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
 423        SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
 424
 425        /*-------------------------------------------------------
 426         *                      (2) ps-poll
 427         *-------------------------------------------------------
 428         */
 429        p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
 430        SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
 431        SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
 432        SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
 433
 434        SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
 435
 436        /*--------------------------------------------------------
 437         *                      (3) null data
 438         *--------------------------------------------------------
 439         */
 440        nullfunc = &reserved_page_packet[NULL_PG * 128];
 441        SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
 442        SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
 443        SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
 444
 445        SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
 446
 447        /*---------------------------------------------------------
 448         *                      (4) probe response
 449         *---------------------------------------------------------
 450         */
 451        p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
 452        SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
 453        SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
 454        SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
 455
 456        SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
 457
 458        totalpacketlen = TOTAL_RESERVED_PKT_LEN;
 459
 460        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
 461                      "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
 462                      &reserved_page_packet[0], totalpacketlen);
 463        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
 464                      "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
 465                      u1rsvdpageloc, 3);
 466
 467        skb = dev_alloc_skb(totalpacketlen);
 468        memcpy((u8 *)skb_put(skb, totalpacketlen),
 469               &reserved_page_packet, totalpacketlen);
 470
 471        rtstatus = rtl_cmd_send_packet(hw, skb);
 472
 473        if (rtstatus)
 474                b_dlok = true;
 475
 476        if (b_dlok) {
 477                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 478                         "Set RSVD page location to Fw.\n");
 479                RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, "H2C_RSVDPAGE:\n",
 480                              u1rsvdpageloc, 3);
 481                rtl8723be_fill_h2c_cmd(hw, H2C_8723B_RSVDPAGE,
 482                                       sizeof(u1rsvdpageloc), u1rsvdpageloc);
 483        } else
 484                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 485                         "Set RSVD page location to Fw FAIL!!!!!!.\n");
 486}
 487
 488/*Should check FW support p2p or not.*/
 489static void rtl8723be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
 490                                             u8 ctwindow)
 491{
 492        u8 u1_ctwindow_period[1] = { ctwindow};
 493
 494        rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_CTW_CMD, 1,
 495                               u1_ctwindow_period);
 496}
 497
 498void rtl8723be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw,
 499                                      u8 p2p_ps_state)
 500{
 501        struct rtl_priv *rtlpriv = rtl_priv(hw);
 502        struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
 503        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 504        struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
 505        struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
 506        u8 i;
 507        u16 ctwindow;
 508        u32 start_time, tsf_low;
 509
 510        switch (p2p_ps_state) {
 511        case P2P_PS_DISABLE:
 512                RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
 513                memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
 514                break;
 515        case P2P_PS_ENABLE:
 516                RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
 517                /* update CTWindow value. */
 518                if (p2pinfo->ctwindow > 0) {
 519                        p2p_ps_offload->ctwindow_en = 1;
 520                        ctwindow = p2pinfo->ctwindow;
 521                        rtl8723be_set_p2p_ctw_period_cmd(hw, ctwindow);
 522                }
 523                /* hw only support 2 set of NoA */
 524                for (i = 0 ; i < p2pinfo->noa_num ; i++) {
 525                        /* To control the register setting
 526                         * for which NOA
 527                         */
 528                        rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
 529                        if (i == 0)
 530                                p2p_ps_offload->noa0_en = 1;
 531                        else
 532                                p2p_ps_offload->noa1_en = 1;
 533
 534                        /* config P2P NoA Descriptor Register */
 535                        rtl_write_dword(rtlpriv, 0x5E0,
 536                                        p2pinfo->noa_duration[i]);
 537                        rtl_write_dword(rtlpriv, 0x5E4,
 538                                        p2pinfo->noa_interval[i]);
 539
 540                        /*Get Current TSF value */
 541                        tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
 542
 543                        start_time = p2pinfo->noa_start_time[i];
 544                        if (p2pinfo->noa_count_type[i] != 1) {
 545                                while (start_time <= (tsf_low + (50 * 1024))) {
 546                                        start_time += p2pinfo->noa_interval[i];
 547                                        if (p2pinfo->noa_count_type[i] != 255)
 548                                                p2pinfo->noa_count_type[i]--;
 549                                }
 550                        }
 551                        rtl_write_dword(rtlpriv, 0x5E8, start_time);
 552                        rtl_write_dword(rtlpriv, 0x5EC,
 553                                        p2pinfo->noa_count_type[i]);
 554                }
 555
 556                if ((p2pinfo->opp_ps == 1) ||
 557                    (p2pinfo->noa_num > 0)) {
 558                        /* rst p2p circuit */
 559                        rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
 560
 561                        p2p_ps_offload->offload_en = 1;
 562
 563                        if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
 564                                p2p_ps_offload->role = 1;
 565                                p2p_ps_offload->allstasleep = 0;
 566                        } else {
 567                                p2p_ps_offload->role = 0;
 568                        }
 569                        p2p_ps_offload->discovery = 0;
 570                }
 571                break;
 572        case P2P_PS_SCAN:
 573                RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
 574                p2p_ps_offload->discovery = 1;
 575                break;
 576        case P2P_PS_SCAN_DONE:
 577                RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
 578                p2p_ps_offload->discovery = 0;
 579                p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
 580                break;
 581        default:
 582                break;
 583        }
 584
 585        rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_OFFLOAD, 1,
 586                               (u8 *)p2p_ps_offload);
 587}
 588
 589static void _rtl8723be_c2h_content_parsing(struct ieee80211_hw *hw,
 590                                           u8 c2h_cmd_id,
 591                                           u8 c2h_cmd_len, u8 *tmp_buf)
 592{
 593        struct rtl_priv *rtlpriv = rtl_priv(hw);
 594
 595        switch (c2h_cmd_id) {
 596        case C2H_8723B_DBG:
 597                RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
 598                         "[C2H], C2H_8723BE_DBG!!\n");
 599                break;
 600        case C2H_8723B_TX_REPORT:
 601                RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
 602                         "[C2H], C2H_8723BE_TX_REPORT!\n");
 603                break;
 604        case C2H_8723B_BT_INFO:
 605                RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
 606                         "[C2H], C2H_8723BE_BT_INFO!!\n");
 607                rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
 608                                                              c2h_cmd_len);
 609                break;
 610        case C2H_8723B_BT_MP:
 611                RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
 612                         "[C2H], C2H_8723BE_BT_MP!!\n");
 613                break;
 614        default:
 615                RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
 616                         "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id);
 617                break;
 618        }
 619}
 620
 621void rtl8723be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
 622{
 623        struct rtl_priv *rtlpriv = rtl_priv(hw);
 624        u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
 625        u8 *tmp_buf = NULL;
 626
 627        c2h_cmd_id = buffer[0];
 628        c2h_cmd_seq = buffer[1];
 629        c2h_cmd_len = len - 2;
 630        tmp_buf = buffer + 2;
 631
 632        RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
 633                 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
 634                 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
 635
 636        RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
 637                      "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
 638
 639        _rtl8723be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
 640}
 641