Merge tag 'wberr-v4.14-1' of git://git.kernel.org/pub/scm/linux/kernel/git/jlayton...
[sfrench/cifs-2.6.git] / drivers / staging / rtlwifi / rtl8822be / fw.c
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
33 static 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
46 static 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
230 void 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
254 void 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
266 void 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
371 void 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
388 static 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, skb->len,
423                                  PCI_DMA_TODEVICE);
424                 kfree_skb(pskb);
425
426 free_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
459 bool 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         memcpy((u8 *)skb_put(skb, size), buf, size);
468
469         if (!_rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, BEACON_QUEUE))
470                 return false;
471
472         /* These code isn't actually need, because halmac will check
473          * BCN_VALID
474          */
475
476         /* Polling Beacon Queue to send Beacon */
477         u1b_tmp = rtl_read_byte(rtlpriv, REG_RX_RXBD_NUM_8822B + 1);
478         count = 0;
479         while ((count < 20) && (u1b_tmp & BIT(4))) {
480                 count++;
481                 udelay(10);
482                 u1b_tmp = rtl_read_byte(rtlpriv, REG_RX_RXBD_NUM_8822B + 1);
483         }
484
485         if (count >= 20)
486                 pr_err("%s polling beacon fail\n", __func__);
487
488         return true;
489 }
490
491 bool rtl8822b_halmac_cb_write_data_h2c(struct rtl_priv *rtlpriv, u8 *buf,
492                                        u32 size)
493 {
494         struct sk_buff *skb = NULL;
495
496         /* without GFP_DMA, pci_map_single() may not work */
497         skb = __netdev_alloc_skb(NULL, size, GFP_ATOMIC | GFP_DMA);
498         memcpy((u8 *)skb_put(skb, size), buf, size);
499
500         return _rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, H2C_QUEUE);
501 }
502
503 /* Rsvd page HALMAC_RSVD_DRV_PGNUM_8822B occupies 16 page (2048 byte) */
504 #define BEACON_PG       0 /* ->1 */
505 #define PSPOLL_PG       2
506 #define NULL_PG 3
507 #define PROBERSP_PG     4 /* ->5 */
508 #define QOS_NULL_PG     6
509 #define BT_QOS_NULL_PG  7
510
511 #define TOTAL_RESERVED_PKT_LEN  1024
512
513 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {/* page size = 128 */
514         /* page 0 beacon */
515         0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
516         0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
517         0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
518         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519         0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
520         0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
521         0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
522         0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
523         0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
524         0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
525         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
527         0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
528         0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
529         0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
530         0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
531
532         /* page 1 beacon */
533         0x00, 0x50, 0xF2, 0x02, 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, 0x30, 0x84, 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         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
549
550         /* page 2  ps-poll */
551         0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
552         0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
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, 0x30, 0x84, 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         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567
568         /* page 3  null */
569         0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
570         0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
571         0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 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, 0x30, 0x84, 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         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585
586         /* page 4  probe_resp */
587         0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
588         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
589         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
590         0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
591         0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
592         0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
593         0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
594         0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
595         0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
596         0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
597         0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600         0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
601         0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603
604         /* page 5  probe_resp */
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         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         0x1A, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
616         0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
617         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619         0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621
622         /* page 6 qos null data */
623         0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
624         0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
625         0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 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         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         0x1A, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
634         0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
635         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637         0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639
640         /* page 7 BT-qos null data */
641         0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
642         0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
643         0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 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         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657 };
658
659 void rtl8822be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
660 {
661         struct rtl_priv *rtlpriv = rtl_priv(hw);
662         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
663         struct sk_buff *skb = NULL;
664
665         u32 totalpacketlen;
666         bool rtstatus;
667         u8 u1_rsvd_page_loc[7] = {0};
668         bool b_dlok = false;
669
670         u8 *beacon;
671         u8 *p_pspoll;
672         u8 *nullfunc;
673         u8 *p_probersp;
674         u8 *qosnull;
675         u8 *btqosnull;
676
677         memset(u1_rsvd_page_loc, 0, sizeof(u1_rsvd_page_loc));
678
679         /*---------------------------------------------------------
680          *                      (1) beacon
681          *---------------------------------------------------------
682          */
683         beacon = &reserved_page_packet[BEACON_PG * 128];
684         SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
685         SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
686
687         /*-------------------------------------------------------
688          *                      (2) ps-poll
689          *--------------------------------------------------------
690          */
691         p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
692         SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
693         SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
694         SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
695
696         SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1_rsvd_page_loc, PSPOLL_PG);
697
698         /*--------------------------------------------------------
699          *                      (3) null data
700          *---------------------------------------------------------
701          */
702         nullfunc = &reserved_page_packet[NULL_PG * 128];
703         SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
704         SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
705         SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
706
707         SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1_rsvd_page_loc, NULL_PG);
708
709         /*---------------------------------------------------------
710          *                      (4) probe response
711          *----------------------------------------------------------
712          */
713         p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
714         SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
715         SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
716         SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
717
718         SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1_rsvd_page_loc, PROBERSP_PG);
719
720         /*---------------------------------------------------------
721          *                      (5) QoS null data
722          *----------------------------------------------------------
723          */
724         qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
725         SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
726         SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
727         SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
728
729         SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1_rsvd_page_loc, QOS_NULL_PG);
730
731         /*---------------------------------------------------------
732          *                      (6) BT QoS null data
733          *----------------------------------------------------------
734          */
735         btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
736         SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
737         SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
738         SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
739
740         SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1_rsvd_page_loc,
741                                                  BT_QOS_NULL_PG);
742
743         totalpacketlen = TOTAL_RESERVED_PKT_LEN;
744
745         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
746                       "rtl8822be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
747                       &reserved_page_packet[0], totalpacketlen);
748         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
749                       "rtl8822be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
750                       u1_rsvd_page_loc, 3);
751
752         skb = dev_alloc_skb(totalpacketlen);
753         memcpy((u8 *)skb_put(skb, totalpacketlen), &reserved_page_packet,
754                totalpacketlen);
755
756         rtstatus = _rtl8822be_send_bcn_or_cmd_packet(hw, skb, BEACON_QUEUE);
757
758         if (rtstatus)
759                 b_dlok = true;
760
761         if (b_dlok) {
762                 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
763                          "Set RSVD page location to Fw.\n");
764                 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C_RSVDPAGE:\n",
765                               u1_rsvd_page_loc, 3);
766                 rtl8822be_fill_h2c_cmd(hw, H2C_8822B_RSVDPAGE,
767                                        sizeof(u1_rsvd_page_loc),
768                                        u1_rsvd_page_loc);
769         } else
770                 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
771                          "Set RSVD page location to Fw FAIL!!!!!!.\n");
772 }
773
774 /* Should check FW support p2p or not. */
775 static void rtl8822be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
776                                              u8 ctwindow)
777 {
778         u8 u1_ctwindow_period[1] = {ctwindow};
779
780         rtl8822be_fill_h2c_cmd(hw, H2C_8822B_P2P_PS_CTW_CMD, 1,
781                                u1_ctwindow_period);
782 }
783
784 void rtl8822be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
785 {
786         struct rtl_priv *rtlpriv = rtl_priv(hw);
787         struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
788         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
789         struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
790         struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
791         u8 i;
792         u16 ctwindow;
793         u32 start_time, tsf_low;
794
795         switch (p2p_ps_state) {
796         case P2P_PS_DISABLE:
797                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
798                 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
799                 break;
800         case P2P_PS_ENABLE:
801                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
802                 /* update CTWindow value. */
803                 if (p2pinfo->ctwindow > 0) {
804                         p2p_ps_offload->ctwindow_en = 1;
805                         ctwindow = p2pinfo->ctwindow;
806                         rtl8822be_set_p2p_ctw_period_cmd(hw, ctwindow);
807                 }
808                 /* hw only support 2 set of NoA */
809                 for (i = 0; i < p2pinfo->noa_num; i++) {
810                         /* To control the register setting for which NOA*/
811                         rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
812                         if (i == 0)
813                                 p2p_ps_offload->noa0_en = 1;
814                         else
815                                 p2p_ps_offload->noa1_en = 1;
816                         /* config P2P NoA Descriptor Register */
817                         rtl_write_dword(rtlpriv, 0x5E0,
818                                         p2pinfo->noa_duration[i]);
819                         rtl_write_dword(rtlpriv, 0x5E4,
820                                         p2pinfo->noa_interval[i]);
821
822                         /*Get Current TSF value */
823                         tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR_8822B);
824
825                         start_time = p2pinfo->noa_start_time[i];
826                         if (p2pinfo->noa_count_type[i] != 1) {
827                                 while (start_time <= (tsf_low + (50 * 1024))) {
828                                         start_time += p2pinfo->noa_interval[i];
829                                         if (p2pinfo->noa_count_type[i] != 255)
830                                                 p2pinfo->noa_count_type[i]--;
831                                 }
832                         }
833                         rtl_write_dword(rtlpriv, 0x5E8, start_time);
834                         rtl_write_dword(rtlpriv, 0x5EC,
835                                         p2pinfo->noa_count_type[i]);
836                 }
837                 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
838                         /* rst p2p circuit */
839                         rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST_8822B, BIT(4));
840                         p2p_ps_offload->offload_en = 1;
841
842                         if (rtlpriv->mac80211.p2p == P2P_ROLE_GO) {
843                                 p2p_ps_offload->role = 1;
844                                 p2p_ps_offload->allstasleep = 0;
845                         } else {
846                                 p2p_ps_offload->role = 0;
847                         }
848                         p2p_ps_offload->discovery = 0;
849                 }
850                 break;
851         case P2P_PS_SCAN:
852                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
853                 p2p_ps_offload->discovery = 1;
854                 break;
855         case P2P_PS_SCAN_DONE:
856                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
857                 p2p_ps_offload->discovery = 0;
858                 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
859                 break;
860         default:
861                 break;
862         }
863
864         rtl8822be_fill_h2c_cmd(hw, H2C_8822B_P2P_PS_OFFLOAD, 1,
865                                (u8 *)p2p_ps_offload);
866 }
867
868 static
869 void rtl8822be_c2h_content_parsing_ext(struct ieee80211_hw *hw,
870                                        u8 c2h_sub_cmd_id,
871                                        u8 c2h_cmd_len,
872                                        u8 *c2h_content_buf)
873 {
874         struct rtl_priv *rtlpriv = rtl_priv(hw);
875         struct rtl_halmac_ops *halmac_ops;
876
877         switch (c2h_sub_cmd_id) {
878         case 0x0F:
879                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
880                          "[C2H], C2H_8822BE_TX_REPORT!\n");
881                 rtl_tx_report_handler(hw, c2h_content_buf, c2h_cmd_len);
882                 break;
883         default:
884                 /* indicate c2h pkt + rx desc to halmac */
885                 halmac_ops = rtlpriv->halmac.ops;
886                 halmac_ops->halmac_c2h_handle(rtlpriv,
887                                               c2h_content_buf - 24 - 2 - 2,
888                                               c2h_cmd_len + 24 + 2 + 2);
889                 break;
890         }
891 }
892
893 void rtl8822be_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
894                                    u8 c2h_cmd_len, u8 *tmp_buf)
895 {
896         struct rtl_priv *rtlpriv = rtl_priv(hw);
897         struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
898
899         if (c2h_cmd_id == 0xFF) {
900                 rtl8822be_c2h_content_parsing_ext(hw, tmp_buf[0],
901                                                   c2h_cmd_len - 2,
902                                                   tmp_buf + 2);
903                 return;
904         }
905
906         switch (c2h_cmd_id) {
907         case C2H_8822B_DBG:
908                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
909                          "[C2H], C2H_8822BE_DBG!!\n");
910                 break;
911         case C2H_8822B_TXBF:
912                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
913                          "[C2H], C2H_8822B_TXBF!!\n");
914                 break;
915         case C2H_8822B_BT_INFO:
916                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
917                          "[C2H], C2H_8822BE_BT_INFO!!\n");
918                 if (rtlpriv->cfg->ops->get_btc_status())
919                         btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
920                                                    c2h_cmd_len);
921                 break;
922         case C2H_8822B_BT_MP:
923                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
924                          "[C2H], C2H_8822BE_BT_MP!!\n");
925                 if (rtlpriv->cfg->ops->get_btc_status())
926                         btc_ops->btc_btmpinfo_notify(rtlpriv, tmp_buf,
927                                                      c2h_cmd_len);
928                 break;
929         default:
930                 if (!rtlpriv->phydm.ops->phydm_c2h_content_parsing(
931                             rtlpriv, c2h_cmd_id, c2h_cmd_len, tmp_buf))
932                         break;
933
934                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
935                          "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id);
936                 break;
937         }
938 }
939
940 void rtl8822be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
941 {
942         struct rtl_priv *rtlpriv = rtl_priv(hw);
943         u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
944         u8 *tmp_buf = NULL;
945
946         c2h_cmd_id = buffer[0];
947         c2h_cmd_seq = buffer[1];
948         c2h_cmd_len = len - 2;
949         tmp_buf = buffer + 2;
950
951         RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
952                  "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
953                  c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
954
955         RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
956                       "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
957
958         switch (c2h_cmd_id) {
959         case C2H_8822B_BT_INFO:
960         case C2H_8822B_BT_MP:
961                 rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
962                 break;
963         default:
964                 rtl8822be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len,
965                                               tmp_buf);
966                 break;
967         }
968 }