blob: 27a0e50c2793ad39274cf02db8549e784249656b [file] [log] [blame]
Larry Fingerb1a3bfc2014-09-26 16:40:23 -05001/******************************************************************************
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"
Larry Finger557f9332014-09-26 16:40:27 -050029#include "../core.h"
Larry Fingerb1a3bfc2014-09-26 16:40:23 -050030#include "reg.h"
31#include "def.h"
32#include "fw.h"
33#include "dm.h"
34
35static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable)
36{
37 struct rtl_priv *rtlpriv = rtl_priv(hw);
38 u8 tmp;
39
40 if (enable) {
41 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05);
42
43 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
44 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
45 } else {
46 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
47 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
48 }
49}
50
51static void _rtl92ee_fw_block_write(struct ieee80211_hw *hw,
52 const u8 *buffer, u32 size)
53{
54 struct rtl_priv *rtlpriv = rtl_priv(hw);
55 u32 blocksize = sizeof(u32);
56 u8 *bufferptr = (u8 *)buffer;
57 u32 *pu4byteptr = (u32 *)buffer;
58 u32 i, offset, blockcount, remainsize;
59
60 blockcount = size / blocksize;
61 remainsize = size % blocksize;
62
63 for (i = 0; i < blockcount; i++) {
64 offset = i * blocksize;
65 rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
66 *(pu4byteptr + i));
67 }
68
69 if (remainsize) {
70 offset = blockcount * blocksize;
71 bufferptr += offset;
72 for (i = 0; i < remainsize; i++) {
73 rtl_write_byte(rtlpriv,
74 (FW_8192C_START_ADDRESS + offset + i),
75 *(bufferptr + i));
76 }
77 }
78}
79
80static void _rtl92ee_fw_page_write(struct ieee80211_hw *hw, u32 page,
81 const u8 *buffer, u32 size)
82{
83 struct rtl_priv *rtlpriv = rtl_priv(hw);
84 u8 value8;
85 u8 u8page = (u8)(page & 0x07);
86
87 value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
88 rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
89
90 _rtl92ee_fw_block_write(hw, buffer, size);
91}
92
93static void _rtl92ee_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
94{
95 u32 fwlen = *pfwlen;
96 u8 remain = (u8)(fwlen % 4);
97
98 remain = (remain == 0) ? 0 : (4 - remain);
99
100 while (remain > 0) {
101 pfwbuf[fwlen] = 0;
102 fwlen++;
103 remain--;
104 }
105
106 *pfwlen = fwlen;
107}
108
109static void _rtl92ee_write_fw(struct ieee80211_hw *hw,
110 enum version_8192e version,
111 u8 *buffer, u32 size)
112{
113 struct rtl_priv *rtlpriv = rtl_priv(hw);
114 u8 *bufferptr = (u8 *)buffer;
115 u32 pagenums, remainsize;
116 u32 page, offset;
117
118 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "FW size is %d bytes,\n", size);
119
120 _rtl92ee_fill_dummy(bufferptr, &size);
121
122 pagenums = size / FW_8192C_PAGE_SIZE;
123 remainsize = size % FW_8192C_PAGE_SIZE;
124
125 if (pagenums > 8) {
126 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
127 "Page numbers should not greater then 8\n");
128 }
129
130 for (page = 0; page < pagenums; page++) {
131 offset = page * FW_8192C_PAGE_SIZE;
132 _rtl92ee_fw_page_write(hw, page, (bufferptr + offset),
133 FW_8192C_PAGE_SIZE);
134 udelay(2);
135 }
136
137 if (remainsize) {
138 offset = pagenums * FW_8192C_PAGE_SIZE;
139 page = pagenums;
140 _rtl92ee_fw_page_write(hw, page, (bufferptr + offset),
141 remainsize);
142 }
143}
144
145static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw)
146{
147 struct rtl_priv *rtlpriv = rtl_priv(hw);
148 int err = -EIO;
149 u32 counter = 0;
150 u32 value32;
151
152 do {
153 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
154 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
155 (!(value32 & FWDL_CHKSUM_RPT)));
156
157 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
158 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
159 "chksum report faill ! REG_MCUFWDL:0x%08x .\n",
160 value32);
161 goto exit;
162 }
163
164 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
165 "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32);
166
167 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
168 value32 |= MCUFWDL_RDY;
169 value32 &= ~WINTINI_RDY;
170 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
171
172 rtl92ee_firmware_selfreset(hw);
173 counter = 0;
174
175 do {
176 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
177 if (value32 & WINTINI_RDY) {
178 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD ,
179 "Polling FW ready success!! REG_MCUFWDL:0x%08x. count = %d\n",
180 value32, counter);
181 err = 0;
182 goto exit;
183 }
184
185 udelay(FW_8192C_POLLING_DELAY*10);
186
187 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
188
189 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
190 "Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n",
191 value32, counter);
192
193exit:
194 return err;
195}
196
197int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw)
198{
199 struct rtl_priv *rtlpriv = rtl_priv(hw);
200 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
Larry Finger8d882bc2015-08-03 15:56:16 -0500201 struct rtlwifi_firmware_header *pfwheader;
Larry Fingerb1a3bfc2014-09-26 16:40:23 -0500202 u8 *pfwdata;
203 u32 fwsize;
204 int err;
205 enum version_8192e version = rtlhal->version;
206
207 if (!rtlhal->pfirmware)
208 return 1;
209
Larry Finger8d882bc2015-08-03 15:56:16 -0500210 pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
211 rtlhal->fw_version = le16_to_cpu(pfwheader->version);
Larry Fingerb1a3bfc2014-09-26 16:40:23 -0500212 rtlhal->fw_subversion = pfwheader->subversion;
213 pfwdata = (u8 *)rtlhal->pfirmware;
214 fwsize = rtlhal->fwsize;
215 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
216 "normal Firmware SIZE %d\n" , fwsize);
217
218 if (IS_FW_HEADER_EXIST(pfwheader)) {
219 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
220 "Firmware Version(%d), Signature(%#x),Size(%d)\n",
221 pfwheader->version, pfwheader->signature,
Larry Finger8d882bc2015-08-03 15:56:16 -0500222 (int)sizeof(struct rtlwifi_firmware_header));
Larry Fingerb1a3bfc2014-09-26 16:40:23 -0500223
Larry Finger8d882bc2015-08-03 15:56:16 -0500224 pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
225 fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
Larry Fingerb1a3bfc2014-09-26 16:40:23 -0500226 } else {
227 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
228 "Firmware no Header, Signature(%#x)\n",
229 pfwheader->signature);
230 }
231
232 if (rtlhal->mac_func_enable) {
233 if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
234 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
235 rtl92ee_firmware_selfreset(hw);
236 }
237 }
238 _rtl92ee_enable_fw_download(hw, true);
239 _rtl92ee_write_fw(hw, version, pfwdata, fwsize);
240 _rtl92ee_enable_fw_download(hw, false);
241
242 err = _rtl92ee_fw_free_to_go(hw);
243 if (err) {
244 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
245 "Firmware is not ready to run!\n");
246 } else {
247 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD ,
248 "Firmware is ready to run!\n");
249 }
250
251 return 0;
252}
253
254static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
255{
256 struct rtl_priv *rtlpriv = rtl_priv(hw);
257 u8 val_hmetfr;
258 bool result = false;
259
260 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
261 if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
262 result = true;
263 return result;
264}
265
266static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
267 u32 cmd_len, u8 *cmdbuffer)
268{
269 struct rtl_priv *rtlpriv = rtl_priv(hw);
270 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
271 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
272 u8 boxnum;
273 u16 box_reg = 0, box_extreg = 0;
274 u8 u1b_tmp;
275 bool isfw_read = false;
276 u8 buf_index = 0;
277 bool bwrite_sucess = false;
278 u8 wait_h2c_limmit = 100;
279 u8 boxcontent[4], boxextcontent[4];
280 u32 h2c_waitcounter = 0;
281 unsigned long flag;
282 u8 idx;
283
284 if (ppsc->dot11_psmode != EACTIVE ||
285 ppsc->inactive_pwrstate == ERFOFF) {
286 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
287 "FillH2CCommand8192E(): Return because RF is off!!!\n");
288 return;
289 }
290
291 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "come in\n");
292
293 /* 1. Prevent race condition in setting H2C cmd.
294 * (copy from MgntActSet_RF_State().)
295 */
296 while (true) {
297 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
298 if (rtlhal->h2c_setinprogress) {
299 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
300 "H2C set in progress! Wait to set..element_id(%d).\n",
301 element_id);
302
303 while (rtlhal->h2c_setinprogress) {
304 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
305 flag);
306 h2c_waitcounter++;
307 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
308 "Wait 100 us (%d times)...\n",
309 h2c_waitcounter);
310 udelay(100);
311
312 if (h2c_waitcounter > 1000)
313 return;
314 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
315 flag);
316 }
317 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
318 } else {
319 rtlhal->h2c_setinprogress = true;
320 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
321 break;
322 }
323 }
324
325 while (!bwrite_sucess) {
326 /* 2. Find the last BOX number which has been writen. */
327 boxnum = rtlhal->last_hmeboxnum;
328 switch (boxnum) {
329 case 0:
330 box_reg = REG_HMEBOX_0;
331 box_extreg = REG_HMEBOX_EXT_0;
332 break;
333 case 1:
334 box_reg = REG_HMEBOX_1;
335 box_extreg = REG_HMEBOX_EXT_1;
336 break;
337 case 2:
338 box_reg = REG_HMEBOX_2;
339 box_extreg = REG_HMEBOX_EXT_2;
340 break;
341 case 3:
342 box_reg = REG_HMEBOX_3;
343 box_extreg = REG_HMEBOX_EXT_3;
344 break;
345 default:
346 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
Joe Perchesad574882016-09-23 11:27:19 -0700347 "switch case %#x not processed\n", boxnum);
Larry Fingerb1a3bfc2014-09-26 16:40:23 -0500348 break;
349 }
350
351 /* 3. Check if the box content is empty. */
352 isfw_read = false;
353 u1b_tmp = rtl_read_byte(rtlpriv, REG_CR);
354
355 if (u1b_tmp != 0xea) {
356 isfw_read = true;
357 } else {
358 if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea ||
359 rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea)
360 rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff);
361 }
362
363 if (isfw_read) {
364 wait_h2c_limmit = 100;
365 isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
366 while (!isfw_read) {
367 wait_h2c_limmit--;
368 if (wait_h2c_limmit == 0) {
369 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
370 "Waiting too long for FW read clear HMEBox(%d)!!!\n",
371 boxnum);
372 break;
373 }
374 udelay(10);
375 isfw_read =
376 _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
377 u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
378 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
379 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
380 boxnum, u1b_tmp);
381 }
382 }
383
384 /* If Fw has not read the last
385 * H2C cmd, break and give up this H2C.
386 */
387 if (!isfw_read) {
388 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
389 "Write H2C reg BOX[%d] fail,Fw don't read.\n",
390 boxnum);
391 break;
392 }
393 /* 4. Fill the H2C cmd into box */
394 memset(boxcontent, 0, sizeof(boxcontent));
395 memset(boxextcontent, 0, sizeof(boxextcontent));
396 boxcontent[0] = element_id;
397 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
398 "Write element_id box_reg(%4x) = %2x\n",
399 box_reg, element_id);
400
401 switch (cmd_len) {
402 case 1:
403 case 2:
404 case 3:
405 /*boxcontent[0] &= ~(BIT(7));*/
406 memcpy((u8 *)(boxcontent) + 1,
407 cmdbuffer + buf_index, cmd_len);
408
409 for (idx = 0; idx < 4; idx++) {
410 rtl_write_byte(rtlpriv, box_reg + idx,
411 boxcontent[idx]);
412 }
413 break;
414 case 4:
415 case 5:
416 case 6:
417 case 7:
418 /*boxcontent[0] |= (BIT(7));*/
419 memcpy((u8 *)(boxextcontent),
420 cmdbuffer + buf_index+3, cmd_len-3);
421 memcpy((u8 *)(boxcontent) + 1,
422 cmdbuffer + buf_index, 3);
423
424 for (idx = 0; idx < 4; idx++) {
425 rtl_write_byte(rtlpriv, box_extreg + idx,
426 boxextcontent[idx]);
427 }
428
429 for (idx = 0; idx < 4; idx++) {
430 rtl_write_byte(rtlpriv, box_reg + idx,
431 boxcontent[idx]);
432 }
433 break;
434 default:
435 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
Joe Perchesad574882016-09-23 11:27:19 -0700436 "switch case %#x not processed\n", cmd_len);
Larry Fingerb1a3bfc2014-09-26 16:40:23 -0500437 break;
438 }
439
440 bwrite_sucess = true;
441
442 rtlhal->last_hmeboxnum = boxnum + 1;
443 if (rtlhal->last_hmeboxnum == 4)
444 rtlhal->last_hmeboxnum = 0;
445
446 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
447 "pHalData->last_hmeboxnum = %d\n",
448 rtlhal->last_hmeboxnum);
449 }
450
451 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
452 rtlhal->h2c_setinprogress = false;
453 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
454
455 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "go out\n");
456}
457
458void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw,
459 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
460{
461 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
462 u32 tmp_cmdbuf[2];
463
464 if (!rtlhal->fw_ready) {
465 RT_ASSERT(false,
466 "return H2C cmd because of Fw download fail!!!\n");
467 return;
468 }
469
470 memset(tmp_cmdbuf, 0, 8);
471 memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
472 _rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
473}
474
475void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw)
476{
477 u8 u1b_tmp;
478 struct rtl_priv *rtlpriv = rtl_priv(hw);
479
480 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
481 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0))));
482
483 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
484 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
485
486 udelay(50);
487
488 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
489 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0)));
490
491 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
492 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
493
494 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD ,
495 " _8051Reset92E(): 8051 reset success .\n");
496}
497
498void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
499{
500 struct rtl_priv *rtlpriv = rtl_priv(hw);
501 u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 };
502 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
503 u8 rlbm , power_state = 0;
504
505 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , "FW LPS mode = %d\n", mode);
506
507 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
508 rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/
509 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
510 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
511 (rtlpriv->mac80211.p2p) ?
512 ppsc->smart_ps : 1);
513 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
514 ppsc->reg_max_lps_awakeintvl);
515 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
516 if (mode == FW_PS_ACTIVE_MODE)
517 power_state |= FW_PWR_STATE_ACTIVE;
518 else
519 power_state |= FW_PWR_STATE_RF_OFF;
520 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
521
522 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
523 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
524 u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
525 rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
526 u1_h2c_set_pwrmode);
527}
528
529void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
530{
531 u8 parm[3] = { 0 , 0 , 0 };
532 /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
533 * bit1=0-->update Media Status to MACID
534 * bit1=1-->update Media Status from MACID to MACID_End
535 * parm[1]: MACID, if this is INFRA_STA, MacID = 0
536 * parm[2]: MACID_End
537 */
538
539 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
540 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
541
542 rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm);
543}
544
Larry Fingerb1a3bfc2014-09-26 16:40:23 -0500545#define BEACON_PG 0 /* ->1 */
546#define PSPOLL_PG 2
547#define NULL_PG 3
548#define PROBERSP_PG 4 /* ->5 */
549
550#define TOTAL_RESERVED_PKT_LEN 768
551
552static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
553 /* page 0 beacon */
554 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
555 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
556 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
559 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
560 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
561 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
562 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
563 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
567 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
568 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
569 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
570
571 /* page 1 beacon */
572 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588
589 /* page 2 ps-poll */
590 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
591 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606
607 /* page 3 null */
608 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
609 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
610 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
620 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624
625 /* page 4 probe_resp */
626 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
627 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
628 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
629 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
630 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
631 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
632 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
633 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
634 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
635 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
636 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
640 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642
643 /* page 5 probe_resp */
644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
660};
661
662void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
663{
664 struct rtl_priv *rtlpriv = rtl_priv(hw);
665 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
666 struct sk_buff *skb = NULL;
Larry Fingera6cafd22017-09-14 13:17:44 -0500667 bool rtstatus;
Larry Fingerb1a3bfc2014-09-26 16:40:23 -0500668 u32 totalpacketlen;
Larry Fingerb1a3bfc2014-09-26 16:40:23 -0500669 u8 u1rsvdpageloc[5] = { 0 };
670 bool b_dlok = false;
671
672 u8 *beacon;
673 u8 *p_pspoll;
674 u8 *nullfunc;
675 u8 *p_probersp;
676 /*---------------------------------------------------------
677 * (1) beacon
678 *---------------------------------------------------------
679 */
680 beacon = &reserved_page_packet[BEACON_PG * 128];
681 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
682 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
683
684 /*-------------------------------------------------------
685 * (2) ps-poll
686 *--------------------------------------------------------
687 */
688 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
689 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
690 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
691 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
692
693 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
694
695 /*--------------------------------------------------------
696 * (3) null data
697 *---------------------------------------------------------
698 */
699 nullfunc = &reserved_page_packet[NULL_PG * 128];
700 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
701 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
702 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
703
704 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
705
706 /*---------------------------------------------------------
707 * (4) probe response
708 *----------------------------------------------------------
709 */
710 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
711 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
712 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
713 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
714
715 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
716
717 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
718
719 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
720 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
721 &reserved_page_packet[0], totalpacketlen);
722 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
723 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
724 u1rsvdpageloc, 3);
725
726 skb = dev_alloc_skb(totalpacketlen);
727 memcpy((u8 *)skb_put(skb, totalpacketlen),
728 &reserved_page_packet, totalpacketlen);
729
Larry Fingera6cafd22017-09-14 13:17:44 -0500730 rtstatus = rtl_cmd_send_packet(hw, skb);
731 if (rtstatus)
732 b_dlok = true;
Larry Fingerb1a3bfc2014-09-26 16:40:23 -0500733
734 if (b_dlok) {
735 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD ,
736 "Set RSVD page location to Fw.\n");
737 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
738 "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
739 rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE,
740 sizeof(u1rsvdpageloc), u1rsvdpageloc);
741 } else {
742 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
743 "Set RSVD page location to Fw FAIL!!!!!!.\n");
744 }
745}
746
747/*Shoud check FW support p2p or not.*/
748static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
749{
750 u8 u1_ctwindow_period[1] = {ctwindow};
751
752 rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
753}
754
755void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
756{
757 struct rtl_priv *rtlpriv = rtl_priv(hw);
758 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
759 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
760 struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
761 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
762 u8 i;
763 u16 ctwindow;
764 u32 start_time, tsf_low;
765
766 switch (p2p_ps_state) {
767 case P2P_PS_DISABLE:
768 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_DISABLE\n");
769 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
770 break;
771 case P2P_PS_ENABLE:
772 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_ENABLE\n");
773 /* update CTWindow value. */
774 if (p2pinfo->ctwindow > 0) {
775 p2p_ps_offload->ctwindow_en = 1;
776 ctwindow = p2pinfo->ctwindow;
777 rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow);
778 }
779 /* hw only support 2 set of NoA */
780 for (i = 0 ; i < p2pinfo->noa_num ; i++) {
781 /* To control the register setting for which NOA*/
782 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
783 if (i == 0)
784 p2p_ps_offload->noa0_en = 1;
785 else
786 p2p_ps_offload->noa1_en = 1;
787 /* config P2P NoA Descriptor Register */
788 rtl_write_dword(rtlpriv, 0x5E0,
789 p2pinfo->noa_duration[i]);
790 rtl_write_dword(rtlpriv, 0x5E4,
791 p2pinfo->noa_interval[i]);
792
793 /*Get Current TSF value */
794 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
795
796 start_time = p2pinfo->noa_start_time[i];
797 if (p2pinfo->noa_count_type[i] != 1) {
798 while (start_time <= (tsf_low + (50 * 1024))) {
799 start_time += p2pinfo->noa_interval[i];
800 if (p2pinfo->noa_count_type[i] != 255)
801 p2pinfo->noa_count_type[i]--;
802 }
803 }
804 rtl_write_dword(rtlpriv, 0x5E8, start_time);
805 rtl_write_dword(rtlpriv, 0x5EC,
806 p2pinfo->noa_count_type[i]);
807 }
808 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
809 /* rst p2p circuit */
810 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
811 p2p_ps_offload->offload_en = 1;
812
813 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
814 p2p_ps_offload->role = 1;
815 p2p_ps_offload->allstasleep = 0;
816 } else {
817 p2p_ps_offload->role = 0;
818 }
819 p2p_ps_offload->discovery = 0;
820 }
821 break;
822 case P2P_PS_SCAN:
823 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN\n");
824 p2p_ps_offload->discovery = 1;
825 break;
826 case P2P_PS_SCAN_DONE:
827 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN_DONE\n");
828 p2p_ps_offload->discovery = 0;
829 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
830 break;
831 default:
832 break;
833 }
834 rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1,
835 (u8 *)p2p_ps_offload);
836}
837
838static void _rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw,
839 u8 *cmd_buf, u8 cmd_len)
840{
841 u8 rate = cmd_buf[0] & 0x3F;
842 bool collision_state = cmd_buf[3] & BIT(0);
843
844 rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state);
845}
846
847static void _rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
848 u8 c2h_cmd_len, u8 *tmp_buf)
849{
850 struct rtl_priv *rtlpriv = rtl_priv(hw);
851
852 switch (c2h_cmd_id) {
853 case C2H_8192E_DBG:
854 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
855 "[C2H], C2H_8723BE_DBG!!\n");
856 break;
857 case C2H_8192E_TXBF:
858 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
859 "[C2H], C2H_8192E_TXBF!!\n");
860 break;
861 case C2H_8192E_TX_REPORT:
862 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE ,
863 "[C2H], C2H_8723BE_TX_REPORT!\n");
864 break;
865 case C2H_8192E_BT_INFO:
866 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
867 "[C2H], C2H_8723BE_BT_INFO!!\n");
868 rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
869 c2h_cmd_len);
870 break;
871 case C2H_8192E_BT_MP:
872 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
873 "[C2H], C2H_8723BE_BT_MP!!\n");
874 break;
875 case C2H_8192E_RA_RPT:
876 _rtl92ee_c2h_ra_report_handler(hw, tmp_buf, c2h_cmd_len);
877 break;
878 default:
879 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
Masanari Iidaad480132015-04-27 23:14:58 +0900880 "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id);
Larry Fingerb1a3bfc2014-09-26 16:40:23 -0500881 break;
882 }
883}
884
885void rtl92ee_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
886{
887 struct rtl_priv *rtlpriv = rtl_priv(hw);
888 u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
889 u8 *tmp_buf = NULL;
890
891 c2h_cmd_id = buffer[0];
892 c2h_cmd_seq = buffer[1];
893 c2h_cmd_len = len - 2;
894 tmp_buf = buffer + 2;
895
896 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
897 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
898 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
899
900 RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
901 "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
902
903 _rtl92ee_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
904}