diff options
Diffstat (limited to 'drivers/net/wireless/rtlwifi/rtl8188ee/fw.c')
-rw-r--r-- | drivers/net/wireless/rtlwifi/rtl8188ee/fw.c | 259 |
1 files changed, 122 insertions, 137 deletions
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c index 4f9376ad4739..c8058aa73ecf 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c | |||
@@ -11,10 +11,6 @@ | |||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
12 | * more details. | 12 | * more details. |
13 | * | 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 | 14 | * The full GNU General Public License is included in this distribution in the |
19 | * file called LICENSE. | 15 | * file called LICENSE. |
20 | * | 16 | * |
@@ -30,12 +26,11 @@ | |||
30 | #include "../wifi.h" | 26 | #include "../wifi.h" |
31 | #include "../pci.h" | 27 | #include "../pci.h" |
32 | #include "../base.h" | 28 | #include "../base.h" |
29 | #include "../core.h" | ||
33 | #include "reg.h" | 30 | #include "reg.h" |
34 | #include "def.h" | 31 | #include "def.h" |
35 | #include "fw.h" | 32 | #include "fw.h" |
36 | 33 | ||
37 | #include <linux/kmemleak.h> | ||
38 | |||
39 | static void _rtl88e_enable_fw_download(struct ieee80211_hw *hw, bool enable) | 34 | static void _rtl88e_enable_fw_download(struct ieee80211_hw *hw, bool enable) |
40 | { | 35 | { |
41 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 36 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -62,26 +57,26 @@ static void _rtl88e_fw_block_write(struct ieee80211_hw *hw, | |||
62 | const u8 *buffer, u32 size) | 57 | const u8 *buffer, u32 size) |
63 | { | 58 | { |
64 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 59 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
65 | u32 blk_sz = sizeof(u32); | 60 | u32 blocksize = sizeof(u32); |
66 | u8 *buf_ptr = (u8 *)buffer; | 61 | u8 *bufferptr = (u8 *)buffer; |
67 | u32 *pu4BytePtr = (u32 *)buffer; | 62 | u32 *pu4BytePtr = (u32 *)buffer; |
68 | u32 i, offset, blk_cnt, remain; | 63 | u32 i, offset, blockcount, remainsize; |
69 | 64 | ||
70 | blk_cnt = size / blk_sz; | 65 | blockcount = size / blocksize; |
71 | remain = size % blk_sz; | 66 | remainsize = size % blocksize; |
72 | 67 | ||
73 | for (i = 0; i < blk_cnt; i++) { | 68 | for (i = 0; i < blockcount; i++) { |
74 | offset = i * blk_sz; | 69 | offset = i * blocksize; |
75 | rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset), | 70 | rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset), |
76 | *(pu4BytePtr + i)); | 71 | *(pu4BytePtr + i)); |
77 | } | 72 | } |
78 | 73 | ||
79 | if (remain) { | 74 | if (remainsize) { |
80 | offset = blk_cnt * blk_sz; | 75 | offset = blockcount * blocksize; |
81 | buf_ptr += offset; | 76 | bufferptr += offset; |
82 | for (i = 0; i < remain; i++) { | 77 | for (i = 0; i < remainsize; i++) { |
83 | rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS + | 78 | rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS + |
84 | offset + i), *(buf_ptr + i)); | 79 | offset + i), *(bufferptr + i)); |
85 | } | 80 | } |
86 | } | 81 | } |
87 | } | 82 | } |
@@ -119,32 +114,33 @@ static void _rtl88e_write_fw(struct ieee80211_hw *hw, | |||
119 | enum version_8188e version, u8 *buffer, u32 size) | 114 | enum version_8188e version, u8 *buffer, u32 size) |
120 | { | 115 | { |
121 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 116 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
122 | u8 *buf_ptr = buffer; | 117 | u8 *bufferptr = (u8 *)buffer; |
123 | u32 page_no, remain; | 118 | u32 pagenums, remainsize; |
124 | u32 page, offset; | 119 | u32 page, offset; |
125 | 120 | ||
126 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size); | 121 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size); |
127 | 122 | ||
128 | _rtl88e_fill_dummy(buf_ptr, &size); | 123 | _rtl88e_fill_dummy(bufferptr, &size); |
129 | 124 | ||
130 | page_no = size / FW_8192C_PAGE_SIZE; | 125 | pagenums = size / FW_8192C_PAGE_SIZE; |
131 | remain = size % FW_8192C_PAGE_SIZE; | 126 | remainsize = size % FW_8192C_PAGE_SIZE; |
132 | 127 | ||
133 | if (page_no > 8) { | 128 | if (pagenums > 8) { |
134 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 129 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
135 | "Page numbers should not greater then 8\n"); | 130 | "Page numbers should not greater then 8\n"); |
136 | } | 131 | } |
137 | 132 | ||
138 | for (page = 0; page < page_no; page++) { | 133 | for (page = 0; page < pagenums; page++) { |
139 | offset = page * FW_8192C_PAGE_SIZE; | 134 | offset = page * FW_8192C_PAGE_SIZE; |
140 | _rtl88e_fw_page_write(hw, page, (buf_ptr + offset), | 135 | _rtl88e_fw_page_write(hw, page, (bufferptr + offset), |
141 | FW_8192C_PAGE_SIZE); | 136 | FW_8192C_PAGE_SIZE); |
142 | } | 137 | } |
143 | 138 | ||
144 | if (remain) { | 139 | if (remainsize) { |
145 | offset = page_no * FW_8192C_PAGE_SIZE; | 140 | offset = pagenums * FW_8192C_PAGE_SIZE; |
146 | page = page_no; | 141 | page = pagenums; |
147 | _rtl88e_fw_page_write(hw, page, (buf_ptr + offset), remain); | 142 | _rtl88e_fw_page_write(hw, page, (bufferptr + offset), |
143 | remainsize); | ||
148 | } | 144 | } |
149 | } | 145 | } |
150 | 146 | ||
@@ -199,7 +195,8 @@ exit: | |||
199 | return err; | 195 | return err; |
200 | } | 196 | } |
201 | 197 | ||
202 | int rtl88e_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw) | 198 | int rtl88e_download_fw(struct ieee80211_hw *hw, |
199 | bool buse_wake_on_wlan_fw) | ||
203 | { | 200 | { |
204 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 201 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
205 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 202 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
@@ -221,8 +218,8 @@ int rtl88e_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw) | |||
221 | if (IS_FW_HEADER_EXIST(pfwheader)) { | 218 | if (IS_FW_HEADER_EXIST(pfwheader)) { |
222 | RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, | 219 | RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, |
223 | "Firmware Version(%d), Signature(%#x), Size(%d)\n", | 220 | "Firmware Version(%d), Signature(%#x), Size(%d)\n", |
224 | pfwheader->version, pfwheader->signature, | 221 | pfwheader->version, pfwheader->signature, |
225 | (int)sizeof(struct rtl92c_firmware_header)); | 222 | (int)sizeof(struct rtl92c_firmware_header)); |
226 | 223 | ||
227 | pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header); | 224 | pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header); |
228 | fwsize = fwsize - sizeof(struct rtl92c_firmware_header); | 225 | fwsize = fwsize - sizeof(struct rtl92c_firmware_header); |
@@ -237,9 +234,14 @@ int rtl88e_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw) | |||
237 | _rtl88e_enable_fw_download(hw, false); | 234 | _rtl88e_enable_fw_download(hw, false); |
238 | 235 | ||
239 | err = _rtl88e_fw_free_to_go(hw); | 236 | err = _rtl88e_fw_free_to_go(hw); |
237 | if (err) { | ||
238 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
239 | "Firmware is not ready to run!\n"); | ||
240 | } else { | ||
241 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, | ||
242 | "Firmware is ready to run!\n"); | ||
243 | } | ||
240 | 244 | ||
241 | RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, | ||
242 | "Firmware is%s ready to run!\n", err ? " not" : ""); | ||
243 | return 0; | 245 | return 0; |
244 | } | 246 | } |
245 | 247 | ||
@@ -266,9 +268,9 @@ static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw, | |||
266 | bool isfw_read = false; | 268 | bool isfw_read = false; |
267 | u8 buf_index = 0; | 269 | u8 buf_index = 0; |
268 | bool write_sucess = false; | 270 | bool write_sucess = false; |
269 | u8 wait_h2c_limit = 100; | 271 | u8 wait_h2c_limmit = 100; |
270 | u8 wait_writeh2c_limit = 100; | 272 | u8 wait_writeh2c_limit = 100; |
271 | u8 boxc[4], boxext[2]; | 273 | u8 boxcontent[4], boxextcontent[4]; |
272 | u32 h2c_waitcounter = 0; | 274 | u32 h2c_waitcounter = 0; |
273 | unsigned long flag; | 275 | unsigned long flag; |
274 | u8 idx; | 276 | u8 idx; |
@@ -331,18 +333,17 @@ static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw, | |||
331 | box_extreg = REG_HMEBOX_EXT_3; | 333 | box_extreg = REG_HMEBOX_EXT_3; |
332 | break; | 334 | break; |
333 | default: | 335 | default: |
334 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 336 | RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, |
335 | "switch case not processed\n"); | 337 | "switch case not process\n"); |
336 | break; | 338 | break; |
337 | } | 339 | } |
338 | |||
339 | isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum); | 340 | isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum); |
340 | while (!isfw_read) { | 341 | while (!isfw_read) { |
341 | wait_h2c_limit--; | 342 | wait_h2c_limmit--; |
342 | if (wait_h2c_limit == 0) { | 343 | if (wait_h2c_limmit == 0) { |
343 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | 344 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, |
344 | "Waiting too long for FW read " | 345 | "Waiting too long for FW read clear HMEBox(%d)!\n", |
345 | "clear HMEBox(%d)!\n", boxnum); | 346 | boxnum); |
346 | break; | 347 | break; |
347 | } | 348 | } |
348 | 349 | ||
@@ -351,20 +352,20 @@ static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw, | |||
351 | isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum); | 352 | isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum); |
352 | u1b_tmp = rtl_read_byte(rtlpriv, 0x130); | 353 | u1b_tmp = rtl_read_byte(rtlpriv, 0x130); |
353 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | 354 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, |
354 | "Waiting for FW read clear HMEBox(%d)!!! " | 355 | "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n", |
355 | "0x130 = %2x\n", boxnum, u1b_tmp); | 356 | boxnum, u1b_tmp); |
356 | } | 357 | } |
357 | 358 | ||
358 | if (!isfw_read) { | 359 | if (!isfw_read) { |
359 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | 360 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, |
360 | "Write H2C register BOX[%d] fail!!!!! " | 361 | "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", |
361 | "Fw do not read.\n", boxnum); | 362 | boxnum); |
362 | break; | 363 | break; |
363 | } | 364 | } |
364 | 365 | ||
365 | memset(boxc, 0, sizeof(boxc)); | 366 | memset(boxcontent, 0, sizeof(boxcontent)); |
366 | memset(boxext, 0, sizeof(boxext)); | 367 | memset(boxextcontent, 0, sizeof(boxextcontent)); |
367 | boxc[0] = element_id; | 368 | boxcontent[0] = element_id; |
368 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | 369 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, |
369 | "Write element_id box_reg(%4x) = %2x\n", | 370 | "Write element_id box_reg(%4x) = %2x\n", |
370 | box_reg, element_id); | 371 | box_reg, element_id); |
@@ -373,33 +374,38 @@ static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw, | |||
373 | case 1: | 374 | case 1: |
374 | case 2: | 375 | case 2: |
375 | case 3: | 376 | case 3: |
376 | /*boxc[0] &= ~(BIT(7));*/ | 377 | /*boxcontent[0] &= ~(BIT(7));*/ |
377 | memcpy((u8 *)(boxc) + 1, cmd_b + buf_index, cmd_len); | 378 | memcpy((u8 *)(boxcontent) + 1, |
379 | cmd_b + buf_index, cmd_len); | ||
378 | 380 | ||
379 | for (idx = 0; idx < 4; idx++) | 381 | for (idx = 0; idx < 4; idx++) { |
380 | rtl_write_byte(rtlpriv, box_reg+idx, boxc[idx]); | 382 | rtl_write_byte(rtlpriv, box_reg + idx, |
383 | boxcontent[idx]); | ||
384 | } | ||
381 | break; | 385 | break; |
382 | case 4: | 386 | case 4: |
383 | case 5: | 387 | case 5: |
384 | case 6: | 388 | case 6: |
385 | case 7: | 389 | case 7: |
386 | /*boxc[0] |= (BIT(7));*/ | 390 | /*boxcontent[0] |= (BIT(7));*/ |
387 | memcpy((u8 *)(boxext), cmd_b + buf_index+3, cmd_len-3); | 391 | memcpy((u8 *)(boxextcontent), |
388 | memcpy((u8 *)(boxc) + 1, cmd_b + buf_index, 3); | 392 | cmd_b + buf_index+3, cmd_len-3); |
393 | memcpy((u8 *)(boxcontent) + 1, | ||
394 | cmd_b + buf_index, 3); | ||
389 | 395 | ||
390 | for (idx = 0; idx < 2; idx++) { | 396 | for (idx = 0; idx < 2; idx++) { |
391 | rtl_write_byte(rtlpriv, box_extreg + idx, | 397 | rtl_write_byte(rtlpriv, box_extreg + idx, |
392 | boxext[idx]); | 398 | boxextcontent[idx]); |
393 | } | 399 | } |
394 | 400 | ||
395 | for (idx = 0; idx < 4; idx++) { | 401 | for (idx = 0; idx < 4; idx++) { |
396 | rtl_write_byte(rtlpriv, box_reg + idx, | 402 | rtl_write_byte(rtlpriv, box_reg + idx, |
397 | boxc[idx]); | 403 | boxcontent[idx]); |
398 | } | 404 | } |
399 | break; | 405 | break; |
400 | default: | 406 | default: |
401 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 407 | RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, |
402 | "switch case not processed\n"); | 408 | "switch case not process\n"); |
403 | break; | 409 | break; |
404 | } | 410 | } |
405 | 411 | ||
@@ -411,7 +417,7 @@ static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw, | |||
411 | 417 | ||
412 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | 418 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, |
413 | "pHalData->last_hmeboxnum = %d\n", | 419 | "pHalData->last_hmeboxnum = %d\n", |
414 | rtlhal->last_hmeboxnum); | 420 | rtlhal->last_hmeboxnum); |
415 | } | 421 | } |
416 | 422 | ||
417 | spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); | 423 | spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); |
@@ -422,18 +428,19 @@ static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw, | |||
422 | } | 428 | } |
423 | 429 | ||
424 | void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw, | 430 | void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw, |
425 | u8 element_id, u32 cmd_len, u8 *cmd_b) | 431 | u8 element_id, u32 cmd_len, u8 *cmdbuffer) |
426 | { | 432 | { |
427 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 433 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
428 | u32 tmp_cmdbuf[2]; | 434 | u32 tmp_cmdbuf[2]; |
429 | 435 | ||
430 | if (rtlhal->fw_ready == false) { | 436 | if (!rtlhal->fw_ready) { |
431 | RT_ASSERT(false, "fail H2C cmd - Fw download fail!!!\n"); | 437 | RT_ASSERT(false, |
438 | "return H2C cmd because of Fw download fail!!!\n"); | ||
432 | return; | 439 | return; |
433 | } | 440 | } |
434 | 441 | ||
435 | memset(tmp_cmdbuf, 0, 8); | 442 | memset(tmp_cmdbuf, 0, 8); |
436 | memcpy(tmp_cmdbuf, cmd_b, cmd_len); | 443 | memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); |
437 | _rtl88e_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); | 444 | _rtl88e_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); |
438 | 445 | ||
439 | return; | 446 | return; |
@@ -448,7 +455,8 @@ void rtl88e_firmware_selfreset(struct ieee80211_hw *hw) | |||
448 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2)))); | 455 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2)))); |
449 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp | BIT(2))); | 456 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp | BIT(2))); |
450 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | 457 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, |
451 | "8051Reset88E(): 8051 reset success.\n"); | 458 | "8051Reset88E(): 8051 reset success\n"); |
459 | |||
452 | } | 460 | } |
453 | 461 | ||
454 | void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) | 462 | void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) |
@@ -456,28 +464,29 @@ void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) | |||
456 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 464 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
457 | u8 u1_h2c_set_pwrmode[H2C_88E_PWEMODE_LENGTH] = { 0 }; | 465 | u8 u1_h2c_set_pwrmode[H2C_88E_PWEMODE_LENGTH] = { 0 }; |
458 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 466 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
459 | u8 power_state = 0; | 467 | u8 rlbm, power_state = 0; |
460 | |||
461 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); | 468 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); |
469 | |||
462 | SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); | 470 | SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); |
463 | SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, 0); | 471 | rlbm = 0;/*YJ, temp, 120316. FW now not support RLBM=2.*/ |
472 | SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm); | ||
464 | SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, | 473 | SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, |
465 | (rtlpriv->mac80211.p2p) ? | 474 | (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1); |
466 | ppsc->smart_ps : 1); | ||
467 | SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, | 475 | SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, |
468 | ppsc->reg_max_lps_awakeintvl); | 476 | ppsc->reg_max_lps_awakeintvl); |
469 | SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); | 477 | SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); |
470 | if (mode == FW_PS_ACTIVE_MODE) | 478 | if (mode == FW_PS_ACTIVE_MODE) |
471 | power_state |= FW_PWR_STATE_ACTIVE; | 479 | power_state |= FW_PWR_STATE_ACTIVE; |
472 | else | 480 | else |
473 | power_state |= FW_PWR_STATE_RF_OFF; | 481 | power_state |= FW_PWR_STATE_RF_OFF; |
482 | |||
474 | SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); | 483 | SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); |
475 | 484 | ||
476 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, | 485 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, |
477 | "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", | 486 | "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", |
478 | u1_h2c_set_pwrmode, H2C_88E_PWEMODE_LENGTH); | 487 | u1_h2c_set_pwrmode, H2C_88E_PWEMODE_LENGTH); |
479 | rtl88e_fill_h2c_cmd(hw, H2C_88E_SETPWRMODE, H2C_88E_PWEMODE_LENGTH, | 488 | rtl88e_fill_h2c_cmd(hw, H2C_88E_SETPWRMODE, |
480 | u1_h2c_set_pwrmode); | 489 | H2C_88E_PWEMODE_LENGTH, u1_h2c_set_pwrmode); |
481 | } | 490 | } |
482 | 491 | ||
483 | void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) | 492 | void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) |
@@ -499,39 +508,9 @@ void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw, | |||
499 | SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid); | 508 | SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid); |
500 | SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0); | 509 | SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0); |
501 | 510 | ||
502 | rtl88e_fill_h2c_cmd(hw, H2C_88E_AP_OFFLOAD, H2C_88E_AP_OFFLOAD_LENGTH, | 511 | rtl88e_fill_h2c_cmd(hw, H2C_88E_AP_OFFLOAD, |
503 | u1_apoffload_parm); | 512 | H2C_88E_AP_OFFLOAD_LENGTH, u1_apoffload_parm); |
504 | } | ||
505 | 513 | ||
506 | static bool _rtl88e_cmd_send_packet(struct ieee80211_hw *hw, | ||
507 | struct sk_buff *skb) | ||
508 | { | ||
509 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
510 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
511 | struct rtl8192_tx_ring *ring; | ||
512 | struct rtl_tx_desc *pdesc; | ||
513 | struct sk_buff *pskb = NULL; | ||
514 | unsigned long flags; | ||
515 | |||
516 | ring = &rtlpci->tx_ring[BEACON_QUEUE]; | ||
517 | |||
518 | pskb = __skb_dequeue(&ring->queue); | ||
519 | if (pskb) | ||
520 | kfree_skb(pskb); | ||
521 | |||
522 | spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); | ||
523 | |||
524 | pdesc = &ring->desc[0]; | ||
525 | |||
526 | rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb); | ||
527 | |||
528 | __skb_queue_tail(&ring->queue, skb); | ||
529 | |||
530 | spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); | ||
531 | |||
532 | rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); | ||
533 | |||
534 | return true; | ||
535 | } | 514 | } |
536 | 515 | ||
537 | #define BEACON_PG 0 /* ->1 */ | 516 | #define BEACON_PG 0 /* ->1 */ |
@@ -656,14 +635,15 @@ void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) | |||
656 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 635 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
657 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 636 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
658 | struct sk_buff *skb = NULL; | 637 | struct sk_buff *skb = NULL; |
659 | |||
660 | u32 totalpacketlen; | 638 | u32 totalpacketlen; |
661 | u8 u1RsvdPageLoc[5] = { 0 }; | 639 | bool rtstatus; |
662 | 640 | u8 u1rsvdpageloc[5] = { 0 }; | |
641 | bool b_dlok = false; | ||
663 | u8 *beacon; | 642 | u8 *beacon; |
664 | u8 *pspoll; | 643 | u8 *p_pspoll; |
665 | u8 *nullfunc; | 644 | u8 *nullfunc; |
666 | u8 *probersp; | 645 | u8 *p_probersp; |
646 | |||
667 | /*--------------------------------------------------------- | 647 | /*--------------------------------------------------------- |
668 | * (1) beacon | 648 | * (1) beacon |
669 | *--------------------------------------------------------- | 649 | *--------------------------------------------------------- |
@@ -676,12 +656,12 @@ void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) | |||
676 | * (2) ps-poll | 656 | * (2) ps-poll |
677 | *-------------------------------------------------------- | 657 | *-------------------------------------------------------- |
678 | */ | 658 | */ |
679 | pspoll = &reserved_page_packet[PSPOLL_PG * 128]; | 659 | p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; |
680 | SET_80211_PS_POLL_AID(pspoll, (mac->assoc_id | 0xc000)); | 660 | SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); |
681 | SET_80211_PS_POLL_BSSID(pspoll, mac->bssid); | 661 | SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); |
682 | SET_80211_PS_POLL_TA(pspoll, mac->mac_addr); | 662 | SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); |
683 | 663 | ||
684 | SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG); | 664 | SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); |
685 | 665 | ||
686 | /*-------------------------------------------------------- | 666 | /*-------------------------------------------------------- |
687 | * (3) null data | 667 | * (3) null data |
@@ -692,18 +672,18 @@ void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) | |||
692 | SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); | 672 | SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); |
693 | SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); | 673 | SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); |
694 | 674 | ||
695 | SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG); | 675 | SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); |
696 | 676 | ||
697 | /*--------------------------------------------------------- | 677 | /*--------------------------------------------------------- |
698 | * (4) probe response | 678 | * (4) probe response |
699 | *---------------------------------------------------------- | 679 | *---------------------------------------------------------- |
700 | */ | 680 | */ |
701 | probersp = &reserved_page_packet[PROBERSP_PG * 128]; | 681 | p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; |
702 | SET_80211_HDR_ADDRESS1(probersp, mac->bssid); | 682 | SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); |
703 | SET_80211_HDR_ADDRESS2(probersp, mac->mac_addr); | 683 | SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); |
704 | SET_80211_HDR_ADDRESS3(probersp, mac->bssid); | 684 | SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); |
705 | 685 | ||
706 | SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG); | 686 | SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); |
707 | 687 | ||
708 | totalpacketlen = TOTAL_RESERVED_PKT_LEN; | 688 | totalpacketlen = TOTAL_RESERVED_PKT_LEN; |
709 | 689 | ||
@@ -712,33 +692,36 @@ void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) | |||
712 | &reserved_page_packet[0], totalpacketlen); | 692 | &reserved_page_packet[0], totalpacketlen); |
713 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, | 693 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, |
714 | "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", | 694 | "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", |
715 | u1RsvdPageLoc, 3); | 695 | u1rsvdpageloc, 3); |
716 | 696 | ||
717 | skb = dev_alloc_skb(totalpacketlen); | 697 | skb = dev_alloc_skb(totalpacketlen); |
718 | if (!skb) | ||
719 | return; | ||
720 | kmemleak_not_leak(skb); | ||
721 | memcpy(skb_put(skb, totalpacketlen), | 698 | memcpy(skb_put(skb, totalpacketlen), |
722 | &reserved_page_packet, totalpacketlen); | 699 | &reserved_page_packet, totalpacketlen); |
723 | 700 | ||
724 | if (_rtl88e_cmd_send_packet(hw, skb)) { | 701 | rtstatus = rtl_cmd_send_packet(hw, skb); |
702 | |||
703 | if (rtstatus) | ||
704 | b_dlok = true; | ||
705 | |||
706 | if (b_dlok) { | ||
725 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | 707 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
726 | "Set RSVD page location to Fw.\n"); | 708 | "Set RSVD page location to Fw.\n"); |
727 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, | 709 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, |
728 | "H2C_RSVDPAGE:\n", u1RsvdPageLoc, 3); | 710 | "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3); |
729 | rtl88e_fill_h2c_cmd(hw, H2C_88E_RSVDPAGE, | 711 | rtl88e_fill_h2c_cmd(hw, H2C_88E_RSVDPAGE, |
730 | sizeof(u1RsvdPageLoc), u1RsvdPageLoc); | 712 | sizeof(u1rsvdpageloc), u1rsvdpageloc); |
731 | } else | 713 | } else |
732 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | 714 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, |
733 | "Set RSVD page location to Fw FAIL!!!!!!.\n"); | 715 | "Set RSVD page location to Fw FAIL!!!!!!.\n"); |
734 | } | 716 | } |
735 | 717 | ||
736 | /*Shoud check FW support p2p or not.*/ | 718 | /*Should check FW support p2p or not.*/ |
737 | static void rtl88e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow) | 719 | static void rtl88e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow) |
738 | { | 720 | { |
739 | u8 u1_ctwindow_period[1] = {ctwindow}; | 721 | u8 u1_ctwindow_period[1] = { ctwindow}; |
740 | 722 | ||
741 | rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); | 723 | rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); |
724 | |||
742 | } | 725 | } |
743 | 726 | ||
744 | void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) | 727 | void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) |
@@ -755,7 +738,7 @@ void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) | |||
755 | switch (p2p_ps_state) { | 738 | switch (p2p_ps_state) { |
756 | case P2P_PS_DISABLE: | 739 | case P2P_PS_DISABLE: |
757 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); | 740 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); |
758 | memset(p2p_ps_offload, 0, sizeof(struct p2p_ps_offload_t)); | 741 | memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); |
759 | break; | 742 | break; |
760 | case P2P_PS_ENABLE: | 743 | case P2P_PS_ENABLE: |
761 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); | 744 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); |
@@ -765,8 +748,9 @@ void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) | |||
765 | ctwindow = p2pinfo->ctwindow; | 748 | ctwindow = p2pinfo->ctwindow; |
766 | rtl88e_set_p2p_ctw_period_cmd(hw, ctwindow); | 749 | rtl88e_set_p2p_ctw_period_cmd(hw, ctwindow); |
767 | } | 750 | } |
751 | |||
768 | /* hw only support 2 set of NoA */ | 752 | /* hw only support 2 set of NoA */ |
769 | for (i = 0; i < p2pinfo->noa_num; i++) { | 753 | for (i = 0 ; i < p2pinfo->noa_num; i++) { |
770 | /* To control the register setting for which NOA*/ | 754 | /* To control the register setting for which NOA*/ |
771 | rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); | 755 | rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); |
772 | if (i == 0) | 756 | if (i == 0) |
@@ -785,7 +769,7 @@ void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) | |||
785 | 769 | ||
786 | start_time = p2pinfo->noa_start_time[i]; | 770 | start_time = p2pinfo->noa_start_time[i]; |
787 | if (p2pinfo->noa_count_type[i] != 1) { | 771 | if (p2pinfo->noa_count_type[i] != 1) { |
788 | while (start_time <= (tsf_low + (50 * 1024))) { | 772 | while (start_time <= (tsf_low+(50*1024))) { |
789 | start_time += p2pinfo->noa_interval[i]; | 773 | start_time += p2pinfo->noa_interval[i]; |
790 | if (p2pinfo->noa_count_type[i] != 255) | 774 | if (p2pinfo->noa_count_type[i] != 255) |
791 | p2pinfo->noa_count_type[i]--; | 775 | p2pinfo->noa_count_type[i]--; |
@@ -804,7 +788,7 @@ void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) | |||
804 | 788 | ||
805 | if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { | 789 | if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { |
806 | p2p_ps_offload->role = 1; | 790 | p2p_ps_offload->role = 1; |
807 | p2p_ps_offload->allstasleep = 0; | 791 | p2p_ps_offload->allstasleep = -1; |
808 | } else { | 792 | } else { |
809 | p2p_ps_offload->role = 0; | 793 | p2p_ps_offload->role = 0; |
810 | } | 794 | } |
@@ -827,4 +811,5 @@ void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) | |||
827 | 811 | ||
828 | rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_OFFLOAD, 1, | 812 | rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_OFFLOAD, 1, |
829 | (u8 *)p2p_ps_offload); | 813 | (u8 *)p2p_ps_offload); |
814 | |||
830 | } | 815 | } |