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