GNU Linux-libre 4.14.251-gnu1
[releases.git] / drivers / net / wireless / realtek / rtlwifi / rtl8192de / fw.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  * The full GNU General Public License is included in this distribution in the
15  * file called LICENSE.
16  *
17  * Contact Information:
18  * wlanfae <wlanfae@realtek.com>
19  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20  * Hsinchu 300, Taiwan.
21  *
22  * Larry Finger <Larry.Finger@lwfinger.net>
23  *
24  *****************************************************************************/
25
26 #include "../wifi.h"
27 #include "../pci.h"
28 #include "../base.h"
29 #include "../efuse.h"
30 #include "reg.h"
31 #include "def.h"
32 #include "fw.h"
33 #include "sw.h"
34
35 static bool _rtl92d_is_fw_downloaded(struct rtl_priv *rtlpriv)
36 {
37         return (rtl_read_dword(rtlpriv, REG_MCUFWDL) & MCUFWDL_RDY) ?
38                 true : false;
39 }
40
41 static void _rtl92d_enable_fw_download(struct ieee80211_hw *hw, bool enable)
42 {
43         struct rtl_priv *rtlpriv = rtl_priv(hw);
44         u8 tmp;
45
46         if (enable) {
47                 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
48                 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
49                 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
50                 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
51                 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
52                 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
53         } else {
54                 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
55                 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
56                 /* Reserved for fw extension.
57                  * 0x81[7] is used for mac0 status ,
58                  * so don't write this reg here
59                  * rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);*/
60         }
61 }
62
63 static void _rtl92d_write_fw(struct ieee80211_hw *hw,
64                              enum version_8192d version, u8 *buffer, u32 size)
65 {
66         struct rtl_priv *rtlpriv = rtl_priv(hw);
67         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
68         u8 *bufferptr = buffer;
69         u32 pagenums, remainsize;
70         u32 page, offset;
71
72         RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size);
73         if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE)
74                 rtl_fill_dummy(bufferptr, &size);
75         pagenums = size / FW_8192D_PAGE_SIZE;
76         remainsize = size % FW_8192D_PAGE_SIZE;
77         if (pagenums > 8)
78                 pr_err("Page numbers should not greater then 8\n");
79         for (page = 0; page < pagenums; page++) {
80                 offset = page * FW_8192D_PAGE_SIZE;
81                 rtl_fw_page_write(hw, page, (bufferptr + offset),
82                                   FW_8192D_PAGE_SIZE);
83         }
84         if (remainsize) {
85                 offset = pagenums * FW_8192D_PAGE_SIZE;
86                 page = pagenums;
87                 rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize);
88         }
89 }
90
91 static int _rtl92d_fw_free_to_go(struct ieee80211_hw *hw)
92 {
93         struct rtl_priv *rtlpriv = rtl_priv(hw);
94         u32 counter = 0;
95         u32 value32;
96
97         do {
98                 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
99         } while ((counter++ < FW_8192D_POLLING_TIMEOUT_COUNT) &&
100                  (!(value32 & FWDL_ChkSum_rpt)));
101         if (counter >= FW_8192D_POLLING_TIMEOUT_COUNT) {
102                 pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n",
103                        value32);
104                 return -EIO;
105         }
106         value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
107         value32 |= MCUFWDL_RDY;
108         rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
109         return 0;
110 }
111
112 void rtl92d_firmware_selfreset(struct ieee80211_hw *hw)
113 {
114         struct rtl_priv *rtlpriv = rtl_priv(hw);
115         u8 u1b_tmp;
116         u8 delay = 100;
117
118         /* Set (REG_HMETFR + 3) to  0x20 is reset 8051 */
119         rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
120         u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
121         while (u1b_tmp & BIT(2)) {
122                 delay--;
123                 if (delay == 0)
124                         break;
125                 udelay(50);
126                 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
127         }
128         WARN_ONCE((delay <= 0), "rtl8192de: 8051 reset failed!\n");
129         RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
130                  "=====> 8051 reset success (%d)\n", delay);
131 }
132
133 static int _rtl92d_fw_init(struct ieee80211_hw *hw)
134 {
135         struct rtl_priv *rtlpriv = rtl_priv(hw);
136         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
137         u32 counter;
138
139         RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, "FW already have download\n");
140         /* polling for FW ready */
141         counter = 0;
142         do {
143                 if (rtlhal->interfaceindex == 0) {
144                         if (rtl_read_byte(rtlpriv, FW_MAC0_READY) &
145                             MAC0_READY) {
146                                 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
147                                          "Polling FW ready success!! REG_MCUFWDL: 0x%x\n",
148                                          rtl_read_byte(rtlpriv,
149                                                        FW_MAC0_READY));
150                                 return 0;
151                         }
152                         udelay(5);
153                 } else {
154                         if (rtl_read_byte(rtlpriv, FW_MAC1_READY) &
155                             MAC1_READY) {
156                                 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
157                                          "Polling FW ready success!! REG_MCUFWDL: 0x%x\n",
158                                          rtl_read_byte(rtlpriv,
159                                                        FW_MAC1_READY));
160                                 return 0;
161                         }
162                         udelay(5);
163                 }
164         } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
165
166         if (rtlhal->interfaceindex == 0) {
167                 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
168                          "Polling FW ready fail!! MAC0 FW init not ready: 0x%x\n",
169                          rtl_read_byte(rtlpriv, FW_MAC0_READY));
170         } else {
171                 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
172                          "Polling FW ready fail!! MAC1 FW init not ready: 0x%x\n",
173                          rtl_read_byte(rtlpriv, FW_MAC1_READY));
174         }
175         RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
176                  "Polling FW ready fail!! REG_MCUFWDL:0x%08x\n",
177                  rtl_read_dword(rtlpriv, REG_MCUFWDL));
178         return -1;
179 }
180
181 int rtl92d_download_fw(struct ieee80211_hw *hw)
182 {
183         struct rtl_priv *rtlpriv = rtl_priv(hw);
184         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
185         u8 *pfwheader;
186         u8 *pfwdata;
187         u32 fwsize;
188         int err;
189         enum version_8192d version = rtlhal->version;
190         u8 value;
191         u32 count;
192         bool fw_downloaded = false, fwdl_in_process = false;
193         unsigned long flags;
194
195         if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
196                 return 1;
197         fwsize = rtlhal->fwsize;
198         pfwheader = rtlhal->pfirmware;
199         pfwdata = rtlhal->pfirmware;
200         rtlhal->fw_version = (u16) GET_FIRMWARE_HDR_VERSION(pfwheader);
201         rtlhal->fw_subversion = (u16) GET_FIRMWARE_HDR_SUB_VER(pfwheader);
202         RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
203                  "FirmwareVersion(%d), FirmwareSubVersion(%d), Signature(%#x)\n",
204                  rtlhal->fw_version, rtlhal->fw_subversion,
205                  GET_FIRMWARE_HDR_SIGNATURE(pfwheader));
206         if (IS_FW_HEADER_EXIST(pfwheader)) {
207                 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
208                          "Shift 32 bytes for FW header!!\n");
209                 pfwdata = pfwdata + 32;
210                 fwsize = fwsize - 32;
211         }
212
213         spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
214         fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv);
215         if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
216                 fwdl_in_process = true;
217         else
218                 fwdl_in_process = false;
219         if (fw_downloaded) {
220                 spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
221                 goto exit;
222         } else if (fwdl_in_process) {
223                 spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
224                 for (count = 0; count < 5000; count++) {
225                         udelay(500);
226                         spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
227                         fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv);
228                         if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
229                                 fwdl_in_process = true;
230                         else
231                                 fwdl_in_process = false;
232                         spin_unlock_irqrestore(&globalmutex_for_fwdownload,
233                                                flags);
234                         if (fw_downloaded)
235                                 goto exit;
236                         else if (!fwdl_in_process)
237                                 break;
238                         else
239                                 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
240                                          "Wait for another mac download fw\n");
241                 }
242                 spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
243                 value = rtl_read_byte(rtlpriv, 0x1f);
244                 value |= BIT(5);
245                 rtl_write_byte(rtlpriv, 0x1f, value);
246                 spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
247         } else {
248                 value = rtl_read_byte(rtlpriv, 0x1f);
249                 value |= BIT(5);
250                 rtl_write_byte(rtlpriv, 0x1f, value);
251                 spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
252         }
253
254         /* If 8051 is running in RAM code, driver should
255          * inform Fw to reset by itself, or it will cause
256          * download Fw fail.*/
257         /* 8051 RAM code */
258         if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
259                 rtl92d_firmware_selfreset(hw);
260                 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
261         }
262         _rtl92d_enable_fw_download(hw, true);
263         _rtl92d_write_fw(hw, version, pfwdata, fwsize);
264         _rtl92d_enable_fw_download(hw, false);
265         spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
266         err = _rtl92d_fw_free_to_go(hw);
267         /* download fw over,clear 0x1f[5] */
268         value = rtl_read_byte(rtlpriv, 0x1f);
269         value &= (~BIT(5));
270         rtl_write_byte(rtlpriv, 0x1f, value);
271         spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
272         if (err)
273                 pr_err("fw is not ready to run!\n");
274 exit:
275         err = _rtl92d_fw_init(hw);
276         return err;
277 }
278
279 static bool _rtl92d_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
280 {
281         struct rtl_priv *rtlpriv = rtl_priv(hw);
282         u8 val_hmetfr;
283         bool result = false;
284
285         val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
286         if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
287                 result = true;
288         return result;
289 }
290
291 static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw,
292                               u8 element_id, u32 cmd_len, u8 *cmdbuffer)
293 {
294         struct rtl_priv *rtlpriv = rtl_priv(hw);
295         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
296         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
297         u8 boxnum;
298         u16 box_reg = 0, box_extreg = 0;
299         u8 u1b_tmp;
300         bool isfw_read = false;
301         u8 buf_index = 0;
302         bool bwrite_success = false;
303         u8 wait_h2c_limmit = 100;
304         u8 wait_writeh2c_limmit = 100;
305         u8 boxcontent[4], boxextcontent[2];
306         u32 h2c_waitcounter = 0;
307         unsigned long flag;
308         u8 idx;
309
310         if (ppsc->rfpwr_state == ERFOFF || ppsc->inactive_pwrstate == ERFOFF) {
311                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
312                          "Return as RF is off!!!\n");
313                 return;
314         }
315         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
316         while (true) {
317                 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
318                 if (rtlhal->h2c_setinprogress) {
319                         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
320                                  "H2C set in progress! Wait to set..element_id(%d)\n",
321                                  element_id);
322
323                         while (rtlhal->h2c_setinprogress) {
324                                 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
325                                                        flag);
326                                 h2c_waitcounter++;
327                                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
328                                          "Wait 100 us (%d times)...\n",
329                                          h2c_waitcounter);
330                                 udelay(100);
331
332                                 if (h2c_waitcounter > 1000)
333                                         return;
334
335                                 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
336                                                   flag);
337                         }
338                         spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
339                 } else {
340                         rtlhal->h2c_setinprogress = true;
341                         spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
342                         break;
343                 }
344         }
345         while (!bwrite_success) {
346                 wait_writeh2c_limmit--;
347                 if (wait_writeh2c_limmit == 0) {
348                         pr_err("Write H2C fail because no trigger for FW INT!\n");
349                         break;
350                 }
351                 boxnum = rtlhal->last_hmeboxnum;
352                 switch (boxnum) {
353                 case 0:
354                         box_reg = REG_HMEBOX_0;
355                         box_extreg = REG_HMEBOX_EXT_0;
356                         break;
357                 case 1:
358                         box_reg = REG_HMEBOX_1;
359                         box_extreg = REG_HMEBOX_EXT_1;
360                         break;
361                 case 2:
362                         box_reg = REG_HMEBOX_2;
363                         box_extreg = REG_HMEBOX_EXT_2;
364                         break;
365                 case 3:
366                         box_reg = REG_HMEBOX_3;
367                         box_extreg = REG_HMEBOX_EXT_3;
368                         break;
369                 default:
370                         pr_err("switch case %#x not processed\n",
371                                boxnum);
372                         break;
373                 }
374                 isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
375                 while (!isfw_read) {
376                         wait_h2c_limmit--;
377                         if (wait_h2c_limmit == 0) {
378                                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
379                                          "Waiting too long for FW read clear HMEBox(%d)!\n",
380                                          boxnum);
381                                 break;
382                         }
383                         udelay(10);
384                         isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
385                         u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
386                         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
387                                  "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n",
388                                  boxnum, u1b_tmp);
389                 }
390                 if (!isfw_read) {
391                         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
392                                  "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
393                                  boxnum);
394                         break;
395                 }
396                 memset(boxcontent, 0, sizeof(boxcontent));
397                 memset(boxextcontent, 0, sizeof(boxextcontent));
398                 boxcontent[0] = element_id;
399                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
400                          "Write element_id box_reg(%4x) = %2x\n",
401                          box_reg, element_id);
402                 switch (cmd_len) {
403                 case 1:
404                         boxcontent[0] &= ~(BIT(7));
405                         memcpy(boxcontent + 1, cmdbuffer + buf_index, 1);
406                         for (idx = 0; idx < 4; idx++)
407                                 rtl_write_byte(rtlpriv, box_reg + idx,
408                                                boxcontent[idx]);
409                         break;
410                 case 2:
411                         boxcontent[0] &= ~(BIT(7));
412                         memcpy(boxcontent + 1, cmdbuffer + buf_index, 2);
413                         for (idx = 0; idx < 4; idx++)
414                                 rtl_write_byte(rtlpriv, box_reg + idx,
415                                                boxcontent[idx]);
416                         break;
417                 case 3:
418                         boxcontent[0] &= ~(BIT(7));
419                         memcpy(boxcontent + 1, cmdbuffer + buf_index, 3);
420                         for (idx = 0; idx < 4; idx++)
421                                 rtl_write_byte(rtlpriv, box_reg + idx,
422                                                boxcontent[idx]);
423                         break;
424                 case 4:
425                         boxcontent[0] |= (BIT(7));
426                         memcpy(boxextcontent, cmdbuffer + buf_index, 2);
427                         memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 2);
428                         for (idx = 0; idx < 2; idx++)
429                                 rtl_write_byte(rtlpriv, box_extreg + idx,
430                                                boxextcontent[idx]);
431                         for (idx = 0; idx < 4; idx++)
432                                 rtl_write_byte(rtlpriv, box_reg + idx,
433                                                boxcontent[idx]);
434                         break;
435                 case 5:
436                         boxcontent[0] |= (BIT(7));
437                         memcpy(boxextcontent, cmdbuffer + buf_index, 2);
438                         memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 3);
439                         for (idx = 0; idx < 2; idx++)
440                                 rtl_write_byte(rtlpriv, box_extreg + idx,
441                                                boxextcontent[idx]);
442                         for (idx = 0; idx < 4; idx++)
443                                 rtl_write_byte(rtlpriv, box_reg + idx,
444                                                boxcontent[idx]);
445                         break;
446                 default:
447                         pr_err("switch case %#x not processed\n",
448                                cmd_len);
449                         break;
450                 }
451                 bwrite_success = true;
452                 rtlhal->last_hmeboxnum = boxnum + 1;
453                 if (rtlhal->last_hmeboxnum == 4)
454                         rtlhal->last_hmeboxnum = 0;
455                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
456                          "pHalData->last_hmeboxnum  = %d\n",
457                          rtlhal->last_hmeboxnum);
458         }
459         spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
460         rtlhal->h2c_setinprogress = false;
461         spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
462         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
463 }
464
465 void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw,
466                          u8 element_id, u32 cmd_len, u8 *cmdbuffer)
467 {
468         u32 tmp_cmdbuf[2];
469
470         memset(tmp_cmdbuf, 0, 8);
471         memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
472         _rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
473         return;
474 }
475
476 static bool _rtl92d_cmd_send_packet(struct ieee80211_hw *hw,
477                                     struct sk_buff *skb)
478 {
479         struct rtl_priv *rtlpriv = rtl_priv(hw);
480         struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
481         struct rtl8192_tx_ring *ring;
482         struct rtl_tx_desc *pdesc;
483         u8 idx = 0;
484         unsigned long flags;
485         struct sk_buff *pskb;
486
487         ring = &rtlpci->tx_ring[BEACON_QUEUE];
488         pskb = __skb_dequeue(&ring->queue);
489         kfree_skb(pskb);
490         spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
491         pdesc = &ring->desc[idx];
492         /* discard output from call below */
493         rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
494         rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
495         __skb_queue_tail(&ring->queue, skb);
496         spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
497         rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
498         return true;
499 }
500
501 #define BEACON_PG               0       /*->1 */
502 #define PSPOLL_PG               2
503 #define NULL_PG                 3
504 #define PROBERSP_PG             4       /*->5 */
505 #define TOTAL_RESERVED_PKT_LEN  768
506
507 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
508         /* page 0 beacon */
509         0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
510         0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
511         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
512         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
513         0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
514         0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
515         0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
516         0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
517         0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
518         0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
519         0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
520         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
522         0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
523         0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
524         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
525
526         /* page 1 beacon */
527         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
528         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
532         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
536         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
537         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539         0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
540         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541         0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543
544         /* page 2  ps-poll */
545         0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
546         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
547         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
549         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
550         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
551         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
552         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
553         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557         0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
558         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
559         0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561
562         /* page 3  null */
563         0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
564         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
565         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
566         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575         0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
576         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
577         0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579
580         /* page 4  probe_resp */
581         0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
582         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
583         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
584         0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
585         0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
586         0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
587         0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
588         0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
589         0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
590         0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
591         0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594         0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
595         0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597
598         /* page 5  probe_resp */
599         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603         0x00, 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         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615 };
616
617 void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
618 {
619         struct rtl_priv *rtlpriv = rtl_priv(hw);
620         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
621         struct sk_buff *skb = NULL;
622         u32 totalpacketlen;
623         bool rtstatus;
624         u8 u1RsvdPageLoc[3] = { 0 };
625         bool dlok = false;
626         u8 *beacon;
627         u8 *p_pspoll;
628         u8 *nullfunc;
629         u8 *p_probersp;
630         /*---------------------------------------------------------
631                                                 (1) beacon
632         ---------------------------------------------------------*/
633         beacon = &reserved_page_packet[BEACON_PG * 128];
634         SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
635         SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
636         /*-------------------------------------------------------
637                                                 (2) ps-poll
638         --------------------------------------------------------*/
639         p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
640         SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
641         SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
642         SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
643         SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
644         /*--------------------------------------------------------
645                                                 (3) null data
646         ---------------------------------------------------------*/
647         nullfunc = &reserved_page_packet[NULL_PG * 128];
648         SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
649         SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
650         SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
651         SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
652         /*---------------------------------------------------------
653                                                 (4) probe response
654         ----------------------------------------------------------*/
655         p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
656         SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
657         SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
658         SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
659         SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
660         totalpacketlen = TOTAL_RESERVED_PKT_LEN;
661         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
662                       "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
663                       &reserved_page_packet[0], totalpacketlen);
664         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
665                       "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
666                       u1RsvdPageLoc, 3);
667         skb = dev_alloc_skb(totalpacketlen);
668         if (!skb) {
669                 dlok = false;
670         } else {
671                 skb_put_data(skb, &reserved_page_packet, totalpacketlen);
672                 rtstatus = _rtl92d_cmd_send_packet(hw, skb);
673
674                 if (rtstatus)
675                         dlok = true;
676         }
677         if (dlok) {
678                 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
679                          "Set RSVD page location to Fw\n");
680                 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
681                               "H2C_RSVDPAGE", u1RsvdPageLoc, 3);
682                 rtl92d_fill_h2c_cmd(hw, H2C_RSVDPAGE,
683                         sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
684         } else
685                 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
686                          "Set RSVD page location to Fw FAIL!!!!!!\n");
687 }
688
689 void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
690 {
691         u8 u1_joinbssrpt_parm[1] = {0};
692
693         SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
694         rtl92d_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
695 }