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