linux/drivers/staging/rtlwifi/rtl8822be/fw.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2016  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 "reg.h"
  30#include "def.h"
  31#include "fw.h"
  32
  33static bool _rtl8822be_check_fw_read_last_h2c(struct ieee80211_hw *hw,
  34                                              u8 boxnum)
  35{
  36        struct rtl_priv *rtlpriv = rtl_priv(hw);
  37        u8 val_hmetfr;
  38        bool result = false;
  39
  40        val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR_8822B);
  41        if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
  42                result = true;
  43        return result;
  44}
  45
  46static void _rtl8822be_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
  47                                        u32 cmd_len, u8 *cmdbuffer)
  48{
  49        struct rtl_priv *rtlpriv = rtl_priv(hw);
  50        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  51        u8 boxnum;
  52        u16 box_reg = 0, box_extreg = 0;
  53        u8 u1b_tmp;
  54        bool isfw_read;
  55        u8 buf_index = 0;
  56        bool bwrite_success = false;
  57        u8 wait_h2c_limmit = 100;
  58        u8 boxcontent[4], boxextcontent[4];
  59        u32 h2c_waitcounter = 0;
  60        unsigned long flag;
  61        u8 idx;
  62
  63        /* 1. Prevent race condition in setting H2C cmd.
  64         * (copy from MgntActSet_RF_State().)
  65         */
  66        while (true) {
  67                spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
  68                if (rtlhal->h2c_setinprogress) {
  69                        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
  70                                 "H2C set in progress! wait..H2C_ID=%d.\n",
  71                                 element_id);
  72
  73                        while (rtlhal->h2c_setinprogress) {
  74                                spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
  75                                                       flag);
  76                                h2c_waitcounter++;
  77                                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
  78                                         "Wait 100 us (%d times)...\n",
  79                                         h2c_waitcounter);
  80                                udelay(100);
  81
  82                                if (h2c_waitcounter > 1000)
  83                                        return;
  84                                spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
  85                                                  flag);
  86                        }
  87                        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
  88                } else {
  89                        rtlhal->h2c_setinprogress = true;
  90                        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
  91                        break;
  92                }
  93        }
  94
  95        while (!bwrite_success) {
  96                /* 2. Find the last BOX number which has been writen. */
  97                boxnum = rtlhal->last_hmeboxnum;
  98                switch (boxnum) {
  99                case 0:
 100                        box_reg = REG_HMEBOX0_8822B;
 101                        box_extreg = REG_HMEBOX_E0_8822B;
 102                        break;
 103                case 1:
 104                        box_reg = REG_HMEBOX1_8822B;
 105                        box_extreg = REG_HMEBOX_E1_8822B;
 106                        break;
 107                case 2:
 108                        box_reg = REG_HMEBOX2_8822B;
 109                        box_extreg = REG_HMEBOX_E2_8822B;
 110                        break;
 111                case 3:
 112                        box_reg = REG_HMEBOX3_8822B;
 113                        box_extreg = REG_HMEBOX_E3_8822B;
 114                        break;
 115                default:
 116                        RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
 117                                 "switch case not process\n");
 118                        break;
 119                }
 120
 121                /* 3. Check if the box content is empty. */
 122                u1b_tmp = rtl_read_byte(rtlpriv, REG_CR_8822B);
 123
 124                if (u1b_tmp == 0xea) {
 125                        if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS_8822B) ==
 126                                    0xea ||
 127                            rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY_8822B) ==
 128                                    0xea)
 129                                rtl_write_byte(rtlpriv, REG_SYS_CFG1_8822B + 3,
 130                                               0xff);
 131
 132                        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 133                                 "REG_CR is unavaliable\n");
 134                        break;
 135                }
 136
 137                wait_h2c_limmit = 100;
 138                isfw_read = _rtl8822be_check_fw_read_last_h2c(hw, boxnum);
 139                while (!isfw_read) {
 140                        wait_h2c_limmit--;
 141                        if (wait_h2c_limmit == 0) {
 142                                RT_TRACE(rtlpriv, COMP_CMD, DBG_WARNING,
 143                                         "Wait too long for FW clear MB%d!!!\n",
 144                                         boxnum);
 145                                break;
 146                        }
 147                        udelay(10);
 148                        isfw_read =
 149                                _rtl8822be_check_fw_read_last_h2c(hw, boxnum);
 150                        u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
 151                        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 152                                 "Waiting for FW clear MB%d!!! 0x130 = %2x\n",
 153                                 boxnum, u1b_tmp);
 154                }
 155
 156                /* If Fw has not read the last H2C cmd,
 157                 * break and give up this H2C.
 158                 */
 159                if (!isfw_read) {
 160                        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 161                                 "Write H2C reg BOX[%d] fail,Fw don't read.\n",
 162                                 boxnum);
 163                        break;
 164                }
 165                /* 4. Fill the H2C cmd into box */
 166                memset(boxcontent, 0, sizeof(boxcontent));
 167                memset(boxextcontent, 0, sizeof(boxextcontent));
 168                boxcontent[0] = element_id;
 169                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 170                         "Write element_id box_reg(%4x) = %2x\n", box_reg,
 171                         element_id);
 172
 173                switch (cmd_len) {
 174                case 1:
 175                case 2:
 176                case 3:
 177                        /*boxcontent[0] &= ~(BIT(7));*/
 178                        memcpy((u8 *)(boxcontent) + 1, cmdbuffer + buf_index,
 179                               cmd_len);
 180
 181                        for (idx = 0; idx < 4; idx++) {
 182                                rtl_write_byte(rtlpriv, box_reg + idx,
 183                                               boxcontent[idx]);
 184                        }
 185                        break;
 186                case 4:
 187                case 5:
 188                case 6:
 189                case 7:
 190                        /*boxcontent[0] |= (BIT(7));*/
 191                        memcpy((u8 *)(boxextcontent), cmdbuffer + buf_index + 3,
 192                               cmd_len - 3);
 193                        memcpy((u8 *)(boxcontent) + 1, cmdbuffer + buf_index,
 194                               3);
 195
 196                        for (idx = 0; idx < 4; idx++) {
 197                                rtl_write_byte(rtlpriv, box_extreg + idx,
 198                                               boxextcontent[idx]);
 199                        }
 200
 201                        for (idx = 0; idx < 4; idx++) {
 202                                rtl_write_byte(rtlpriv, box_reg + idx,
 203                                               boxcontent[idx]);
 204                        }
 205                        break;
 206                default:
 207                        RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
 208                                 "switch case not process\n");
 209                        break;
 210                }
 211
 212                bwrite_success = true;
 213
 214                rtlhal->last_hmeboxnum = boxnum + 1;
 215                if (rtlhal->last_hmeboxnum == 4)
 216                        rtlhal->last_hmeboxnum = 0;
 217
 218                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 219                         "pHalData->last_hmeboxnum  = %d\n",
 220                         rtlhal->last_hmeboxnum);
 221        }
 222
 223        spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
 224        rtlhal->h2c_setinprogress = false;
 225        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 226
 227        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
 228}
 229
 230void rtl8822be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, u32 cmd_len,
 231                            u8 *cmdbuffer)
 232{
 233        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 234        struct rtl_priv *rtlpriv = rtl_priv(hw);
 235        u8 tmp_cmdbuf[8];
 236
 237        if (!rtlhal->fw_ready) {
 238                WARN_ONCE(true,
 239                          "return H2C cmd because of Fw download fail!!!\n");
 240                return;
 241        }
 242
 243        memset(tmp_cmdbuf, 0, 8);
 244        memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
 245
 246        RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG,
 247                 "h2c cmd: len=%d %02X%02X%02X%02X %02X%02X%02X%02X\n", cmd_len,
 248                 tmp_cmdbuf[2], tmp_cmdbuf[1], tmp_cmdbuf[0], element_id,
 249                 tmp_cmdbuf[6], tmp_cmdbuf[5], tmp_cmdbuf[4], tmp_cmdbuf[3]);
 250
 251        _rtl8822be_fill_h2c_command(hw, element_id, cmd_len, tmp_cmdbuf);
 252}
 253
 254void rtl8822be_set_default_port_id_cmd(struct ieee80211_hw *hw)
 255{
 256        u8 h2c_set_default_port_id[H2C_DEFAULT_PORT_ID_LEN];
 257
 258        SET_H2CCMD_DFTPID_PORT_ID(h2c_set_default_port_id, 0);
 259        SET_H2CCMD_DFTPID_MAC_ID(h2c_set_default_port_id, 0);
 260
 261        rtl8822be_fill_h2c_cmd(hw, H2C_8822B_DEFAULT_PORT_ID,
 262                               H2C_DEFAULT_PORT_ID_LEN,
 263                               h2c_set_default_port_id);
 264}
 265
 266void rtl8822be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
 267{
 268        struct rtl_priv *rtlpriv = rtl_priv(hw);
 269        u8 u1_h2c_set_pwrmode[H2C_8822B_PWEMODE_LENGTH] = {0};
 270        static u8 prev_h2c[H2C_8822B_PWEMODE_LENGTH] = {0};
 271        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 272        u8 rlbm, power_state = 0, byte5 = 0;
 273        u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
 274        u8 smart_ps = 0;
 275        struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
 276        bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
 277                            btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
 278        bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ?
 279                          btc_ops->btc_is_bt_lps_on(rtlpriv) : false);
 280
 281        memset(u1_h2c_set_pwrmode, 0, H2C_8822B_PWEMODE_LENGTH);
 282
 283        if (bt_ctrl_lps)
 284                mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE);
 285
 286        RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
 287                 mode, bt_ctrl_lps);
 288
 289        switch (mode) {
 290        case FW_PS_MIN_MODE:
 291                rlbm = 0;
 292                awake_intvl = 2;
 293                smart_ps = ppsc->smart_ps;
 294                break;
 295        case FW_PS_MAX_MODE:
 296                rlbm = 1;
 297                awake_intvl = 2;
 298                smart_ps = ppsc->smart_ps;
 299                break;
 300        case FW_PS_DTIM_MODE:
 301                rlbm = 2;
 302                awake_intvl = ppsc->reg_max_lps_awakeintvl;
 303                /*
 304                 * hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
 305                 * is only used in swlps.
 306                 */
 307                smart_ps = ppsc->smart_ps;
 308                break;
 309        case FW_PS_ACTIVE_MODE:
 310                rlbm = 0;
 311                awake_intvl = 1;
 312                break;
 313        default:
 314                rlbm = 2;
 315                awake_intvl = 4;
 316                smart_ps = ppsc->smart_ps;
 317                break;
 318        }
 319
 320        if (rtlpriv->mac80211.p2p) {
 321                awake_intvl = 2;
 322                rlbm = 1;
 323        }
 324
 325        if (mode == FW_PS_ACTIVE_MODE) {
 326                byte5 = 0x40;
 327                power_state = FW_PWR_STATE_ACTIVE;
 328        } else {
 329                if (bt_ctrl_lps) {
 330                        byte5 = btc_ops->btc_get_lps_val(rtlpriv);
 331                        power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
 332
 333                        if (rlbm == 2 && (byte5 & BIT(4))) {
 334                                /* Keep awake interval to 1 to prevent from
 335                                 * decreasing coex performance
 336                                 */
 337                                awake_intvl = 2;
 338                                rlbm = 2;
 339                        }
 340                        smart_ps = 0;
 341                } else {
 342                        byte5 = 0x40;
 343                        power_state = FW_PWR_STATE_RF_OFF;
 344                }
 345        }
 346
 347        SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
 348        SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
 349        SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, smart_ps);
 350        SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, awake_intvl);
 351        SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
 352        SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
 353        SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
 354
 355        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
 356                      "rtl8822be_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
 357                      u1_h2c_set_pwrmode, H2C_8822B_PWEMODE_LENGTH);
 358        if (rtlpriv->cfg->ops->get_btc_status())
 359                btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
 360                                             H2C_8822B_PWEMODE_LENGTH);
 361
 362        if (!memcmp(prev_h2c, u1_h2c_set_pwrmode, H2C_8822B_PWEMODE_LENGTH))
 363                return;
 364        memcpy(prev_h2c, u1_h2c_set_pwrmode, H2C_8822B_PWEMODE_LENGTH);
 365
 366        rtl8822be_set_default_port_id_cmd(hw);
 367        rtl8822be_fill_h2c_cmd(hw, H2C_8822B_SETPWRMODE,
 368                               H2C_8822B_PWEMODE_LENGTH, u1_h2c_set_pwrmode);
 369}
 370
 371void rtl8822be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
 372{
 373        u8 parm[4] = {0, 0, 0, 0};
 374        /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
 375         *          bit1=0-->update Media Status to MACID
 376         *          bit1=1-->update Media Status from MACID to MACID_End
 377         * parm[1]: MACID, if this is INFRA_STA, MacID = 0
 378         * parm[2]: MACID_End
 379         * parm[3]: bit2-0: port ID
 380         */
 381
 382        SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
 383        SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
 384
 385        rtl8822be_fill_h2c_cmd(hw, H2C_8822B_MSRRPT, 4, parm);
 386}
 387
 388static bool _rtl8822be_send_bcn_or_cmd_packet(struct ieee80211_hw *hw,
 389                                              struct sk_buff *skb, u8 hw_queue)
 390{
 391        struct rtl_priv *rtlpriv = rtl_priv(hw);
 392        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 393        struct rtl8192_tx_ring *ring;
 394        struct rtl_tx_desc *pdesc;
 395        struct rtl_tx_buffer_desc *pbd_desc;
 396        unsigned long flags;
 397        struct sk_buff *pskb = NULL;
 398        u8 *pdesc_or_bddesc;
 399        dma_addr_t dma_addr;
 400
 401        if (hw_queue != BEACON_QUEUE && hw_queue != H2C_QUEUE)
 402                return false;
 403
 404        ring = &rtlpci->tx_ring[hw_queue];
 405
 406        spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
 407
 408        if (hw_queue == BEACON_QUEUE) {
 409                pdesc = &ring->desc[0];
 410                pbd_desc = &ring->buffer_desc[0];
 411                pdesc_or_bddesc = (u8 *)pbd_desc;
 412
 413                /* free previous beacon queue */
 414                pskb = __skb_dequeue(&ring->queue);
 415
 416                if (!pskb)
 417                        goto free_prev_skb_done;
 418
 419                dma_addr = rtlpriv->cfg->ops->get_desc(
 420                                hw, (u8 *)pbd_desc, true, HW_DESC_TXBUFF_ADDR);
 421
 422                pci_unmap_single(rtlpci->pdev, dma_addr, pskb->len,
 423                                 PCI_DMA_TODEVICE);
 424                kfree_skb(pskb);
 425
 426free_prev_skb_done:
 427                ;
 428
 429        } else { /* hw_queue == TXCMD_QUEUE */
 430                if (rtlpriv->cfg->ops->get_available_desc(hw, hw_queue) == 0) {
 431                        RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 432                                 "get_available_desc fail hw_queue=%d\n",
 433                                 hw_queue);
 434                        spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock,
 435                                               flags);
 436                        return false;
 437                }
 438
 439                pdesc = &ring->desc[ring->cur_tx_wp];
 440                pbd_desc = &ring->buffer_desc[ring->cur_tx_wp];
 441                pdesc_or_bddesc = (u8 *)pdesc;
 442        }
 443
 444        rtlpriv->cfg->ops->fill_tx_special_desc(hw, (u8 *)pdesc, (u8 *)pbd_desc,
 445                                                skb, hw_queue);
 446
 447        __skb_queue_tail(&ring->queue, skb);
 448
 449        rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc_or_bddesc, true,
 450                                    HW_DESC_OWN, (u8 *)&hw_queue);
 451
 452        spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
 453
 454        rtlpriv->cfg->ops->tx_polling(hw, hw_queue);
 455
 456        return true;
 457}
 458
 459bool rtl8822b_halmac_cb_write_data_rsvd_page(struct rtl_priv *rtlpriv, u8 *buf,
 460                                             u32 size)
 461{
 462        struct sk_buff *skb = NULL;
 463        u8 u1b_tmp;
 464        int count;
 465
 466        skb = dev_alloc_skb(size);
 467        if (!skb)
 468                return false;
 469        memcpy((u8 *)skb_put(skb, size), buf, size);
 470
 471        if (!_rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, BEACON_QUEUE))
 472                return false;
 473
 474        /* These code isn't actually need, because halmac will check
 475         * BCN_VALID
 476         */
 477
 478        /* Polling Beacon Queue to send Beacon */
 479        u1b_tmp = rtl_read_byte(rtlpriv, REG_RX_RXBD_NUM_8822B + 1);
 480        count = 0;
 481        while ((count < 20) && (u1b_tmp & BIT(4))) {
 482                count++;
 483                udelay(10);
 484                u1b_tmp = rtl_read_byte(rtlpriv, REG_RX_RXBD_NUM_8822B + 1);
 485        }
 486
 487        if (count >= 20)
 488                pr_err("%s polling beacon fail\n", __func__);
 489
 490        return true;
 491}
 492
 493bool rtl8822b_halmac_cb_write_data_h2c(struct rtl_priv *rtlpriv, u8 *buf,
 494                                       u32 size)
 495{
 496        struct sk_buff *skb = NULL;
 497
 498        /* without GFP_DMA, pci_map_single() may not work */
 499        skb = __netdev_alloc_skb(NULL, size, GFP_ATOMIC | GFP_DMA);
 500        memcpy((u8 *)skb_put(skb, size), buf, size);
 501
 502        return _rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, H2C_QUEUE);
 503}
 504
 505/* Rsvd page HALMAC_RSVD_DRV_PGNUM_8822B occupies 16 page (2048 byte) */
 506#define BEACON_PG       0 /* ->1 */
 507#define PSPOLL_PG       2
 508#define NULL_PG 3
 509#define PROBERSP_PG     4 /* ->5 */
 510#define QOS_NULL_PG     6
 511#define BT_QOS_NULL_PG  7
 512
 513#define TOTAL_RESERVED_PKT_LEN  1024
 514
 515static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {/* page size = 128 */
 516        /* page 0 beacon */
 517        0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
 518        0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
 519        0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
 520        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 521        0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
 522        0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
 523        0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
 524        0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
 525        0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
 526        0x09, 0x03, 0xFF, 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, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
 530        0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
 531        0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
 532        0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
 533
 534        /* page 1 beacon */
 535        0x00, 0x50, 0xF2, 0x02, 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        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 544        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 545        0x10, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
 546        0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 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
 552        /* page 2  ps-poll */
 553        0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
 554        0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
 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        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 562        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 563        0x18, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
 564        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
 565        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 566        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 567        0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 568        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 569
 570        /* page 3  null */
 571        0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
 572        0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
 573        0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 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        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 580        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 581        0x72, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
 582        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
 583        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 584        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 585        0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 586        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 587
 588        /* page 4  probe_resp */
 589        0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
 590        0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 591        0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
 592        0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
 593        0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
 594        0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
 595        0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
 596        0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
 597        0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
 598        0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
 599        0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 600        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 601        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 602        0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
 603        0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 604        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 605
 606        /* page 5  probe_resp */
 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        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 612        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 613        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 614        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 615        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 616        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 617        0x1A, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
 618        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
 619        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 620        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 621        0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 622        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 623
 624        /* page 6 qos null data */
 625        0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
 626        0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
 627        0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
 628        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 629        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 630        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 631        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 632        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 633        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 634        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 635        0x1A, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
 636        0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
 637        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 638        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 639        0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 640        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 641
 642        /* page 7 BT-qos null data */
 643        0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
 644        0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
 645        0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 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        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 657        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 658        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 659};
 660
 661void rtl8822be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
 662{
 663        struct rtl_priv *rtlpriv = rtl_priv(hw);
 664        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 665        struct sk_buff *skb = NULL;
 666
 667        u32 totalpacketlen;
 668        bool rtstatus;
 669        u8 u1_rsvd_page_loc[7] = {0};
 670        bool b_dlok = false;
 671
 672        u8 *beacon;
 673        u8 *p_pspoll;
 674        u8 *nullfunc;
 675        u8 *p_probersp;
 676        u8 *qosnull;
 677        u8 *btqosnull;
 678
 679        memset(u1_rsvd_page_loc, 0, sizeof(u1_rsvd_page_loc));
 680
 681        /*---------------------------------------------------------
 682         *                      (1) beacon
 683         *---------------------------------------------------------
 684         */
 685        beacon = &reserved_page_packet[BEACON_PG * 128];
 686        SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
 687        SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
 688
 689        /*-------------------------------------------------------
 690         *                      (2) ps-poll
 691         *--------------------------------------------------------
 692         */
 693        p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
 694        SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
 695        SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
 696        SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
 697
 698        SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1_rsvd_page_loc, PSPOLL_PG);
 699
 700        /*--------------------------------------------------------
 701         *                      (3) null data
 702         *---------------------------------------------------------
 703         */
 704        nullfunc = &reserved_page_packet[NULL_PG * 128];
 705        SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
 706        SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
 707        SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
 708
 709        SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1_rsvd_page_loc, NULL_PG);
 710
 711        /*---------------------------------------------------------
 712         *                      (4) probe response
 713         *----------------------------------------------------------
 714         */
 715        p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
 716        SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
 717        SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
 718        SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
 719
 720        SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1_rsvd_page_loc, PROBERSP_PG);
 721
 722        /*---------------------------------------------------------
 723         *                      (5) QoS null data
 724         *----------------------------------------------------------
 725         */
 726        qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
 727        SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
 728        SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
 729        SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
 730
 731        SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1_rsvd_page_loc, QOS_NULL_PG);
 732
 733        /*---------------------------------------------------------
 734         *                      (6) BT QoS null data
 735         *----------------------------------------------------------
 736         */
 737        btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
 738        SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
 739        SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
 740        SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
 741
 742        SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1_rsvd_page_loc,
 743                                                 BT_QOS_NULL_PG);
 744
 745        totalpacketlen = TOTAL_RESERVED_PKT_LEN;
 746
 747        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
 748                      "rtl8822be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
 749                      &reserved_page_packet[0], totalpacketlen);
 750        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
 751                      "rtl8822be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
 752                      u1_rsvd_page_loc, 3);
 753
 754        skb = dev_alloc_skb(totalpacketlen);
 755        memcpy((u8 *)skb_put(skb, totalpacketlen), &reserved_page_packet,
 756               totalpacketlen);
 757
 758        rtstatus = _rtl8822be_send_bcn_or_cmd_packet(hw, skb, BEACON_QUEUE);
 759
 760        if (rtstatus)
 761                b_dlok = true;
 762
 763        if (b_dlok) {
 764                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 765                         "Set RSVD page location to Fw.\n");
 766                RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C_RSVDPAGE:\n",
 767                              u1_rsvd_page_loc, 3);
 768                rtl8822be_fill_h2c_cmd(hw, H2C_8822B_RSVDPAGE,
 769                                       sizeof(u1_rsvd_page_loc),
 770                                       u1_rsvd_page_loc);
 771        } else {
 772                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 773                         "Set RSVD page location to Fw FAIL!!!!!!.\n");
 774        }
 775}
 776
 777/* Should check FW support p2p or not. */
 778static void rtl8822be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
 779                                             u8 ctwindow)
 780{
 781        u8 u1_ctwindow_period[1] = {ctwindow};
 782
 783        rtl8822be_fill_h2c_cmd(hw, H2C_8822B_P2P_PS_CTW_CMD, 1,
 784                               u1_ctwindow_period);
 785}
 786
 787void rtl8822be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
 788{
 789        struct rtl_priv *rtlpriv = rtl_priv(hw);
 790        struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
 791        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 792        struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
 793        struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
 794        u8 i;
 795        u16 ctwindow;
 796        u32 start_time, tsf_low;
 797
 798        switch (p2p_ps_state) {
 799        case P2P_PS_DISABLE:
 800                RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
 801                memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
 802                break;
 803        case P2P_PS_ENABLE:
 804                RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
 805                /* update CTWindow value. */
 806                if (p2pinfo->ctwindow > 0) {
 807                        p2p_ps_offload->ctwindow_en = 1;
 808                        ctwindow = p2pinfo->ctwindow;
 809                        rtl8822be_set_p2p_ctw_period_cmd(hw, ctwindow);
 810                }
 811                /* hw only support 2 set of NoA */
 812                for (i = 0; i < p2pinfo->noa_num; i++) {
 813                        /* To control the register setting for which NOA*/
 814                        rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
 815                        if (i == 0)
 816                                p2p_ps_offload->noa0_en = 1;
 817                        else
 818                                p2p_ps_offload->noa1_en = 1;
 819                        /* config P2P NoA Descriptor Register */
 820                        rtl_write_dword(rtlpriv, 0x5E0,
 821                                        p2pinfo->noa_duration[i]);
 822                        rtl_write_dword(rtlpriv, 0x5E4,
 823                                        p2pinfo->noa_interval[i]);
 824
 825                        /*Get Current TSF value */
 826                        tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR_8822B);
 827
 828                        start_time = p2pinfo->noa_start_time[i];
 829                        if (p2pinfo->noa_count_type[i] != 1) {
 830                                while (start_time <= (tsf_low + (50 * 1024))) {
 831                                        start_time += p2pinfo->noa_interval[i];
 832                                        if (p2pinfo->noa_count_type[i] != 255)
 833                                                p2pinfo->noa_count_type[i]--;
 834                                }
 835                        }
 836                        rtl_write_dword(rtlpriv, 0x5E8, start_time);
 837                        rtl_write_dword(rtlpriv, 0x5EC,
 838                                        p2pinfo->noa_count_type[i]);
 839                }
 840                if (p2pinfo->opp_ps == 1 || p2pinfo->noa_num > 0) {
 841                        /* rst p2p circuit */
 842                        rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST_8822B, BIT(4));
 843                        p2p_ps_offload->offload_en = 1;
 844
 845                        if (rtlpriv->mac80211.p2p == P2P_ROLE_GO) {
 846                                p2p_ps_offload->role = 1;
 847                                p2p_ps_offload->allstasleep = 0;
 848                        } else {
 849                                p2p_ps_offload->role = 0;
 850                        }
 851                        p2p_ps_offload->discovery = 0;
 852                }
 853                break;
 854        case P2P_PS_SCAN:
 855                RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
 856                p2p_ps_offload->discovery = 1;
 857                break;
 858        case P2P_PS_SCAN_DONE:
 859                RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
 860                p2p_ps_offload->discovery = 0;
 861                p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
 862                break;
 863        default:
 864                break;
 865        }
 866
 867        rtl8822be_fill_h2c_cmd(hw, H2C_8822B_P2P_PS_OFFLOAD, 1,
 868                               (u8 *)p2p_ps_offload);
 869}
 870
 871static
 872void rtl8822be_c2h_content_parsing_ext(struct ieee80211_hw *hw,
 873                                       u8 c2h_sub_cmd_id,
 874                                       u8 c2h_cmd_len,
 875                                       u8 *c2h_content_buf)
 876{
 877        struct rtl_priv *rtlpriv = rtl_priv(hw);
 878        struct rtl_halmac_ops *halmac_ops;
 879
 880        switch (c2h_sub_cmd_id) {
 881        case 0x0F:
 882                RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
 883                         "[C2H], C2H_8822BE_TX_REPORT!\n");
 884                rtl_tx_report_handler(hw, c2h_content_buf, c2h_cmd_len);
 885                break;
 886        default:
 887                /* indicate c2h pkt + rx desc to halmac */
 888                halmac_ops = rtlpriv->halmac.ops;
 889                halmac_ops->halmac_c2h_handle(rtlpriv,
 890                                              c2h_content_buf - 24 - 2 - 2,
 891                                              c2h_cmd_len + 24 + 2 + 2);
 892                break;
 893        }
 894}
 895
 896void rtl8822be_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
 897                                   u8 c2h_cmd_len, u8 *tmp_buf)
 898{
 899        struct rtl_priv *rtlpriv = rtl_priv(hw);
 900        struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
 901
 902        if (c2h_cmd_id == 0xFF) {
 903                rtl8822be_c2h_content_parsing_ext(hw, tmp_buf[0],
 904                                                  c2h_cmd_len - 2,
 905                                                  tmp_buf + 2);
 906                return;
 907        }
 908
 909        switch (c2h_cmd_id) {
 910        case C2H_8822B_DBG:
 911                RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
 912                         "[C2H], C2H_8822BE_DBG!!\n");
 913                break;
 914        case C2H_8822B_TXBF:
 915                RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
 916                         "[C2H], C2H_8822B_TXBF!!\n");
 917                break;
 918        case C2H_8822B_BT_INFO:
 919                RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
 920                         "[C2H], C2H_8822BE_BT_INFO!!\n");
 921                if (rtlpriv->cfg->ops->get_btc_status())
 922                        btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
 923                                                   c2h_cmd_len);
 924                break;
 925        case C2H_8822B_BT_MP:
 926                RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
 927                         "[C2H], C2H_8822BE_BT_MP!!\n");
 928                if (rtlpriv->cfg->ops->get_btc_status())
 929                        btc_ops->btc_btmpinfo_notify(rtlpriv, tmp_buf,
 930                                                     c2h_cmd_len);
 931                break;
 932        default:
 933                if (!rtlpriv->phydm.ops->phydm_c2h_content_parsing(
 934                            rtlpriv, c2h_cmd_id, c2h_cmd_len, tmp_buf))
 935                        break;
 936
 937                RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
 938                         "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id);
 939                break;
 940        }
 941}
 942
 943void rtl8822be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
 944{
 945        struct rtl_priv *rtlpriv = rtl_priv(hw);
 946        u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
 947        u8 *tmp_buf = NULL;
 948
 949        c2h_cmd_id = buffer[0];
 950        c2h_cmd_seq = buffer[1];
 951        c2h_cmd_len = len - 2;
 952        tmp_buf = buffer + 2;
 953
 954        RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
 955                 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
 956                 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
 957
 958        RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
 959                      "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
 960
 961        switch (c2h_cmd_id) {
 962        case C2H_8822B_BT_INFO:
 963        case C2H_8822B_BT_MP:
 964                rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
 965                break;
 966        default:
 967                rtl8822be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len,
 968                                              tmp_buf);
 969                break;
 970        }
 971}
 972