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