blob: 82bbc8384aca5205013e550e85a843e1e13d1343 [file] [log] [blame]
Larry Finger0c817332010-12-08 11:12:31 -06001/******************************************************************************
2 *
Larry Fingerfc616852012-01-07 20:46:43 -06003 * Copyright(c) 2009-2012 Realtek Corporation.
Larry Finger0c817332010-12-08 11:12:31 -06004 *
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
Larry Finger0c817332010-12-08 11:12:31 -060030#include "../wifi.h"
31#include "../pci.h"
32#include "../base.h"
Larry Finger1472d3a2011-02-23 10:24:58 -060033#include "../rtl8192ce/reg.h"
34#include "../rtl8192ce/def.h"
35#include "fw_common.h"
Larry Fingerd273bb22012-01-27 13:59:25 -060036#include <linux/export.h>
Larry Finger0c817332010-12-08 11:12:31 -060037
38static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
39{
40 struct rtl_priv *rtlpriv = rtl_priv(hw);
41 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
42
43 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) {
44 u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
45 if (enable)
46 value32 |= MCUFWDL_EN;
47 else
48 value32 &= ~MCUFWDL_EN;
49 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
50 } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) {
51 u8 tmp;
52 if (enable) {
53
54 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
55 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1,
56 tmp | 0x04);
57
58 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
59 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
60
61 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
62 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
63 } else {
64
65 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
66 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
67
68 rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
69 }
70 }
71}
72
Larry Fingerff6ff962011-11-17 12:14:43 -060073static void rtl_block_fw_writeN(struct ieee80211_hw *hw, const u8 *buffer,
74 u32 size)
75{
76 struct rtl_priv *rtlpriv = rtl_priv(hw);
77 u32 blockSize = REALTEK_USB_VENQT_MAX_BUF_SIZE - 20;
78 u8 *bufferPtr = (u8 *) buffer;
79 u32 i, offset, blockCount, remainSize;
80
81 blockCount = size / blockSize;
82 remainSize = size % blockSize;
83
84 for (i = 0; i < blockCount; i++) {
85 offset = i * blockSize;
86 rtlpriv->io.writeN_sync(rtlpriv,
87 (FW_8192C_START_ADDRESS + offset),
88 (void *)(bufferPtr + offset),
89 blockSize);
90 }
91
92 if (remainSize) {
93 offset = blockCount * blockSize;
94 rtlpriv->io.writeN_sync(rtlpriv,
95 (FW_8192C_START_ADDRESS + offset),
96 (void *)(bufferPtr + offset),
97 remainSize);
98 }
99}
100
Larry Finger0c817332010-12-08 11:12:31 -0600101static void _rtl92c_fw_block_write(struct ieee80211_hw *hw,
102 const u8 *buffer, u32 size)
103{
104 struct rtl_priv *rtlpriv = rtl_priv(hw);
105 u32 blockSize = sizeof(u32);
106 u8 *bufferPtr = (u8 *) buffer;
107 u32 *pu4BytePtr = (u32 *) buffer;
108 u32 i, offset, blockCount, remainSize;
Larry Fingerabfabc92011-11-17 12:14:44 -0600109 u32 data;
Larry Finger0c817332010-12-08 11:12:31 -0600110
Larry Fingerff6ff962011-11-17 12:14:43 -0600111 if (rtlpriv->io.writeN_sync) {
112 rtl_block_fw_writeN(hw, buffer, size);
113 return;
114 }
Larry Finger0c817332010-12-08 11:12:31 -0600115 blockCount = size / blockSize;
116 remainSize = size % blockSize;
Larry Fingerabfabc92011-11-17 12:14:44 -0600117 if (remainSize) {
118 /* the last word is < 4 bytes - pad it with zeros */
119 for (i = 0; i < 4 - remainSize; i++)
120 *(bufferPtr + size + i) = 0;
121 blockCount++;
122 }
Larry Finger0c817332010-12-08 11:12:31 -0600123
124 for (i = 0; i < blockCount; i++) {
125 offset = i * blockSize;
Larry Fingerabfabc92011-11-17 12:14:44 -0600126 /* for big-endian platforms, the firmware data need to be byte
127 * swapped as it was read as a byte string and will be written
128 * as 32-bit dwords and byte swapped when written
129 */
130 data = le32_to_cpu(*(__le32 *)(pu4BytePtr + i));
Larry Finger0c817332010-12-08 11:12:31 -0600131 rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
Larry Fingerabfabc92011-11-17 12:14:44 -0600132 data);
Larry Finger0c817332010-12-08 11:12:31 -0600133 }
134}
135
136static void _rtl92c_fw_page_write(struct ieee80211_hw *hw,
137 u32 page, const u8 *buffer, u32 size)
138{
139 struct rtl_priv *rtlpriv = rtl_priv(hw);
140 u8 value8;
141 u8 u8page = (u8) (page & 0x07);
142
143 value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
144
145 rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
146 _rtl92c_fw_block_write(hw, buffer, size);
147}
148
149static void _rtl92c_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
150{
151 u32 fwlen = *pfwlen;
152 u8 remain = (u8) (fwlen % 4);
153
154 remain = (remain == 0) ? 0 : (4 - remain);
155
156 while (remain > 0) {
157 pfwbuf[fwlen] = 0;
158 fwlen++;
159 remain--;
160 }
161
162 *pfwlen = fwlen;
163}
164
165static void _rtl92c_write_fw(struct ieee80211_hw *hw,
166 enum version_8192c version, u8 *buffer, u32 size)
167{
168 struct rtl_priv *rtlpriv = rtl_priv(hw);
169 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
Larry Finger0c817332010-12-08 11:12:31 -0600170 u8 *bufferPtr = (u8 *) buffer;
171
Joe Perchesf30d7502012-01-04 19:40:41 -0800172 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes\n", size);
Larry Finger0c817332010-12-08 11:12:31 -0600173
Larry Finger25b2bc32011-02-11 14:34:03 -0600174 if (IS_CHIP_VER_B(version)) {
Larry Finger0c817332010-12-08 11:12:31 -0600175 u32 pageNums, remainSize;
176 u32 page, offset;
177
Larry Finger25b2bc32011-02-11 14:34:03 -0600178 if (IS_HARDWARE_TYPE_8192CE(rtlhal))
Larry Finger0c817332010-12-08 11:12:31 -0600179 _rtl92c_fill_dummy(bufferPtr, &size);
180
181 pageNums = size / FW_8192C_PAGE_SIZE;
182 remainSize = size % FW_8192C_PAGE_SIZE;
183
184 if (pageNums > 4) {
185 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
Joe Perchesf30d7502012-01-04 19:40:41 -0800186 "Page numbers should not greater then 4\n");
Larry Finger0c817332010-12-08 11:12:31 -0600187 }
188
189 for (page = 0; page < pageNums; page++) {
190 offset = page * FW_8192C_PAGE_SIZE;
191 _rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
192 FW_8192C_PAGE_SIZE);
193 }
194
195 if (remainSize) {
196 offset = pageNums * FW_8192C_PAGE_SIZE;
197 page = pageNums;
198 _rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
199 remainSize);
200 }
201 } else {
202 _rtl92c_fw_block_write(hw, buffer, size);
203 }
204}
205
206static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw)
207{
208 struct rtl_priv *rtlpriv = rtl_priv(hw);
Larry Finger0c817332010-12-08 11:12:31 -0600209 u32 counter = 0;
210 u32 value32;
211
212 do {
213 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
214 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
215 (!(value32 & FWDL_ChkSum_rpt)));
216
217 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
218 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
Joe Perchesf30d7502012-01-04 19:40:41 -0800219 "chksum report faill ! REG_MCUFWDL:0x%08x\n", value32);
Larry Finger32473282011-03-27 16:19:57 -0500220 return -EIO;
Larry Finger0c817332010-12-08 11:12:31 -0600221 }
222
223 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
Joe Perchesf30d7502012-01-04 19:40:41 -0800224 "Checksum report OK ! REG_MCUFWDL:0x%08x\n", value32);
Larry Finger0c817332010-12-08 11:12:31 -0600225
226 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
227 value32 |= MCUFWDL_RDY;
228 value32 &= ~WINTINI_RDY;
229 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
230
231 counter = 0;
232
233 do {
234 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
235 if (value32 & WINTINI_RDY) {
236 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
Joe Perchesf30d7502012-01-04 19:40:41 -0800237 "Polling FW ready success!! REG_MCUFWDL:0x%08x\n",
238 value32);
Larry Finger32473282011-03-27 16:19:57 -0500239 return 0;
Larry Finger0c817332010-12-08 11:12:31 -0600240 }
241
242 mdelay(FW_8192C_POLLING_DELAY);
243
244 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
245
246 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
Joe Perchesf30d7502012-01-04 19:40:41 -0800247 "Polling FW ready fail!! REG_MCUFWDL:0x%08x\n", value32);
Larry Finger32473282011-03-27 16:19:57 -0500248 return -EIO;
Larry Finger0c817332010-12-08 11:12:31 -0600249}
250
251int rtl92c_download_fw(struct ieee80211_hw *hw)
252{
253 struct rtl_priv *rtlpriv = rtl_priv(hw);
254 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
255 struct rtl92c_firmware_header *pfwheader;
256 u8 *pfwdata;
257 u32 fwsize;
Larry Finger0c817332010-12-08 11:12:31 -0600258 enum version_8192c version = rtlhal->version;
259
Chaoming_Li3ac5e262011-04-25 12:53:40 -0500260 if (!rtlhal->pfirmware)
Larry Finger0c817332010-12-08 11:12:31 -0600261 return 1;
Larry Finger0c817332010-12-08 11:12:31 -0600262
Larry Finger8ff08b42011-11-30 10:58:14 -0600263 pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
Larry Finger0c817332010-12-08 11:12:31 -0600264 pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
265 pfwdata = (u8 *) rtlhal->pfirmware;
Chaoming_Li3ac5e262011-04-25 12:53:40 -0500266 fwsize = rtlhal->fwsize;
Larry Finger0c817332010-12-08 11:12:31 -0600267
268 if (IS_FW_HEADER_EXIST(pfwheader)) {
269 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
Joe Perchesf30d7502012-01-04 19:40:41 -0800270 "Firmware Version(%d), Signature(%#x),Size(%d)\n",
Larry Fingerabfabc92011-11-17 12:14:44 -0600271 le16_to_cpu(pfwheader->version),
272 le16_to_cpu(pfwheader->signature),
Joe Perchesf30d7502012-01-04 19:40:41 -0800273 (uint)sizeof(struct rtl92c_firmware_header));
Larry Finger0c817332010-12-08 11:12:31 -0600274
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
Larry Finger32473282011-03-27 16:19:57 -0500283 if (_rtl92c_fw_free_to_go(hw)) {
Larry Finger0c817332010-12-08 11:12:31 -0600284 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
Joe Perchesf30d7502012-01-04 19:40:41 -0800285 "Firmware is not ready to run!\n");
Larry Finger0c817332010-12-08 11:12:31 -0600286 } else {
287 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
Joe Perchesf30d7502012-01-04 19:40:41 -0800288 "Firmware is ready to run!\n");
Larry Finger0c817332010-12-08 11:12:31 -0600289 }
290
291 return 0;
292}
Larry Finger1472d3a2011-02-23 10:24:58 -0600293EXPORT_SYMBOL(rtl92c_download_fw);
Larry Finger0c817332010-12-08 11:12:31 -0600294
295static 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
309static 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;
Larry Finger9f219bd2011-04-13 21:00:02 -0500315 u16 box_reg = 0, box_extreg = 0;
Larry Finger0c817332010-12-08 11:12:31 -0600316 u8 u1b_tmp;
317 bool isfw_read = false;
Larry Finger0c817332010-12-08 11:12:31 -0600318 bool bwrite_sucess = 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
Joe Perchesf30d7502012-01-04 19:40:41 -0800326 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
Larry Finger0c817332010-12-08 11:12:31 -0600327
328 while (true) {
329 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
Larry Finger7ea47242011-02-19 16:28:57 -0600330 if (rtlhal->h2c_setinprogress) {
Larry Finger0c817332010-12-08 11:12:31 -0600331 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800332 "H2C set in progress! Wait to set..element_id(%d)\n",
333 element_id);
Larry Finger0c817332010-12-08 11:12:31 -0600334
Larry Finger7ea47242011-02-19 16:28:57 -0600335 while (rtlhal->h2c_setinprogress) {
Larry Finger0c817332010-12-08 11:12:31 -0600336 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
337 flag);
338 h2c_waitcounter++;
339 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800340 "Wait 100 us (%d times)...\n",
341 h2c_waitcounter);
Larry Finger0c817332010-12-08 11:12:31 -0600342 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 {
Larry Finger7ea47242011-02-19 16:28:57 -0600351 rtlhal->h2c_setinprogress = true;
Larry Finger0c817332010-12-08 11:12:31 -0600352 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
353 break;
354 }
355 }
356
357 while (!bwrite_sucess) {
358 wait_writeh2c_limmit--;
359 if (wait_writeh2c_limmit == 0) {
360 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
Joe Perchesf30d7502012-01-04 19:40:41 -0800361 "Write H2C fail because no trigger for FW INT!\n");
Larry Finger0c817332010-12-08 11:12:31 -0600362 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,
Joe Perchesf30d7502012-01-04 19:40:41 -0800385 "switch case not processed\n");
Larry Finger0c817332010-12-08 11:12:31 -0600386 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,
Joe Perchesf30d7502012-01-04 19:40:41 -0800395 "Waiting too long for FW read clear HMEBox(%d)!\n",
396 boxnum);
Larry Finger0c817332010-12-08 11:12:31 -0600397 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,
Joe Perchesf30d7502012-01-04 19:40:41 -0800405 "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n",
406 boxnum, u1b_tmp);
Larry Finger0c817332010-12-08 11:12:31 -0600407 }
408
409 if (!isfw_read) {
410 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800411 "Write H2C register BOX[%d] fail!!!!! Fw do not read\n",
412 boxnum);
Larry Finger0c817332010-12-08 11:12:31 -0600413 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,
Joe Perchesf30d7502012-01-04 19:40:41 -0800420 "Write element_id box_reg(%4x) = %2x\n",
421 box_reg, element_id);
Larry Finger0c817332010-12-08 11:12:31 -0600422
423 switch (cmd_len) {
424 case 1:
425 boxcontent[0] &= ~(BIT(7));
426 memcpy((u8 *) (boxcontent) + 1,
Larry Finger32473282011-03-27 16:19:57 -0500427 p_cmdbuffer, 1);
Larry Finger0c817332010-12-08 11:12:31 -0600428
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,
Larry Finger32473282011-03-27 16:19:57 -0500437 p_cmdbuffer, 2);
Larry Finger0c817332010-12-08 11:12:31 -0600438
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,
Larry Finger32473282011-03-27 16:19:57 -0500447 p_cmdbuffer, 3);
Larry Finger0c817332010-12-08 11:12:31 -0600448
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),
Larry Finger32473282011-03-27 16:19:57 -0500457 p_cmdbuffer, 2);
Larry Finger0c817332010-12-08 11:12:31 -0600458 memcpy((u8 *) (boxcontent) + 1,
Larry Finger32473282011-03-27 16:19:57 -0500459 p_cmdbuffer + 2, 2);
Larry Finger0c817332010-12-08 11:12:31 -0600460
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),
Larry Finger32473282011-03-27 16:19:57 -0500474 p_cmdbuffer, 2);
Larry Finger0c817332010-12-08 11:12:31 -0600475 memcpy((u8 *) (boxcontent) + 1,
Larry Finger32473282011-03-27 16:19:57 -0500476 p_cmdbuffer + 2, 3);
Larry Finger0c817332010-12-08 11:12:31 -0600477
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,
Joe Perchesf30d7502012-01-04 19:40:41 -0800490 "switch case not processed\n");
Larry Finger0c817332010-12-08 11:12:31 -0600491 break;
492 }
493
494 bwrite_sucess = 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,
Joe Perchesf30d7502012-01-04 19:40:41 -0800501 "pHalData->last_hmeboxnum = %d\n",
502 rtlhal->last_hmeboxnum);
Larry Finger0c817332010-12-08 11:12:31 -0600503 }
504
505 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
Larry Finger7ea47242011-02-19 16:28:57 -0600506 rtlhal->h2c_setinprogress = false;
Larry Finger0c817332010-12-08 11:12:31 -0600507 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
508
Joe Perchesf30d7502012-01-04 19:40:41 -0800509 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
Larry Finger0c817332010-12-08 11:12:31 -0600510}
511
512void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
513 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
514{
515 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
516 u32 tmp_cmdbuf[2];
517
Larry Finger7ea47242011-02-19 16:28:57 -0600518 if (rtlhal->fw_ready == false) {
Joe Perches9d833ed2012-01-04 19:40:43 -0800519 RT_ASSERT(false,
520 "return H2C cmd because of Fw download fail!!!\n");
Larry Finger0c817332010-12-08 11:12:31 -0600521 return;
522 }
523
524 memset(tmp_cmdbuf, 0, 8);
525 memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
526 _rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
527
528 return;
529}
Larry Finger1472d3a2011-02-23 10:24:58 -0600530EXPORT_SYMBOL(rtl92c_fill_h2c_cmd);
Larry Finger0c817332010-12-08 11:12:31 -0600531
532void rtl92c_firmware_selfreset(struct ieee80211_hw *hw)
533{
534 u8 u1b_tmp;
535 u8 delay = 100;
536 struct rtl_priv *rtlpriv = rtl_priv(hw);
537
538 rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
539 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
540
541 while (u1b_tmp & BIT(2)) {
542 delay--;
543 if (delay == 0) {
Joe Perches9d833ed2012-01-04 19:40:43 -0800544 RT_ASSERT(false, "8051 reset fail\n");
Larry Finger0c817332010-12-08 11:12:31 -0600545 break;
546 }
547 udelay(50);
548 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
549 }
550}
Larry Finger1472d3a2011-02-23 10:24:58 -0600551EXPORT_SYMBOL(rtl92c_firmware_selfreset);
Larry Finger0c817332010-12-08 11:12:31 -0600552
553void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
554{
555 struct rtl_priv *rtlpriv = rtl_priv(hw);
556 u8 u1_h2c_set_pwrmode[3] = {0};
557 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
558
Joe Perchesf30d7502012-01-04 19:40:41 -0800559 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
Larry Finger0c817332010-12-08 11:12:31 -0600560
561 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
562 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1);
563 SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
564 ppsc->reg_max_lps_awakeintvl);
565
566 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
Joe Perchesaf086872012-01-04 19:40:40 -0800567 "rtl92c_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode",
Larry Finger0c817332010-12-08 11:12:31 -0600568 u1_h2c_set_pwrmode, 3);
569 rtl92c_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
570
571}
Larry Finger1472d3a2011-02-23 10:24:58 -0600572EXPORT_SYMBOL(rtl92c_set_fw_pwrmode_cmd);
Larry Finger0c817332010-12-08 11:12:31 -0600573
Chaoming_Li3ac5e262011-04-25 12:53:40 -0500574static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
575 struct sk_buff *skb)
576{
577 struct rtl_priv *rtlpriv = rtl_priv(hw);
578 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
579 struct rtl8192_tx_ring *ring;
580 struct rtl_tx_desc *pdesc;
Chaoming_Li3ac5e262011-04-25 12:53:40 -0500581 unsigned long flags;
582 struct sk_buff *pskb = NULL;
583
584 ring = &rtlpci->tx_ring[BEACON_QUEUE];
585
586 pskb = __skb_dequeue(&ring->queue);
587 if (pskb)
588 kfree_skb(pskb);
589
590 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
591
592 pdesc = &ring->desc[0];
Chaoming_Li3ac5e262011-04-25 12:53:40 -0500593
594 rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
595
596 __skb_queue_tail(&ring->queue, skb);
597
598 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
599
600 rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
601
602 return true;
603}
604
Larry Finger0c817332010-12-08 11:12:31 -0600605#define BEACON_PG 0 /*->1*/
606#define PSPOLL_PG 2
607#define NULL_PG 3
608#define PROBERSP_PG 4 /*->5*/
609
610#define TOTAL_RESERVED_PKT_LEN 768
611
612static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
613 /* page 0 beacon */
614 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
615 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
616 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
619 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
620 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
621 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
622 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
623 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
624 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
628 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630
631 /* page 1 beacon */
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648
649 /* page 2 ps-poll */
650 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
651 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
662 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
664 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
666
667 /* page 3 null */
668 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
669 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
670 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
672 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
673 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
675 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
676 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
677 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
679 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
680 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
681 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
682 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
683 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
684
685 /* page 4 probe_resp */
686 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
687 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
688 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
689 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
690 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
691 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
692 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
693 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
694 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
695 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
696 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
700 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
702
703 /* page 5 probe_resp */
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
713 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
714 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
715 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
716 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
717 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
718 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
719 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
720};
721
Chaoming_Li3ac5e262011-04-25 12:53:40 -0500722void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
Larry Finger0c817332010-12-08 11:12:31 -0600723{
724 struct rtl_priv *rtlpriv = rtl_priv(hw);
725 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
726 struct sk_buff *skb = NULL;
727
728 u32 totalpacketlen;
729 bool rtstatus;
730 u8 u1RsvdPageLoc[3] = {0};
Chaoming_Li3ac5e262011-04-25 12:53:40 -0500731 bool dlok = false;
Larry Finger0c817332010-12-08 11:12:31 -0600732
733 u8 *beacon;
Chaoming_Li3ac5e262011-04-25 12:53:40 -0500734 u8 *pspoll;
Larry Finger0c817332010-12-08 11:12:31 -0600735 u8 *nullfunc;
Chaoming_Li3ac5e262011-04-25 12:53:40 -0500736 u8 *probersp;
Larry Finger0c817332010-12-08 11:12:31 -0600737 /*---------------------------------------------------------
738 (1) beacon
739 ---------------------------------------------------------*/
740 beacon = &reserved_page_packet[BEACON_PG * 128];
741 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
742 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
743
744 /*-------------------------------------------------------
745 (2) ps-poll
746 --------------------------------------------------------*/
Chaoming_Li3ac5e262011-04-25 12:53:40 -0500747 pspoll = &reserved_page_packet[PSPOLL_PG * 128];
748 SET_80211_PS_POLL_AID(pspoll, (mac->assoc_id | 0xc000));
749 SET_80211_PS_POLL_BSSID(pspoll, mac->bssid);
750 SET_80211_PS_POLL_TA(pspoll, mac->mac_addr);
Larry Finger0c817332010-12-08 11:12:31 -0600751
752 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
753
754 /*--------------------------------------------------------
755 (3) null data
756 ---------------------------------------------------------*/
757 nullfunc = &reserved_page_packet[NULL_PG * 128];
758 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
759 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
760 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
761
762 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
763
764 /*---------------------------------------------------------
765 (4) probe response
766 ----------------------------------------------------------*/
Chaoming_Li3ac5e262011-04-25 12:53:40 -0500767 probersp = &reserved_page_packet[PROBERSP_PG * 128];
768 SET_80211_HDR_ADDRESS1(probersp, mac->bssid);
769 SET_80211_HDR_ADDRESS2(probersp, mac->mac_addr);
770 SET_80211_HDR_ADDRESS3(probersp, mac->bssid);
Larry Finger0c817332010-12-08 11:12:31 -0600771
772 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
773
774 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
775
776 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
Joe Perchesaf086872012-01-04 19:40:40 -0800777 "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
Larry Finger0c817332010-12-08 11:12:31 -0600778 &reserved_page_packet[0], totalpacketlen);
779 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
Joe Perchesaf086872012-01-04 19:40:40 -0800780 "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
Larry Finger0c817332010-12-08 11:12:31 -0600781 u1RsvdPageLoc, 3);
782
783
784 skb = dev_alloc_skb(totalpacketlen);
Larry Finger76a92be2012-01-07 20:46:40 -0600785 if (!skb)
786 return;
Larry Finger0c817332010-12-08 11:12:31 -0600787 memcpy((u8 *) skb_put(skb, totalpacketlen),
788 &reserved_page_packet, totalpacketlen);
789
Chaoming_Li3ac5e262011-04-25 12:53:40 -0500790 rtstatus = _rtl92c_cmd_send_packet(hw, skb);
Larry Finger0c817332010-12-08 11:12:31 -0600791
792 if (rtstatus)
Chaoming_Li3ac5e262011-04-25 12:53:40 -0500793 dlok = true;
Larry Finger0c817332010-12-08 11:12:31 -0600794
Chaoming_Li3ac5e262011-04-25 12:53:40 -0500795 if (dlok) {
Larry Finger0c817332010-12-08 11:12:31 -0600796 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800797 "Set RSVD page location to Fw\n");
Larry Finger0c817332010-12-08 11:12:31 -0600798 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
Joe Perchesaf086872012-01-04 19:40:40 -0800799 "H2C_RSVDPAGE", u1RsvdPageLoc, 3);
Larry Finger0c817332010-12-08 11:12:31 -0600800 rtl92c_fill_h2c_cmd(hw, H2C_RSVDPAGE,
801 sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
802 } else
803 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
Joe Perchesf30d7502012-01-04 19:40:41 -0800804 "Set RSVD page location to Fw FAIL!!!!!!\n");
Larry Finger0c817332010-12-08 11:12:31 -0600805}
Larry Finger1472d3a2011-02-23 10:24:58 -0600806EXPORT_SYMBOL(rtl92c_set_fw_rsvdpagepkt);
Larry Finger0c817332010-12-08 11:12:31 -0600807
808void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
809{
810 u8 u1_joinbssrpt_parm[1] = {0};
811
812 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
813
814 rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
815}
Larry Finger1472d3a2011-02-23 10:24:58 -0600816EXPORT_SYMBOL(rtl92c_set_fw_joinbss_report_cmd);