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