Merge branch 'hash' of git://ftp.sciencehorizons.net/linux
[deliverable/linux.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 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
101 "Write H2C fail because no trigger for FW INT!\n");
102 break;
103 }
104
105 boxnum = rtlhal->last_hmeboxnum;
106 switch (boxnum) {
107 case 0:
108 box_reg = REG_HMEBOX_0;
109 box_extreg = REG_HMEBOX_EXT_0;
110 break;
111 case 1:
112 box_reg = REG_HMEBOX_1;
113 box_extreg = REG_HMEBOX_EXT_1;
114 break;
115 case 2:
116 box_reg = REG_HMEBOX_2;
117 box_extreg = REG_HMEBOX_EXT_2;
118 break;
119 case 3:
120 box_reg = REG_HMEBOX_3;
121 box_extreg = REG_HMEBOX_EXT_3;
122 break;
123 default:
124 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
125 "switch case not process\n");
126 break;
127 }
128
129 isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, boxnum);
130 while (!isfw_read) {
131 wait_h2c_limmit--;
132 if (wait_h2c_limmit == 0) {
133 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
134 "Waiting too long for FW read clear HMEBox(%d)!\n",
135 boxnum);
136 break;
137 }
138
139 udelay(10);
140
141 isfw_read = _rtl8723be_check_fw_read_last_h2c(hw,
142 boxnum);
143 u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
144 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
145 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
146 boxnum, u1b_tmp);
147 }
148
149 if (!isfw_read) {
150 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
151 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
152 boxnum);
153 break;
154 }
155
156 memset(boxcontent, 0, sizeof(boxcontent));
157 memset(boxextcontent, 0, sizeof(boxextcontent));
158 boxcontent[0] = element_id;
159 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
160 "Write element_id box_reg(%4x) = %2x\n",
161 box_reg, element_id);
162
163 switch (cmd_len) {
164 case 1:
165 case 2:
166 case 3:
167 /*boxcontent[0] &= ~(BIT(7));*/
168 memcpy((u8 *)(boxcontent) + 1,
169 p_cmdbuffer + buf_index, cmd_len);
170
171 for (idx = 0; idx < 4; idx++) {
172 rtl_write_byte(rtlpriv, box_reg + idx,
173 boxcontent[idx]);
174 }
175 break;
176 case 4:
177 case 5:
178 case 6:
179 case 7:
180 /*boxcontent[0] |= (BIT(7));*/
181 memcpy((u8 *)(boxextcontent),
182 p_cmdbuffer + buf_index+3, cmd_len-3);
183 memcpy((u8 *)(boxcontent) + 1,
184 p_cmdbuffer + buf_index, 3);
185
186 for (idx = 0; idx < 4; idx++) {
187 rtl_write_byte(rtlpriv, box_extreg + idx,
188 boxextcontent[idx]);
189 }
190
191 for (idx = 0; idx < 4; idx++) {
192 rtl_write_byte(rtlpriv, box_reg + idx,
193 boxcontent[idx]);
194 }
195 break;
196 default:
197 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
198 "switch case not process\n");
199 break;
200 }
201
202 bwrite_sucess = true;
203
204 rtlhal->last_hmeboxnum = boxnum + 1;
205 if (rtlhal->last_hmeboxnum == 4)
206 rtlhal->last_hmeboxnum = 0;
207
208 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
209 "pHalData->last_hmeboxnum = %d\n",
210 rtlhal->last_hmeboxnum);
211 }
212
213 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
214 rtlhal->h2c_setinprogress = false;
215 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
216
217 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
218 }
219
220 void rtl8723be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
221 u32 cmd_len, u8 *p_cmdbuffer)
222 {
223 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
224 u32 tmp_cmdbuf[2];
225
226 if (!rtlhal->fw_ready) {
227 RT_ASSERT(false,
228 "return H2C cmd because of Fw download fail!!!\n");
229 return;
230 }
231
232 memset(tmp_cmdbuf, 0, 8);
233 memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
234 _rtl8723be_fill_h2c_command(hw, element_id, cmd_len,
235 (u8 *)&tmp_cmdbuf);
236 return;
237 }
238
239 void rtl8723be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
240 {
241 struct rtl_priv *rtlpriv = rtl_priv(hw);
242 u8 u1_h2c_set_pwrmode[H2C_PWEMODE_LENGTH] = { 0 };
243 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
244 u8 rlbm, power_state = 0;
245 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
246
247 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
248 rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/
249 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
250 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
251 (rtlpriv->mac80211.p2p) ?
252 ppsc->smart_ps : 1);
253 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
254 ppsc->reg_max_lps_awakeintvl);
255 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
256 if (mode == FW_PS_ACTIVE_MODE)
257 power_state |= FW_PWR_STATE_ACTIVE;
258 else
259 power_state |= FW_PWR_STATE_RF_OFF;
260 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
261
262 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
263 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
264 u1_h2c_set_pwrmode, H2C_PWEMODE_LENGTH);
265 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_SETPWRMODE, H2C_PWEMODE_LENGTH,
266 u1_h2c_set_pwrmode);
267 }
268
269 void rtl8723be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
270 {
271 u8 parm[3] = { 0, 0, 0 };
272 /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
273 * bit1=0-->update Media Status to MACID
274 * bit1=1-->update Media Status from MACID to MACID_End
275 * parm[1]: MACID, if this is INFRA_STA, MacID = 0
276 * parm[2]: MACID_End
277 */
278 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
279 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
280
281 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_MSRRPT, 3, parm);
282 }
283
284 #define BEACON_PG 0 /* ->1 */
285 #define PSPOLL_PG 2
286 #define NULL_PG 3
287 #define PROBERSP_PG 4 /* ->5 */
288
289 #define TOTAL_RESERVED_PKT_LEN 768
290
291 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
292 /* page 0 beacon */
293 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
294 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
295 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
297 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
298 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
299 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
300 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
301 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
302 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
304 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
305 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
306 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
307 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
308 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
309
310 /* page 1 beacon */
311 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
313 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
323 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 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
328 /* page 2 ps-poll */
329 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
330 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
336 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
337 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
340 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
341 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
342 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
344 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
345
346 /* page 3 null */
347 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
348 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
349 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
351 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
352 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
358 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
359 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
362 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
363
364 /* page 4 probe_resp */
365 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
366 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
367 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
368 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
369 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
370 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
371 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
372 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
373 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
374 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
375 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
379 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
381
382 /* page 5 probe_resp */
383 0x00, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
387 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
399 };
400
401 void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
402 bool b_dl_finished)
403 {
404 struct rtl_priv *rtlpriv = rtl_priv(hw);
405 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
406 struct sk_buff *skb = NULL;
407
408 u32 totalpacketlen;
409 bool rtstatus;
410 u8 u1rsvdpageloc[5] = { 0 };
411 bool b_dlok = false;
412
413 u8 *beacon;
414 u8 *p_pspoll;
415 u8 *nullfunc;
416 u8 *p_probersp;
417 /*---------------------------------------------------------
418 * (1) beacon
419 *---------------------------------------------------------
420 */
421 beacon = &reserved_page_packet[BEACON_PG * 128];
422 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
423 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
424
425 /*-------------------------------------------------------
426 * (2) ps-poll
427 *-------------------------------------------------------
428 */
429 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
430 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
431 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
432 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
433
434 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
435
436 /*--------------------------------------------------------
437 * (3) null data
438 *--------------------------------------------------------
439 */
440 nullfunc = &reserved_page_packet[NULL_PG * 128];
441 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
442 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
443 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
444
445 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
446
447 /*---------------------------------------------------------
448 * (4) probe response
449 *---------------------------------------------------------
450 */
451 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
452 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
453 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
454 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
455
456 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
457
458 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
459
460 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
461 "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
462 &reserved_page_packet[0], totalpacketlen);
463 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
464 "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
465 u1rsvdpageloc, 3);
466
467 skb = dev_alloc_skb(totalpacketlen);
468 memcpy((u8 *)skb_put(skb, totalpacketlen),
469 &reserved_page_packet, totalpacketlen);
470
471 rtstatus = rtl_cmd_send_packet(hw, skb);
472
473 if (rtstatus)
474 b_dlok = true;
475
476 if (b_dlok) {
477 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
478 "Set RSVD page location to Fw.\n");
479 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, "H2C_RSVDPAGE:\n",
480 u1rsvdpageloc, 3);
481 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_RSVDPAGE,
482 sizeof(u1rsvdpageloc), u1rsvdpageloc);
483 } else
484 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
485 "Set RSVD page location to Fw FAIL!!!!!!.\n");
486 }
487
488 /*Should check FW support p2p or not.*/
489 static void rtl8723be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
490 u8 ctwindow)
491 {
492 u8 u1_ctwindow_period[1] = { ctwindow};
493
494 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_CTW_CMD, 1,
495 u1_ctwindow_period);
496 }
497
498 void rtl8723be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw,
499 u8 p2p_ps_state)
500 {
501 struct rtl_priv *rtlpriv = rtl_priv(hw);
502 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
503 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
504 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
505 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
506 u8 i;
507 u16 ctwindow;
508 u32 start_time, tsf_low;
509
510 switch (p2p_ps_state) {
511 case P2P_PS_DISABLE:
512 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
513 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
514 break;
515 case P2P_PS_ENABLE:
516 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
517 /* update CTWindow value. */
518 if (p2pinfo->ctwindow > 0) {
519 p2p_ps_offload->ctwindow_en = 1;
520 ctwindow = p2pinfo->ctwindow;
521 rtl8723be_set_p2p_ctw_period_cmd(hw, ctwindow);
522 }
523 /* hw only support 2 set of NoA */
524 for (i = 0 ; i < p2pinfo->noa_num ; i++) {
525 /* To control the register setting
526 * for which NOA
527 */
528 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
529 if (i == 0)
530 p2p_ps_offload->noa0_en = 1;
531 else
532 p2p_ps_offload->noa1_en = 1;
533
534 /* config P2P NoA Descriptor Register */
535 rtl_write_dword(rtlpriv, 0x5E0,
536 p2pinfo->noa_duration[i]);
537 rtl_write_dword(rtlpriv, 0x5E4,
538 p2pinfo->noa_interval[i]);
539
540 /*Get Current TSF value */
541 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
542
543 start_time = p2pinfo->noa_start_time[i];
544 if (p2pinfo->noa_count_type[i] != 1) {
545 while (start_time <= (tsf_low + (50 * 1024))) {
546 start_time += p2pinfo->noa_interval[i];
547 if (p2pinfo->noa_count_type[i] != 255)
548 p2pinfo->noa_count_type[i]--;
549 }
550 }
551 rtl_write_dword(rtlpriv, 0x5E8, start_time);
552 rtl_write_dword(rtlpriv, 0x5EC,
553 p2pinfo->noa_count_type[i]);
554 }
555
556 if ((p2pinfo->opp_ps == 1) ||
557 (p2pinfo->noa_num > 0)) {
558 /* rst p2p circuit */
559 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
560
561 p2p_ps_offload->offload_en = 1;
562
563 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
564 p2p_ps_offload->role = 1;
565 p2p_ps_offload->allstasleep = 0;
566 } else {
567 p2p_ps_offload->role = 0;
568 }
569 p2p_ps_offload->discovery = 0;
570 }
571 break;
572 case P2P_PS_SCAN:
573 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
574 p2p_ps_offload->discovery = 1;
575 break;
576 case P2P_PS_SCAN_DONE:
577 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
578 p2p_ps_offload->discovery = 0;
579 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
580 break;
581 default:
582 break;
583 }
584
585 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_OFFLOAD, 1,
586 (u8 *)p2p_ps_offload);
587 }
588
589 static void _rtl8723be_c2h_content_parsing(struct ieee80211_hw *hw,
590 u8 c2h_cmd_id,
591 u8 c2h_cmd_len, u8 *tmp_buf)
592 {
593 struct rtl_priv *rtlpriv = rtl_priv(hw);
594
595 switch (c2h_cmd_id) {
596 case C2H_8723B_DBG:
597 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
598 "[C2H], C2H_8723BE_DBG!!\n");
599 break;
600 case C2H_8723B_TX_REPORT:
601 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
602 "[C2H], C2H_8723BE_TX_REPORT!\n");
603 break;
604 case C2H_8723B_BT_INFO:
605 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
606 "[C2H], C2H_8723BE_BT_INFO!!\n");
607 rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
608 c2h_cmd_len);
609 break;
610 case C2H_8723B_BT_MP:
611 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
612 "[C2H], C2H_8723BE_BT_MP!!\n");
613 break;
614 default:
615 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
616 "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id);
617 break;
618 }
619 }
620
621 void rtl8723be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
622 {
623 struct rtl_priv *rtlpriv = rtl_priv(hw);
624 u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
625 u8 *tmp_buf = NULL;
626
627 c2h_cmd_id = buffer[0];
628 c2h_cmd_seq = buffer[1];
629 c2h_cmd_len = len - 2;
630 tmp_buf = buffer + 2;
631
632 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
633 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
634 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
635
636 RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
637 "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
638
639 _rtl8723be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
640 }
This page took 0.079417 seconds and 5 git commands to generate.