GNU Linux-libre 4.14.290-gnu1
[releases.git] / drivers / net / wireless / realtek / rtlwifi / rtl8723ae / fw.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2009-2012  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 _rtl8723e_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, val_mcutst_1;
40         bool result = false;
41
42         val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
43         val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
44
45         if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
46                 result = true;
47         return result;
48 }
49
50 static void _rtl8723e_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
51                                        u32 cmd_len, u8 *cmdbuffer)
52 {
53         struct rtl_priv *rtlpriv = rtl_priv(hw);
54         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
55         u8 boxnum;
56         u16 box_reg = 0, box_extreg = 0;
57         u8 u1b_tmp;
58         bool isfw_read = false;
59         u8 buf_index = 0;
60         bool bwrite_sucess = false;
61         u8 wait_h2c_limmit = 100;
62         u8 wait_writeh2c_limmit = 100;
63         u8 boxcontent[4], boxextcontent[2];
64         u32 h2c_waitcounter = 0;
65         unsigned long flag;
66         u8 idx;
67
68         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
69
70         while (true) {
71                 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
72                 if (rtlhal->h2c_setinprogress) {
73                         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
74                                  "H2C set in progress! Wait to set..element_id(%d).\n",
75                                  element_id);
76
77                         while (rtlhal->h2c_setinprogress) {
78                                 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
79                                                        flag);
80                                 h2c_waitcounter++;
81                                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
82                                          "Wait 100 us (%d times)...\n",
83                                           h2c_waitcounter);
84                                 udelay(100);
85
86                                 if (h2c_waitcounter > 1000)
87                                         return;
88                                 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
89                                                   flag);
90                         }
91                         spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
92                 } else {
93                         rtlhal->h2c_setinprogress = true;
94                         spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
95                         break;
96                 }
97         }
98
99         while (!bwrite_sucess) {
100                 wait_writeh2c_limmit--;
101                 if (wait_writeh2c_limmit == 0) {
102                         pr_err("Write H2C fail because no trigger for FW INT!\n");
103                         break;
104                 }
105
106                 boxnum = rtlhal->last_hmeboxnum;
107                 switch (boxnum) {
108                 case 0:
109                         box_reg = REG_HMEBOX_0;
110                         box_extreg = REG_HMEBOX_EXT_0;
111                         break;
112                 case 1:
113                         box_reg = REG_HMEBOX_1;
114                         box_extreg = REG_HMEBOX_EXT_1;
115                         break;
116                 case 2:
117                         box_reg = REG_HMEBOX_2;
118                         box_extreg = REG_HMEBOX_EXT_2;
119                         break;
120                 case 3:
121                         box_reg = REG_HMEBOX_3;
122                         box_extreg = REG_HMEBOX_EXT_3;
123                         break;
124                 default:
125                         pr_err("switch case %#x not processed\n",
126                                boxnum);
127                         break;
128                 }
129
130                 isfw_read = _rtl8723e_check_fw_read_last_h2c(hw, boxnum);
131                 while (!isfw_read) {
132
133                         wait_h2c_limmit--;
134                         if (wait_h2c_limmit == 0) {
135                                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
136                                          "Waiting too long for FW read clear HMEBox(%d)!\n",
137                                          boxnum);
138                                 break;
139                         }
140
141                         udelay(10);
142
143                         isfw_read = _rtl8723e_check_fw_read_last_h2c(hw,
144                                                                 boxnum);
145                         u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
146                         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
147                                  "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n",
148                                  boxnum, u1b_tmp);
149                 }
150
151                 if (!isfw_read) {
152                         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
153                                  "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
154                                  boxnum);
155                         break;
156                 }
157
158                 memset(boxcontent, 0, sizeof(boxcontent));
159                 memset(boxextcontent, 0, sizeof(boxextcontent));
160                 boxcontent[0] = element_id;
161                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
162                          "Write element_id box_reg(%4x) = %2x\n",
163                           box_reg, element_id);
164
165                 switch (cmd_len) {
166                 case 1:
167                         boxcontent[0] &= ~(BIT(7));
168                         memcpy((u8 *)(boxcontent) + 1,
169                                cmdbuffer + buf_index, 1);
170
171                         for (idx = 0; idx < 4; idx++) {
172                                 rtl_write_byte(rtlpriv, box_reg + idx,
173                                                boxcontent[idx]);
174                         }
175                         break;
176                 case 2:
177                         boxcontent[0] &= ~(BIT(7));
178                         memcpy((u8 *)(boxcontent) + 1,
179                                cmdbuffer + buf_index, 2);
180
181                         for (idx = 0; idx < 4; idx++) {
182                                 rtl_write_byte(rtlpriv, box_reg + idx,
183                                                boxcontent[idx]);
184                         }
185                         break;
186                 case 3:
187                         boxcontent[0] &= ~(BIT(7));
188                         memcpy((u8 *)(boxcontent) + 1,
189                                cmdbuffer + buf_index, 3);
190
191                         for (idx = 0; idx < 4; idx++) {
192                                 rtl_write_byte(rtlpriv, box_reg + idx,
193                                                boxcontent[idx]);
194                         }
195                         break;
196                 case 4:
197                         boxcontent[0] |= (BIT(7));
198                         memcpy((u8 *)(boxextcontent),
199                                cmdbuffer + buf_index, 2);
200                         memcpy((u8 *)(boxcontent) + 1,
201                                cmdbuffer + buf_index + 2, 2);
202
203                         for (idx = 0; idx < 2; idx++) {
204                                 rtl_write_byte(rtlpriv, box_extreg + idx,
205                                                boxextcontent[idx]);
206                         }
207
208                         for (idx = 0; idx < 4; idx++) {
209                                 rtl_write_byte(rtlpriv, box_reg + idx,
210                                                boxcontent[idx]);
211                         }
212                         break;
213                 case 5:
214                         boxcontent[0] |= (BIT(7));
215                         memcpy((u8 *)(boxextcontent),
216                                cmdbuffer + buf_index, 2);
217                         memcpy((u8 *)(boxcontent) + 1,
218                                cmdbuffer + buf_index + 2, 3);
219
220                         for (idx = 0; idx < 2; idx++) {
221                                 rtl_write_byte(rtlpriv, box_extreg + idx,
222                                                boxextcontent[idx]);
223                         }
224
225                         for (idx = 0; idx < 4; idx++) {
226                                 rtl_write_byte(rtlpriv, box_reg + idx,
227                                                boxcontent[idx]);
228                         }
229                         break;
230                 default:
231                         pr_err("switch case %#x not processed\n",
232                                cmd_len);
233                         break;
234                 }
235
236                 bwrite_sucess = true;
237
238                 rtlhal->last_hmeboxnum = boxnum + 1;
239                 if (rtlhal->last_hmeboxnum == 4)
240                         rtlhal->last_hmeboxnum = 0;
241
242                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
243                          "pHalData->last_hmeboxnum  = %d\n",
244                           rtlhal->last_hmeboxnum);
245         }
246
247         spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
248         rtlhal->h2c_setinprogress = false;
249         spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
250
251         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
252 }
253
254 void rtl8723e_fill_h2c_cmd(struct ieee80211_hw *hw,
255                            u8 element_id, u32 cmd_len, u8 *cmdbuffer)
256 {
257         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
258         u32 tmp_cmdbuf[2];
259
260         if (!rtlhal->fw_ready) {
261                 WARN_ONCE(true,
262                           "rtl8723ae: error H2C cmd because of Fw download fail!!!\n");
263                 return;
264         }
265         memset(tmp_cmdbuf, 0, 8);
266         memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
267         _rtl8723e_fill_h2c_command(hw, element_id, cmd_len,
268                                    (u8 *)&tmp_cmdbuf);
269 }
270
271 void rtl8723e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
272 {
273         struct rtl_priv *rtlpriv = rtl_priv(hw);
274         u8 u1_h2c_set_pwrmode[3] = { 0 };
275         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
276
277         RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
278
279         SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
280         SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
281                 (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1);
282         SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
283                                               ppsc->reg_max_lps_awakeintvl);
284
285         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
286                       "rtl8723e_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
287                       u1_h2c_set_pwrmode, 3);
288         rtl8723e_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
289 }
290
291 #define BEACON_PG               0 /* ->1 */
292 #define PSPOLL_PG               2
293 #define NULL_PG                 3
294 #define PROBERSP_PG             4 /* ->5 */
295
296 #define TOTAL_RESERVED_PKT_LEN  768
297
298 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
299         /* page 0 beacon */
300         0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
301         0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
302         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
303         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
304         0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
305         0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
306         0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
307         0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
308         0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
309         0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
310         0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
311         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
312         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
313         0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
314         0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316
317         /* page 1 beacon */
318         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
322         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
323         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
324         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
325         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
326         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
327         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
328         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
329         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330         0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
331         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332         0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
333         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
334
335         /* page 2  ps-poll */
336         0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
337         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
338         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
340         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
341         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
342         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
343         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
344         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
345         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
346         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
347         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
348         0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
349         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
350         0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
351         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
352
353         /* page 3  null */
354         0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
355         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
356         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
357         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
358         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
360         0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
364         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366         0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
367         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
368         0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
369         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
370
371         /* page 4  probe_resp */
372         0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
373         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
374         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
375         0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
376         0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
377         0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
378         0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
379         0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
380         0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
381         0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
382         0x03, 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         0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
386         0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
387         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
388
389         /* page 5  probe_resp */
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         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
399         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
400         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
401         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
402         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
403         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
404         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
405         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
406 };
407
408 void rtl8723e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
409 {
410         struct rtl_priv *rtlpriv = rtl_priv(hw);
411         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
412         struct sk_buff *skb = NULL;
413         u32 totalpacketlen;
414         bool rtstatus;
415         u8 u1rsvdpageloc[3] = { 0 };
416         bool b_dlok = false;
417         u8 *beacon;
418         u8 *p_pspoll;
419         u8 *nullfunc;
420         u8 *p_probersp;
421
422         /*---------------------------------------------------------
423          *                      (1) beacon
424          *---------------------------------------------------------
425          */
426         beacon = &reserved_page_packet[BEACON_PG * 128];
427         SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
428         SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
429
430         /*-------------------------------------------------------
431          *                      (2) ps-poll
432          *--------------------------------------------------------
433          */
434         p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
435         SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
436         SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
437         SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
438
439         SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
440
441         /*--------------------------------------------------------
442          *                      (3) null data
443          *---------------------------------------------------------
444          */
445         nullfunc = &reserved_page_packet[NULL_PG * 128];
446         SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
447         SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
448         SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
449
450         SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
451
452         /*---------------------------------------------------------
453          *                      (4) probe response
454          *----------------------------------------------------------
455          */
456         p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
457         SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
458         SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
459         SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
460
461         SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
462
463         totalpacketlen = TOTAL_RESERVED_PKT_LEN;
464
465         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
466                       "rtl8723e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
467                       &reserved_page_packet[0], totalpacketlen);
468         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
469                       "rtl8723e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
470                       u1rsvdpageloc, 3);
471
472         skb = dev_alloc_skb(totalpacketlen);
473         if (!skb)
474                 return;
475         skb_put_data(skb, &reserved_page_packet, totalpacketlen);
476
477         rtstatus = rtl_cmd_send_packet(hw, skb);
478
479         if (rtstatus)
480                 b_dlok = true;
481
482         if (b_dlok) {
483                 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
484                          "Set RSVD page location to Fw.\n");
485                 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
486                               "H2C_RSVDPAGE:\n",
487                               u1rsvdpageloc, 3);
488                 rtl8723e_fill_h2c_cmd(hw, H2C_RSVDPAGE,
489                                       sizeof(u1rsvdpageloc), u1rsvdpageloc);
490         } else
491                 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
492                          "Set RSVD page location to Fw FAIL!!!!!!.\n");
493 }
494
495 void rtl8723e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
496 {
497         u8 u1_joinbssrpt_parm[1] = { 0 };
498
499         SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
500
501         rtl8723e_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
502 }
503
504 static void rtl8723e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
505                                             u8 ctwindow)
506 {
507         u8 u1_ctwindow_period[1] = { ctwindow};
508
509         rtl8723e_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
510
511 }
512
513 void rtl8723e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
514 {
515         struct rtl_priv *rtlpriv = rtl_priv(hw);
516         struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
517         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
518         struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
519         struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
520         u8      i;
521         u16     ctwindow;
522         u32     start_time, tsf_low;
523
524         switch (p2p_ps_state) {
525         case P2P_PS_DISABLE:
526                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
527                 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
528                 break;
529         case P2P_PS_ENABLE:
530                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
531                 /* update CTWindow value. */
532                 if (p2pinfo->ctwindow > 0) {
533                         p2p_ps_offload->ctwindow_en = 1;
534                         ctwindow = p2pinfo->ctwindow;
535                         rtl8723e_set_p2p_ctw_period_cmd(hw, ctwindow);
536                 }
537
538                 /* hw only support 2 set of NoA */
539                 for (i = 0 ; i < p2pinfo->noa_num ; i++) {
540                         /* To control the register setting for which NOA*/
541                         rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
542                         if (i == 0)
543                                 p2p_ps_offload->noa0_en = 1;
544                         else
545                                 p2p_ps_offload->noa1_en = 1;
546
547                         /* config P2P NoA Descriptor Register */
548                         rtl_write_dword(rtlpriv, 0x5E0,
549                                         p2pinfo->noa_duration[i]);
550                         rtl_write_dword(rtlpriv, 0x5E4,
551                                         p2pinfo->noa_interval[i]);
552
553                         /*Get Current TSF value */
554                         tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
555
556                         start_time = p2pinfo->noa_start_time[i];
557                         if (p2pinfo->noa_count_type[i] != 1) {
558                                 while (start_time <=
559                                         (tsf_low+(50*1024))) {
560                                         start_time +=
561                                                 p2pinfo->noa_interval[i];
562                                         if (p2pinfo->noa_count_type[i] != 255)
563                                                 p2pinfo->noa_count_type[i]--;
564                                 }
565                         }
566                         rtl_write_dword(rtlpriv, 0x5E8, start_time);
567                         rtl_write_dword(rtlpriv, 0x5EC,
568                                 p2pinfo->noa_count_type[i]);
569
570                 }
571
572                 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
573                         /* rst p2p circuit */
574                         rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
575
576                         p2p_ps_offload->offload_en = 1;
577
578                         if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
579                                 p2p_ps_offload->role = 1;
580                                 p2p_ps_offload->allstasleep = 0;
581                         } else {
582                                 p2p_ps_offload->role = 0;
583                         }
584
585                         p2p_ps_offload->discovery = 0;
586                 }
587                 break;
588         case P2P_PS_SCAN:
589                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
590                 p2p_ps_offload->discovery = 1;
591                 break;
592         case P2P_PS_SCAN_DONE:
593                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
594                 p2p_ps_offload->discovery = 0;
595                 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
596                 break;
597         default:
598                 break;
599         }
600
601         rtl8723e_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload);
602
603 }