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