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 33 static void _rtl92s_fw_set_rqpn(struct ieee80211_hw *hw) 34 { 35 struct rtl_priv *rtlpriv = rtl_priv(hw); 36 37 rtl_write_dword(rtlpriv, RQPN, 0xffffffff); 38 rtl_write_dword(rtlpriv, RQPN + 4, 0xffffffff); 39 rtl_write_byte(rtlpriv, RQPN + 8, 0xff); 40 rtl_write_byte(rtlpriv, RQPN + 0xB, 0x80); 41 } 42 43 static bool _rtl92s_firmware_enable_cpu(struct ieee80211_hw *hw) 44 { 45 struct rtl_priv *rtlpriv = rtl_priv(hw); 46 u32 ichecktime = 200; 47 u16 tmpu2b; 48 u8 tmpu1b, cpustatus = 0; 49 50 _rtl92s_fw_set_rqpn(hw); 51 52 /* Enable CPU. */ 53 tmpu1b = rtl_read_byte(rtlpriv, SYS_CLKR); 54 /* AFE source */ 55 rtl_write_byte(rtlpriv, SYS_CLKR, (tmpu1b | SYS_CPU_CLKSEL)); 56 57 tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); 58 rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | FEN_CPUEN)); 59 60 /* Polling IMEM Ready after CPU has refilled. */ 61 do { 62 cpustatus = rtl_read_byte(rtlpriv, TCR); 63 if (cpustatus & IMEM_RDY) { 64 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, 65 "IMEM Ready after CPU has refilled\n"); 66 break; 67 } 68 69 udelay(100); 70 } while (ichecktime--); 71 72 if (!(cpustatus & IMEM_RDY)) 73 return false; 74 75 return true; 76 } 77 78 static enum fw_status _rtl92s_firmware_get_nextstatus( 79 enum fw_status fw_currentstatus) 80 { 81 enum fw_status next_fwstatus = 0; 82 83 switch (fw_currentstatus) { 84 case FW_STATUS_INIT: 85 next_fwstatus = FW_STATUS_LOAD_IMEM; 86 break; 87 case FW_STATUS_LOAD_IMEM: 88 next_fwstatus = FW_STATUS_LOAD_EMEM; 89 break; 90 case FW_STATUS_LOAD_EMEM: 91 next_fwstatus = FW_STATUS_LOAD_DMEM; 92 break; 93 case FW_STATUS_LOAD_DMEM: 94 next_fwstatus = FW_STATUS_READY; 95 break; 96 default: 97 break; 98 } 99 100 return next_fwstatus; 101 } 102 103 static u8 _rtl92s_firmware_header_map_rftype(struct ieee80211_hw *hw) 104 { 105 struct rtl_priv *rtlpriv = rtl_priv(hw); 106 struct rtl_phy *rtlphy = &(rtlpriv->phy); 107 108 switch (rtlphy->rf_type) { 109 case RF_1T1R: 110 return 0x11; 111 case RF_1T2R: 112 return 0x12; 113 case RF_2T2R: 114 return 0x22; 115 default: 116 pr_err("Unknown RF type(%x)\n", rtlphy->rf_type); 117 break; 118 } 119 return 0x22; 120 } 121 122 static void _rtl92s_firmwareheader_priveupdate(struct ieee80211_hw *hw, 123 struct fw_priv *pfw_priv) 124 { 125 /* Update RF types for RATR settings. */ 126 pfw_priv->rf_config = _rtl92s_firmware_header_map_rftype(hw); 127 } 128 129 130 131 static bool _rtl92s_cmd_send_packet(struct ieee80211_hw *hw, 132 struct sk_buff *skb, u8 last) 133 { 134 struct rtl_priv *rtlpriv = rtl_priv(hw); 135 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 136 struct rtl8192_tx_ring *ring; 137 struct rtl_tx_desc *pdesc; 138 unsigned long flags; 139 u8 idx = 0; 140 141 ring = &rtlpci->tx_ring[TXCMD_QUEUE]; 142 143 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); 144 145 idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; 146 pdesc = &ring->desc[idx]; 147 rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb); 148 __skb_queue_tail(&ring->queue, skb); 149 150 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); 151 152 return true; 153 } 154 155 static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw, 156 u8 *code_virtual_address, u32 buffer_len) 157 { 158 struct rtl_priv *rtlpriv = rtl_priv(hw); 159 struct sk_buff *skb; 160 struct rtl_tcb_desc *tcb_desc; 161 unsigned char *seg_ptr; 162 u16 frag_threshold = MAX_FIRMWARE_CODE_SIZE; 163 u16 frag_length, frag_offset = 0; 164 u16 extra_descoffset = 0; 165 u8 last_inipkt = 0; 166 167 _rtl92s_fw_set_rqpn(hw); 168 169 if (buffer_len >= MAX_FIRMWARE_CODE_SIZE) { 170 pr_err("Size over FIRMWARE_CODE_SIZE!\n"); 171 return false; 172 } 173 174 extra_descoffset = 0; 175 176 do { 177 if ((buffer_len - frag_offset) > frag_threshold) { 178 frag_length = frag_threshold + extra_descoffset; 179 } else { 180 frag_length = (u16)(buffer_len - frag_offset + 181 extra_descoffset); 182 last_inipkt = 1; 183 } 184 185 /* Allocate skb buffer to contain firmware */ 186 /* info and tx descriptor info. */ 187 skb = dev_alloc_skb(frag_length); 188 if (!skb) 189 return false; 190 skb_reserve(skb, extra_descoffset); 191 seg_ptr = (u8 *)skb_put(skb, (u32)(frag_length - 192 extra_descoffset)); 193 memcpy(seg_ptr, code_virtual_address + frag_offset, 194 (u32)(frag_length - extra_descoffset)); 195 196 tcb_desc = (struct rtl_tcb_desc *)(skb->cb); 197 tcb_desc->queue_index = TXCMD_QUEUE; 198 tcb_desc->cmd_or_init = DESC_PACKET_TYPE_INIT; 199 tcb_desc->last_inipkt = last_inipkt; 200 201 _rtl92s_cmd_send_packet(hw, skb, last_inipkt); 202 203 frag_offset += (frag_length - extra_descoffset); 204 205 } while (frag_offset < buffer_len); 206 207 rtl_write_byte(rtlpriv, TP_POLL, TPPOLL_CQ); 208 209 return true ; 210 } 211 212 static bool _rtl92s_firmware_checkready(struct ieee80211_hw *hw, 213 u8 loadfw_status) 214 { 215 struct rtl_priv *rtlpriv = rtl_priv(hw); 216 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 217 struct rt_firmware *firmware = (struct rt_firmware *)rtlhal->pfirmware; 218 u32 tmpu4b; 219 u8 cpustatus = 0; 220 short pollingcnt = 1000; 221 bool rtstatus = true; 222 223 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, 224 "LoadStaus(%d)\n", loadfw_status); 225 226 firmware->fwstatus = (enum fw_status)loadfw_status; 227 228 switch (loadfw_status) { 229 case FW_STATUS_LOAD_IMEM: 230 /* Polling IMEM code done. */ 231 do { 232 cpustatus = rtl_read_byte(rtlpriv, TCR); 233 if (cpustatus & IMEM_CODE_DONE) 234 break; 235 udelay(5); 236 } while (pollingcnt--); 237 238 if (!(cpustatus & IMEM_CHK_RPT) || (pollingcnt <= 0)) { 239 pr_err("FW_STATUS_LOAD_IMEM FAIL CPU, Status=%x\n", 240 cpustatus); 241 goto status_check_fail; 242 } 243 break; 244 245 case FW_STATUS_LOAD_EMEM: 246 /* Check Put Code OK and Turn On CPU */ 247 /* Polling EMEM code done. */ 248 do { 249 cpustatus = rtl_read_byte(rtlpriv, TCR); 250 if (cpustatus & EMEM_CODE_DONE) 251 break; 252 udelay(5); 253 } while (pollingcnt--); 254 255 if (!(cpustatus & EMEM_CHK_RPT) || (pollingcnt <= 0)) { 256 pr_err("FW_STATUS_LOAD_EMEM FAIL CPU, Status=%x\n", 257 cpustatus); 258 goto status_check_fail; 259 } 260 261 /* Turn On CPU */ 262 rtstatus = _rtl92s_firmware_enable_cpu(hw); 263 if (!rtstatus) { 264 pr_err("Enable CPU fail!\n"); 265 goto status_check_fail; 266 } 267 break; 268 269 case FW_STATUS_LOAD_DMEM: 270 /* Polling DMEM code done */ 271 do { 272 cpustatus = rtl_read_byte(rtlpriv, TCR); 273 if (cpustatus & DMEM_CODE_DONE) 274 break; 275 udelay(5); 276 } while (pollingcnt--); 277 278 if (!(cpustatus & DMEM_CODE_DONE) || (pollingcnt <= 0)) { 279 pr_err("Polling DMEM code done fail ! cpustatus(%#x)\n", 280 cpustatus); 281 goto status_check_fail; 282 } 283 284 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, 285 "DMEM code download success, cpustatus(%#x)\n", 286 cpustatus); 287 288 /* Prevent Delay too much and being scheduled out */ 289 /* Polling Load Firmware ready */ 290 pollingcnt = 2000; 291 do { 292 cpustatus = rtl_read_byte(rtlpriv, TCR); 293 if (cpustatus & FWRDY) 294 break; 295 udelay(40); 296 } while (pollingcnt--); 297 298 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, 299 "Polling Load Firmware ready, cpustatus(%x)\n", 300 cpustatus); 301 302 if (((cpustatus & LOAD_FW_READY) != LOAD_FW_READY) || 303 (pollingcnt <= 0)) { 304 pr_err("Polling Load Firmware ready fail ! cpustatus(%x)\n", 305 cpustatus); 306 goto status_check_fail; 307 } 308 309 /* If right here, we can set TCR/RCR to desired value */ 310 /* and config MAC lookback mode to normal mode */ 311 tmpu4b = rtl_read_dword(rtlpriv, TCR); 312 rtl_write_dword(rtlpriv, TCR, (tmpu4b & (~TCR_ICV))); 313 314 tmpu4b = rtl_read_dword(rtlpriv, RCR); 315 rtl_write_dword(rtlpriv, RCR, (tmpu4b | RCR_APPFCS | 316 RCR_APP_ICV | RCR_APP_MIC)); 317 318 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, 319 "Current RCR settings(%#x)\n", tmpu4b); 320 321 /* Set to normal mode. */ 322 rtl_write_byte(rtlpriv, LBKMD_SEL, LBK_NORMAL); 323 break; 324 325 default: 326 pr_err("Unknown status check!\n"); 327 rtstatus = false; 328 break; 329 } 330 331 status_check_fail: 332 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, 333 "loadfw_status(%d), rtstatus(%x)\n", 334 loadfw_status, rtstatus); 335 return rtstatus; 336 } 337 338 int rtl92s_download_fw(struct ieee80211_hw *hw) 339 { 340 struct rtl_priv *rtlpriv = rtl_priv(hw); 341 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 342 struct rt_firmware *firmware = NULL; 343 struct fw_hdr *pfwheader; 344 struct fw_priv *pfw_priv = NULL; 345 u8 *puc_mappedfile = NULL; 346 u32 ul_filelength = 0; 347 u8 fwhdr_size = RT_8192S_FIRMWARE_HDR_SIZE; 348 u8 fwstatus = FW_STATUS_INIT; 349 bool rtstatus = true; 350 351 if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware) 352 return 1; 353 354 firmware = (struct rt_firmware *)rtlhal->pfirmware; 355 firmware->fwstatus = FW_STATUS_INIT; 356 357 puc_mappedfile = firmware->sz_fw_tmpbuffer; 358 359 /* 1. Retrieve FW header. */ 360 firmware->pfwheader = (struct fw_hdr *) puc_mappedfile; 361 pfwheader = firmware->pfwheader; 362 firmware->firmwareversion = byte(pfwheader->version, 0); 363 firmware->pfwheader->fwpriv.hci_sel = 1;/* pcie */ 364 365 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, 366 "signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n", 367 pfwheader->signature, 368 pfwheader->version, pfwheader->dmem_size, 369 pfwheader->img_imem_size, pfwheader->img_sram_size); 370 371 /* 2. Retrieve IMEM image. */ 372 if ((pfwheader->img_imem_size == 0) || (pfwheader->img_imem_size > 373 sizeof(firmware->fw_imem))) { 374 pr_err("memory for data image is less than IMEM required\n"); 375 goto fail; 376 } else { 377 puc_mappedfile += fwhdr_size; 378 379 memcpy(firmware->fw_imem, puc_mappedfile, 380 pfwheader->img_imem_size); 381 firmware->fw_imem_len = pfwheader->img_imem_size; 382 } 383 384 /* 3. Retriecve EMEM image. */ 385 if (pfwheader->img_sram_size > sizeof(firmware->fw_emem)) { 386 pr_err("memory for data image is less than EMEM required\n"); 387 goto fail; 388 } else { 389 puc_mappedfile += firmware->fw_imem_len; 390 391 memcpy(firmware->fw_emem, puc_mappedfile, 392 pfwheader->img_sram_size); 393 firmware->fw_emem_len = pfwheader->img_sram_size; 394 } 395 396 /* 4. download fw now */ 397 fwstatus = _rtl92s_firmware_get_nextstatus(firmware->fwstatus); 398 while (fwstatus != FW_STATUS_READY) { 399 /* Image buffer redirection. */ 400 switch (fwstatus) { 401 case FW_STATUS_LOAD_IMEM: 402 puc_mappedfile = firmware->fw_imem; 403 ul_filelength = firmware->fw_imem_len; 404 break; 405 case FW_STATUS_LOAD_EMEM: 406 puc_mappedfile = firmware->fw_emem; 407 ul_filelength = firmware->fw_emem_len; 408 break; 409 case FW_STATUS_LOAD_DMEM: 410 /* Partial update the content of header private. */ 411 pfwheader = firmware->pfwheader; 412 pfw_priv = &pfwheader->fwpriv; 413 _rtl92s_firmwareheader_priveupdate(hw, pfw_priv); 414 puc_mappedfile = (u8 *)(firmware->pfwheader) + 415 RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE; 416 ul_filelength = fwhdr_size - 417 RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE; 418 break; 419 default: 420 pr_err("Unexpected Download step!!\n"); 421 goto fail; 422 } 423 424 /* <2> Download image file */ 425 rtstatus = _rtl92s_firmware_downloadcode(hw, puc_mappedfile, 426 ul_filelength); 427 428 if (!rtstatus) { 429 pr_err("fail!\n"); 430 goto fail; 431 } 432 433 /* <3> Check whether load FW process is ready */ 434 rtstatus = _rtl92s_firmware_checkready(hw, fwstatus); 435 if (!rtstatus) { 436 pr_err("rtl8192se: firmware fail!\n"); 437 goto fail; 438 } 439 440 fwstatus = _rtl92s_firmware_get_nextstatus(firmware->fwstatus); 441 } 442 443 return rtstatus; 444 fail: 445 return 0; 446 } 447 448 static u32 _rtl92s_fill_h2c_cmd(struct sk_buff *skb, u32 h2cbufferlen, 449 u32 cmd_num, u32 *pelement_id, u32 *pcmd_len, 450 u8 **pcmb_buffer, u8 *cmd_start_seq) 451 { 452 u32 totallen = 0, len = 0, tx_desclen = 0; 453 u32 pre_continueoffset = 0; 454 u8 *ph2c_buffer; 455 u8 i = 0; 456 457 do { 458 /* 8 - Byte alignment */ 459 len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8); 460 461 /* Buffer length is not enough */ 462 if (h2cbufferlen < totallen + len + tx_desclen) 463 break; 464 465 /* Clear content */ 466 ph2c_buffer = (u8 *)skb_put(skb, (u32)len); 467 memset((ph2c_buffer + totallen + tx_desclen), 0, len); 468 469 /* CMD len */ 470 SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), 471 0, 16, pcmd_len[i]); 472 473 /* CMD ID */ 474 SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), 475 16, 8, pelement_id[i]); 476 477 /* CMD Sequence */ 478 *cmd_start_seq = *cmd_start_seq % 0x80; 479 SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), 480 24, 7, *cmd_start_seq); 481 ++*cmd_start_seq; 482 483 /* Copy memory */ 484 memcpy((ph2c_buffer + totallen + tx_desclen + 485 H2C_TX_CMD_HDR_LEN), pcmb_buffer[i], pcmd_len[i]); 486 487 /* CMD continue */ 488 /* set the continue in prevoius cmd. */ 489 if (i < cmd_num - 1) 490 SET_BITS_TO_LE_4BYTE((ph2c_buffer + pre_continueoffset), 491 31, 1, 1); 492 493 pre_continueoffset = totallen; 494 495 totallen += len; 496 } while (++i < cmd_num); 497 498 return totallen; 499 } 500 501 static u32 _rtl92s_get_h2c_cmdlen(u32 h2cbufferlen, u32 cmd_num, u32 *pcmd_len) 502 { 503 u32 totallen = 0, len = 0, tx_desclen = 0; 504 u8 i = 0; 505 506 do { 507 /* 8 - Byte alignment */ 508 len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8); 509 510 /* Buffer length is not enough */ 511 if (h2cbufferlen < totallen + len + tx_desclen) 512 break; 513 514 totallen += len; 515 } while (++i < cmd_num); 516 517 return totallen + tx_desclen; 518 } 519 520 static bool _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw *hw, u8 h2c_cmd, 521 u8 *pcmd_buffer) 522 { 523 struct rtl_priv *rtlpriv = rtl_priv(hw); 524 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 525 struct rtl_tcb_desc *cb_desc; 526 struct sk_buff *skb; 527 u32 element_id = 0; 528 u32 cmd_len = 0; 529 u32 len; 530 531 switch (h2c_cmd) { 532 case FW_H2C_SETPWRMODE: 533 element_id = H2C_SETPWRMODE_CMD ; 534 cmd_len = sizeof(struct h2c_set_pwrmode_parm); 535 break; 536 case FW_H2C_JOINBSSRPT: 537 element_id = H2C_JOINBSSRPT_CMD; 538 cmd_len = sizeof(struct h2c_joinbss_rpt_parm); 539 break; 540 case FW_H2C_WOWLAN_UPDATE_GTK: 541 element_id = H2C_WOWLAN_UPDATE_GTK_CMD; 542 cmd_len = sizeof(struct h2c_wpa_two_way_parm); 543 break; 544 case FW_H2C_WOWLAN_UPDATE_IV: 545 element_id = H2C_WOWLAN_UPDATE_IV_CMD; 546 cmd_len = sizeof(unsigned long long); 547 break; 548 case FW_H2C_WOWLAN_OFFLOAD: 549 element_id = H2C_WOWLAN_FW_OFFLOAD; 550 cmd_len = sizeof(u8); 551 break; 552 default: 553 break; 554 } 555 556 len = _rtl92s_get_h2c_cmdlen(MAX_TRANSMIT_BUFFER_SIZE, 1, &cmd_len); 557 skb = dev_alloc_skb(len); 558 if (!skb) 559 return false; 560 cb_desc = (struct rtl_tcb_desc *)(skb->cb); 561 cb_desc->queue_index = TXCMD_QUEUE; 562 cb_desc->cmd_or_init = DESC_PACKET_TYPE_NORMAL; 563 cb_desc->last_inipkt = false; 564 565 _rtl92s_fill_h2c_cmd(skb, MAX_TRANSMIT_BUFFER_SIZE, 1, &element_id, 566 &cmd_len, &pcmd_buffer, &rtlhal->h2c_txcmd_seq); 567 _rtl92s_cmd_send_packet(hw, skb, false); 568 rtlpriv->cfg->ops->tx_polling(hw, TXCMD_QUEUE); 569 570 return true; 571 } 572 573 void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 Mode) 574 { 575 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 576 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 577 struct h2c_set_pwrmode_parm pwrmode; 578 u16 max_wakeup_period = 0; 579 580 pwrmode.mode = Mode; 581 pwrmode.flag_low_traffic_en = 0; 582 pwrmode.flag_lpnav_en = 0; 583 pwrmode.flag_rf_low_snr_en = 0; 584 pwrmode.flag_dps_en = 0; 585 pwrmode.bcn_rx_en = 0; 586 pwrmode.bcn_to = 0; 587 SET_BITS_TO_LE_2BYTE((u8 *)(&pwrmode) + 8, 0, 16, 588 mac->vif->bss_conf.beacon_int); 589 pwrmode.app_itv = 0; 590 pwrmode.awake_bcn_itvl = ppsc->reg_max_lps_awakeintvl; 591 pwrmode.smart_ps = 1; 592 pwrmode.bcn_pass_period = 10; 593 594 /* Set beacon pass count */ 595 if (pwrmode.mode == FW_PS_MIN_MODE) 596 max_wakeup_period = mac->vif->bss_conf.beacon_int; 597 else if (pwrmode.mode == FW_PS_MAX_MODE) 598 max_wakeup_period = mac->vif->bss_conf.beacon_int * 599 mac->vif->bss_conf.dtim_period; 600 601 if (max_wakeup_period >= 500) 602 pwrmode.bcn_pass_cnt = 1; 603 else if ((max_wakeup_period >= 300) && (max_wakeup_period < 500)) 604 pwrmode.bcn_pass_cnt = 2; 605 else if ((max_wakeup_period >= 200) && (max_wakeup_period < 300)) 606 pwrmode.bcn_pass_cnt = 3; 607 else if ((max_wakeup_period >= 20) && (max_wakeup_period < 200)) 608 pwrmode.bcn_pass_cnt = 5; 609 else 610 pwrmode.bcn_pass_cnt = 1; 611 612 _rtl92s_firmware_set_h2c_cmd(hw, FW_H2C_SETPWRMODE, (u8 *)&pwrmode); 613 614 } 615 616 void rtl92s_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, 617 u8 mstatus, u8 ps_qosinfo) 618 { 619 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 620 struct h2c_joinbss_rpt_parm joinbss_rpt; 621 622 joinbss_rpt.opmode = mstatus; 623 joinbss_rpt.ps_qos_info = ps_qosinfo; 624 joinbss_rpt.bssid[0] = mac->bssid[0]; 625 joinbss_rpt.bssid[1] = mac->bssid[1]; 626 joinbss_rpt.bssid[2] = mac->bssid[2]; 627 joinbss_rpt.bssid[3] = mac->bssid[3]; 628 joinbss_rpt.bssid[4] = mac->bssid[4]; 629 joinbss_rpt.bssid[5] = mac->bssid[5]; 630 SET_BITS_TO_LE_2BYTE((u8 *)(&joinbss_rpt) + 8, 0, 16, 631 mac->vif->bss_conf.beacon_int); 632 SET_BITS_TO_LE_2BYTE((u8 *)(&joinbss_rpt) + 10, 0, 16, mac->assoc_id); 633 634 _rtl92s_firmware_set_h2c_cmd(hw, FW_H2C_JOINBSSRPT, (u8 *)&joinbss_rpt); 635 } 636 637