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