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