GNU Linux-libre 4.14.266-gnu1
[releases.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, pskb->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         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
493 bool 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
515 static 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
661 void 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         if (!skb)
756                 return;
757         memcpy((u8 *)skb_put(skb, totalpacketlen), &reserved_page_packet,
758                totalpacketlen);
759
760         rtstatus = _rtl8822be_send_bcn_or_cmd_packet(hw, skb, BEACON_QUEUE);
761
762         if (rtstatus)
763                 b_dlok = true;
764
765         if (b_dlok) {
766                 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
767                          "Set RSVD page location to Fw.\n");
768                 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C_RSVDPAGE:\n",
769                               u1_rsvd_page_loc, 3);
770                 rtl8822be_fill_h2c_cmd(hw, H2C_8822B_RSVDPAGE,
771                                        sizeof(u1_rsvd_page_loc),
772                                        u1_rsvd_page_loc);
773         } else
774                 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
775                          "Set RSVD page location to Fw FAIL!!!!!!.\n");
776 }
777
778 /* Should check FW support p2p or not. */
779 static void rtl8822be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
780                                              u8 ctwindow)
781 {
782         u8 u1_ctwindow_period[1] = {ctwindow};
783
784         rtl8822be_fill_h2c_cmd(hw, H2C_8822B_P2P_PS_CTW_CMD, 1,
785                                u1_ctwindow_period);
786 }
787
788 void rtl8822be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
789 {
790         struct rtl_priv *rtlpriv = rtl_priv(hw);
791         struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
792         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
793         struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
794         struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
795         u8 i;
796         u16 ctwindow;
797         u32 start_time, tsf_low;
798
799         switch (p2p_ps_state) {
800         case P2P_PS_DISABLE:
801                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
802                 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
803                 break;
804         case P2P_PS_ENABLE:
805                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
806                 /* update CTWindow value. */
807                 if (p2pinfo->ctwindow > 0) {
808                         p2p_ps_offload->ctwindow_en = 1;
809                         ctwindow = p2pinfo->ctwindow;
810                         rtl8822be_set_p2p_ctw_period_cmd(hw, ctwindow);
811                 }
812                 /* hw only support 2 set of NoA */
813                 for (i = 0; i < p2pinfo->noa_num; i++) {
814                         /* To control the register setting for which NOA*/
815                         rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
816                         if (i == 0)
817                                 p2p_ps_offload->noa0_en = 1;
818                         else
819                                 p2p_ps_offload->noa1_en = 1;
820                         /* config P2P NoA Descriptor Register */
821                         rtl_write_dword(rtlpriv, 0x5E0,
822                                         p2pinfo->noa_duration[i]);
823                         rtl_write_dword(rtlpriv, 0x5E4,
824                                         p2pinfo->noa_interval[i]);
825
826                         /*Get Current TSF value */
827                         tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR_8822B);
828
829                         start_time = p2pinfo->noa_start_time[i];
830                         if (p2pinfo->noa_count_type[i] != 1) {
831                                 while (start_time <= (tsf_low + (50 * 1024))) {
832                                         start_time += p2pinfo->noa_interval[i];
833                                         if (p2pinfo->noa_count_type[i] != 255)
834                                                 p2pinfo->noa_count_type[i]--;
835                                 }
836                         }
837                         rtl_write_dword(rtlpriv, 0x5E8, start_time);
838                         rtl_write_dword(rtlpriv, 0x5EC,
839                                         p2pinfo->noa_count_type[i]);
840                 }
841                 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
842                         /* rst p2p circuit */
843                         rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST_8822B, BIT(4));
844                         p2p_ps_offload->offload_en = 1;
845
846                         if (rtlpriv->mac80211.p2p == P2P_ROLE_GO) {
847                                 p2p_ps_offload->role = 1;
848                                 p2p_ps_offload->allstasleep = 0;
849                         } else {
850                                 p2p_ps_offload->role = 0;
851                         }
852                         p2p_ps_offload->discovery = 0;
853                 }
854                 break;
855         case P2P_PS_SCAN:
856                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
857                 p2p_ps_offload->discovery = 1;
858                 break;
859         case P2P_PS_SCAN_DONE:
860                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
861                 p2p_ps_offload->discovery = 0;
862                 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
863                 break;
864         default:
865                 break;
866         }
867
868         rtl8822be_fill_h2c_cmd(hw, H2C_8822B_P2P_PS_OFFLOAD, 1,
869                                (u8 *)p2p_ps_offload);
870 }
871
872 static
873 void rtl8822be_c2h_content_parsing_ext(struct ieee80211_hw *hw,
874                                        u8 c2h_sub_cmd_id,
875                                        u8 c2h_cmd_len,
876                                        u8 *c2h_content_buf)
877 {
878         struct rtl_priv *rtlpriv = rtl_priv(hw);
879         struct rtl_halmac_ops *halmac_ops;
880
881         switch (c2h_sub_cmd_id) {
882         case 0x0F:
883                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
884                          "[C2H], C2H_8822BE_TX_REPORT!\n");
885                 rtl_tx_report_handler(hw, c2h_content_buf, c2h_cmd_len);
886                 break;
887         default:
888                 /* indicate c2h pkt + rx desc to halmac */
889                 halmac_ops = rtlpriv->halmac.ops;
890                 halmac_ops->halmac_c2h_handle(rtlpriv,
891                                               c2h_content_buf - 24 - 2 - 2,
892                                               c2h_cmd_len + 24 + 2 + 2);
893                 break;
894         }
895 }
896
897 void rtl8822be_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
898                                    u8 c2h_cmd_len, u8 *tmp_buf)
899 {
900         struct rtl_priv *rtlpriv = rtl_priv(hw);
901         struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
902
903         if (c2h_cmd_id == 0xFF) {
904                 rtl8822be_c2h_content_parsing_ext(hw, tmp_buf[0],
905                                                   c2h_cmd_len - 2,
906                                                   tmp_buf + 2);
907                 return;
908         }
909
910         switch (c2h_cmd_id) {
911         case C2H_8822B_DBG:
912                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
913                          "[C2H], C2H_8822BE_DBG!!\n");
914                 break;
915         case C2H_8822B_TXBF:
916                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
917                          "[C2H], C2H_8822B_TXBF!!\n");
918                 break;
919         case C2H_8822B_BT_INFO:
920                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
921                          "[C2H], C2H_8822BE_BT_INFO!!\n");
922                 if (rtlpriv->cfg->ops->get_btc_status())
923                         btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
924                                                    c2h_cmd_len);
925                 break;
926         case C2H_8822B_BT_MP:
927                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
928                          "[C2H], C2H_8822BE_BT_MP!!\n");
929                 if (rtlpriv->cfg->ops->get_btc_status())
930                         btc_ops->btc_btmpinfo_notify(rtlpriv, tmp_buf,
931                                                      c2h_cmd_len);
932                 break;
933         default:
934                 if (!rtlpriv->phydm.ops->phydm_c2h_content_parsing(
935                             rtlpriv, c2h_cmd_id, c2h_cmd_len, tmp_buf))
936                         break;
937
938                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
939                          "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id);
940                 break;
941         }
942 }
943
944 void rtl8822be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
945 {
946         struct rtl_priv *rtlpriv = rtl_priv(hw);
947         u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
948         u8 *tmp_buf = NULL;
949
950         c2h_cmd_id = buffer[0];
951         c2h_cmd_seq = buffer[1];
952         c2h_cmd_len = len - 2;
953         tmp_buf = buffer + 2;
954
955         RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
956                  "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
957                  c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
958
959         RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
960                       "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
961
962         switch (c2h_cmd_id) {
963         case C2H_8822B_BT_INFO:
964         case C2H_8822B_BT_MP:
965                 rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
966                 break;
967         default:
968                 rtl8822be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len,
969                                               tmp_buf);
970                 break;
971         }
972 }