blob: 0f3522db5b3725ab4853337d0a4859488232e4ec [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;
58 u8 wait_h2c_limit = 100;
59 u8 wait_writeh2c_limit = 100;
60 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,
71 "H2C set in progress! Wait to set.."
72 "element_id(%d).\n", element_id);
73
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 }
95 while (!bwrite_sucess) {
96 wait_writeh2c_limit--;
97 if (wait_writeh2c_limit == 0) {
98 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
99 "Write H2C fail because no trigger "
100 "for FW INT!\n");
101 break;
102 }
103 boxnum = rtlhal->last_hmeboxnum;
104 switch (boxnum) {
105 case 0:
106 box_reg = REG_HMEBOX_0;
107 box_extreg = REG_HMEBOX_EXT_0;
108 break;
109 case 1:
110 box_reg = REG_HMEBOX_1;
111 box_extreg = REG_HMEBOX_EXT_1;
112 break;
113 case 2:
114 box_reg = REG_HMEBOX_2;
115 box_extreg = REG_HMEBOX_EXT_2;
116 break;
117 case 3:
118 box_reg = REG_HMEBOX_3;
119 box_extreg = REG_HMEBOX_EXT_3;
120 break;
121 default:
122 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
123 "switch case not processed\n");
124 break;
125 }
126 isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, boxnum);
127 while (!isfw_read) {
128 wait_h2c_limit--;
129 if (wait_h2c_limit == 0) {
130 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
131 "Wating too long for FW read "
132 "clear HMEBox(%d)!\n", boxnum);
133 break;
134 }
135 udelay(10);
136
137 isfw_read = _rtl8723be_check_fw_read_last_h2c(hw,
138 boxnum);
139 u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
140 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
141 "Wating for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
142 boxnum, u1b_tmp);
143 }
144 if (!isfw_read) {
145 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
146 "Write H2C register BOX[%d] fail!!!!! "
147 "Fw do not read.\n", boxnum);
148 break;
149 }
150 memset(boxcontent, 0, sizeof(boxcontent));
151 memset(boxextcontent, 0, sizeof(boxextcontent));
152 boxcontent[0] = element_id;
153 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
154 "Write element_id box_reg(%4x) = %2x\n",
155 box_reg, element_id);
156
157 switch (cmd_len) {
158 case 1:
159 case 2:
160 case 3:
161 /*boxcontent[0] &= ~(BIT(7));*/
162 memcpy((u8 *)(boxcontent) + 1,
163 p_cmdbuffer + buf_index, cmd_len);
164
165 for (idx = 0; idx < 4; idx++) {
166 rtl_write_byte(rtlpriv, box_reg + idx,
167 boxcontent[idx]);
168 }
169 break;
170 case 4:
171 case 5:
172 case 6:
173 case 7:
174 /*boxcontent[0] |= (BIT(7));*/
175 memcpy((u8 *)(boxextcontent),
176 p_cmdbuffer + buf_index+3, cmd_len-3);
177 memcpy((u8 *)(boxcontent) + 1,
178 p_cmdbuffer + buf_index, 3);
179
180 for (idx = 0; idx < 4; idx++) {
181 rtl_write_byte(rtlpriv, box_extreg + idx,
182 boxextcontent[idx]);
183 }
184 for (idx = 0; idx < 4; idx++) {
185 rtl_write_byte(rtlpriv, box_reg + idx,
186 boxcontent[idx]);
187 }
188 break;
189 default:
190 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
191 "switch case not process\n");
192 break;
193 }
194 bwrite_sucess = true;
195
196 rtlhal->last_hmeboxnum = boxnum + 1;
197 if (rtlhal->last_hmeboxnum == 4)
198 rtlhal->last_hmeboxnum = 0;
199
200 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
201 "pHalData->last_hmeboxnum = %d\n",
202 rtlhal->last_hmeboxnum);
203 }
204 if (!rtlpriv) {
205 pr_err("rtlpriv bad\n");
206 return;
207 }
208 if (!rtlhal) {
209 pr_err("rtlhal bad\n");
210 return;
211 }
212 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 }
230 memset(tmp_cmdbuf, 0, 8);
231 memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
232 _rtl8723be_fill_h2c_command(hw, element_id, cmd_len,
233 (u8 *)&tmp_cmdbuf);
234 return;
235}
236
237void rtl8723be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
238{
239 struct rtl_priv *rtlpriv = rtl_priv(hw);
240 u8 u1_h2c_set_pwrmode[H2C_8723BE_PWEMODE_LENGTH] = { 0 };
241 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
242 u8 rlbm, power_state = 0;
243 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
244
245 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
246 rlbm = 0;/*YJ, temp, 120316. FW now not support RLBM = 2.*/
247 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
248 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
249 (rtlpriv->mac80211.p2p) ?
250 ppsc->smart_ps : 1);
251 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
252 ppsc->reg_max_lps_awakeintvl);
253 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
254 if (mode == FW_PS_ACTIVE_MODE)
255 power_state |= FW_PWR_STATE_ACTIVE;
256 else
257 power_state |= FW_PWR_STATE_RF_OFF;
258 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
259
260 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
261 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
262 u1_h2c_set_pwrmode, H2C_8723BE_PWEMODE_LENGTH);
263 rtl8723be_fill_h2c_cmd(hw, H2C_8723BE_SETPWRMODE,
264 H2C_8723BE_PWEMODE_LENGTH,
265 u1_h2c_set_pwrmode);
266}
267
268static bool _rtl8723be_cmd_send_packet(struct ieee80211_hw *hw,
269 struct sk_buff *skb)
270{
271 struct rtl_priv *rtlpriv = rtl_priv(hw);
272 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
273 struct rtl8192_tx_ring *ring;
274 struct rtl_tx_desc *pdesc;
275 struct sk_buff *pskb = NULL;
276 u8 own;
277 unsigned long flags;
278
279 ring = &rtlpci->tx_ring[BEACON_QUEUE];
280
281 pskb = __skb_dequeue(&ring->queue);
282 if (pskb)
283 kfree_skb(pskb);
284
285 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
286
287 pdesc = &ring->desc[0];
288 own = (u8) rtlpriv->cfg->ops->get_desc((u8 *)pdesc, true, HW_DESC_OWN);
289
290 rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb);
291
292 __skb_queue_tail(&ring->queue, skb);
293
294 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
295
296 rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
297
298 return true;
299}
300#define BEACON_PG 0 /* ->1 */
301#define PSPOLL_PG 2
302#define NULL_PG 3
303#define PROBERSP_PG 4 /* ->5 */
304
305#define TOTAL_RESERVED_PKT_LEN 768
306
307static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
308 /* page 0 beacon */
309 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
310 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
311 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
313 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
314 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
315 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
316 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
317 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
318 0x09, 0x03, 0xFF, 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, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
322 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
323 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
324 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
325
326 /* page 1 beacon */
327 0x00, 0x50, 0xF2, 0x02, 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 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 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
339 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 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
344 /* page 2 ps-poll */
345 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
346 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
347 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
348 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
357 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
360 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361
362 /* page 3 null */
363 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
364 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
365 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
373 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
374 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
375 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
378 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379
380 /* page 4 probe_resp */
381 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
382 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
383 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
384 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
385 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
386 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
387 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
388 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
389 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
390 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
391 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
395 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
397
398 /* page 5 probe_resp */
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
408 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
409 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
410 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
413 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415};
416
417void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
418 bool dl_finished)
419{
420 struct rtl_priv *rtlpriv = rtl_priv(hw);
421 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
422 struct sk_buff *skb = NULL;
423
424 u32 totalpacketlen;
425 bool rtstatus;
426 u8 u1rsvdpageloc[5] = { 0 };
427 bool dlok = false;
428
429 u8 *beacon;
430 u8 *p_pspoll;
431 u8 *nullfunc;
432 u8 *p_probersp;
433 /*---------------------------------------------------------
434 * (1) beacon
435 *---------------------------------------------------------
436 */
437 beacon = &reserved_page_packet[BEACON_PG * 128];
438 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
439 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
440
441 /*-------------------------------------------------------
442 * (2) ps-poll
443 *-------------------------------------------------------
444 */
445 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
446 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
447 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
448 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
449
450 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
451
452 /*--------------------------------------------------------
453 * (3) null data
454 *--------------------------------------------------------
455 */
456 nullfunc = &reserved_page_packet[NULL_PG * 128];
457 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
458 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
459 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
460
461 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
462
463 /*---------------------------------------------------------
464 * (4) probe response
465 *---------------------------------------------------------
466 */
467 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
468 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
469 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
470 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
471
472 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
473
474 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
475
476 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
477 "rtl8723be_set_fw_rsvdpagepkt(): "
478 "HW_VAR_SET_TX_CMD: ALL\n",
479 &reserved_page_packet[0], totalpacketlen);
480 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
481 "rtl8723be_set_fw_rsvdpagepkt(): "
482 "HW_VAR_SET_TX_CMD: ALL\n", u1rsvdpageloc, 3);
483
484
485 skb = dev_alloc_skb(totalpacketlen);
486 memcpy((u8 *)skb_put(skb, totalpacketlen),
487 &reserved_page_packet, totalpacketlen);
488
489 rtstatus = _rtl8723be_cmd_send_packet(hw, skb);
490
491 if (rtstatus)
492 dlok = true;
493
494 if (dlok) {
495 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
496 "Set RSVD page location to Fw.\n");
497 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, "H2C_RSVDPAGE:\n",
498 u1rsvdpageloc, 3);
499 rtl8723be_fill_h2c_cmd(hw, H2C_8723BE_RSVDPAGE,
500 sizeof(u1rsvdpageloc), u1rsvdpageloc);
501 } else {
502 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
503 "Set RSVD page location to Fw FAIL!!!!!!.\n");
504 }
505}
506
507/*Should check FW support p2p or not.*/
508static void rtl8723be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
509 u8 ctwindow)
510{
511 u8 u1_ctwindow_period[1] = {ctwindow};
512
513 rtl8723be_fill_h2c_cmd(hw, H2C_8723BE_P2P_PS_CTW_CMD, 1,
514 u1_ctwindow_period);
515}
516
517void rtl8723be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw,
518 u8 p2p_ps_state)
519{
520 struct rtl_priv *rtlpriv = rtl_priv(hw);
521 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
522 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
523 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
524 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
525 u8 i;
526 u16 ctwindow;
527 u32 start_time, tsf_low;
528
529 switch (p2p_ps_state) {
530 case P2P_PS_DISABLE:
531 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
532 memset(p2p_ps_offload, 0, sizeof(struct p2p_ps_offload_t));
533 break;
534 case P2P_PS_ENABLE:
535 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
536 /* update CTWindow value. */
537 if (p2pinfo->ctwindow > 0) {
538 p2p_ps_offload->ctwindow_en = 1;
539 ctwindow = p2pinfo->ctwindow;
540 rtl8723be_set_p2p_ctw_period_cmd(hw, ctwindow);
541 }
542 /* hw only support 2 set of NoA */
543 for (i = 0; i < p2pinfo->noa_num; i++) {
544 /* To control the register setting
545 * for which NOA
546 */
547 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
548 if (i == 0)
549 p2p_ps_offload->noa0_en = 1;
550 else
551 p2p_ps_offload->noa1_en = 1;
552
553 /* config P2P NoA Descriptor Register */
554 rtl_write_dword(rtlpriv, 0x5E0,
555 p2pinfo->noa_duration[i]);
556 rtl_write_dword(rtlpriv, 0x5E4,
557 p2pinfo->noa_interval[i]);
558
559 /*Get Current TSF value */
560 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
561
562 start_time = p2pinfo->noa_start_time[i];
563 if (p2pinfo->noa_count_type[i] != 1) {
564 while (start_time <= (tsf_low + (50 * 1024))) {
565 start_time += p2pinfo->noa_interval[i];
566 if (p2pinfo->noa_count_type[i] != 255)
567 p2pinfo->noa_count_type[i]--;
568 }
569 }
570 rtl_write_dword(rtlpriv, 0x5E8, start_time);
571 rtl_write_dword(rtlpriv, 0x5EC,
572 p2pinfo->noa_count_type[i]);
573 }
574 if ((p2pinfo->opp_ps == 1) ||
575 (p2pinfo->noa_num > 0)) {
576 /* rst p2p circuit */
577 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
578
579 p2p_ps_offload->offload_en = 1;
580
581 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
582 p2p_ps_offload->role = 1;
583 p2p_ps_offload->allstasleep = 0;
584 } else {
585 p2p_ps_offload->role = 0;
586 }
587 p2p_ps_offload->discovery = 0;
588 }
589 break;
590 case P2P_PS_SCAN:
591 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
592 p2p_ps_offload->discovery = 1;
593 break;
594 case P2P_PS_SCAN_DONE:
595 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
596 p2p_ps_offload->discovery = 0;
597 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
598 break;
599 default:
600 break;
601 }
602 rtl8723be_fill_h2c_cmd(hw, H2C_8723BE_P2P_PS_OFFLOAD, 1,
603 (u8 *)p2p_ps_offload);
604}
605
606void rtl8723be_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
607{
608 u8 u1_joinbssrpt_parm[1] = { 0 };
609
610 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
611
612 rtl8723be_fill_h2c_cmd(hw, H2C_8723BE_JOINBSSRPT, 1,
613 u1_joinbssrpt_parm);
614}
615
616void rtl8723be_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw,
617 u8 ap_offload_enable)
618{
619 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
620 u8 u1_apoffload_parm[H2C_8723BE_AP_OFFLOAD_LENGTH] = { 0 };
621
622 SET_H2CCMD_AP_OFFLOAD_ON(u1_apoffload_parm, ap_offload_enable);
623 SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid);
624 SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0);
625
626 rtl8723be_fill_h2c_cmd(hw, H2C_8723BE_AP_OFFLOAD,
627 H2C_8723BE_AP_OFFLOAD_LENGTH, u1_apoffload_parm);
628}