]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c
a954a87b0ed9bf9f14f937a6e4b8d98e3836306b
[mirror_ubuntu-artful-kernel.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 memcpy((u8 *)skb_put(skb, totalpacketlen),
474 &reserved_page_packet, totalpacketlen);
475
476 rtstatus = rtl_cmd_send_packet(hw, skb);
477
478 if (rtstatus)
479 b_dlok = true;
480
481 if (b_dlok) {
482 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
483 "Set RSVD page location to Fw.\n");
484 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
485 "H2C_RSVDPAGE:\n",
486 u1rsvdpageloc, 3);
487 rtl8723e_fill_h2c_cmd(hw, H2C_RSVDPAGE,
488 sizeof(u1rsvdpageloc), u1rsvdpageloc);
489 } else
490 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
491 "Set RSVD page location to Fw FAIL!!!!!!.\n");
492 }
493
494 void rtl8723e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
495 {
496 u8 u1_joinbssrpt_parm[1] = { 0 };
497
498 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
499
500 rtl8723e_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
501 }
502
503 static void rtl8723e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
504 u8 ctwindow)
505 {
506 u8 u1_ctwindow_period[1] = { ctwindow};
507
508 rtl8723e_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
509
510 }
511
512 void rtl8723e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
513 {
514 struct rtl_priv *rtlpriv = rtl_priv(hw);
515 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
516 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
517 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
518 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
519 u8 i;
520 u16 ctwindow;
521 u32 start_time, tsf_low;
522
523 switch (p2p_ps_state) {
524 case P2P_PS_DISABLE:
525 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
526 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
527 break;
528 case P2P_PS_ENABLE:
529 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
530 /* update CTWindow value. */
531 if (p2pinfo->ctwindow > 0) {
532 p2p_ps_offload->ctwindow_en = 1;
533 ctwindow = p2pinfo->ctwindow;
534 rtl8723e_set_p2p_ctw_period_cmd(hw, ctwindow);
535 }
536
537 /* hw only support 2 set of NoA */
538 for (i = 0 ; i < p2pinfo->noa_num ; i++) {
539 /* To control the register setting for which NOA*/
540 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
541 if (i == 0)
542 p2p_ps_offload->noa0_en = 1;
543 else
544 p2p_ps_offload->noa1_en = 1;
545
546 /* config P2P NoA Descriptor Register */
547 rtl_write_dword(rtlpriv, 0x5E0,
548 p2pinfo->noa_duration[i]);
549 rtl_write_dword(rtlpriv, 0x5E4,
550 p2pinfo->noa_interval[i]);
551
552 /*Get Current TSF value */
553 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
554
555 start_time = p2pinfo->noa_start_time[i];
556 if (p2pinfo->noa_count_type[i] != 1) {
557 while (start_time <=
558 (tsf_low+(50*1024))) {
559 start_time +=
560 p2pinfo->noa_interval[i];
561 if (p2pinfo->noa_count_type[i] != 255)
562 p2pinfo->noa_count_type[i]--;
563 }
564 }
565 rtl_write_dword(rtlpriv, 0x5E8, start_time);
566 rtl_write_dword(rtlpriv, 0x5EC,
567 p2pinfo->noa_count_type[i]);
568
569 }
570
571 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
572 /* rst p2p circuit */
573 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
574
575 p2p_ps_offload->offload_en = 1;
576
577 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
578 p2p_ps_offload->role = 1;
579 p2p_ps_offload->allstasleep = 0;
580 } else {
581 p2p_ps_offload->role = 0;
582 }
583
584 p2p_ps_offload->discovery = 0;
585 }
586 break;
587 case P2P_PS_SCAN:
588 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
589 p2p_ps_offload->discovery = 1;
590 break;
591 case P2P_PS_SCAN_DONE:
592 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
593 p2p_ps_offload->discovery = 0;
594 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
595 break;
596 default:
597 break;
598 }
599
600 rtl8723e_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload);
601
602 }