GNU Linux-libre 4.14.266-gnu1
[releases.git] / drivers / net / wireless / realtek / rtlwifi / rtl8723be / 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 "reg.h"
31 #include "def.h"
32 #include "fw.h"
33 #include "../rtl8723com/fw_common.h"
34
35 static bool _rtl8723be_check_fw_read_last_h2c(struct ieee80211_hw *hw,
36                                               u8 boxnum)
37 {
38         struct rtl_priv *rtlpriv = rtl_priv(hw);
39         u8 val_hmetfr;
40         bool result = false;
41
42         val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
43         if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
44                 result = true;
45         return result;
46 }
47
48 static void _rtl8723be_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
49                                         u32 cmd_len, u8 *p_cmdbuffer)
50 {
51         struct rtl_priv *rtlpriv = rtl_priv(hw);
52         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
53         u8 boxnum;
54         u16 box_reg = 0, box_extreg = 0;
55         u8 u1b_tmp;
56         bool isfw_read = false;
57         u8 buf_index = 0;
58         bool bwrite_sucess = false;
59         u8 wait_h2c_limmit = 100;
60         u8 wait_writeh2c_limmit = 100;
61         u8 boxcontent[4], boxextcontent[4];
62         u32 h2c_waitcounter = 0;
63         unsigned long flag;
64         u8 idx;
65
66         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
67
68         while (true) {
69                 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
70                 if (rtlhal->h2c_setinprogress) {
71                         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
72                                  "H2C set in progress! Wait to set..element_id(%d).\n",
73                                  element_id);
74
75                         while (rtlhal->h2c_setinprogress) {
76                                 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
77                                                        flag);
78                                 h2c_waitcounter++;
79                                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
80                                          "Wait 100 us (%d times)...\n",
81                                          h2c_waitcounter);
82                                 udelay(100);
83
84                                 if (h2c_waitcounter > 1000)
85                                         return;
86                                 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
87                                                   flag);
88                         }
89                         spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
90                 } else {
91                         rtlhal->h2c_setinprogress = true;
92                         spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
93                         break;
94                 }
95         }
96
97         while (!bwrite_sucess) {
98                 wait_writeh2c_limmit--;
99                 if (wait_writeh2c_limmit == 0) {
100                         pr_err("Write H2C fail because no trigger for FW INT!\n");
101                         break;
102                 }
103
104                 boxnum = rtlhal->last_hmeboxnum;
105                 switch (boxnum) {
106                 case 0:
107                         box_reg = REG_HMEBOX_0;
108                         box_extreg = REG_HMEBOX_EXT_0;
109                         break;
110                 case 1:
111                         box_reg = REG_HMEBOX_1;
112                         box_extreg = REG_HMEBOX_EXT_1;
113                         break;
114                 case 2:
115                         box_reg = REG_HMEBOX_2;
116                         box_extreg = REG_HMEBOX_EXT_2;
117                         break;
118                 case 3:
119                         box_reg = REG_HMEBOX_3;
120                         box_extreg = REG_HMEBOX_EXT_3;
121                         break;
122                 default:
123                         pr_err("switch case %#x not processed\n",
124                                boxnum);
125                         break;
126                 }
127
128                 isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, boxnum);
129                 while (!isfw_read) {
130                         wait_h2c_limmit--;
131                         if (wait_h2c_limmit == 0) {
132                                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
133                                          "Waiting too long for FW read clear HMEBox(%d)!\n",
134                                          boxnum);
135                                 break;
136                         }
137
138                         udelay(10);
139
140                         isfw_read = _rtl8723be_check_fw_read_last_h2c(hw,
141                                                                 boxnum);
142                         u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
143                         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
144                                  "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
145                                  boxnum, u1b_tmp);
146                 }
147
148                 if (!isfw_read) {
149                         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
150                                  "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
151                                  boxnum);
152                         break;
153                 }
154
155                 memset(boxcontent, 0, sizeof(boxcontent));
156                 memset(boxextcontent, 0, sizeof(boxextcontent));
157                 boxcontent[0] = element_id;
158                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
159                          "Write element_id box_reg(%4x) = %2x\n",
160                           box_reg, element_id);
161
162                 switch (cmd_len) {
163                 case 1:
164                 case 2:
165                 case 3:
166                         /*boxcontent[0] &= ~(BIT(7));*/
167                         memcpy((u8 *)(boxcontent) + 1,
168                                p_cmdbuffer + buf_index, cmd_len);
169
170                         for (idx = 0; idx < 4; idx++) {
171                                 rtl_write_byte(rtlpriv, box_reg + idx,
172                                                boxcontent[idx]);
173                         }
174                         break;
175                 case 4:
176                 case 5:
177                 case 6:
178                 case 7:
179                         /*boxcontent[0] |= (BIT(7));*/
180                         memcpy((u8 *)(boxextcontent),
181                                p_cmdbuffer + buf_index+3, cmd_len-3);
182                         memcpy((u8 *)(boxcontent) + 1,
183                                p_cmdbuffer + buf_index, 3);
184
185                         for (idx = 0; idx < 4; idx++) {
186                                 rtl_write_byte(rtlpriv, box_extreg + idx,
187                                                boxextcontent[idx]);
188                         }
189
190                         for (idx = 0; idx < 4; idx++) {
191                                 rtl_write_byte(rtlpriv, box_reg + idx,
192                                                boxcontent[idx]);
193                         }
194                         break;
195                 default:
196                         pr_err("switch case %#x not processed\n",
197                                cmd_len);
198                         break;
199                 }
200
201                 bwrite_sucess = true;
202
203                 rtlhal->last_hmeboxnum = boxnum + 1;
204                 if (rtlhal->last_hmeboxnum == 4)
205                         rtlhal->last_hmeboxnum = 0;
206
207                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
208                          "pHalData->last_hmeboxnum  = %d\n",
209                           rtlhal->last_hmeboxnum);
210         }
211
212         spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
213         rtlhal->h2c_setinprogress = false;
214         spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
215
216         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
217 }
218
219 void rtl8723be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
220                             u32 cmd_len, u8 *p_cmdbuffer)
221 {
222         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
223         u32 tmp_cmdbuf[2];
224
225         if (!rtlhal->fw_ready) {
226                 WARN_ONCE(true,
227                           "rtl8723be: error H2C cmd because of Fw download fail!!!\n");
228                 return;
229         }
230
231         memset(tmp_cmdbuf, 0, 8);
232         memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
233         _rtl8723be_fill_h2c_command(hw, element_id, cmd_len,
234                                     (u8 *)&tmp_cmdbuf);
235         return;
236 }
237
238 void rtl8723be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
239 {
240         struct rtl_priv *rtlpriv = rtl_priv(hw);
241         u8 u1_h2c_set_pwrmode[H2C_PWEMODE_LENGTH] = { 0 };
242         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
243         u8 rlbm, power_state = 0, byte5 = 0;
244         u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
245         struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
246         bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
247                             btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
248         bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ?
249                           btc_ops->btc_is_bt_lps_on(rtlpriv) : false);
250
251         if (bt_ctrl_lps)
252                 mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE);
253
254         RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
255                  mode, bt_ctrl_lps);
256
257         switch (mode) {
258         case FW_PS_MIN_MODE:
259                 rlbm = 0;
260                 awake_intvl = 2;
261                 break;
262         case FW_PS_MAX_MODE:
263                 rlbm = 1;
264                 awake_intvl = 2;
265                 break;
266         case FW_PS_DTIM_MODE:
267                 rlbm = 2;
268                 awake_intvl = ppsc->reg_max_lps_awakeintvl;
269                 /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
270                  * is only used in swlps.
271                  */
272                 break;
273         default:
274                 rlbm = 2;
275                 awake_intvl = 4;
276                 break;
277         }
278
279         if (rtlpriv->mac80211.p2p) {
280                 awake_intvl = 2;
281                 rlbm = 1;
282         }
283
284         if (mode == FW_PS_ACTIVE_MODE) {
285                 byte5 = 0x40;
286                 power_state = FW_PWR_STATE_ACTIVE;
287         } else {
288                 if (bt_ctrl_lps) {
289                         byte5 = btc_ops->btc_get_lps_val(rtlpriv);
290                         power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
291
292                         if ((rlbm == 2) && (byte5 & BIT(4))) {
293                                 /* Keep awake interval to 1 to prevent from
294                                  * decreasing coex performance
295                                  */
296                                 awake_intvl = 2;
297                                 rlbm = 2;
298                         }
299                 } else {
300                         byte5 = 0x40;
301                         power_state = FW_PWR_STATE_RF_OFF;
302                 }
303         }
304
305         SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
306         SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
307         SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
308                                          bt_ctrl_lps ? 0 : ppsc->smart_ps);
309         SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
310                                                awake_intvl);
311         SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
312         SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
313         SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
314
315         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
316                       "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
317                       u1_h2c_set_pwrmode, H2C_PWEMODE_LENGTH);
318         if (rtlpriv->cfg->ops->get_btc_status())
319                 btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
320                                              H2C_PWEMODE_LENGTH);
321         rtl8723be_fill_h2c_cmd(hw, H2C_8723B_SETPWRMODE, H2C_PWEMODE_LENGTH,
322                                u1_h2c_set_pwrmode);
323 }
324
325 void rtl8723be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
326 {
327         u8 parm[3] = { 0, 0, 0 };
328         /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
329          *          bit1=0-->update Media Status to MACID
330          *          bit1=1-->update Media Status from MACID to MACID_End
331          * parm[1]: MACID, if this is INFRA_STA, MacID = 0
332          * parm[2]: MACID_End
333         */
334         SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
335         SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
336
337         rtl8723be_fill_h2c_cmd(hw, H2C_8723B_MSRRPT, 3, parm);
338 }
339
340 #define BEACON_PG               0 /* ->1 */
341 #define PSPOLL_PG               2
342 #define NULL_PG                 3
343 #define PROBERSP_PG             4 /* ->5 */
344 #define QOS_NULL_PG             6
345 #define BT_QOS_NULL_PG  7
346
347 #define TOTAL_RESERVED_PKT_LEN  1024    /* can be up to 1280 (tx_bndy=245) */
348
349 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
350         /* page 0 beacon */
351         0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
352         0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
353         0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
354         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
355         0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
356         0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
357         0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
358         0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
359         0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
360         0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
361         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
362         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
363         0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
364         0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
365         0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
366         0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
367
368         /* page 1 beacon */
369         0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
370         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
372         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
373         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
374         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
375         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
376         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
378         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
380         0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
381         0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
382         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
383         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
384         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385
386         /* page 2  ps-poll */
387         0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
388         0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
389         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
390         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
391         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
392         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
393         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
394         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
395         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
396         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
397         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
398         0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
399         0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
400         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
401         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
402         0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
403
404         /* page 3  null */
405         0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
406         0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
407         0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
408         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
409         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
410         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
412         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
413         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
416         0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
417         0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
418         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
419         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420         0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
421
422         /* page 4  probe_resp */
423         0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
424         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
425         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
426         0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
427         0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
428         0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
429         0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
430         0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
431         0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
432         0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
433         0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
434         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
435         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
436         0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
437         0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
438         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
439
440         /* page 5  probe_resp */
441         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
442         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
443         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
444         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
445         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
446         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
448         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
451         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
452         0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
453         0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
454         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
455         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
456         0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
457
458         /* page 6 qos null data */
459         0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
460         0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
461         0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
462         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
463         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
464         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
465         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
467         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
468         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
469         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
470         0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
471         0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
472         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474         0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
475
476         /* page 7 BT-qos null data */
477         0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
478         0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
479         0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
480         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
481         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
483         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
484         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
485         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
486         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
487         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
488         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
489         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
492         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
493
494 };
495
496 void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
497                                   bool b_dl_finished)
498 {
499         struct rtl_priv *rtlpriv = rtl_priv(hw);
500         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
501         struct sk_buff *skb = NULL;
502
503         u32 totalpacketlen;
504         bool rtstatus;
505         u8 u1rsvdpageloc[5] = { 0 };
506         bool b_dlok = false;
507
508         u8 *beacon;
509         u8 *p_pspoll;
510         u8 *nullfunc;
511         u8 *p_probersp;
512         u8 *qosnull;
513         u8 *btqosnull;
514         /*---------------------------------------------------------
515          *                      (1) beacon
516          *---------------------------------------------------------
517          */
518         beacon = &reserved_page_packet[BEACON_PG * 128];
519         SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
520         SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
521
522         /*-------------------------------------------------------
523          *                      (2) ps-poll
524          *-------------------------------------------------------
525          */
526         p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
527         SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
528         SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
529         SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
530
531         SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
532
533         /*--------------------------------------------------------
534          *                      (3) null data
535          *--------------------------------------------------------
536          */
537         nullfunc = &reserved_page_packet[NULL_PG * 128];
538         SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
539         SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
540         SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
541
542         SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
543
544         /*---------------------------------------------------------
545          *                      (4) probe response
546          *---------------------------------------------------------
547          */
548         p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
549         SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
550         SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
551         SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
552
553         SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
554
555         /*---------------------------------------------------------
556          *                      (5) QoS Null
557          *---------------------------------------------------------
558          */
559         qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
560         SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
561         SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
562         SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
563
564         SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOS_NULL_PG);
565
566         /*---------------------------------------------------------
567          *                      (5) QoS Null
568          *---------------------------------------------------------
569          */
570         btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
571         SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
572         SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
573         SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
574
575         SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOS_NULL_PG);
576
577         totalpacketlen = TOTAL_RESERVED_PKT_LEN;
578
579         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
580                       "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
581                       &reserved_page_packet[0], totalpacketlen);
582         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
583                       "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
584                       u1rsvdpageloc, sizeof(u1rsvdpageloc));
585
586         skb = dev_alloc_skb(totalpacketlen);
587         if (!skb)
588                 return;
589         skb_put_data(skb, &reserved_page_packet, totalpacketlen);
590
591         rtstatus = rtl_cmd_send_packet(hw, skb);
592
593         if (rtstatus)
594                 b_dlok = true;
595
596         if (b_dlok) {
597                 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
598                          "Set RSVD page location to Fw.\n");
599                 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, "H2C_RSVDPAGE:\n",
600                               u1rsvdpageloc, sizeof(u1rsvdpageloc));
601                 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_RSVDPAGE,
602                                        sizeof(u1rsvdpageloc), u1rsvdpageloc);
603         } else
604                 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
605                          "Set RSVD page location to Fw FAIL!!!!!!.\n");
606 }
607
608 /*Should check FW support p2p or not.*/
609 static void rtl8723be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
610                                              u8 ctwindow)
611 {
612         u8 u1_ctwindow_period[1] = { ctwindow};
613
614         rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_CTW_CMD, 1,
615                                u1_ctwindow_period);
616 }
617
618 void rtl8723be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw,
619                                       u8 p2p_ps_state)
620 {
621         struct rtl_priv *rtlpriv = rtl_priv(hw);
622         struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
623         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
624         struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
625         struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
626         u8 i;
627         u16 ctwindow;
628         u32 start_time, tsf_low;
629
630         switch (p2p_ps_state) {
631         case P2P_PS_DISABLE:
632                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
633                 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
634                 break;
635         case P2P_PS_ENABLE:
636                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
637                 /* update CTWindow value. */
638                 if (p2pinfo->ctwindow > 0) {
639                         p2p_ps_offload->ctwindow_en = 1;
640                         ctwindow = p2pinfo->ctwindow;
641                         rtl8723be_set_p2p_ctw_period_cmd(hw, ctwindow);
642                 }
643                 /* hw only support 2 set of NoA */
644                 for (i = 0 ; i < p2pinfo->noa_num ; i++) {
645                         /* To control the register setting
646                          * for which NOA
647                          */
648                         rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
649                         if (i == 0)
650                                 p2p_ps_offload->noa0_en = 1;
651                         else
652                                 p2p_ps_offload->noa1_en = 1;
653
654                         /* config P2P NoA Descriptor Register */
655                         rtl_write_dword(rtlpriv, 0x5E0,
656                                         p2pinfo->noa_duration[i]);
657                         rtl_write_dword(rtlpriv, 0x5E4,
658                                         p2pinfo->noa_interval[i]);
659
660                         /*Get Current TSF value */
661                         tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
662
663                         start_time = p2pinfo->noa_start_time[i];
664                         if (p2pinfo->noa_count_type[i] != 1) {
665                                 while (start_time <= (tsf_low + (50 * 1024))) {
666                                         start_time += p2pinfo->noa_interval[i];
667                                         if (p2pinfo->noa_count_type[i] != 255)
668                                                 p2pinfo->noa_count_type[i]--;
669                                 }
670                         }
671                         rtl_write_dword(rtlpriv, 0x5E8, start_time);
672                         rtl_write_dword(rtlpriv, 0x5EC,
673                                         p2pinfo->noa_count_type[i]);
674                 }
675
676                 if ((p2pinfo->opp_ps == 1) ||
677                     (p2pinfo->noa_num > 0)) {
678                         /* rst p2p circuit */
679                         rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
680
681                         p2p_ps_offload->offload_en = 1;
682
683                         if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
684                                 p2p_ps_offload->role = 1;
685                                 p2p_ps_offload->allstasleep = 0;
686                         } else {
687                                 p2p_ps_offload->role = 0;
688                         }
689                         p2p_ps_offload->discovery = 0;
690                 }
691                 break;
692         case P2P_PS_SCAN:
693                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
694                 p2p_ps_offload->discovery = 1;
695                 break;
696         case P2P_PS_SCAN_DONE:
697                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
698                 p2p_ps_offload->discovery = 0;
699                 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
700                 break;
701         default:
702                 break;
703         }
704
705         rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_OFFLOAD, 1,
706                                (u8 *)p2p_ps_offload);
707 }
708
709 void rtl8723be_c2h_content_parsing(struct ieee80211_hw *hw,
710                                    u8 c2h_cmd_id,
711                                    u8 c2h_cmd_len, u8 *tmp_buf)
712 {
713         struct rtl_priv *rtlpriv = rtl_priv(hw);
714         struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
715
716         switch (c2h_cmd_id) {
717         case C2H_8723B_DBG:
718                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
719                          "[C2H], C2H_8723BE_DBG!!\n");
720                 break;
721         case C2H_8723B_TX_REPORT:
722                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
723                          "[C2H], C2H_8723BE_TX_REPORT!\n");
724                 rtl_tx_report_handler(hw, tmp_buf, c2h_cmd_len);
725                 break;
726         case C2H_8723B_BT_INFO:
727                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
728                          "[C2H], C2H_8723BE_BT_INFO!!\n");
729                 if (rtlpriv->cfg->ops->get_btc_status())
730                         btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
731                                                    c2h_cmd_len);
732                 break;
733         case C2H_8723B_BT_MP:
734                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
735                          "[C2H], C2H_8723BE_BT_MP!!\n");
736                 if (rtlpriv->cfg->ops->get_btc_status())
737                         btc_ops->btc_btmpinfo_notify(rtlpriv, tmp_buf,
738                                                      c2h_cmd_len);
739                 break;
740         default:
741                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
742                          "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id);
743                 break;
744         }
745 }
746
747 void rtl8723be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
748 {
749         struct rtl_priv *rtlpriv = rtl_priv(hw);
750         u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
751         u8 *tmp_buf = NULL;
752
753         c2h_cmd_id = buffer[0];
754         c2h_cmd_seq = buffer[1];
755         c2h_cmd_len = len - 2;
756         tmp_buf = buffer + 2;
757
758         RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
759                  "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
760                  c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
761
762         RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
763                       "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
764
765         switch (c2h_cmd_id) {
766         case C2H_8723B_BT_INFO:
767         case C2H_8723B_BT_MP:
768                 rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
769                 break;
770
771         default:
772                 rtl8723be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len,
773                                               tmp_buf);
774                 break;
775         }
776 }