]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c
rtlwifi: btcoexist control to enter/leave LPS
[karo-tx-linux.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
431         RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
432                  mode, bt_ctrl_lps);
433
434         switch (mode) {
435         case FW_PS_MIN_MODE:
436                 rlbm = 0;
437                 awake_intvl = 2;
438                 break;
439         case FW_PS_MAX_MODE:
440                 rlbm = 1;
441                 awake_intvl = 2;
442                 break;
443         case FW_PS_DTIM_MODE:
444                 rlbm = 2;
445                 awake_intvl = ppsc->reg_max_lps_awakeintvl;
446                 /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
447                  * is only used in swlps.
448                  */
449                 break;
450         default:
451                 rlbm = 2;
452                 awake_intvl = 4;
453                 break;
454         }
455
456         if (rtlpriv->mac80211.p2p) {
457                 awake_intvl = 2;
458                 rlbm = 1;
459         }
460
461         if (mode == FW_PS_ACTIVE_MODE) {
462                 byte5 = 0x40;
463                 power_state = FW_PWR_STATE_ACTIVE;
464         } else {
465                 if (bt_ctrl_lps) {
466                         byte5 = btc_ops->btc_get_lps_val(rtlpriv);
467                         power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
468
469                         if ((rlbm == 2) && (byte5 & BIT(4))) {
470                                 /* Keep awake interval to 1 to prevent from
471                                  * decreasing coex performance
472                                  */
473                                 awake_intvl = 2;
474                                 rlbm = 2;
475                         }
476                 } else {
477                         byte5 = 0x40;
478                         power_state = FW_PWR_STATE_RF_OFF;
479                 }
480         }
481
482         SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
483         SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
484         SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
485                                          (rtlpriv->mac80211.p2p) ?
486                                          ppsc->smart_ps : 1);
487         SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
488                                                awake_intvl);
489         SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
490         SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
491         SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
492
493         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
494                       "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
495                       u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
496         if (rtlpriv->cfg->ops->get_btc_status())
497                 btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
498                                              H2C_92E_PWEMODE_LENGTH);
499         rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
500                              u1_h2c_set_pwrmode);
501 }
502
503 void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
504 {
505         u8 parm[3] = { 0 , 0 , 0 };
506         /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
507          *          bit1=0-->update Media Status to MACID
508          *          bit1=1-->update Media Status from MACID to MACID_End
509          * parm[1]: MACID, if this is INFRA_STA, MacID = 0
510          * parm[2]: MACID_End
511          */
512
513         SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
514         SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
515
516         rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm);
517 }
518
519 #define BEACON_PG               0 /* ->1 */
520 #define PSPOLL_PG               2
521 #define NULL_PG                 3
522 #define PROBERSP_PG             4 /* ->5 */
523 #define QOS_NULL_PG             6
524 #define BT_QOS_NULL_PG  7
525
526 #define TOTAL_RESERVED_PKT_LEN  1024
527
528 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
529         /* page 0 beacon */
530         0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
531         0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
532         0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
533         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534         0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
535         0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
536         0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
537         0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
538         0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
539         0x09, 0x03, 0xFF, 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, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
543         0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
544         0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
545         0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
546
547         /* page 1 beacon */
548         0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
549         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
550         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
551         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
552         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
553         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         0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
560         0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 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
565         /* page 2  ps-poll */
566         0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
567         0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
568         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572         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         0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
578         0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
579         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581         0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582
583         /* page 3  null */
584         0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
585         0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
586         0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
587         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595         0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
596         0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
597         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599         0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600
601         /* page 4  probe_resp */
602         0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
603         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
604         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
605         0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
606         0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
607         0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
608         0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
609         0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
610         0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
611         0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
612         0x03, 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         0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
616         0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618
619         /* page 5  probe_resp */
620         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
626         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627         0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
628         0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
629         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631         0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632
633         /* page 6 qos null data */
634         0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
635         0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
636         0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
637         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645         0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
646         0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
647         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649         0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650
651         /* page 7 BT-qos null data */
652         0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
653         0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
654         0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 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         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
660         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 };
673
674 void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
675 {
676         struct rtl_priv *rtlpriv = rtl_priv(hw);
677         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
678         struct sk_buff *skb = NULL;
679
680         u32 totalpacketlen;
681         u8 u1rsvdpageloc[5] = { 0 };
682         bool b_dlok = false;
683
684         u8 *beacon;
685         u8 *p_pspoll;
686         u8 *nullfunc;
687         u8 *p_probersp;
688         u8 *qosnull;
689         u8 *btqosnull;
690         /*---------------------------------------------------------
691          *                      (1) beacon
692          *---------------------------------------------------------
693          */
694         beacon = &reserved_page_packet[BEACON_PG * 128];
695         SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
696         SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
697
698         /*-------------------------------------------------------
699          *                      (2) ps-poll
700          *--------------------------------------------------------
701          */
702         p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
703         SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
704         SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
705         SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
706
707         SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
708
709         /*--------------------------------------------------------
710          *                      (3) null data
711          *---------------------------------------------------------
712          */
713         nullfunc = &reserved_page_packet[NULL_PG * 128];
714         SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
715         SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
716         SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
717
718         SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
719
720         /*---------------------------------------------------------
721          *                      (4) probe response
722          *----------------------------------------------------------
723          */
724         p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
725         SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
726         SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
727         SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
728
729         SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
730
731         /*---------------------------------------------------------
732          *                      (5) QoS null data
733          *----------------------------------------------------------
734          */
735         qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
736         SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
737         SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
738         SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
739
740         SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOS_NULL_PG);
741
742         /*---------------------------------------------------------
743          *                      (6) BT QoS null data
744          *----------------------------------------------------------
745          */
746         btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
747         SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
748         SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
749         SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
750
751         SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOS_NULL_PG);
752
753         totalpacketlen = TOTAL_RESERVED_PKT_LEN;
754
755         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
756                       "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
757                       &reserved_page_packet[0], totalpacketlen);
758         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
759                       "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
760                       u1rsvdpageloc, 3);
761
762         skb = dev_alloc_skb(totalpacketlen);
763         memcpy((u8 *)skb_put(skb, totalpacketlen),
764                &reserved_page_packet, totalpacketlen);
765
766         b_dlok = true;
767
768         if (b_dlok) {
769                 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD ,
770                          "Set RSVD page location to Fw.\n");
771                 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
772                               "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
773                 rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE,
774                                      sizeof(u1rsvdpageloc), u1rsvdpageloc);
775         } else {
776                 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
777                          "Set RSVD page location to Fw FAIL!!!!!!.\n");
778         }
779 }
780
781 /*Shoud check FW support p2p or not.*/
782 static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
783 {
784         u8 u1_ctwindow_period[1] = {ctwindow};
785
786         rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
787 }
788
789 void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
790 {
791         struct rtl_priv *rtlpriv = rtl_priv(hw);
792         struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
793         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
794         struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
795         struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
796         u8 i;
797         u16 ctwindow;
798         u32 start_time, tsf_low;
799
800         switch (p2p_ps_state) {
801         case P2P_PS_DISABLE:
802                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_DISABLE\n");
803                 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
804                 break;
805         case P2P_PS_ENABLE:
806                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_ENABLE\n");
807                 /* update CTWindow value. */
808                 if (p2pinfo->ctwindow > 0) {
809                         p2p_ps_offload->ctwindow_en = 1;
810                         ctwindow = p2pinfo->ctwindow;
811                         rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow);
812                 }
813                 /* hw only support 2 set of NoA */
814                 for (i = 0 ; i < p2pinfo->noa_num ; i++) {
815                         /* To control the register setting for which NOA*/
816                         rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
817                         if (i == 0)
818                                 p2p_ps_offload->noa0_en = 1;
819                         else
820                                 p2p_ps_offload->noa1_en = 1;
821                         /* config P2P NoA Descriptor Register */
822                         rtl_write_dword(rtlpriv, 0x5E0,
823                                         p2pinfo->noa_duration[i]);
824                         rtl_write_dword(rtlpriv, 0x5E4,
825                                         p2pinfo->noa_interval[i]);
826
827                         /*Get Current TSF value */
828                         tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
829
830                         start_time = p2pinfo->noa_start_time[i];
831                         if (p2pinfo->noa_count_type[i] != 1) {
832                                 while (start_time <= (tsf_low + (50 * 1024))) {
833                                         start_time += p2pinfo->noa_interval[i];
834                                         if (p2pinfo->noa_count_type[i] != 255)
835                                                 p2pinfo->noa_count_type[i]--;
836                                 }
837                         }
838                         rtl_write_dword(rtlpriv, 0x5E8, start_time);
839                         rtl_write_dword(rtlpriv, 0x5EC,
840                                         p2pinfo->noa_count_type[i]);
841                 }
842                 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
843                         /* rst p2p circuit */
844                         rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
845                         p2p_ps_offload->offload_en = 1;
846
847                         if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
848                                 p2p_ps_offload->role = 1;
849                                 p2p_ps_offload->allstasleep = 0;
850                         } else {
851                                 p2p_ps_offload->role = 0;
852                         }
853                         p2p_ps_offload->discovery = 0;
854                 }
855                 break;
856         case P2P_PS_SCAN:
857                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN\n");
858                 p2p_ps_offload->discovery = 1;
859                 break;
860         case P2P_PS_SCAN_DONE:
861                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN_DONE\n");
862                 p2p_ps_offload->discovery = 0;
863                 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
864                 break;
865         default:
866                 break;
867         }
868         rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1,
869                              (u8 *)p2p_ps_offload);
870 }
871
872 static void _rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw,
873                                            u8 *cmd_buf, u8 cmd_len)
874 {
875         u8 rate = cmd_buf[0] & 0x3F;
876         bool collision_state = cmd_buf[3] & BIT(0);
877
878         rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state);
879 }
880
881 void rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
882                                  u8 c2h_cmd_len, u8 *tmp_buf)
883 {
884         struct rtl_priv *rtlpriv = rtl_priv(hw);
885
886         switch (c2h_cmd_id) {
887         case C2H_8192E_DBG:
888                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
889                          "[C2H], C2H_8723BE_DBG!!\n");
890                 break;
891         case C2H_8192E_TXBF:
892                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
893                          "[C2H], C2H_8192E_TXBF!!\n");
894                 break;
895         case C2H_8192E_TX_REPORT:
896                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE ,
897                          "[C2H], C2H_8723BE_TX_REPORT!\n");
898                 rtl_tx_report_handler(hw, tmp_buf, c2h_cmd_len);
899                 break;
900         case C2H_8192E_BT_INFO:
901                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
902                          "[C2H], C2H_8723BE_BT_INFO!!\n");
903                 rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
904                                                               c2h_cmd_len);
905                 break;
906         case C2H_8192E_BT_MP:
907                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
908                          "[C2H], C2H_8723BE_BT_MP!!\n");
909                 break;
910         case C2H_8192E_RA_RPT:
911                 _rtl92ee_c2h_ra_report_handler(hw, tmp_buf, c2h_cmd_len);
912                 break;
913         default:
914                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
915                          "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id);
916                 break;
917         }
918 }
919
920 void rtl92ee_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
921 {
922         struct rtl_priv *rtlpriv = rtl_priv(hw);
923         u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
924         u8 *tmp_buf = NULL;
925
926         c2h_cmd_id = buffer[0];
927         c2h_cmd_seq = buffer[1];
928         c2h_cmd_len = len - 2;
929         tmp_buf = buffer + 2;
930
931         RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
932                  "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
933                  c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
934
935         RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
936                       "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
937
938         switch (c2h_cmd_id) {
939         case C2H_8192E_BT_INFO:
940         case C2H_8192E_BT_MP:
941                 rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
942                 break;
943         default:
944                 rtl92ee_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len,
945                                             tmp_buf);
946                 break;
947         }
948 }