linux/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 2009-2014  Realtek Corporation.*/
   3
   4#include "../wifi.h"
   5#include "../pci.h"
   6#include "../base.h"
   7#include "../core.h"
   8#include "../efuse.h"
   9#include "reg.h"
  10#include "def.h"
  11#include "fw.h"
  12#include "dm.h"
  13
  14static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable)
  15{
  16        struct rtl_priv *rtlpriv = rtl_priv(hw);
  17        u8 tmp;
  18
  19        if (enable) {
  20                rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05);
  21
  22                tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
  23                rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
  24        } else {
  25                tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
  26                rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
  27        }
  28}
  29
  30static void _rtl92ee_write_fw(struct ieee80211_hw *hw,
  31                              enum version_8192e version,
  32                              u8 *buffer, u32 size)
  33{
  34        struct rtl_priv *rtlpriv = rtl_priv(hw);
  35        u8 *bufferptr = (u8 *)buffer;
  36        u32 pagenums, remainsize;
  37        u32 page, offset;
  38
  39        RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "FW size is %d bytes,\n", size);
  40
  41        rtl_fill_dummy(bufferptr, &size);
  42
  43        pagenums = size / FW_8192C_PAGE_SIZE;
  44        remainsize = size % FW_8192C_PAGE_SIZE;
  45
  46        if (pagenums > 8)
  47                pr_err("Page numbers should not greater then 8\n");
  48
  49        for (page = 0; page < pagenums; page++) {
  50                offset = page * FW_8192C_PAGE_SIZE;
  51                rtl_fw_page_write(hw, page, (bufferptr + offset),
  52                                  FW_8192C_PAGE_SIZE);
  53                udelay(2);
  54        }
  55
  56        if (remainsize) {
  57                offset = pagenums * FW_8192C_PAGE_SIZE;
  58                page = pagenums;
  59                rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize);
  60        }
  61}
  62
  63static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw)
  64{
  65        struct rtl_priv *rtlpriv = rtl_priv(hw);
  66        int err = -EIO;
  67        u32 counter = 0;
  68        u32 value32;
  69
  70        do {
  71                value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
  72        } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
  73                 (!(value32 & FWDL_CHKSUM_RPT)));
  74
  75        if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
  76                pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n",
  77                       value32);
  78                goto exit;
  79        }
  80        value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
  81        value32 |= MCUFWDL_RDY;
  82        value32 &= ~WINTINI_RDY;
  83        rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
  84
  85        rtl92ee_firmware_selfreset(hw);
  86        counter = 0;
  87
  88        do {
  89                value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
  90                if (value32 & WINTINI_RDY)
  91                        return 0;
  92
  93                udelay(FW_8192C_POLLING_DELAY*10);
  94
  95        } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
  96
  97        pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n",
  98               value32, counter);
  99
 100exit:
 101        return err;
 102}
 103
 104int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw)
 105{
 106        struct rtl_priv *rtlpriv = rtl_priv(hw);
 107        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 108        struct rtlwifi_firmware_header *pfwheader;
 109        u8 *pfwdata;
 110        u32 fwsize;
 111        int err;
 112        enum version_8192e version = rtlhal->version;
 113
 114        if (!rtlhal->pfirmware)
 115                return 1;
 116
 117        pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
 118        rtlhal->fw_version = le16_to_cpu(pfwheader->version);
 119        rtlhal->fw_subversion = pfwheader->subversion;
 120        pfwdata = (u8 *)rtlhal->pfirmware;
 121        fwsize = rtlhal->fwsize;
 122        RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
 123                 "normal Firmware SIZE %d\n" , fwsize);
 124
 125        if (IS_FW_HEADER_EXIST(pfwheader)) {
 126                RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
 127                         "Firmware Version(%d), Signature(%#x),Size(%d)\n",
 128                          pfwheader->version, pfwheader->signature,
 129                          (int)sizeof(struct rtlwifi_firmware_header));
 130
 131                pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
 132                fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
 133        } else {
 134                RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
 135                         "Firmware no Header, Signature(%#x)\n",
 136                          pfwheader->signature);
 137        }
 138
 139        if (rtlhal->mac_func_enable) {
 140                if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
 141                        rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
 142                        rtl92ee_firmware_selfreset(hw);
 143                }
 144        }
 145        _rtl92ee_enable_fw_download(hw, true);
 146        _rtl92ee_write_fw(hw, version, pfwdata, fwsize);
 147        _rtl92ee_enable_fw_download(hw, false);
 148
 149        err = _rtl92ee_fw_free_to_go(hw);
 150
 151        return 0;
 152}
 153
 154static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
 155{
 156        struct rtl_priv *rtlpriv = rtl_priv(hw);
 157        u8 val_hmetfr;
 158        bool result = false;
 159
 160        val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
 161        if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
 162                result = true;
 163        return result;
 164}
 165
 166static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
 167                                      u32 cmd_len, u8 *cmdbuffer)
 168{
 169        struct rtl_priv *rtlpriv = rtl_priv(hw);
 170        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 171        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 172        u8 boxnum;
 173        u16 box_reg = 0, box_extreg = 0;
 174        u8 u1b_tmp;
 175        bool isfw_read = false;
 176        u8 buf_index = 0;
 177        bool bwrite_sucess = false;
 178        u8 wait_h2c_limmit = 100;
 179        u8 boxcontent[4], boxextcontent[4];
 180        u32 h2c_waitcounter = 0;
 181        unsigned long flag;
 182        u8 idx;
 183
 184        if (ppsc->dot11_psmode != EACTIVE ||
 185            ppsc->inactive_pwrstate == ERFOFF) {
 186                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
 187                         "FillH2CCommand8192E(): Return because RF is off!!!\n");
 188                return;
 189        }
 190
 191        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "come in\n");
 192
 193        /* 1. Prevent race condition in setting H2C cmd.
 194         * (copy from MgntActSet_RF_State().)
 195         */
 196        while (true) {
 197                spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
 198                if (rtlhal->h2c_setinprogress) {
 199                        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
 200                                 "H2C set in progress! Wait to set..element_id(%d).\n",
 201                                  element_id);
 202
 203                        while (rtlhal->h2c_setinprogress) {
 204                                spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
 205                                                       flag);
 206                                h2c_waitcounter++;
 207                                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
 208                                         "Wait 100 us (%d times)...\n",
 209                                          h2c_waitcounter);
 210                                udelay(100);
 211
 212                                if (h2c_waitcounter > 1000)
 213                                        return;
 214                                spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
 215                                                  flag);
 216                        }
 217                        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 218                } else {
 219                        rtlhal->h2c_setinprogress = true;
 220                        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 221                        break;
 222                }
 223        }
 224
 225        while (!bwrite_sucess) {
 226                /* 2. Find the last BOX number which has been writen. */
 227                boxnum = rtlhal->last_hmeboxnum;
 228                switch (boxnum) {
 229                case 0:
 230                        box_reg = REG_HMEBOX_0;
 231                        box_extreg = REG_HMEBOX_EXT_0;
 232                        break;
 233                case 1:
 234                        box_reg = REG_HMEBOX_1;
 235                        box_extreg = REG_HMEBOX_EXT_1;
 236                        break;
 237                case 2:
 238                        box_reg = REG_HMEBOX_2;
 239                        box_extreg = REG_HMEBOX_EXT_2;
 240                        break;
 241                case 3:
 242                        box_reg = REG_HMEBOX_3;
 243                        box_extreg = REG_HMEBOX_EXT_3;
 244                        break;
 245                default:
 246                        RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
 247                                 "switch case %#x not processed\n", boxnum);
 248                        break;
 249                }
 250
 251                /* 3. Check if the box content is empty. */
 252                isfw_read = false;
 253                u1b_tmp = rtl_read_byte(rtlpriv, REG_CR);
 254
 255                if (u1b_tmp != 0xea) {
 256                        isfw_read = true;
 257                } else {
 258                        if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea ||
 259                            rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea)
 260                                rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff);
 261                }
 262
 263                if (isfw_read) {
 264                        wait_h2c_limmit = 100;
 265                        isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
 266                        while (!isfw_read) {
 267                                wait_h2c_limmit--;
 268                                if (wait_h2c_limmit == 0) {
 269                                        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
 270                                                 "Waiting too long for FW read clear HMEBox(%d)!!!\n",
 271                                                 boxnum);
 272                                        break;
 273                                }
 274                                udelay(10);
 275                                isfw_read =
 276                                  _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
 277                                u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
 278                                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
 279                                         "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
 280                                         boxnum, u1b_tmp);
 281                        }
 282                }
 283
 284                /* If Fw has not read the last
 285                 * H2C cmd, break and give up this H2C.
 286                 */
 287                if (!isfw_read) {
 288                        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
 289                                 "Write H2C reg BOX[%d] fail,Fw don't read.\n",
 290                                 boxnum);
 291                        break;
 292                }
 293                /* 4. Fill the H2C cmd into box */
 294                memset(boxcontent, 0, sizeof(boxcontent));
 295                memset(boxextcontent, 0, sizeof(boxextcontent));
 296                boxcontent[0] = element_id;
 297                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
 298                         "Write element_id box_reg(%4x) = %2x\n",
 299                          box_reg, element_id);
 300
 301                switch (cmd_len) {
 302                case 1:
 303                case 2:
 304                case 3:
 305                        /*boxcontent[0] &= ~(BIT(7));*/
 306                        memcpy((u8 *)(boxcontent) + 1,
 307                               cmdbuffer + buf_index, cmd_len);
 308
 309                        for (idx = 0; idx < 4; idx++) {
 310                                rtl_write_byte(rtlpriv, box_reg + idx,
 311                                               boxcontent[idx]);
 312                        }
 313                        break;
 314                case 4:
 315                case 5:
 316                case 6:
 317                case 7:
 318                        /*boxcontent[0] |= (BIT(7));*/
 319                        memcpy((u8 *)(boxextcontent),
 320                               cmdbuffer + buf_index+3, cmd_len-3);
 321                        memcpy((u8 *)(boxcontent) + 1,
 322                               cmdbuffer + buf_index, 3);
 323
 324                        for (idx = 0; idx < 4; idx++) {
 325                                rtl_write_byte(rtlpriv, box_extreg + idx,
 326                                               boxextcontent[idx]);
 327                        }
 328
 329                        for (idx = 0; idx < 4; idx++) {
 330                                rtl_write_byte(rtlpriv, box_reg + idx,
 331                                               boxcontent[idx]);
 332                        }
 333                        break;
 334                default:
 335                        RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
 336                                 "switch case %#x not processed\n", cmd_len);
 337                        break;
 338                }
 339
 340                bwrite_sucess = true;
 341
 342                rtlhal->last_hmeboxnum = boxnum + 1;
 343                if (rtlhal->last_hmeboxnum == 4)
 344                        rtlhal->last_hmeboxnum = 0;
 345
 346                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
 347                         "pHalData->last_hmeboxnum  = %d\n",
 348                          rtlhal->last_hmeboxnum);
 349        }
 350
 351        spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
 352        rtlhal->h2c_setinprogress = false;
 353        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 354
 355        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "go out\n");
 356}
 357
 358void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw,
 359                          u8 element_id, u32 cmd_len, u8 *cmdbuffer)
 360{
 361        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 362        u32 tmp_cmdbuf[2];
 363
 364        if (!rtlhal->fw_ready) {
 365                WARN_ONCE(true,
 366                          "rtl8192ee: error H2C cmd because of Fw download fail!!!\n");
 367                return;
 368        }
 369
 370        memset(tmp_cmdbuf, 0, 8);
 371        memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
 372        _rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
 373}
 374
 375void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw)
 376{
 377        u8 u1b_tmp;
 378        struct rtl_priv *rtlpriv = rtl_priv(hw);
 379
 380        u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
 381        rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0))));
 382
 383        u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
 384        rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
 385
 386        udelay(50);
 387
 388        u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
 389        rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0)));
 390
 391        u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
 392        rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
 393
 394        RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD ,
 395                 "  _8051Reset92E(): 8051 reset success .\n");
 396}
 397
 398void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
 399{
 400        struct rtl_priv *rtlpriv = rtl_priv(hw);
 401        u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 };
 402        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 403        u8 rlbm, power_state = 0, byte5 = 0;
 404        u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
 405        struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
 406        bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
 407                            btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
 408        bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ?
 409                          btc_ops->btc_is_bt_lps_on(rtlpriv) : false);
 410
 411        if (bt_ctrl_lps)
 412                mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE);
 413
 414        RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
 415                 mode, bt_ctrl_lps);
 416
 417        switch (mode) {
 418        case FW_PS_MIN_MODE:
 419                rlbm = 0;
 420                awake_intvl = 2;
 421                break;
 422        case FW_PS_MAX_MODE:
 423                rlbm = 1;
 424                awake_intvl = 2;
 425                break;
 426        case FW_PS_DTIM_MODE:
 427                rlbm = 2;
 428                awake_intvl = ppsc->reg_max_lps_awakeintvl;
 429                /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
 430                 * is only used in swlps.
 431                 */
 432                break;
 433        default:
 434                rlbm = 2;
 435                awake_intvl = 4;
 436                break;
 437        }
 438
 439        if (rtlpriv->mac80211.p2p) {
 440                awake_intvl = 2;
 441                rlbm = 1;
 442        }
 443
 444        if (mode == FW_PS_ACTIVE_MODE) {
 445                byte5 = 0x40;
 446                power_state = FW_PWR_STATE_ACTIVE;
 447        } else {
 448                if (bt_ctrl_lps) {
 449                        byte5 = btc_ops->btc_get_lps_val(rtlpriv);
 450                        power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
 451
 452                        if ((rlbm == 2) && (byte5 & BIT(4))) {
 453                                /* Keep awake interval to 1 to prevent from
 454                                 * decreasing coex performance
 455                                 */
 456                                awake_intvl = 2;
 457                                rlbm = 2;
 458                        }
 459                } else {
 460                        byte5 = 0x40;
 461                        power_state = FW_PWR_STATE_RF_OFF;
 462                }
 463        }
 464
 465        SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
 466        SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
 467        SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
 468                                         bt_ctrl_lps ? 0 :
 469                                         ((rtlpriv->mac80211.p2p) ?
 470                                          ppsc->smart_ps : 1));
 471        SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
 472                                               awake_intvl);
 473        SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
 474        SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
 475        SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
 476
 477        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
 478                      "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
 479                      u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
 480        if (rtlpriv->cfg->ops->get_btc_status())
 481                btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
 482                                             H2C_92E_PWEMODE_LENGTH);
 483        rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
 484                             u1_h2c_set_pwrmode);
 485}
 486
 487void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
 488{
 489        u8 parm[3] = { 0 , 0 , 0 };
 490        /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
 491         *          bit1=0-->update Media Status to MACID
 492         *          bit1=1-->update Media Status from MACID to MACID_End
 493         * parm[1]: MACID, if this is INFRA_STA, MacID = 0
 494         * parm[2]: MACID_End
 495         */
 496
 497        SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
 498        SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
 499
 500        rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm);
 501}
 502
 503#define BEACON_PG               0 /* ->1 */
 504#define PSPOLL_PG               2
 505#define NULL_PG                 3
 506#define PROBERSP_PG             4 /* ->5 */
 507#define QOS_NULL_PG             6
 508#define BT_QOS_NULL_PG  7
 509
 510#define TOTAL_RESERVED_PKT_LEN  1024
 511
 512static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
 513        /* page 0 beacon */
 514        0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
 515        0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
 516        0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
 517        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 518        0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
 519        0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
 520        0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
 521        0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
 522        0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
 523        0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
 524        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 525        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 526        0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
 527        0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
 528        0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
 529        0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
 530
 531        /* page 1 beacon */
 532        0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
 533        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 534        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 535        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 536        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 537        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 538        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 539        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 540        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 541        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 542        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 543        0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
 544        0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
 545        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 546        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 547        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 548
 549        /* page 2  ps-poll */
 550        0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
 551        0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
 552        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 553        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 554        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 555        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 556        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 557        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 558        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 559        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 560        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 561        0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
 562        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
 563        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 564        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 565        0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 566
 567        /* page 3  null */
 568        0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
 569        0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
 570        0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
 571        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 572        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 573        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 574        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 575        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 576        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 577        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 578        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 579        0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
 580        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
 581        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 582        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 583        0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 584
 585        /* page 4  probe_resp */
 586        0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
 587        0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 588        0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
 589        0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
 590        0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
 591        0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
 592        0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
 593        0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
 594        0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
 595        0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
 596        0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 597        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 598        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 599        0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
 600        0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 601        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 602
 603        /* page 5  probe_resp */
 604        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 605        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 606        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 607        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 608        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 609        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 610        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 611        0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
 612        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
 613        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 614        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 615        0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 616
 617        /* page 6 qos null data */
 618        0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
 619        0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
 620        0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
 621        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 622        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 623        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 624        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 625        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 626        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 627        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 628        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 629        0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
 630        0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
 631        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 632        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 633        0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 634
 635        /* page 7 BT-qos null data */
 636        0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
 637        0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
 638        0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
 639        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 640        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 641        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 642        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 643        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 644        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 645        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 646        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 647        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 648        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 649        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 650        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 651        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 652        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 653        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 654        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 655        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 656};
 657
 658void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
 659{
 660        struct rtl_priv *rtlpriv = rtl_priv(hw);
 661        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 662        struct sk_buff *skb = NULL;
 663        bool rtstatus;
 664        u32 totalpacketlen;
 665        u8 u1rsvdpageloc[5] = { 0 };
 666        bool b_dlok = false;
 667
 668        u8 *beacon;
 669        u8 *p_pspoll;
 670        u8 *nullfunc;
 671        u8 *p_probersp;
 672        u8 *qosnull;
 673        u8 *btqosnull;
 674        /*---------------------------------------------------------
 675         *                      (1) beacon
 676         *---------------------------------------------------------
 677         */
 678        beacon = &reserved_page_packet[BEACON_PG * 128];
 679        SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
 680        SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
 681
 682        /*-------------------------------------------------------
 683         *                      (2) ps-poll
 684         *--------------------------------------------------------
 685         */
 686        p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
 687        SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
 688        SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
 689        SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
 690
 691        SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
 692
 693        /*--------------------------------------------------------
 694         *                      (3) null data
 695         *---------------------------------------------------------
 696         */
 697        nullfunc = &reserved_page_packet[NULL_PG * 128];
 698        SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
 699        SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
 700        SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
 701
 702        SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
 703
 704        /*---------------------------------------------------------
 705         *                      (4) probe response
 706         *----------------------------------------------------------
 707         */
 708        p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
 709        SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
 710        SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
 711        SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
 712
 713        SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
 714
 715        /*---------------------------------------------------------
 716         *                      (5) QoS null data
 717         *----------------------------------------------------------
 718         */
 719        qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
 720        SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
 721        SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
 722        SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
 723
 724        SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOS_NULL_PG);
 725
 726        /*---------------------------------------------------------
 727         *                      (6) BT QoS null data
 728         *----------------------------------------------------------
 729         */
 730        btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
 731        SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
 732        SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
 733        SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
 734
 735        SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOS_NULL_PG);
 736
 737        totalpacketlen = TOTAL_RESERVED_PKT_LEN;
 738
 739        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
 740                      "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
 741                      &reserved_page_packet[0], totalpacketlen);
 742        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
 743                      "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
 744                      u1rsvdpageloc, 3);
 745
 746        skb = dev_alloc_skb(totalpacketlen);
 747        skb_put_data(skb, &reserved_page_packet, totalpacketlen);
 748
 749        rtstatus = rtl_cmd_send_packet(hw, skb);
 750        if (rtstatus)
 751                b_dlok = true;
 752
 753        if (b_dlok) {
 754                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD ,
 755                         "Set RSVD page location to Fw.\n");
 756                RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
 757                              "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
 758                rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE,
 759                                     sizeof(u1rsvdpageloc), u1rsvdpageloc);
 760        } else {
 761                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 762                         "Set RSVD page location to Fw FAIL!!!!!!.\n");
 763        }
 764}
 765
 766/*Shoud check FW support p2p or not.*/
 767static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
 768{
 769        u8 u1_ctwindow_period[1] = {ctwindow};
 770
 771        rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
 772}
 773
 774void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
 775{
 776        struct rtl_priv *rtlpriv = rtl_priv(hw);
 777        struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
 778        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 779        struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
 780        struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
 781        u8 i;
 782        u16 ctwindow;
 783        u32 start_time, tsf_low;
 784
 785        switch (p2p_ps_state) {
 786        case P2P_PS_DISABLE:
 787                RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_DISABLE\n");
 788                memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
 789                break;
 790        case P2P_PS_ENABLE:
 791                RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_ENABLE\n");
 792                /* update CTWindow value. */
 793                if (p2pinfo->ctwindow > 0) {
 794                        p2p_ps_offload->ctwindow_en = 1;
 795                        ctwindow = p2pinfo->ctwindow;
 796                        rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow);
 797                }
 798                /* hw only support 2 set of NoA */
 799                for (i = 0 ; i < p2pinfo->noa_num ; i++) {
 800                        /* To control the register setting for which NOA*/
 801                        rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
 802                        if (i == 0)
 803                                p2p_ps_offload->noa0_en = 1;
 804                        else
 805                                p2p_ps_offload->noa1_en = 1;
 806                        /* config P2P NoA Descriptor Register */
 807                        rtl_write_dword(rtlpriv, 0x5E0,
 808                                        p2pinfo->noa_duration[i]);
 809                        rtl_write_dword(rtlpriv, 0x5E4,
 810                                        p2pinfo->noa_interval[i]);
 811
 812                        /*Get Current TSF value */
 813                        tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
 814
 815                        start_time = p2pinfo->noa_start_time[i];
 816                        if (p2pinfo->noa_count_type[i] != 1) {
 817                                while (start_time <= (tsf_low + (50 * 1024))) {
 818                                        start_time += p2pinfo->noa_interval[i];
 819                                        if (p2pinfo->noa_count_type[i] != 255)
 820                                                p2pinfo->noa_count_type[i]--;
 821                                }
 822                        }
 823                        rtl_write_dword(rtlpriv, 0x5E8, start_time);
 824                        rtl_write_dword(rtlpriv, 0x5EC,
 825                                        p2pinfo->noa_count_type[i]);
 826                }
 827                if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
 828                        /* rst p2p circuit */
 829                        rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
 830                        p2p_ps_offload->offload_en = 1;
 831
 832                        if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
 833                                p2p_ps_offload->role = 1;
 834                                p2p_ps_offload->allstasleep = 0;
 835                        } else {
 836                                p2p_ps_offload->role = 0;
 837                        }
 838                        p2p_ps_offload->discovery = 0;
 839                }
 840                break;
 841        case P2P_PS_SCAN:
 842                RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN\n");
 843                p2p_ps_offload->discovery = 1;
 844                break;
 845        case P2P_PS_SCAN_DONE:
 846                RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN_DONE\n");
 847                p2p_ps_offload->discovery = 0;
 848                p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
 849                break;
 850        default:
 851                break;
 852        }
 853        rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1,
 854                             (u8 *)p2p_ps_offload);
 855}
 856
 857void rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw,
 858                                   u8 *cmd_buf, u8 cmd_len)
 859{
 860        u8 rate = cmd_buf[0] & 0x3F;
 861        bool collision_state = cmd_buf[3] & BIT(0);
 862
 863        rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state);
 864}
 865