]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/staging/rtl8192ee/rtl8192ee/fw.c
staging: rtl8192ee: Fix RT_TRACE #define and uses
[mirror_ubuntu-artful-kernel.git] / drivers / staging / rtl8192ee / rtl8192ee / fw.c
1 /******************************************************************************
2 *
3 * Copyright(c) 2009-2010 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 "dm.h"
33
34 static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable)
35 {
36 struct rtl_priv *rtlpriv = rtl_priv(hw);
37 u8 tmp;
38
39 if (enable) {
40 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05);
41
42 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
43 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
44 } else {
45
46 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
47 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
48 }
49 }
50
51 static 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
80 static 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
93 static 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
109 static 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(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(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 }
145
146 static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw)
147 {
148 struct rtl_priv *rtlpriv = rtl_priv(hw);
149 int err = -EIO;
150 u32 counter = 0;
151 u32 value32;
152
153 do {
154 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
155 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
156 (!(value32 & FWDL_ChkSum_rpt)));
157
158 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
159 RT_TRACE(COMP_ERR, DBG_EMERG,
160 "chksum report faill ! REG_MCUFWDL:0x%08x\n",
161 value32);
162 goto exit;
163 }
164
165 RT_TRACE(COMP_FW, DBG_TRACE,
166 "Checksum report OK ! REG_MCUFWDL:0x%08x\n", value32);
167
168 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
169 value32 |= MCUFWDL_RDY;
170 value32 &= ~WINTINI_RDY;
171 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
172
173 rtl92ee_firmware_selfreset(hw);
174 counter = 0;
175
176 do {
177 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
178 if (value32 & WINTINI_RDY) {
179 RT_TRACE(COMP_FW, DBG_LOUD,
180 "Polling FW ready success!! REG_MCUFWDL:0x%08x. count = %d\n",
181 value32, counter);
182 err = 0;
183 goto exit;
184 }
185
186 udelay(FW_8192C_POLLING_DELAY*10);
187
188 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
189
190 RT_TRACE(COMP_ERR, DBG_EMERG,
191 "Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n",
192 value32, counter);
193
194 exit:
195 return err;
196 }
197
198 int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw)
199 {
200 struct rtl_priv *rtlpriv = rtl_priv(hw);
201 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
202 struct rtl92c_firmware_header *pfwheader;
203 u8 *pfwdata;
204 u32 fwsize;
205 int err;
206 enum version_8192e version = rtlhal->version;
207
208 if (!rtlhal->pfirmware)
209 return 1;
210
211 pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
212 rtlhal->fw_version = pfwheader->version;
213 rtlhal->fw_subversion = pfwheader->subversion;
214 pfwdata = (u8 *) rtlhal->pfirmware;
215 fwsize = rtlhal->fwsize;
216 RT_TRACE(COMP_FW, DBG_DMESG, "normal Firmware SIZE %d\n", fwsize);
217
218 if (IS_FW_HEADER_EXIST(pfwheader)) {
219 RT_TRACE(COMP_FW, DBG_DMESG,
220 "Firmware Version(%d), Signature(%#x), Size(%d)\n",
221 pfwheader->version, pfwheader->signature,
222 (int)sizeof(struct rtl92c_firmware_header));
223
224 pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header);
225 fwsize = fwsize - sizeof(struct rtl92c_firmware_header);
226 } else {
227 RT_TRACE(COMP_FW, DBG_DMESG,
228 "Firmware no Header, Signature(%#x)\n",
229 pfwheader->signature);
230 }
231
232 if (rtlhal->b_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(COMP_ERR, DBG_EMERG,
245 "Firmware is not ready to run!\n");
246 } else {
247 RT_TRACE(COMP_FW, DBG_LOUD, "Firmware is ready to run!\n");
248 }
249
250 return 0;
251 }
252
253 static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
254 {
255 struct rtl_priv *rtlpriv = rtl_priv(hw);
256 u8 val_hmetfr;
257 bool result = false;
258
259 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
260 if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
261 result = true;
262 return result;
263 }
264
265 static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
266 u32 cmd_len, u8 *p_cmdbuffer)
267 {
268 struct rtl_priv *rtlpriv = rtl_priv(hw);
269 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
270 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
271 u8 boxnum;
272 u16 box_reg = 0, box_extreg = 0;
273 u8 u1b_tmp;
274 bool isfw_read = false;
275 u8 buf_index = 0;
276 bool bwrite_sucess = false;
277 u8 wait_h2c_limmit = 100;
278 u8 boxcontent[4], boxextcontent[4];
279 u32 h2c_waitcounter = 0;
280 unsigned long flag;
281 u8 idx;
282
283 if (ppsc->dot11_psmode != EACTIVE ||
284 ppsc->inactive_pwrstate == ERFOFF) {
285 RT_TRACE(COMP_CMD, DBG_LOUD,
286 "FillH2CCommand8192E(): Return because RF is off!!!\n");
287 return;
288 }
289
290 RT_TRACE(COMP_CMD, DBG_LOUD, "come in\n");
291
292 /* 1. Prevent race condition in setting H2C cmd.
293 * (copy from MgntActSet_RF_State().)
294 */
295 while (true) {
296 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
297 if (rtlhal->b_h2c_setinprogress) {
298 RT_TRACE(COMP_CMD, DBG_LOUD ,
299 "H2C set in progress! Wait to set..element_id(%d)\n",
300 element_id);
301
302 while (rtlhal->b_h2c_setinprogress) {
303 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
304 flag);
305 h2c_waitcounter++;
306 RT_TRACE(COMP_CMD, DBG_LOUD,
307 "Wait 100 us (%d times)...\n",
308 h2c_waitcounter);
309 udelay(100);
310
311 if (h2c_waitcounter > 1000)
312 return;
313 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
314 flag);
315 }
316 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
317 } else {
318 rtlhal->b_h2c_setinprogress = true;
319 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
320 break;
321 }
322 }
323
324 while (!bwrite_sucess) {
325 /* cosa remove this because never reach this. */
326 /*wait_writeh2c_limmit--;
327 if (wait_writeh2c_limmit == 0) {
328 RT_TRACE(COMP_ERR, DBG_EMERG,
329 "Write H2C fail because no trigger for FW INT!\n");
330 break;
331 }
332 */
333 /* 2. Find the last BOX number which has been writen. */
334 boxnum = rtlhal->last_hmeboxnum;
335 switch (boxnum) {
336 case 0:
337 box_reg = REG_HMEBOX_0;
338 box_extreg = REG_HMEBOX_EXT_0;
339 break;
340 case 1:
341 box_reg = REG_HMEBOX_1;
342 box_extreg = REG_HMEBOX_EXT_1;
343 break;
344 case 2:
345 box_reg = REG_HMEBOX_2;
346 box_extreg = REG_HMEBOX_EXT_2;
347 break;
348 case 3:
349 box_reg = REG_HMEBOX_3;
350 box_extreg = REG_HMEBOX_EXT_3;
351 break;
352 default:
353 RT_TRACE(COMP_ERR, DBG_EMERG,
354 "switch case not processed\n");
355 break;
356 }
357
358 /* 3. Check if the box content is empty. */
359 isfw_read = false;
360 u1b_tmp = rtl_read_byte(rtlpriv, REG_CR);
361
362 if (u1b_tmp != 0xea) {
363 isfw_read = true;
364 } else {
365 if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea ||
366 rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea)
367 rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff);
368 }
369
370 if (isfw_read == true) {
371 wait_h2c_limmit = 100;
372 isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
373 while (!isfw_read) {
374 wait_h2c_limmit--;
375 if (wait_h2c_limmit == 0) {
376 RT_TRACE(COMP_CMD, DBG_LOUD,
377 "Wating too long for FW read clear HMEBox(%d)!!!\n",
378 boxnum);
379 break;
380 }
381 udelay(10);
382 isfw_read = _rtl92ee_check_fw_read_last_h2c(hw,
383 boxnum);
384 u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
385 RT_TRACE(COMP_CMD, DBG_LOUD,
386 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
387 boxnum, u1b_tmp);
388 }
389 }
390
391 /* If Fw has not read the last
392 H2C cmd, break and give up this H2C. */
393 if (!isfw_read) {
394 RT_TRACE(COMP_CMD, DBG_LOUD ,
395 "Write H2C reg BOX[%d] fail, Fw doesn't read\n",
396 boxnum);
397 break;
398 }
399 /* 4. Fill the H2C cmd into box */
400 memset(boxcontent, 0, sizeof(boxcontent));
401 memset(boxextcontent, 0, sizeof(boxextcontent));
402 boxcontent[0] = element_id;
403 RT_TRACE(COMP_CMD, DBG_LOUD,
404 "Write element_id box_reg(%4x) = %2x\n",
405 box_reg, element_id);
406
407 switch (cmd_len) {
408 case 1:
409 case 2:
410 case 3:
411 /*boxcontent[0] &= ~(BIT(7));*/
412 memcpy((u8 *) (boxcontent) + 1,
413 p_cmdbuffer + buf_index, cmd_len);
414
415 for (idx = 0; idx < 4; idx++) {
416 rtl_write_byte(rtlpriv, box_reg + idx,
417 boxcontent[idx]);
418 }
419 break;
420 case 4:
421 case 5:
422 case 6:
423 case 7:
424 /*boxcontent[0] |= (BIT(7));*/
425 memcpy((u8 *) (boxextcontent),
426 p_cmdbuffer + buf_index+3, cmd_len-3);
427 memcpy((u8 *) (boxcontent) + 1,
428 p_cmdbuffer + buf_index, 3);
429
430 for (idx = 0; idx < 4; idx++) {
431 rtl_write_byte(rtlpriv, box_extreg + idx,
432 boxextcontent[idx]);
433 }
434
435 for (idx = 0; idx < 4; idx++) {
436 rtl_write_byte(rtlpriv, box_reg + idx,
437 boxcontent[idx]);
438 }
439 break;
440 default:
441 RT_TRACE(COMP_ERR, DBG_EMERG,
442 "switch case not processed\n");
443 break;
444 }
445
446 bwrite_sucess = true;
447
448 rtlhal->last_hmeboxnum = boxnum + 1;
449 if (rtlhal->last_hmeboxnum == 4)
450 rtlhal->last_hmeboxnum = 0;
451
452 RT_TRACE(COMP_CMD, DBG_LOUD, "pHalData->last_hmeboxnum = %d\n",
453 rtlhal->last_hmeboxnum);
454 }
455
456 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
457 rtlhal->b_h2c_setinprogress = false;
458 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
459
460 RT_TRACE(COMP_CMD, DBG_LOUD, "go out\n");
461 }
462
463 void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw,
464 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
465 {
466 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
467 u32 tmp_cmdbuf[2];
468
469 if (rtlhal->bfw_ready == false) {
470 RT_ASSERT(false, ("return H2C cmd because of Fw "
471 "download fail!!!\n"));
472 return;
473 }
474
475 memset(tmp_cmdbuf, 0, 8);
476 memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
477 _rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
478
479 return;
480 }
481
482 void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw)
483 {
484 u8 u1b_tmp;
485 struct rtl_priv *rtlpriv = rtl_priv(hw);
486
487 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
488 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0))));
489
490 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
491 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
492
493 udelay(50);
494
495 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
496 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0)));
497
498 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
499 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
500
501 RT_TRACE(COMP_INIT, DBG_LOUD,
502 " _8051Reset92E(): 8051 reset success\n");
503 }
504
505 void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
506 {
507 struct rtl_priv *rtlpriv = rtl_priv(hw);
508 u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 };
509 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
510 u8 rlbm , power_state = 0;
511 RT_TRACE(COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
512
513 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
514 rlbm = 0;/*YJ, temp, 120316. FW now not support RLBM = 2.*/
515 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
516 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
517 (rtlpriv->mac80211.p2p) ?
518 ppsc->smart_ps : 1);
519 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
520 ppsc->reg_max_lps_awakeintvl);
521 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
522 if (mode == FW_PS_ACTIVE_MODE)
523 power_state |= FW_PWR_STATE_ACTIVE;
524 else
525 power_state |= FW_PWR_STATE_RF_OFF;
526 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
527
528 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
529 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
530 u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
531 rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
532 u1_h2c_set_pwrmode);
533
534 }
535
536 void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
537 {
538 u8 parm[3] = { 0 , 0 , 0 };
539 /* parm[0]: bit0 = 0-->Disconnect, bit0 = 1-->Connect
540 * bit1 = 0-->update Media Status to MACID
541 * bit1 = 1-->update Media Status from MACID to MACID_End
542 * parm[1]: MACID, if this is INFRA_STA, MacID = 0
543 * parm[2]: MACID_End*/
544
545 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
546 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
547
548 rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm);
549 }
550
551 static bool _rtl92ee_cmd_send_packet(struct ieee80211_hw *hw,
552 struct sk_buff *skb)
553 {
554 struct rtl_priv *rtlpriv = rtl_priv(hw);
555 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
556 struct rtl8192_tx_ring *ring;
557 struct rtl_tx_desc *pdesc;
558 unsigned long flags;
559 struct sk_buff *pskb = NULL;
560
561 ring = &rtlpci->tx_ring[BEACON_QUEUE];
562
563 pskb = __skb_dequeue(&ring->queue);
564 if (pskb)
565 kfree_skb(pskb);
566
567 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
568 /*this is wrong, fill_tx_cmddesc needs update*/
569 pdesc = &ring->desc[0];
570
571 rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
572
573 __skb_queue_tail(&ring->queue, skb);
574
575 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
576
577 return true;
578 }
579
580 #define BEACON_PG 0 /* ->1 */
581 #define PSPOLL_PG 2
582 #define NULL_PG 3
583 #define PROBERSP_PG 4 /* ->5 */
584
585 #define TOTAL_RESERVED_PKT_LEN 768
586
587
588
589 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
590 /* page 0 beacon */
591 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
592 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
593 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
596 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
597 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
598 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
599 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
600 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
604 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
605 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
606 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
607
608 /* page 1 beacon */
609 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
621 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625
626 /* page 2 ps-poll */
627 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
628 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
629 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
639 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643
644 /* page 3 null */
645 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
646 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
647 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 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 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
657 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
660 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661
662 /* page 4 probe_resp */
663 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
664 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
665 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
666 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
667 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
668 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
669 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
670 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
671 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
672 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
673 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
675 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
676 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
677 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
679
680 /* page 5 probe_resp */
681 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
682 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
683 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
685 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
686 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
687 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
688 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
693 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
694 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
695 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
697 };
698
699
700
701 void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
702 {
703 struct rtl_priv *rtlpriv = rtl_priv(hw);
704 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
705 struct sk_buff *skb = NULL;
706
707 u32 totalpacketlen;
708 bool rtstatus;
709 u8 u1RsvdPageLoc[5] = { 0 };
710 bool b_dlok = false;
711
712 u8 *beacon;
713 u8 *p_pspoll;
714 u8 *nullfunc;
715 u8 *p_probersp;
716 /*---------------------------------------------------------
717 (1) beacon
718 ---------------------------------------------------------*/
719 beacon = &reserved_page_packet[BEACON_PG * 128];
720 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
721 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
722
723 /*-------------------------------------------------------
724 (2) ps-poll
725 --------------------------------------------------------*/
726 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
727 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
728 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
729 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
730
731 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
732
733 /*--------------------------------------------------------
734 (3) null data
735 ---------------------------------------------------------*/
736 nullfunc = &reserved_page_packet[NULL_PG * 128];
737 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
738 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
739 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
740
741 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
742
743 /*---------------------------------------------------------
744 (4) probe response
745 ----------------------------------------------------------*/
746 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
747 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
748 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
749 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
750
751 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
752
753 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
754
755 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
756 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
757 &reserved_page_packet[0], totalpacketlen);
758 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
759 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
760 u1RsvdPageLoc, 3);
761
762
763 skb = dev_alloc_skb(totalpacketlen);
764 memcpy((u8 *) skb_put(skb, totalpacketlen),
765 &reserved_page_packet, totalpacketlen);
766
767 rtstatus = _rtl92ee_cmd_send_packet(hw, skb);
768
769 if (rtstatus)
770 b_dlok = true;
771
772 if (b_dlok) {
773 RT_TRACE(COMP_POWER, DBG_LOUD,
774 "Set RSVD page location to Fw\n");
775 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
776 "H2C_RSVDPAGE:\n", u1RsvdPageLoc, 3);
777 rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE,
778 sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
779 } else
780 RT_TRACE(COMP_ERR, DBG_WARNING,
781 "Set RSVD page location to Fw FAIL!!!!!!\n");
782 }
783
784 /*Shoud check FW support p2p or not.*/
785 static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
786 {
787 u8 u1_ctwindow_period[1] = {ctwindow};
788
789 rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
790
791 }
792
793 void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
794 {
795 struct rtl_priv *rtlpriv = rtl_priv(hw);
796 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
797 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
798 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
799 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
800 u8 i;
801 u16 ctwindow;
802 u32 start_time, tsf_low;
803
804 switch (p2p_ps_state) {
805 case P2P_PS_DISABLE:
806 RT_TRACE(COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
807 memset(p2p_ps_offload, 0, 1);
808 break;
809 case P2P_PS_ENABLE:
810 RT_TRACE(COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
811 /* update CTWindow value. */
812 if (p2pinfo->ctwindow > 0) {
813 p2p_ps_offload->CTWindow_En = 1;
814 ctwindow = p2pinfo->ctwindow;
815 rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow);
816 }
817 /* hw only support 2 set of NoA */
818 for (i = 0 ; i < p2pinfo->noa_num ; i++) {
819 /* To control the register setting for which NOA*/
820 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
821 if (i == 0)
822 p2p_ps_offload->NoA0_En = 1;
823 else
824 p2p_ps_offload->NoA1_En = 1;
825 /* config P2P NoA Descriptor Register */
826 rtl_write_dword(rtlpriv, 0x5E0,
827 p2pinfo->noa_duration[i]);
828 rtl_write_dword(rtlpriv, 0x5E4,
829 p2pinfo->noa_interval[i]);
830
831 /*Get Current \14TSF value */
832 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
833
834 start_time = p2pinfo->noa_start_time[i];
835 if (p2pinfo->noa_count_type[i] != 1) {
836 while (start_time <= (tsf_low + (50 * 1024))) {
837 start_time += p2pinfo->noa_interval[i];
838 if (p2pinfo->noa_count_type[i] != 255)
839 p2pinfo->noa_count_type[i]--;
840 }
841 }
842 rtl_write_dword(rtlpriv, 0x5E8, start_time);
843 rtl_write_dword(rtlpriv, 0x5EC,
844 p2pinfo->noa_count_type[i]);
845 }
846 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
847 /* rst p2p circuit */
848 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
849 p2p_ps_offload->Offload_En = 1;
850
851 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
852 p2p_ps_offload->role = 1;
853 p2p_ps_offload->AllStaSleep = 0;
854 } else {
855 p2p_ps_offload->role = 0;
856 }
857 p2p_ps_offload->discovery = 0;
858 }
859 break;
860 case P2P_PS_SCAN:
861 RT_TRACE(COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
862 p2p_ps_offload->discovery = 1;
863 break;
864 case P2P_PS_SCAN_DONE:
865 RT_TRACE(COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
866 p2p_ps_offload->discovery = 0;
867 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
868 break;
869 default:
870 break;
871 }
872
873 rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1,
874 (u8 *)p2p_ps_offload);
875
876 }
877
878 static void _rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw,
879 u8 *cmd_buf, u8 cmd_len)
880 {
881 u8 rate = cmd_buf[0] & 0x3F;
882 bool collision_state = cmd_buf[3] & BIT(0);
883
884 rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state);
885 }
886
887 static void _rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
888 u8 c2h_cmd_len, u8 *tmp_buf)
889 {
890 struct rtl_priv *rtlpriv = rtl_priv(hw);
891
892 switch (c2h_cmd_id) {
893 case C2H_8192E_DBG:
894 RT_TRACE(COMP_FW, DBG_TRACE, "[C2H], C2H_8723BE_DBG!!\n");
895 break;
896 case C2H_8192E_TXBF:
897 RT_TRACE(COMP_FW, DBG_TRACE, "[C2H], C2H_8192E_TXBF!!\n");
898 break;
899 case C2H_8192E_TX_REPORT:
900 RT_TRACE(COMP_FW, DBG_TRACE, "[C2H], C2H_8723BE_TX_REPORT!\n");
901 break;
902 case C2H_8192E_BT_INFO:
903 RT_TRACE(COMP_FW, DBG_TRACE, "[C2H], C2H_8723BE_BT_INFO!!\n");
904 rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
905 c2h_cmd_len);
906 break;
907 case C2H_8192E_BT_MP:
908 RT_TRACE(COMP_FW, DBG_TRACE, "[C2H], C2H_8723BE_BT_MP!!\n");
909 break;
910 case C2H_8192E_RA_RPT:
911 _rtl92ee_c2h_ra_report_handler(hw, tmp_buf, c2h_cmd_len);
912 break;
913 default:
914 RT_TRACE(COMP_FW, DBG_TRACE,
915 "[C2H], Unkown packet!! CmdId(%#X)!\n", c2h_cmd_id);
916 break;
917 }
918 }
919
920 void rtl92ee_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
921 {
922 struct rtl_priv *rtlpriv = rtl_priv(hw);
923 u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
924 u8 *tmp_buf = NULL;
925
926 c2h_cmd_id = buffer[0];
927 c2h_cmd_seq = buffer[1];
928 c2h_cmd_len = len - 2;
929 tmp_buf = buffer + 2;
930
931 RT_TRACE(COMP_FW, DBG_TRACE,
932 "[C2H packet], c2hCmdId = 0x%x, c2hCmdSeq = 0x%x, c2hCmdLen =%d\n",
933 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
934
935 RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
936 "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
937
938 _rtl92ee_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
939 }