blob: 0c07992985b9d44e0a1cccb4816c6ba9747425b5 [file] [log] [blame]
Larry Fingera619d1a2014-02-28 15:16:50 -06001/******************************************************************************
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 "reg.h"
30#include "def.h"
31#include "fw.h"
32#include "../rtl8723com/fw_common.h"
33
34static bool _rtl8723be_check_fw_read_last_h2c(struct ieee80211_hw *hw,
35 u8 boxnum)
36{
37 struct rtl_priv *rtlpriv = rtl_priv(hw);
38 u8 val_hmetfr;
39 bool result = false;
40
41 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
42 if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
43 result = true;
44 return result;
45}
46
47static void _rtl8723be_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
48 u32 cmd_len, u8 *p_cmdbuffer)
49{
50 struct rtl_priv *rtlpriv = rtl_priv(hw);
51 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
52 u8 boxnum;
53 u16 box_reg = 0, box_extreg = 0;
54 u8 u1b_tmp;
55 bool isfw_read = false;
56 u8 buf_index = 0;
57 bool bwrite_sucess = false;
Larry Finger5c99f042014-09-26 16:40:25 -050058 u8 wait_h2c_limmit = 100;
59 u8 wait_writeh2c_limmit = 100;
Larry Fingera619d1a2014-02-28 15:16:50 -060060 u8 boxcontent[4], boxextcontent[4];
61 u32 h2c_waitcounter = 0;
62 unsigned long flag;
63 u8 idx;
64
65 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
66
67 while (true) {
68 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
69 if (rtlhal->h2c_setinprogress) {
70 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
Larry Finger5c99f042014-09-26 16:40:25 -050071 "H2C set in progress! Wait to set..element_id(%d).\n",
72 element_id);
Larry Fingera619d1a2014-02-28 15:16:50 -060073
74 while (rtlhal->h2c_setinprogress) {
75 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
76 flag);
77 h2c_waitcounter++;
78 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
79 "Wait 100 us (%d times)...\n",
80 h2c_waitcounter);
81 udelay(100);
82
83 if (h2c_waitcounter > 1000)
84 return;
85 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
86 flag);
87 }
88 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
89 } else {
90 rtlhal->h2c_setinprogress = true;
91 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
92 break;
93 }
94 }
Larry Finger5c99f042014-09-26 16:40:25 -050095
Larry Fingera619d1a2014-02-28 15:16:50 -060096 while (!bwrite_sucess) {
Larry Finger5c99f042014-09-26 16:40:25 -050097 wait_writeh2c_limmit--;
98 if (wait_writeh2c_limmit == 0) {
Larry Fingera619d1a2014-02-28 15:16:50 -060099 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
Larry Finger5c99f042014-09-26 16:40:25 -0500100 "Write H2C fail because no trigger for FW INT!\n");
Larry Fingera619d1a2014-02-28 15:16:50 -0600101 break;
102 }
Larry Finger5c99f042014-09-26 16:40:25 -0500103
Larry Fingera619d1a2014-02-28 15:16:50 -0600104 boxnum = rtlhal->last_hmeboxnum;
105 switch (boxnum) {
106 case 0:
107 box_reg = REG_HMEBOX_0;
108 box_extreg = REG_HMEBOX_EXT_0;
109 break;
110 case 1:
111 box_reg = REG_HMEBOX_1;
112 box_extreg = REG_HMEBOX_EXT_1;
113 break;
114 case 2:
115 box_reg = REG_HMEBOX_2;
116 box_extreg = REG_HMEBOX_EXT_2;
117 break;
118 case 3:
119 box_reg = REG_HMEBOX_3;
120 box_extreg = REG_HMEBOX_EXT_3;
121 break;
122 default:
123 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
Larry Finger5c99f042014-09-26 16:40:25 -0500124 "switch case not process\n");
Larry Fingera619d1a2014-02-28 15:16:50 -0600125 break;
126 }
Larry Finger5c99f042014-09-26 16:40:25 -0500127
Larry Fingera619d1a2014-02-28 15:16:50 -0600128 isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, boxnum);
129 while (!isfw_read) {
Larry Finger5c99f042014-09-26 16:40:25 -0500130 wait_h2c_limmit--;
131 if (wait_h2c_limmit == 0) {
Larry Fingera619d1a2014-02-28 15:16:50 -0600132 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
Larry Finger5c99f042014-09-26 16:40:25 -0500133 "Waiting too long for FW read clear HMEBox(%d)!\n",
134 boxnum);
Larry Fingera619d1a2014-02-28 15:16:50 -0600135 break;
136 }
Larry Finger5c99f042014-09-26 16:40:25 -0500137
Larry Fingera619d1a2014-02-28 15:16:50 -0600138 udelay(10);
139
140 isfw_read = _rtl8723be_check_fw_read_last_h2c(hw,
141 boxnum);
142 u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
143 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
Larry Finger5c99f042014-09-26 16:40:25 -0500144 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
Larry Fingera619d1a2014-02-28 15:16:50 -0600145 boxnum, u1b_tmp);
146 }
Larry Finger5c99f042014-09-26 16:40:25 -0500147
Larry Fingera619d1a2014-02-28 15:16:50 -0600148 if (!isfw_read) {
149 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
Larry Finger5c99f042014-09-26 16:40:25 -0500150 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
151 boxnum);
Larry Fingera619d1a2014-02-28 15:16:50 -0600152 break;
153 }
Larry Finger5c99f042014-09-26 16:40:25 -0500154
Larry Fingera619d1a2014-02-28 15:16:50 -0600155 memset(boxcontent, 0, sizeof(boxcontent));
156 memset(boxextcontent, 0, sizeof(boxextcontent));
157 boxcontent[0] = element_id;
158 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
159 "Write element_id box_reg(%4x) = %2x\n",
Larry Finger5c99f042014-09-26 16:40:25 -0500160 box_reg, element_id);
Larry Fingera619d1a2014-02-28 15:16:50 -0600161
162 switch (cmd_len) {
163 case 1:
164 case 2:
165 case 3:
166 /*boxcontent[0] &= ~(BIT(7));*/
167 memcpy((u8 *)(boxcontent) + 1,
168 p_cmdbuffer + buf_index, cmd_len);
169
170 for (idx = 0; idx < 4; idx++) {
171 rtl_write_byte(rtlpriv, box_reg + idx,
172 boxcontent[idx]);
173 }
174 break;
175 case 4:
176 case 5:
177 case 6:
178 case 7:
179 /*boxcontent[0] |= (BIT(7));*/
180 memcpy((u8 *)(boxextcontent),
181 p_cmdbuffer + buf_index+3, cmd_len-3);
182 memcpy((u8 *)(boxcontent) + 1,
183 p_cmdbuffer + buf_index, 3);
184
185 for (idx = 0; idx < 4; idx++) {
186 rtl_write_byte(rtlpriv, box_extreg + idx,
187 boxextcontent[idx]);
188 }
Larry Finger5c99f042014-09-26 16:40:25 -0500189
Larry Fingera619d1a2014-02-28 15:16:50 -0600190 for (idx = 0; idx < 4; idx++) {
191 rtl_write_byte(rtlpriv, box_reg + idx,
192 boxcontent[idx]);
193 }
194 break;
195 default:
196 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
197 "switch case not process\n");
198 break;
199 }
Larry Finger5c99f042014-09-26 16:40:25 -0500200
Larry Fingera619d1a2014-02-28 15:16:50 -0600201 bwrite_sucess = true;
202
203 rtlhal->last_hmeboxnum = boxnum + 1;
204 if (rtlhal->last_hmeboxnum == 4)
205 rtlhal->last_hmeboxnum = 0;
206
207 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
208 "pHalData->last_hmeboxnum = %d\n",
Larry Finger5c99f042014-09-26 16:40:25 -0500209 rtlhal->last_hmeboxnum);
Larry Fingera619d1a2014-02-28 15:16:50 -0600210 }
Larry Finger5c99f042014-09-26 16:40:25 -0500211
Larry Fingera619d1a2014-02-28 15:16:50 -0600212 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
213 rtlhal->h2c_setinprogress = false;
214 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
215
216 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
217}
218
219void rtl8723be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
220 u32 cmd_len, u8 *p_cmdbuffer)
221{
222 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
223 u32 tmp_cmdbuf[2];
224
225 if (!rtlhal->fw_ready) {
226 RT_ASSERT(false,
227 "return H2C cmd because of Fw download fail!!!\n");
228 return;
229 }
Larry Finger5c99f042014-09-26 16:40:25 -0500230
Larry Fingera619d1a2014-02-28 15:16:50 -0600231 memset(tmp_cmdbuf, 0, 8);
232 memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
233 _rtl8723be_fill_h2c_command(hw, element_id, cmd_len,
234 (u8 *)&tmp_cmdbuf);
235 return;
236}
237
238void rtl8723be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
239{
240 struct rtl_priv *rtlpriv = rtl_priv(hw);
Larry Finger5c99f042014-09-26 16:40:25 -0500241 u8 u1_h2c_set_pwrmode[H2C_PWEMODE_LENGTH] = { 0 };
Larry Fingera619d1a2014-02-28 15:16:50 -0600242 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
243 u8 rlbm, power_state = 0;
244 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
245
246 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
Larry Finger5c99f042014-09-26 16:40:25 -0500247 rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/
Larry Fingera619d1a2014-02-28 15:16:50 -0600248 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
249 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
250 (rtlpriv->mac80211.p2p) ?
Larry Finger5c99f042014-09-26 16:40:25 -0500251 ppsc->smart_ps : 1);
Larry Fingera619d1a2014-02-28 15:16:50 -0600252 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
253 ppsc->reg_max_lps_awakeintvl);
254 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
255 if (mode == FW_PS_ACTIVE_MODE)
256 power_state |= FW_PWR_STATE_ACTIVE;
257 else
258 power_state |= FW_PWR_STATE_RF_OFF;
259 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
260
261 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
262 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
Larry Finger5c99f042014-09-26 16:40:25 -0500263 u1_h2c_set_pwrmode, H2C_PWEMODE_LENGTH);
264 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_SETPWRMODE, H2C_PWEMODE_LENGTH,
Larry Fingera619d1a2014-02-28 15:16:50 -0600265 u1_h2c_set_pwrmode);
266}
267
Larry Finger5c99f042014-09-26 16:40:25 -0500268void rtl8723be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
Larry Fingera619d1a2014-02-28 15:16:50 -0600269{
Larry Finger5c99f042014-09-26 16:40:25 -0500270 u8 parm[3] = { 0, 0, 0 };
271 /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
272 * bit1=0-->update Media Status to MACID
273 * bit1=1-->update Media Status from MACID to MACID_End
274 * parm[1]: MACID, if this is INFRA_STA, MacID = 0
275 * parm[2]: MACID_End
276 */
277 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
278 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
Larry Fingera619d1a2014-02-28 15:16:50 -0600279
Larry Finger5c99f042014-09-26 16:40:25 -0500280 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_MSRRPT, 3, parm);
Larry Fingera619d1a2014-02-28 15:16:50 -0600281}
Larry Finger5c99f042014-09-26 16:40:25 -0500282
Larry Fingera619d1a2014-02-28 15:16:50 -0600283#define BEACON_PG 0 /* ->1 */
284#define PSPOLL_PG 2
285#define NULL_PG 3
286#define PROBERSP_PG 4 /* ->5 */
287
288#define TOTAL_RESERVED_PKT_LEN 768
289
290static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
291 /* page 0 beacon */
292 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
293 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
294 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
297 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
298 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
299 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
300 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
301 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
304 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
305 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
306 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
307 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
308
309 /* page 1 beacon */
310 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
311 0x00, 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 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 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
322 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 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
327 /* page 2 ps-poll */
328 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
329 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
340 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
341 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
342 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
343 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
344
345 /* page 3 null */
346 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
347 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
348 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
349 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
358 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
362
363 /* page 4 probe_resp */
364 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
365 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
366 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
367 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
368 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
369 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
370 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
371 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
372 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
373 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
374 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
378 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
380
381 /* page 5 probe_resp */
382 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 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};
399
400void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
Larry Finger5c99f042014-09-26 16:40:25 -0500401 bool b_dl_finished)
Larry Fingera619d1a2014-02-28 15:16:50 -0600402{
403 struct rtl_priv *rtlpriv = rtl_priv(hw);
404 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
405 struct sk_buff *skb = NULL;
406
407 u32 totalpacketlen;
408 bool rtstatus;
409 u8 u1rsvdpageloc[5] = { 0 };
Larry Finger5c99f042014-09-26 16:40:25 -0500410 bool b_dlok = false;
Larry Fingera619d1a2014-02-28 15:16:50 -0600411
412 u8 *beacon;
413 u8 *p_pspoll;
414 u8 *nullfunc;
415 u8 *p_probersp;
416 /*---------------------------------------------------------
417 * (1) beacon
418 *---------------------------------------------------------
419 */
420 beacon = &reserved_page_packet[BEACON_PG * 128];
421 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
422 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
423
424 /*-------------------------------------------------------
425 * (2) ps-poll
426 *-------------------------------------------------------
427 */
428 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
429 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
430 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
431 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
432
433 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
434
435 /*--------------------------------------------------------
436 * (3) null data
437 *--------------------------------------------------------
438 */
439 nullfunc = &reserved_page_packet[NULL_PG * 128];
440 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
441 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
442 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
443
444 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
445
446 /*---------------------------------------------------------
447 * (4) probe response
448 *---------------------------------------------------------
449 */
450 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
451 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
452 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
453 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
454
455 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
456
457 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
458
459 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
Larry Finger5c99f042014-09-26 16:40:25 -0500460 "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
Larry Fingera619d1a2014-02-28 15:16:50 -0600461 &reserved_page_packet[0], totalpacketlen);
462 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
Larry Finger5c99f042014-09-26 16:40:25 -0500463 "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
464 u1rsvdpageloc, 3);
Larry Fingera619d1a2014-02-28 15:16:50 -0600465
466 skb = dev_alloc_skb(totalpacketlen);
467 memcpy((u8 *)skb_put(skb, totalpacketlen),
468 &reserved_page_packet, totalpacketlen);
469
Larry Finger5c99f042014-09-26 16:40:25 -0500470 rtstatus = rtl8723_cmd_send_packet(hw, skb);
Larry Fingera619d1a2014-02-28 15:16:50 -0600471
472 if (rtstatus)
Larry Finger5c99f042014-09-26 16:40:25 -0500473 b_dlok = true;
Larry Fingera619d1a2014-02-28 15:16:50 -0600474
Larry Finger5c99f042014-09-26 16:40:25 -0500475 if (b_dlok) {
Larry Fingera619d1a2014-02-28 15:16:50 -0600476 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
477 "Set RSVD page location to Fw.\n");
478 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, "H2C_RSVDPAGE:\n",
479 u1rsvdpageloc, 3);
Larry Finger5c99f042014-09-26 16:40:25 -0500480 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_RSVDPAGE,
Larry Fingera619d1a2014-02-28 15:16:50 -0600481 sizeof(u1rsvdpageloc), u1rsvdpageloc);
Larry Finger5c99f042014-09-26 16:40:25 -0500482 } else
Larry Fingera619d1a2014-02-28 15:16:50 -0600483 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
484 "Set RSVD page location to Fw FAIL!!!!!!.\n");
Larry Fingera619d1a2014-02-28 15:16:50 -0600485}
486
487/*Should check FW support p2p or not.*/
488static void rtl8723be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
489 u8 ctwindow)
490{
Larry Finger5c99f042014-09-26 16:40:25 -0500491 u8 u1_ctwindow_period[1] = { ctwindow};
Larry Fingera619d1a2014-02-28 15:16:50 -0600492
Larry Finger5c99f042014-09-26 16:40:25 -0500493 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_CTW_CMD, 1,
Larry Fingera619d1a2014-02-28 15:16:50 -0600494 u1_ctwindow_period);
495}
496
497void rtl8723be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw,
498 u8 p2p_ps_state)
499{
500 struct rtl_priv *rtlpriv = rtl_priv(hw);
501 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
502 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
503 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
504 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
505 u8 i;
506 u16 ctwindow;
507 u32 start_time, tsf_low;
508
509 switch (p2p_ps_state) {
510 case P2P_PS_DISABLE:
511 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
Larry Finger5c99f042014-09-26 16:40:25 -0500512 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
Larry Fingera619d1a2014-02-28 15:16:50 -0600513 break;
514 case P2P_PS_ENABLE:
515 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
516 /* update CTWindow value. */
517 if (p2pinfo->ctwindow > 0) {
518 p2p_ps_offload->ctwindow_en = 1;
519 ctwindow = p2pinfo->ctwindow;
520 rtl8723be_set_p2p_ctw_period_cmd(hw, ctwindow);
521 }
522 /* hw only support 2 set of NoA */
Larry Finger5c99f042014-09-26 16:40:25 -0500523 for (i = 0 ; i < p2pinfo->noa_num ; i++) {
Larry Fingera619d1a2014-02-28 15:16:50 -0600524 /* To control the register setting
525 * for which NOA
526 */
527 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
528 if (i == 0)
529 p2p_ps_offload->noa0_en = 1;
530 else
531 p2p_ps_offload->noa1_en = 1;
532
533 /* config P2P NoA Descriptor Register */
534 rtl_write_dword(rtlpriv, 0x5E0,
535 p2pinfo->noa_duration[i]);
536 rtl_write_dword(rtlpriv, 0x5E4,
537 p2pinfo->noa_interval[i]);
538
539 /*Get Current TSF value */
540 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
541
542 start_time = p2pinfo->noa_start_time[i];
543 if (p2pinfo->noa_count_type[i] != 1) {
544 while (start_time <= (tsf_low + (50 * 1024))) {
545 start_time += p2pinfo->noa_interval[i];
546 if (p2pinfo->noa_count_type[i] != 255)
547 p2pinfo->noa_count_type[i]--;
548 }
549 }
550 rtl_write_dword(rtlpriv, 0x5E8, start_time);
551 rtl_write_dword(rtlpriv, 0x5EC,
552 p2pinfo->noa_count_type[i]);
553 }
Larry Finger5c99f042014-09-26 16:40:25 -0500554
Larry Fingera619d1a2014-02-28 15:16:50 -0600555 if ((p2pinfo->opp_ps == 1) ||
556 (p2pinfo->noa_num > 0)) {
557 /* rst p2p circuit */
558 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
559
560 p2p_ps_offload->offload_en = 1;
561
562 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
563 p2p_ps_offload->role = 1;
564 p2p_ps_offload->allstasleep = 0;
565 } else {
566 p2p_ps_offload->role = 0;
567 }
568 p2p_ps_offload->discovery = 0;
569 }
570 break;
571 case P2P_PS_SCAN:
572 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
573 p2p_ps_offload->discovery = 1;
574 break;
575 case P2P_PS_SCAN_DONE:
576 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
577 p2p_ps_offload->discovery = 0;
578 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
579 break;
580 default:
581 break;
582 }
Larry Finger5c99f042014-09-26 16:40:25 -0500583
584 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_OFFLOAD, 1,
Larry Fingera619d1a2014-02-28 15:16:50 -0600585 (u8 *)p2p_ps_offload);
586}
587
Larry Finger5c99f042014-09-26 16:40:25 -0500588static void _rtl8723be_c2h_content_parsing(struct ieee80211_hw *hw,
589 u8 c2h_cmd_id,
590 u8 c2h_cmd_len, u8 *tmp_buf)
Larry Fingera619d1a2014-02-28 15:16:50 -0600591{
Larry Finger5c99f042014-09-26 16:40:25 -0500592 struct rtl_priv *rtlpriv = rtl_priv(hw);
Larry Fingera619d1a2014-02-28 15:16:50 -0600593
Larry Finger5c99f042014-09-26 16:40:25 -0500594 switch (c2h_cmd_id) {
595 case C2H_8723B_DBG:
596 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
597 "[C2H], C2H_8723BE_DBG!!\n");
598 break;
599 case C2H_8723B_TX_REPORT:
600 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
601 "[C2H], C2H_8723BE_TX_REPORT!\n");
602 break;
603 case C2H_8723B_BT_INFO:
604 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
605 "[C2H], C2H_8723BE_BT_INFO!!\n");
606 rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
607 c2h_cmd_len);
608 break;
609 case C2H_8723B_BT_MP:
610 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
611 "[C2H], C2H_8723BE_BT_MP!!\n");
612 break;
613 default:
614 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
615 "[C2H], Unkown packet!! CmdId(%#X)!\n", c2h_cmd_id);
616 break;
617 }
Larry Fingera619d1a2014-02-28 15:16:50 -0600618}
619
Larry Finger5c99f042014-09-26 16:40:25 -0500620void rtl8723be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
Larry Fingera619d1a2014-02-28 15:16:50 -0600621{
Larry Finger5c99f042014-09-26 16:40:25 -0500622 struct rtl_priv *rtlpriv = rtl_priv(hw);
623 u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
624 u8 *tmp_buf = NULL;
Larry Fingera619d1a2014-02-28 15:16:50 -0600625
Larry Finger5c99f042014-09-26 16:40:25 -0500626 c2h_cmd_id = buffer[0];
627 c2h_cmd_seq = buffer[1];
628 c2h_cmd_len = len - 2;
629 tmp_buf = buffer + 2;
Larry Fingera619d1a2014-02-28 15:16:50 -0600630
Larry Finger5c99f042014-09-26 16:40:25 -0500631 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
632 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
633 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
634
635 RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
636 "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
637
638 _rtl8723be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
Larry Fingera619d1a2014-02-28 15:16:50 -0600639}