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