linux/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 2009-2012  Realtek Corporation.*/
   3
   4#include "../wifi.h"
   5#include "../pci.h"
   6#include "../base.h"
   7#include "../efuse.h"
   8#include "reg.h"
   9#include "def.h"
  10#include "fw.h"
  11#include "sw.h"
  12
  13static bool _rtl92d_is_fw_downloaded(struct rtl_priv *rtlpriv)
  14{
  15        return (rtl_read_dword(rtlpriv, REG_MCUFWDL) & MCUFWDL_RDY) ?
  16                true : false;
  17}
  18
  19static void _rtl92d_enable_fw_download(struct ieee80211_hw *hw, bool enable)
  20{
  21        struct rtl_priv *rtlpriv = rtl_priv(hw);
  22        u8 tmp;
  23
  24        if (enable) {
  25                tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
  26                rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
  27                tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
  28                rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
  29                tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
  30                rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
  31        } else {
  32                tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
  33                rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
  34                /* Reserved for fw extension.
  35                 * 0x81[7] is used for mac0 status ,
  36                 * so don't write this reg here
  37                 * rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);*/
  38        }
  39}
  40
  41static void _rtl92d_write_fw(struct ieee80211_hw *hw,
  42                             enum version_8192d version, u8 *buffer, u32 size)
  43{
  44        struct rtl_priv *rtlpriv = rtl_priv(hw);
  45        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  46        u8 *bufferptr = buffer;
  47        u32 pagenums, remainsize;
  48        u32 page, offset;
  49
  50        rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size);
  51        if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE)
  52                rtl_fill_dummy(bufferptr, &size);
  53        pagenums = size / FW_8192D_PAGE_SIZE;
  54        remainsize = size % FW_8192D_PAGE_SIZE;
  55        if (pagenums > 8)
  56                pr_err("Page numbers should not greater then 8\n");
  57        for (page = 0; page < pagenums; page++) {
  58                offset = page * FW_8192D_PAGE_SIZE;
  59                rtl_fw_page_write(hw, page, (bufferptr + offset),
  60                                  FW_8192D_PAGE_SIZE);
  61        }
  62        if (remainsize) {
  63                offset = pagenums * FW_8192D_PAGE_SIZE;
  64                page = pagenums;
  65                rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize);
  66        }
  67}
  68
  69static int _rtl92d_fw_free_to_go(struct ieee80211_hw *hw)
  70{
  71        struct rtl_priv *rtlpriv = rtl_priv(hw);
  72        u32 counter = 0;
  73        u32 value32;
  74
  75        do {
  76                value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
  77        } while ((counter++ < FW_8192D_POLLING_TIMEOUT_COUNT) &&
  78                 (!(value32 & FWDL_CHKSUM_RPT)));
  79        if (counter >= FW_8192D_POLLING_TIMEOUT_COUNT) {
  80                pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n",
  81                       value32);
  82                return -EIO;
  83        }
  84        value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
  85        value32 |= MCUFWDL_RDY;
  86        rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
  87        return 0;
  88}
  89
  90void rtl92d_firmware_selfreset(struct ieee80211_hw *hw)
  91{
  92        struct rtl_priv *rtlpriv = rtl_priv(hw);
  93        u8 u1b_tmp;
  94        u8 delay = 100;
  95
  96        /* Set (REG_HMETFR + 3) to  0x20 is reset 8051 */
  97        rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
  98        u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
  99        while (u1b_tmp & BIT(2)) {
 100                delay--;
 101                if (delay == 0)
 102                        break;
 103                udelay(50);
 104                u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
 105        }
 106        WARN_ONCE((delay <= 0), "rtl8192de: 8051 reset failed!\n");
 107        rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
 108                "=====> 8051 reset success (%d)\n", delay);
 109}
 110
 111static int _rtl92d_fw_init(struct ieee80211_hw *hw)
 112{
 113        struct rtl_priv *rtlpriv = rtl_priv(hw);
 114        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 115        u32 counter;
 116
 117        rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG, "FW already have download\n");
 118        /* polling for FW ready */
 119        counter = 0;
 120        do {
 121                if (rtlhal->interfaceindex == 0) {
 122                        if (rtl_read_byte(rtlpriv, FW_MAC0_READY) &
 123                            MAC0_READY) {
 124                                rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
 125                                        "Polling FW ready success!! REG_MCUFWDL: 0x%x\n",
 126                                        rtl_read_byte(rtlpriv,
 127                                                      FW_MAC0_READY));
 128                                return 0;
 129                        }
 130                        udelay(5);
 131                } else {
 132                        if (rtl_read_byte(rtlpriv, FW_MAC1_READY) &
 133                            MAC1_READY) {
 134                                rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
 135                                        "Polling FW ready success!! REG_MCUFWDL: 0x%x\n",
 136                                        rtl_read_byte(rtlpriv,
 137                                                      FW_MAC1_READY));
 138                                return 0;
 139                        }
 140                        udelay(5);
 141                }
 142        } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
 143
 144        if (rtlhal->interfaceindex == 0) {
 145                rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
 146                        "Polling FW ready fail!! MAC0 FW init not ready: 0x%x\n",
 147                        rtl_read_byte(rtlpriv, FW_MAC0_READY));
 148        } else {
 149                rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
 150                        "Polling FW ready fail!! MAC1 FW init not ready: 0x%x\n",
 151                        rtl_read_byte(rtlpriv, FW_MAC1_READY));
 152        }
 153        rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
 154                "Polling FW ready fail!! REG_MCUFWDL:0x%08x\n",
 155                rtl_read_dword(rtlpriv, REG_MCUFWDL));
 156        return -1;
 157}
 158
 159int rtl92d_download_fw(struct ieee80211_hw *hw)
 160{
 161        struct rtl_priv *rtlpriv = rtl_priv(hw);
 162        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 163        u8 *pfwheader;
 164        u8 *pfwdata;
 165        u32 fwsize;
 166        int err;
 167        enum version_8192d version = rtlhal->version;
 168        u8 value;
 169        u32 count;
 170        bool fw_downloaded = false, fwdl_in_process = false;
 171        unsigned long flags;
 172
 173        if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
 174                return 1;
 175        fwsize = rtlhal->fwsize;
 176        pfwheader = rtlhal->pfirmware;
 177        pfwdata = rtlhal->pfirmware;
 178        rtlhal->fw_version = (u16) GET_FIRMWARE_HDR_VERSION(pfwheader);
 179        rtlhal->fw_subversion = (u16) GET_FIRMWARE_HDR_SUB_VER(pfwheader);
 180        rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
 181                "FirmwareVersion(%d), FirmwareSubVersion(%d), Signature(%#x)\n",
 182                rtlhal->fw_version, rtlhal->fw_subversion,
 183                GET_FIRMWARE_HDR_SIGNATURE(pfwheader));
 184        if (IS_FW_HEADER_EXIST(pfwheader)) {
 185                rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
 186                        "Shift 32 bytes for FW header!!\n");
 187                pfwdata = pfwdata + 32;
 188                fwsize = fwsize - 32;
 189        }
 190
 191        spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
 192        fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv);
 193        if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
 194                fwdl_in_process = true;
 195        else
 196                fwdl_in_process = false;
 197        if (fw_downloaded) {
 198                spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
 199                goto exit;
 200        } else if (fwdl_in_process) {
 201                spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
 202                for (count = 0; count < 5000; count++) {
 203                        udelay(500);
 204                        spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
 205                        fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv);
 206                        if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
 207                                fwdl_in_process = true;
 208                        else
 209                                fwdl_in_process = false;
 210                        spin_unlock_irqrestore(&globalmutex_for_fwdownload,
 211                                               flags);
 212                        if (fw_downloaded)
 213                                goto exit;
 214                        else if (!fwdl_in_process)
 215                                break;
 216                        else
 217                                rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
 218                                        "Wait for another mac download fw\n");
 219                }
 220                spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
 221                value = rtl_read_byte(rtlpriv, 0x1f);
 222                value |= BIT(5);
 223                rtl_write_byte(rtlpriv, 0x1f, value);
 224                spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
 225        } else {
 226                value = rtl_read_byte(rtlpriv, 0x1f);
 227                value |= BIT(5);
 228                rtl_write_byte(rtlpriv, 0x1f, value);
 229                spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
 230        }
 231
 232        /* If 8051 is running in RAM code, driver should
 233         * inform Fw to reset by itself, or it will cause
 234         * download Fw fail.*/
 235        /* 8051 RAM code */
 236        if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
 237                rtl92d_firmware_selfreset(hw);
 238                rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
 239        }
 240        _rtl92d_enable_fw_download(hw, true);
 241        _rtl92d_write_fw(hw, version, pfwdata, fwsize);
 242        _rtl92d_enable_fw_download(hw, false);
 243        spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
 244        err = _rtl92d_fw_free_to_go(hw);
 245        /* download fw over,clear 0x1f[5] */
 246        value = rtl_read_byte(rtlpriv, 0x1f);
 247        value &= (~BIT(5));
 248        rtl_write_byte(rtlpriv, 0x1f, value);
 249        spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
 250        if (err)
 251                pr_err("fw is not ready to run!\n");
 252exit:
 253        err = _rtl92d_fw_init(hw);
 254        return err;
 255}
 256
 257static bool _rtl92d_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
 258{
 259        struct rtl_priv *rtlpriv = rtl_priv(hw);
 260        u8 val_hmetfr;
 261        bool result = false;
 262
 263        val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
 264        if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
 265                result = true;
 266        return result;
 267}
 268
 269static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw,
 270                              u8 element_id, u32 cmd_len, u8 *cmdbuffer)
 271{
 272        struct rtl_priv *rtlpriv = rtl_priv(hw);
 273        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 274        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 275        u8 boxnum;
 276        u16 box_reg = 0, box_extreg = 0;
 277        u8 u1b_tmp;
 278        bool isfw_read = false;
 279        u8 buf_index = 0;
 280        bool bwrite_success = false;
 281        u8 wait_h2c_limmit = 100;
 282        u8 wait_writeh2c_limmit = 100;
 283        u8 boxcontent[4], boxextcontent[2];
 284        u32 h2c_waitcounter = 0;
 285        unsigned long flag;
 286        u8 idx;
 287
 288        if (ppsc->rfpwr_state == ERFOFF || ppsc->inactive_pwrstate == ERFOFF) {
 289                rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 290                        "Return as RF is off!!!\n");
 291                return;
 292        }
 293        rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
 294        while (true) {
 295                spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
 296                if (rtlhal->h2c_setinprogress) {
 297                        rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 298                                "H2C set in progress! Wait to set..element_id(%d)\n",
 299                                element_id);
 300
 301                        while (rtlhal->h2c_setinprogress) {
 302                                spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
 303                                                       flag);
 304                                h2c_waitcounter++;
 305                                rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 306                                        "Wait 100 us (%d times)...\n",
 307                                        h2c_waitcounter);
 308                                udelay(100);
 309
 310                                if (h2c_waitcounter > 1000)
 311                                        return;
 312
 313                                spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
 314                                                  flag);
 315                        }
 316                        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 317                } else {
 318                        rtlhal->h2c_setinprogress = true;
 319                        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 320                        break;
 321                }
 322        }
 323        while (!bwrite_success) {
 324                wait_writeh2c_limmit--;
 325                if (wait_writeh2c_limmit == 0) {
 326                        pr_err("Write H2C fail because no trigger for FW INT!\n");
 327                        break;
 328                }
 329                boxnum = rtlhal->last_hmeboxnum;
 330                switch (boxnum) {
 331                case 0:
 332                        box_reg = REG_HMEBOX_0;
 333                        box_extreg = REG_HMEBOX_EXT_0;
 334                        break;
 335                case 1:
 336                        box_reg = REG_HMEBOX_1;
 337                        box_extreg = REG_HMEBOX_EXT_1;
 338                        break;
 339                case 2:
 340                        box_reg = REG_HMEBOX_2;
 341                        box_extreg = REG_HMEBOX_EXT_2;
 342                        break;
 343                case 3:
 344                        box_reg = REG_HMEBOX_3;
 345                        box_extreg = REG_HMEBOX_EXT_3;
 346                        break;
 347                default:
 348                        pr_err("switch case %#x not processed\n",
 349                               boxnum);
 350                        break;
 351                }
 352                isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
 353                while (!isfw_read) {
 354                        wait_h2c_limmit--;
 355                        if (wait_h2c_limmit == 0) {
 356                                rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 357                                        "Waiting too long for FW read clear HMEBox(%d)!\n",
 358                                        boxnum);
 359                                break;
 360                        }
 361                        udelay(10);
 362                        isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
 363                        u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
 364                        rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 365                                "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n",
 366                                boxnum, u1b_tmp);
 367                }
 368                if (!isfw_read) {
 369                        rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 370                                "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
 371                                boxnum);
 372                        break;
 373                }
 374                memset(boxcontent, 0, sizeof(boxcontent));
 375                memset(boxextcontent, 0, sizeof(boxextcontent));
 376                boxcontent[0] = element_id;
 377                rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 378                        "Write element_id box_reg(%4x) = %2x\n",
 379                        box_reg, element_id);
 380                switch (cmd_len) {
 381                case 1:
 382                        boxcontent[0] &= ~(BIT(7));
 383                        memcpy(boxcontent + 1, cmdbuffer + buf_index, 1);
 384                        for (idx = 0; idx < 4; idx++)
 385                                rtl_write_byte(rtlpriv, box_reg + idx,
 386                                               boxcontent[idx]);
 387                        break;
 388                case 2:
 389                        boxcontent[0] &= ~(BIT(7));
 390                        memcpy(boxcontent + 1, cmdbuffer + buf_index, 2);
 391                        for (idx = 0; idx < 4; idx++)
 392                                rtl_write_byte(rtlpriv, box_reg + idx,
 393                                               boxcontent[idx]);
 394                        break;
 395                case 3:
 396                        boxcontent[0] &= ~(BIT(7));
 397                        memcpy(boxcontent + 1, cmdbuffer + buf_index, 3);
 398                        for (idx = 0; idx < 4; idx++)
 399                                rtl_write_byte(rtlpriv, box_reg + idx,
 400                                               boxcontent[idx]);
 401                        break;
 402                case 4:
 403                        boxcontent[0] |= (BIT(7));
 404                        memcpy(boxextcontent, cmdbuffer + buf_index, 2);
 405                        memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 2);
 406                        for (idx = 0; idx < 2; idx++)
 407                                rtl_write_byte(rtlpriv, box_extreg + idx,
 408                                               boxextcontent[idx]);
 409                        for (idx = 0; idx < 4; idx++)
 410                                rtl_write_byte(rtlpriv, box_reg + idx,
 411                                               boxcontent[idx]);
 412                        break;
 413                case 5:
 414                        boxcontent[0] |= (BIT(7));
 415                        memcpy(boxextcontent, cmdbuffer + buf_index, 2);
 416                        memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 3);
 417                        for (idx = 0; idx < 2; idx++)
 418                                rtl_write_byte(rtlpriv, box_extreg + idx,
 419                                               boxextcontent[idx]);
 420                        for (idx = 0; idx < 4; idx++)
 421                                rtl_write_byte(rtlpriv, box_reg + idx,
 422                                               boxcontent[idx]);
 423                        break;
 424                default:
 425                        pr_err("switch case %#x not processed\n",
 426                               cmd_len);
 427                        break;
 428                }
 429                bwrite_success = true;
 430                rtlhal->last_hmeboxnum = boxnum + 1;
 431                if (rtlhal->last_hmeboxnum == 4)
 432                        rtlhal->last_hmeboxnum = 0;
 433                rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
 434                        "pHalData->last_hmeboxnum  = %d\n",
 435                        rtlhal->last_hmeboxnum);
 436        }
 437        spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
 438        rtlhal->h2c_setinprogress = false;
 439        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 440        rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
 441}
 442
 443void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw,
 444                         u8 element_id, u32 cmd_len, u8 *cmdbuffer)
 445{
 446        u32 tmp_cmdbuf[2];
 447
 448        memset(tmp_cmdbuf, 0, 8);
 449        memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
 450        _rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
 451        return;
 452}
 453
 454static bool _rtl92d_cmd_send_packet(struct ieee80211_hw *hw,
 455                                    struct sk_buff *skb)
 456{
 457        struct rtl_priv *rtlpriv = rtl_priv(hw);
 458        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 459        struct rtl8192_tx_ring *ring;
 460        struct rtl_tx_desc *pdesc;
 461        u8 idx = 0;
 462        unsigned long flags;
 463        struct sk_buff *pskb;
 464
 465        ring = &rtlpci->tx_ring[BEACON_QUEUE];
 466        pskb = __skb_dequeue(&ring->queue);
 467        kfree_skb(pskb);
 468        spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
 469        pdesc = &ring->desc[idx];
 470        /* discard output from call below */
 471        rtlpriv->cfg->ops->get_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN);
 472        rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
 473        __skb_queue_tail(&ring->queue, skb);
 474        spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
 475        rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
 476        return true;
 477}
 478
 479#define BEACON_PG               0       /*->1 */
 480#define PSPOLL_PG               2
 481#define NULL_PG                 3
 482#define PROBERSP_PG             4       /*->5 */
 483#define TOTAL_RESERVED_PKT_LEN  768
 484
 485static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
 486        /* page 0 beacon */
 487        0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
 488        0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 489        0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
 490        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 491        0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
 492        0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
 493        0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
 494        0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
 495        0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
 496        0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
 497        0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 498        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 499        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 500        0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
 501        0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 502        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 503
 504        /* page 1 beacon */
 505        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 506        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 507        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 508        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 509        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 510        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 511        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 512        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 513        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 514        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 515        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 516        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 517        0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
 518        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 519        0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 520        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 521
 522        /* page 2  ps-poll */
 523        0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
 524        0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 525        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 526        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 527        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 528        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 529        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 530        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 531        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 532        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 533        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 534        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 535        0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
 536        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
 537        0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 538        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 539
 540        /* page 3  null */
 541        0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
 542        0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 543        0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
 544        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 549        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 550        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 551        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 552        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 553        0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
 554        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
 555        0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 556        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 557
 558        /* page 4  probe_resp */
 559        0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
 560        0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 561        0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
 562        0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
 563        0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
 564        0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
 565        0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
 566        0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
 567        0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
 568        0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
 569        0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 570        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 571        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 572        0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
 573        0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 574        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 575
 576        /* page 5  probe_resp */
 577        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 578        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 579        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 580        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 581        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 582        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 583        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 584        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 585        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 586        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 587        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 588        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 589        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 590        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 591        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 592        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 593};
 594
 595void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
 596{
 597        struct rtl_priv *rtlpriv = rtl_priv(hw);
 598        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 599        struct sk_buff *skb = NULL;
 600        u32 totalpacketlen;
 601        bool rtstatus;
 602        u8 u1rsvdpageloc[3] = { 0 };
 603        bool dlok = false;
 604        u8 *beacon;
 605        u8 *p_pspoll;
 606        u8 *nullfunc;
 607        u8 *p_probersp;
 608        /*---------------------------------------------------------
 609                                                (1) beacon
 610        ---------------------------------------------------------*/
 611        beacon = &reserved_page_packet[BEACON_PG * 128];
 612        SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
 613        SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
 614        /*-------------------------------------------------------
 615                                                (2) ps-poll
 616        --------------------------------------------------------*/
 617        p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
 618        SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
 619        SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
 620        SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
 621        SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
 622        /*--------------------------------------------------------
 623                                                (3) null data
 624        ---------------------------------------------------------*/
 625        nullfunc = &reserved_page_packet[NULL_PG * 128];
 626        SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
 627        SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
 628        SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
 629        SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
 630        /*---------------------------------------------------------
 631                                                (4) probe response
 632        ----------------------------------------------------------*/
 633        p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
 634        SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
 635        SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
 636        SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
 637        SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
 638        totalpacketlen = TOTAL_RESERVED_PKT_LEN;
 639        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
 640                      "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
 641                      &reserved_page_packet[0], totalpacketlen);
 642        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
 643                      "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
 644                      u1rsvdpageloc, 3);
 645        skb = dev_alloc_skb(totalpacketlen);
 646        if (!skb) {
 647                dlok = false;
 648        } else {
 649                skb_put_data(skb, &reserved_page_packet, totalpacketlen);
 650                rtstatus = _rtl92d_cmd_send_packet(hw, skb);
 651
 652                if (rtstatus)
 653                        dlok = true;
 654        }
 655        if (dlok) {
 656                rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
 657                        "Set RSVD page location to Fw\n");
 658                RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
 659                              "H2C_RSVDPAGE", u1rsvdpageloc, 3);
 660                rtl92d_fill_h2c_cmd(hw, H2C_RSVDPAGE,
 661                        sizeof(u1rsvdpageloc), u1rsvdpageloc);
 662        } else
 663                rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
 664                        "Set RSVD page location to Fw FAIL!!!!!!\n");
 665}
 666
 667void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
 668{
 669        u8 u1_joinbssrpt_parm[1] = {0};
 670
 671        SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
 672        rtl92d_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
 673}
 674