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