]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
[mirror_ubuntu-artful-kernel.git] / drivers / net / wireless / rtlwifi / rtl8192c / fw_common.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 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17 *
18 * The full GNU General Public License is included in this distribution in the
19 * file called LICENSE.
20 *
21 * Contact Information:
22 * wlanfae <wlanfae@realtek.com>
23 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24 * Hsinchu 300, Taiwan.
25 *
26 * Larry Finger <Larry.Finger@lwfinger.net>
27 *
28 *****************************************************************************/
29
30 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31
32 #include <linux/firmware.h>
33 #include <linux/export.h>
34 #include "../wifi.h"
35 #include "../pci.h"
36 #include "../base.h"
37 #include "../rtl8192ce/reg.h"
38 #include "../rtl8192ce/def.h"
39 #include "fw_common.h"
40
41 static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
42 {
43 struct rtl_priv *rtlpriv = rtl_priv(hw);
44 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
45
46 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) {
47 u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
48 if (enable)
49 value32 |= MCUFWDL_EN;
50 else
51 value32 &= ~MCUFWDL_EN;
52 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
53 } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) {
54 u8 tmp;
55 if (enable) {
56
57 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
58 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1,
59 tmp | 0x04);
60
61 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
62 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
63
64 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
65 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
66 } else {
67
68 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
69 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
70
71 rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
72 }
73 }
74 }
75
76 static void rtl_block_fw_writeN(struct ieee80211_hw *hw, const u8 *buffer,
77 u32 size)
78 {
79 struct rtl_priv *rtlpriv = rtl_priv(hw);
80 u32 blockSize = REALTEK_USB_VENQT_MAX_BUF_SIZE - 20;
81 u8 *bufferPtr = (u8 *) buffer;
82 u32 i, offset, blockCount, remainSize;
83
84 blockCount = size / blockSize;
85 remainSize = size % blockSize;
86
87 for (i = 0; i < blockCount; i++) {
88 offset = i * blockSize;
89 rtlpriv->io.writeN_sync(rtlpriv,
90 (FW_8192C_START_ADDRESS + offset),
91 (void *)(bufferPtr + offset),
92 blockSize);
93 }
94
95 if (remainSize) {
96 offset = blockCount * blockSize;
97 rtlpriv->io.writeN_sync(rtlpriv,
98 (FW_8192C_START_ADDRESS + offset),
99 (void *)(bufferPtr + offset),
100 remainSize);
101 }
102 }
103
104 static void _rtl92c_fw_block_write(struct ieee80211_hw *hw,
105 const u8 *buffer, u32 size)
106 {
107 struct rtl_priv *rtlpriv = rtl_priv(hw);
108 u32 blockSize = sizeof(u32);
109 u8 *bufferPtr = (u8 *) buffer;
110 u32 *pu4BytePtr = (u32 *) buffer;
111 u32 i, offset, blockCount, remainSize;
112 u32 data;
113
114 if (rtlpriv->io.writeN_sync) {
115 rtl_block_fw_writeN(hw, buffer, size);
116 return;
117 }
118 blockCount = size / blockSize;
119 remainSize = size % blockSize;
120 if (remainSize) {
121 /* the last word is < 4 bytes - pad it with zeros */
122 for (i = 0; i < 4 - remainSize; i++)
123 *(bufferPtr + size + i) = 0;
124 blockCount++;
125 }
126
127 for (i = 0; i < blockCount; i++) {
128 offset = i * blockSize;
129 /* for big-endian platforms, the firmware data need to be byte
130 * swapped as it was read as a byte string and will be written
131 * as 32-bit dwords and byte swapped when written
132 */
133 data = le32_to_cpu(*(__le32 *)(pu4BytePtr + i));
134 rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
135 data);
136 }
137 }
138
139 static void _rtl92c_fw_page_write(struct ieee80211_hw *hw,
140 u32 page, const u8 *buffer, u32 size)
141 {
142 struct rtl_priv *rtlpriv = rtl_priv(hw);
143 u8 value8;
144 u8 u8page = (u8) (page & 0x07);
145
146 value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
147
148 rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
149 _rtl92c_fw_block_write(hw, buffer, size);
150 }
151
152 static void _rtl92c_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
153 {
154 u32 fwlen = *pfwlen;
155 u8 remain = (u8) (fwlen % 4);
156
157 remain = (remain == 0) ? 0 : (4 - remain);
158
159 while (remain > 0) {
160 pfwbuf[fwlen] = 0;
161 fwlen++;
162 remain--;
163 }
164
165 *pfwlen = fwlen;
166 }
167
168 static void _rtl92c_write_fw(struct ieee80211_hw *hw,
169 enum version_8192c version, u8 *buffer, u32 size)
170 {
171 struct rtl_priv *rtlpriv = rtl_priv(hw);
172 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
173 u8 *bufferPtr = (u8 *) buffer;
174
175 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, ("FW size is %d bytes,\n", size));
176
177 if (IS_CHIP_VER_B(version)) {
178 u32 pageNums, remainSize;
179 u32 page, offset;
180
181 if (IS_HARDWARE_TYPE_8192CE(rtlhal))
182 _rtl92c_fill_dummy(bufferPtr, &size);
183
184 pageNums = size / FW_8192C_PAGE_SIZE;
185 remainSize = size % FW_8192C_PAGE_SIZE;
186
187 if (pageNums > 4) {
188 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
189 ("Page numbers should not greater then 4\n"));
190 }
191
192 for (page = 0; page < pageNums; page++) {
193 offset = page * FW_8192C_PAGE_SIZE;
194 _rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
195 FW_8192C_PAGE_SIZE);
196 }
197
198 if (remainSize) {
199 offset = pageNums * FW_8192C_PAGE_SIZE;
200 page = pageNums;
201 _rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
202 remainSize);
203 }
204 } else {
205 _rtl92c_fw_block_write(hw, buffer, size);
206 }
207 }
208
209 static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw)
210 {
211 struct rtl_priv *rtlpriv = rtl_priv(hw);
212 u32 counter = 0;
213 u32 value32;
214
215 do {
216 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
217 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
218 (!(value32 & FWDL_ChkSum_rpt)));
219
220 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
221 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
222 ("chksum report faill ! REG_MCUFWDL:0x%08x .\n",
223 value32));
224 return -EIO;
225 }
226
227 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
228 ("Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32));
229
230 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
231 value32 |= MCUFWDL_RDY;
232 value32 &= ~WINTINI_RDY;
233 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
234
235 counter = 0;
236
237 do {
238 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
239 if (value32 & WINTINI_RDY) {
240 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
241 ("Polling FW ready success!!"
242 " REG_MCUFWDL:0x%08x .\n",
243 value32));
244 return 0;
245 }
246
247 mdelay(FW_8192C_POLLING_DELAY);
248
249 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
250
251 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
252 ("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32));
253 return -EIO;
254 }
255
256 int rtl92c_download_fw(struct ieee80211_hw *hw)
257 {
258 struct rtl_priv *rtlpriv = rtl_priv(hw);
259 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
260 struct rtl92c_firmware_header *pfwheader;
261 u8 *pfwdata;
262 u32 fwsize;
263 enum version_8192c version = rtlhal->version;
264
265 pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
266 if (!rtlhal->pfirmware)
267 return 1;
268
269 pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
270 pfwdata = (u8 *) rtlhal->pfirmware;
271 fwsize = rtlhal->fwsize;
272
273 if (IS_FW_HEADER_EXIST(pfwheader)) {
274 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
275 ("Firmware Version(%d), Signature(%#x),Size(%d)\n",
276 le16_to_cpu(pfwheader->version),
277 le16_to_cpu(pfwheader->signature),
278 (uint)sizeof(struct rtl92c_firmware_header)));
279
280 pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header);
281 fwsize = fwsize - sizeof(struct rtl92c_firmware_header);
282 }
283
284 _rtl92c_enable_fw_download(hw, true);
285 _rtl92c_write_fw(hw, version, pfwdata, fwsize);
286 _rtl92c_enable_fw_download(hw, false);
287
288 if (_rtl92c_fw_free_to_go(hw)) {
289 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
290 ("Firmware is not ready to run!\n"));
291 } else {
292 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
293 ("Firmware is ready to run!\n"));
294 }
295
296 return 0;
297 }
298 EXPORT_SYMBOL(rtl92c_download_fw);
299
300 static bool _rtl92c_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
301 {
302 struct rtl_priv *rtlpriv = rtl_priv(hw);
303 u8 val_hmetfr, val_mcutst_1;
304 bool result = false;
305
306 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
307 val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
308
309 if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
310 result = true;
311 return result;
312 }
313
314 static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw,
315 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
316 {
317 struct rtl_priv *rtlpriv = rtl_priv(hw);
318 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
319 u8 boxnum;
320 u16 box_reg = 0, box_extreg = 0;
321 u8 u1b_tmp;
322 bool isfw_read = false;
323 bool bwrite_sucess = false;
324 u8 wait_h2c_limmit = 100;
325 u8 wait_writeh2c_limmit = 100;
326 u8 boxcontent[4], boxextcontent[2];
327 u32 h2c_waitcounter = 0;
328 unsigned long flag;
329 u8 idx;
330
331 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("come in\n"));
332
333 while (true) {
334 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
335 if (rtlhal->h2c_setinprogress) {
336 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
337 ("H2C set in progress! Wait to set.."
338 "element_id(%d).\n", element_id));
339
340 while (rtlhal->h2c_setinprogress) {
341 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
342 flag);
343 h2c_waitcounter++;
344 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
345 ("Wait 100 us (%d times)...\n",
346 h2c_waitcounter));
347 udelay(100);
348
349 if (h2c_waitcounter > 1000)
350 return;
351 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
352 flag);
353 }
354 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
355 } else {
356 rtlhal->h2c_setinprogress = true;
357 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
358 break;
359 }
360 }
361
362 while (!bwrite_sucess) {
363 wait_writeh2c_limmit--;
364 if (wait_writeh2c_limmit == 0) {
365 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
366 ("Write H2C fail because no trigger "
367 "for FW INT!\n"));
368 break;
369 }
370
371 boxnum = rtlhal->last_hmeboxnum;
372 switch (boxnum) {
373 case 0:
374 box_reg = REG_HMEBOX_0;
375 box_extreg = REG_HMEBOX_EXT_0;
376 break;
377 case 1:
378 box_reg = REG_HMEBOX_1;
379 box_extreg = REG_HMEBOX_EXT_1;
380 break;
381 case 2:
382 box_reg = REG_HMEBOX_2;
383 box_extreg = REG_HMEBOX_EXT_2;
384 break;
385 case 3:
386 box_reg = REG_HMEBOX_3;
387 box_extreg = REG_HMEBOX_EXT_3;
388 break;
389 default:
390 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
391 ("switch case not process\n"));
392 break;
393 }
394
395 isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
396 while (!isfw_read) {
397
398 wait_h2c_limmit--;
399 if (wait_h2c_limmit == 0) {
400 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
401 ("Wating too long for FW read "
402 "clear HMEBox(%d)!\n", boxnum));
403 break;
404 }
405
406 udelay(10);
407
408 isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
409 u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
410 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
411 ("Wating for FW read clear HMEBox(%d)!!! "
412 "0x1BF = %2x\n", boxnum, u1b_tmp));
413 }
414
415 if (!isfw_read) {
416 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
417 ("Write H2C register BOX[%d] fail!!!!! "
418 "Fw do not read.\n", boxnum));
419 break;
420 }
421
422 memset(boxcontent, 0, sizeof(boxcontent));
423 memset(boxextcontent, 0, sizeof(boxextcontent));
424 boxcontent[0] = element_id;
425 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
426 ("Write element_id box_reg(%4x) = %2x\n",
427 box_reg, element_id));
428
429 switch (cmd_len) {
430 case 1:
431 boxcontent[0] &= ~(BIT(7));
432 memcpy((u8 *) (boxcontent) + 1,
433 p_cmdbuffer, 1);
434
435 for (idx = 0; idx < 4; idx++) {
436 rtl_write_byte(rtlpriv, box_reg + idx,
437 boxcontent[idx]);
438 }
439 break;
440 case 2:
441 boxcontent[0] &= ~(BIT(7));
442 memcpy((u8 *) (boxcontent) + 1,
443 p_cmdbuffer, 2);
444
445 for (idx = 0; idx < 4; idx++) {
446 rtl_write_byte(rtlpriv, box_reg + idx,
447 boxcontent[idx]);
448 }
449 break;
450 case 3:
451 boxcontent[0] &= ~(BIT(7));
452 memcpy((u8 *) (boxcontent) + 1,
453 p_cmdbuffer, 3);
454
455 for (idx = 0; idx < 4; idx++) {
456 rtl_write_byte(rtlpriv, box_reg + idx,
457 boxcontent[idx]);
458 }
459 break;
460 case 4:
461 boxcontent[0] |= (BIT(7));
462 memcpy((u8 *) (boxextcontent),
463 p_cmdbuffer, 2);
464 memcpy((u8 *) (boxcontent) + 1,
465 p_cmdbuffer + 2, 2);
466
467 for (idx = 0; idx < 2; idx++) {
468 rtl_write_byte(rtlpriv, box_extreg + idx,
469 boxextcontent[idx]);
470 }
471
472 for (idx = 0; idx < 4; idx++) {
473 rtl_write_byte(rtlpriv, box_reg + idx,
474 boxcontent[idx]);
475 }
476 break;
477 case 5:
478 boxcontent[0] |= (BIT(7));
479 memcpy((u8 *) (boxextcontent),
480 p_cmdbuffer, 2);
481 memcpy((u8 *) (boxcontent) + 1,
482 p_cmdbuffer + 2, 3);
483
484 for (idx = 0; idx < 2; idx++) {
485 rtl_write_byte(rtlpriv, box_extreg + idx,
486 boxextcontent[idx]);
487 }
488
489 for (idx = 0; idx < 4; idx++) {
490 rtl_write_byte(rtlpriv, box_reg + idx,
491 boxcontent[idx]);
492 }
493 break;
494 default:
495 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
496 ("switch case not process\n"));
497 break;
498 }
499
500 bwrite_sucess = true;
501
502 rtlhal->last_hmeboxnum = boxnum + 1;
503 if (rtlhal->last_hmeboxnum == 4)
504 rtlhal->last_hmeboxnum = 0;
505
506 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
507 ("pHalData->last_hmeboxnum = %d\n",
508 rtlhal->last_hmeboxnum));
509 }
510
511 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
512 rtlhal->h2c_setinprogress = false;
513 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
514
515 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("go out\n"));
516 }
517
518 void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
519 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
520 {
521 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
522 u32 tmp_cmdbuf[2];
523
524 if (rtlhal->fw_ready == false) {
525 RT_ASSERT(false, ("return H2C cmd because of Fw "
526 "download fail!!!\n"));
527 return;
528 }
529
530 memset(tmp_cmdbuf, 0, 8);
531 memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
532 _rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
533
534 return;
535 }
536 EXPORT_SYMBOL(rtl92c_fill_h2c_cmd);
537
538 void rtl92c_firmware_selfreset(struct ieee80211_hw *hw)
539 {
540 u8 u1b_tmp;
541 u8 delay = 100;
542 struct rtl_priv *rtlpriv = rtl_priv(hw);
543
544 rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
545 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
546
547 while (u1b_tmp & BIT(2)) {
548 delay--;
549 if (delay == 0) {
550 RT_ASSERT(false, ("8051 reset fail.\n"));
551 break;
552 }
553 udelay(50);
554 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
555 }
556 }
557 EXPORT_SYMBOL(rtl92c_firmware_selfreset);
558
559 void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
560 {
561 struct rtl_priv *rtlpriv = rtl_priv(hw);
562 u8 u1_h2c_set_pwrmode[3] = {0};
563 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
564
565 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("FW LPS mode = %d\n", mode));
566
567 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
568 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1);
569 SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
570 ppsc->reg_max_lps_awakeintvl);
571
572 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
573 "rtl92c_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
574 u1_h2c_set_pwrmode, 3);
575 rtl92c_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
576
577 }
578 EXPORT_SYMBOL(rtl92c_set_fw_pwrmode_cmd);
579
580 static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
581 struct sk_buff *skb)
582 {
583 struct rtl_priv *rtlpriv = rtl_priv(hw);
584 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
585 struct rtl8192_tx_ring *ring;
586 struct rtl_tx_desc *pdesc;
587 unsigned long flags;
588 struct sk_buff *pskb = NULL;
589
590 ring = &rtlpci->tx_ring[BEACON_QUEUE];
591
592 pskb = __skb_dequeue(&ring->queue);
593 if (pskb)
594 kfree_skb(pskb);
595
596 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
597
598 pdesc = &ring->desc[0];
599
600 rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
601
602 __skb_queue_tail(&ring->queue, skb);
603
604 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
605
606 rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
607
608 return true;
609 }
610
611 #define BEACON_PG 0 /*->1*/
612 #define PSPOLL_PG 2
613 #define NULL_PG 3
614 #define PROBERSP_PG 4 /*->5*/
615
616 #define TOTAL_RESERVED_PKT_LEN 768
617
618 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
619 /* page 0 beacon */
620 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
621 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
622 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
625 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
626 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
627 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
628 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
629 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
630 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
634 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636
637 /* page 1 beacon */
638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654
655 /* page 2 ps-poll */
656 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
657 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
667 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
668 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
669 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
670 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
672
673 /* page 3 null */
674 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
675 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
676 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
677 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
679 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
680 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
687 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
688 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690
691 /* page 4 probe_resp */
692 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
693 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
694 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
695 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
696 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
697 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
698 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
699 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
700 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
701 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
702 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
703 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
704 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
705 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
706 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
707 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
708
709 /* page 5 probe_resp */
710 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
711 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
712 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
713 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
714 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
715 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
716 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
717 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
718 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
719 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
720 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
721 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
722 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
723 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
724 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
725 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
726 };
727
728 void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
729 {
730 struct rtl_priv *rtlpriv = rtl_priv(hw);
731 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
732 struct sk_buff *skb = NULL;
733
734 u32 totalpacketlen;
735 bool rtstatus;
736 u8 u1RsvdPageLoc[3] = {0};
737 bool dlok = false;
738
739 u8 *beacon;
740 u8 *pspoll;
741 u8 *nullfunc;
742 u8 *probersp;
743 /*---------------------------------------------------------
744 (1) beacon
745 ---------------------------------------------------------*/
746 beacon = &reserved_page_packet[BEACON_PG * 128];
747 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
748 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
749
750 /*-------------------------------------------------------
751 (2) ps-poll
752 --------------------------------------------------------*/
753 pspoll = &reserved_page_packet[PSPOLL_PG * 128];
754 SET_80211_PS_POLL_AID(pspoll, (mac->assoc_id | 0xc000));
755 SET_80211_PS_POLL_BSSID(pspoll, mac->bssid);
756 SET_80211_PS_POLL_TA(pspoll, mac->mac_addr);
757
758 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
759
760 /*--------------------------------------------------------
761 (3) null data
762 ---------------------------------------------------------*/
763 nullfunc = &reserved_page_packet[NULL_PG * 128];
764 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
765 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
766 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
767
768 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
769
770 /*---------------------------------------------------------
771 (4) probe response
772 ----------------------------------------------------------*/
773 probersp = &reserved_page_packet[PROBERSP_PG * 128];
774 SET_80211_HDR_ADDRESS1(probersp, mac->bssid);
775 SET_80211_HDR_ADDRESS2(probersp, mac->mac_addr);
776 SET_80211_HDR_ADDRESS3(probersp, mac->bssid);
777
778 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
779
780 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
781
782 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
783 "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
784 &reserved_page_packet[0], totalpacketlen);
785 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
786 "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
787 u1RsvdPageLoc, 3);
788
789
790 skb = dev_alloc_skb(totalpacketlen);
791 memcpy((u8 *) skb_put(skb, totalpacketlen),
792 &reserved_page_packet, totalpacketlen);
793
794 rtstatus = _rtl92c_cmd_send_packet(hw, skb);
795
796 if (rtstatus)
797 dlok = true;
798
799 if (dlok) {
800 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
801 ("Set RSVD page location to Fw.\n"));
802 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
803 "H2C_RSVDPAGE:\n",
804 u1RsvdPageLoc, 3);
805 rtl92c_fill_h2c_cmd(hw, H2C_RSVDPAGE,
806 sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
807 } else
808 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
809 ("Set RSVD page location to Fw FAIL!!!!!!.\n"));
810 }
811 EXPORT_SYMBOL(rtl92c_set_fw_rsvdpagepkt);
812
813 void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
814 {
815 u8 u1_joinbssrpt_parm[1] = {0};
816
817 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
818
819 rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
820 }
821 EXPORT_SYMBOL(rtl92c_set_fw_joinbss_report_cmd);