]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/net/wireless/rtlwifi/rtl8723ae/fw.c
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[karo-tx-linux.git] / drivers / net / wireless / 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                         RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
103                                  "Write H2C fail because no trigger for FW INT!\n");
104                         break;
105                 }
106
107                 boxnum = rtlhal->last_hmeboxnum;
108                 switch (boxnum) {
109                 case 0:
110                         box_reg = REG_HMEBOX_0;
111                         box_extreg = REG_HMEBOX_EXT_0;
112                         break;
113                 case 1:
114                         box_reg = REG_HMEBOX_1;
115                         box_extreg = REG_HMEBOX_EXT_1;
116                         break;
117                 case 2:
118                         box_reg = REG_HMEBOX_2;
119                         box_extreg = REG_HMEBOX_EXT_2;
120                         break;
121                 case 3:
122                         box_reg = REG_HMEBOX_3;
123                         box_extreg = REG_HMEBOX_EXT_3;
124                         break;
125                 default:
126                         RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
127                                  "switch case not process\n");
128                         break;
129                 }
130
131                 isfw_read = _rtl8723e_check_fw_read_last_h2c(hw, boxnum);
132                 while (!isfw_read) {
133
134                         wait_h2c_limmit--;
135                         if (wait_h2c_limmit == 0) {
136                                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
137                                          "Wating too long for FW read clear HMEBox(%d)!\n",
138                                          boxnum);
139                                 break;
140                         }
141
142                         udelay(10);
143
144                         isfw_read = _rtl8723e_check_fw_read_last_h2c(hw,
145                                                                 boxnum);
146                         u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
147                         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
148                                  "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n",
149                                  boxnum, u1b_tmp);
150                 }
151
152                 if (!isfw_read) {
153                         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
154                                  "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
155                                  boxnum);
156                         break;
157                 }
158
159                 memset(boxcontent, 0, sizeof(boxcontent));
160                 memset(boxextcontent, 0, sizeof(boxextcontent));
161                 boxcontent[0] = element_id;
162                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
163                          "Write element_id box_reg(%4x) = %2x\n",
164                           box_reg, element_id);
165
166                 switch (cmd_len) {
167                 case 1:
168                         boxcontent[0] &= ~(BIT(7));
169                         memcpy((u8 *)(boxcontent) + 1,
170                                cmdbuffer + buf_index, 1);
171
172                         for (idx = 0; idx < 4; idx++) {
173                                 rtl_write_byte(rtlpriv, box_reg + idx,
174                                                boxcontent[idx]);
175                         }
176                         break;
177                 case 2:
178                         boxcontent[0] &= ~(BIT(7));
179                         memcpy((u8 *)(boxcontent) + 1,
180                                cmdbuffer + buf_index, 2);
181
182                         for (idx = 0; idx < 4; idx++) {
183                                 rtl_write_byte(rtlpriv, box_reg + idx,
184                                                boxcontent[idx]);
185                         }
186                         break;
187                 case 3:
188                         boxcontent[0] &= ~(BIT(7));
189                         memcpy((u8 *)(boxcontent) + 1,
190                                cmdbuffer + buf_index, 3);
191
192                         for (idx = 0; idx < 4; idx++) {
193                                 rtl_write_byte(rtlpriv, box_reg + idx,
194                                                boxcontent[idx]);
195                         }
196                         break;
197                 case 4:
198                         boxcontent[0] |= (BIT(7));
199                         memcpy((u8 *)(boxextcontent),
200                                cmdbuffer + buf_index, 2);
201                         memcpy((u8 *)(boxcontent) + 1,
202                                cmdbuffer + buf_index + 2, 2);
203
204                         for (idx = 0; idx < 2; idx++) {
205                                 rtl_write_byte(rtlpriv, box_extreg + idx,
206                                                boxextcontent[idx]);
207                         }
208
209                         for (idx = 0; idx < 4; idx++) {
210                                 rtl_write_byte(rtlpriv, box_reg + idx,
211                                                boxcontent[idx]);
212                         }
213                         break;
214                 case 5:
215                         boxcontent[0] |= (BIT(7));
216                         memcpy((u8 *)(boxextcontent),
217                                cmdbuffer + buf_index, 2);
218                         memcpy((u8 *)(boxcontent) + 1,
219                                cmdbuffer + buf_index + 2, 3);
220
221                         for (idx = 0; idx < 2; idx++) {
222                                 rtl_write_byte(rtlpriv, box_extreg + idx,
223                                                boxextcontent[idx]);
224                         }
225
226                         for (idx = 0; idx < 4; idx++) {
227                                 rtl_write_byte(rtlpriv, box_reg + idx,
228                                                boxcontent[idx]);
229                         }
230                         break;
231                 default:
232                         RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
233                                  "switch case not process\n");
234                         break;
235                 }
236
237                 bwrite_sucess = true;
238
239                 rtlhal->last_hmeboxnum = boxnum + 1;
240                 if (rtlhal->last_hmeboxnum == 4)
241                         rtlhal->last_hmeboxnum = 0;
242
243                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
244                          "pHalData->last_hmeboxnum  = %d\n",
245                           rtlhal->last_hmeboxnum);
246         }
247
248         spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
249         rtlhal->h2c_setinprogress = false;
250         spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
251
252         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
253 }
254
255 void rtl8723e_fill_h2c_cmd(struct ieee80211_hw *hw,
256                            u8 element_id, u32 cmd_len, u8 *cmdbuffer)
257 {
258         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
259         u32 tmp_cmdbuf[2];
260
261         if (!rtlhal->fw_ready) {
262                 RT_ASSERT(false,
263                           "return H2C cmd because of Fw download fail!!!\n");
264                 return;
265         }
266         memset(tmp_cmdbuf, 0, 8);
267         memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
268         _rtl8723e_fill_h2c_command(hw, element_id, cmd_len,
269                                    (u8 *)&tmp_cmdbuf);
270 }
271
272 void rtl8723e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
273 {
274         struct rtl_priv *rtlpriv = rtl_priv(hw);
275         u8 u1_h2c_set_pwrmode[3] = { 0 };
276         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
277
278         RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
279
280         SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
281         SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
282                 (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1);
283         SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
284                                               ppsc->reg_max_lps_awakeintvl);
285
286         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
287                       "rtl8723e_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
288                       u1_h2c_set_pwrmode, 3);
289         rtl8723e_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
290 }
291
292 #define BEACON_PG               0 /* ->1 */
293 #define PSPOLL_PG               2
294 #define NULL_PG                 3
295 #define PROBERSP_PG             4 /* ->5 */
296
297 #define TOTAL_RESERVED_PKT_LEN  768
298
299 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
300         /* page 0 beacon */
301         0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
302         0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
303         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
304         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
305         0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
306         0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
307         0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
308         0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
309         0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
310         0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
311         0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
312         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
313         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
314         0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
315         0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
317
318         /* page 1 beacon */
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         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
331         0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
332         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
333         0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
334         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335
336         /* page 2  ps-poll */
337         0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
338         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
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         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
349         0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
350         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
351         0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
352         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
353
354         /* page 3  null */
355         0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
356         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
357         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 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         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367         0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
368         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
369         0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
370         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371
372         /* page 4  probe_resp */
373         0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
374         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
375         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
376         0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
377         0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
378         0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
379         0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
380         0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
381         0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
382         0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
383         0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
384         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
386         0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
387         0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
388         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
389
390         /* page 5  probe_resp */
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         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
407 };
408
409 void rtl8723e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
410 {
411         struct rtl_priv *rtlpriv = rtl_priv(hw);
412         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
413         struct sk_buff *skb = NULL;
414         u32 totalpacketlen;
415         bool rtstatus;
416         u8 u1rsvdpageloc[3] = { 0 };
417         bool b_dlok = false;
418         u8 *beacon;
419         u8 *p_pspoll;
420         u8 *nullfunc;
421         u8 *p_probersp;
422
423         /*---------------------------------------------------------
424          *                      (1) beacon
425          *---------------------------------------------------------
426          */
427         beacon = &reserved_page_packet[BEACON_PG * 128];
428         SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
429         SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
430
431         /*-------------------------------------------------------
432          *                      (2) ps-poll
433          *--------------------------------------------------------
434          */
435         p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
436         SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
437         SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
438         SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
439
440         SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
441
442         /*--------------------------------------------------------
443          *                      (3) null data
444          *---------------------------------------------------------
445          */
446         nullfunc = &reserved_page_packet[NULL_PG * 128];
447         SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
448         SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
449         SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
450
451         SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
452
453         /*---------------------------------------------------------
454          *                      (4) probe response
455          *----------------------------------------------------------
456          */
457         p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
458         SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
459         SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
460         SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
461
462         SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
463
464         totalpacketlen = TOTAL_RESERVED_PKT_LEN;
465
466         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
467                       "rtl8723e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
468                       &reserved_page_packet[0], totalpacketlen);
469         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
470                       "rtl8723e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
471                       u1rsvdpageloc, 3);
472
473         skb = dev_alloc_skb(totalpacketlen);
474         memcpy((u8 *)skb_put(skb, totalpacketlen),
475                &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 }