Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2009-2012  Realtek Corporation.*/
0003 
0004 #include "../wifi.h"
0005 #include "../pci.h"
0006 #include "../base.h"
0007 #include "reg.h"
0008 #include "def.h"
0009 #include "fw.h"
0010 
0011 static void _rtl92s_fw_set_rqpn(struct ieee80211_hw *hw)
0012 {
0013     struct rtl_priv *rtlpriv = rtl_priv(hw);
0014 
0015     rtl_write_dword(rtlpriv, RQPN, 0xffffffff);
0016     rtl_write_dword(rtlpriv, RQPN + 4, 0xffffffff);
0017     rtl_write_byte(rtlpriv, RQPN + 8, 0xff);
0018     rtl_write_byte(rtlpriv, RQPN + 0xB, 0x80);
0019 }
0020 
0021 static bool _rtl92s_firmware_enable_cpu(struct ieee80211_hw *hw)
0022 {
0023     struct rtl_priv *rtlpriv = rtl_priv(hw);
0024     u32 ichecktime = 200;
0025     u16 tmpu2b;
0026     u8 tmpu1b, cpustatus = 0;
0027 
0028     _rtl92s_fw_set_rqpn(hw);
0029 
0030     /* Enable CPU. */
0031     tmpu1b = rtl_read_byte(rtlpriv, SYS_CLKR);
0032     /* AFE source */
0033     rtl_write_byte(rtlpriv, SYS_CLKR, (tmpu1b | SYS_CPU_CLKSEL));
0034 
0035     tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
0036     rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | FEN_CPUEN));
0037 
0038     /* Polling IMEM Ready after CPU has refilled. */
0039     do {
0040         cpustatus = rtl_read_byte(rtlpriv, TCR);
0041         if (cpustatus & IMEM_RDY) {
0042             rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
0043                 "IMEM Ready after CPU has refilled\n");
0044             break;
0045         }
0046 
0047         udelay(100);
0048     } while (ichecktime--);
0049 
0050     if (!(cpustatus & IMEM_RDY))
0051         return false;
0052 
0053     return true;
0054 }
0055 
0056 static enum fw_status _rtl92s_firmware_get_nextstatus(
0057         enum fw_status fw_currentstatus)
0058 {
0059     enum fw_status  next_fwstatus = 0;
0060 
0061     switch (fw_currentstatus) {
0062     case FW_STATUS_INIT:
0063         next_fwstatus = FW_STATUS_LOAD_IMEM;
0064         break;
0065     case FW_STATUS_LOAD_IMEM:
0066         next_fwstatus = FW_STATUS_LOAD_EMEM;
0067         break;
0068     case FW_STATUS_LOAD_EMEM:
0069         next_fwstatus = FW_STATUS_LOAD_DMEM;
0070         break;
0071     case FW_STATUS_LOAD_DMEM:
0072         next_fwstatus = FW_STATUS_READY;
0073         break;
0074     default:
0075         break;
0076     }
0077 
0078     return next_fwstatus;
0079 }
0080 
0081 static u8 _rtl92s_firmware_header_map_rftype(struct ieee80211_hw *hw)
0082 {
0083     struct rtl_priv *rtlpriv = rtl_priv(hw);
0084     struct rtl_phy *rtlphy = &(rtlpriv->phy);
0085 
0086     switch (rtlphy->rf_type) {
0087     case RF_1T1R:
0088         return 0x11;
0089     case RF_1T2R:
0090         return 0x12;
0091     case RF_2T2R:
0092         return 0x22;
0093     default:
0094         pr_err("Unknown RF type(%x)\n", rtlphy->rf_type);
0095         break;
0096     }
0097     return 0x22;
0098 }
0099 
0100 static void _rtl92s_firmwareheader_priveupdate(struct ieee80211_hw *hw,
0101         struct fw_priv *pfw_priv)
0102 {
0103     /* Update RF types for RATR settings. */
0104     pfw_priv->rf_config = _rtl92s_firmware_header_map_rftype(hw);
0105 }
0106 
0107 
0108 
0109 static bool _rtl92s_cmd_send_packet(struct ieee80211_hw *hw,
0110         struct sk_buff *skb, u8 last)
0111 {
0112     struct rtl_priv *rtlpriv = rtl_priv(hw);
0113     struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
0114     struct rtl8192_tx_ring *ring;
0115     struct rtl_tx_desc *pdesc;
0116     unsigned long flags;
0117     u8 idx = 0;
0118 
0119     ring = &rtlpci->tx_ring[TXCMD_QUEUE];
0120 
0121     spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
0122 
0123     idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries;
0124     pdesc = &ring->desc[idx];
0125     rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb);
0126     __skb_queue_tail(&ring->queue, skb);
0127 
0128     spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
0129 
0130     return true;
0131 }
0132 
0133 static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw,
0134         u8 *code_virtual_address, u32 buffer_len)
0135 {
0136     struct rtl_priv *rtlpriv = rtl_priv(hw);
0137     struct sk_buff *skb;
0138     struct rtl_tcb_desc *tcb_desc;
0139     u16 frag_threshold = MAX_FIRMWARE_CODE_SIZE;
0140     u16 frag_length, frag_offset = 0;
0141     u16 extra_descoffset = 0;
0142     u8 last_inipkt = 0;
0143 
0144     _rtl92s_fw_set_rqpn(hw);
0145 
0146     if (buffer_len >= MAX_FIRMWARE_CODE_SIZE) {
0147         pr_err("Size over FIRMWARE_CODE_SIZE!\n");
0148         return false;
0149     }
0150 
0151     extra_descoffset = 0;
0152 
0153     do {
0154         if ((buffer_len - frag_offset) > frag_threshold) {
0155             frag_length = frag_threshold + extra_descoffset;
0156         } else {
0157             frag_length = (u16)(buffer_len - frag_offset +
0158                         extra_descoffset);
0159             last_inipkt = 1;
0160         }
0161 
0162         /* Allocate skb buffer to contain firmware */
0163         /* info and tx descriptor info. */
0164         skb = dev_alloc_skb(frag_length);
0165         if (!skb)
0166             return false;
0167         skb_reserve(skb, extra_descoffset);
0168         skb_put_data(skb, code_virtual_address + frag_offset,
0169                  (u32)(frag_length - extra_descoffset));
0170 
0171         tcb_desc = (struct rtl_tcb_desc *)(skb->cb);
0172         tcb_desc->queue_index = TXCMD_QUEUE;
0173         tcb_desc->cmd_or_init = DESC_PACKET_TYPE_INIT;
0174         tcb_desc->last_inipkt = last_inipkt;
0175 
0176         _rtl92s_cmd_send_packet(hw, skb, last_inipkt);
0177 
0178         frag_offset += (frag_length - extra_descoffset);
0179 
0180     } while (frag_offset < buffer_len);
0181 
0182     rtl_write_byte(rtlpriv, TP_POLL, TPPOLL_CQ);
0183 
0184     return true ;
0185 }
0186 
0187 static bool _rtl92s_firmware_checkready(struct ieee80211_hw *hw,
0188         u8 loadfw_status)
0189 {
0190     struct rtl_priv *rtlpriv = rtl_priv(hw);
0191     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0192     struct rt_firmware *firmware = (struct rt_firmware *)rtlhal->pfirmware;
0193     u32 tmpu4b;
0194     u8 cpustatus = 0;
0195     short pollingcnt = 1000;
0196     bool rtstatus = true;
0197 
0198     rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
0199         "LoadStaus(%d)\n", loadfw_status);
0200 
0201     firmware->fwstatus = (enum fw_status)loadfw_status;
0202 
0203     switch (loadfw_status) {
0204     case FW_STATUS_LOAD_IMEM:
0205         /* Polling IMEM code done. */
0206         do {
0207             cpustatus = rtl_read_byte(rtlpriv, TCR);
0208             if (cpustatus & IMEM_CODE_DONE)
0209                 break;
0210             udelay(5);
0211         } while (pollingcnt--);
0212 
0213         if (!(cpustatus & IMEM_CHK_RPT) || (pollingcnt <= 0)) {
0214             pr_err("FW_STATUS_LOAD_IMEM FAIL CPU, Status=%x\n",
0215                    cpustatus);
0216             goto status_check_fail;
0217         }
0218         break;
0219 
0220     case FW_STATUS_LOAD_EMEM:
0221         /* Check Put Code OK and Turn On CPU */
0222         /* Polling EMEM code done. */
0223         do {
0224             cpustatus = rtl_read_byte(rtlpriv, TCR);
0225             if (cpustatus & EMEM_CODE_DONE)
0226                 break;
0227             udelay(5);
0228         } while (pollingcnt--);
0229 
0230         if (!(cpustatus & EMEM_CHK_RPT) || (pollingcnt <= 0)) {
0231             pr_err("FW_STATUS_LOAD_EMEM FAIL CPU, Status=%x\n",
0232                    cpustatus);
0233             goto status_check_fail;
0234         }
0235 
0236         /* Turn On CPU */
0237         rtstatus = _rtl92s_firmware_enable_cpu(hw);
0238         if (!rtstatus) {
0239             pr_err("Enable CPU fail!\n");
0240             goto status_check_fail;
0241         }
0242         break;
0243 
0244     case FW_STATUS_LOAD_DMEM:
0245         /* Polling DMEM code done */
0246         do {
0247             cpustatus = rtl_read_byte(rtlpriv, TCR);
0248             if (cpustatus & DMEM_CODE_DONE)
0249                 break;
0250             udelay(5);
0251         } while (pollingcnt--);
0252 
0253         if (!(cpustatus & DMEM_CODE_DONE) || (pollingcnt <= 0)) {
0254             pr_err("Polling DMEM code done fail ! cpustatus(%#x)\n",
0255                    cpustatus);
0256             goto status_check_fail;
0257         }
0258 
0259         rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
0260             "DMEM code download success, cpustatus(%#x)\n",
0261             cpustatus);
0262 
0263         /* Prevent Delay too much and being scheduled out */
0264         /* Polling Load Firmware ready */
0265         pollingcnt = 2000;
0266         do {
0267             cpustatus = rtl_read_byte(rtlpriv, TCR);
0268             if (cpustatus & FWRDY)
0269                 break;
0270             udelay(40);
0271         } while (pollingcnt--);
0272 
0273         rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
0274             "Polling Load Firmware ready, cpustatus(%x)\n",
0275             cpustatus);
0276 
0277         if (((cpustatus & LOAD_FW_READY) != LOAD_FW_READY) ||
0278             (pollingcnt <= 0)) {
0279             pr_err("Polling Load Firmware ready fail ! cpustatus(%x)\n",
0280                    cpustatus);
0281             goto status_check_fail;
0282         }
0283 
0284         /* If right here, we can set TCR/RCR to desired value  */
0285         /* and config MAC lookback mode to normal mode */
0286         tmpu4b = rtl_read_dword(rtlpriv, TCR);
0287         rtl_write_dword(rtlpriv, TCR, (tmpu4b & (~TCR_ICV)));
0288 
0289         tmpu4b = rtl_read_dword(rtlpriv, RCR);
0290         rtl_write_dword(rtlpriv, RCR, (tmpu4b | RCR_APPFCS |
0291                 RCR_APP_ICV | RCR_APP_MIC));
0292 
0293         rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
0294             "Current RCR settings(%#x)\n", tmpu4b);
0295 
0296         /* Set to normal mode. */
0297         rtl_write_byte(rtlpriv, LBKMD_SEL, LBK_NORMAL);
0298         break;
0299 
0300     default:
0301         pr_err("Unknown status check!\n");
0302         rtstatus = false;
0303         break;
0304     }
0305 
0306 status_check_fail:
0307     rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
0308         "loadfw_status(%d), rtstatus(%x)\n",
0309         loadfw_status, rtstatus);
0310     return rtstatus;
0311 }
0312 
0313 int rtl92s_download_fw(struct ieee80211_hw *hw)
0314 {
0315     struct rtl_priv *rtlpriv = rtl_priv(hw);
0316     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0317     struct rt_firmware *firmware = NULL;
0318     struct fw_hdr *pfwheader;
0319     struct fw_priv *pfw_priv = NULL;
0320     u8 *puc_mappedfile = NULL;
0321     u32 ul_filelength = 0;
0322     u8 fwhdr_size = RT_8192S_FIRMWARE_HDR_SIZE;
0323     u8 fwstatus = FW_STATUS_INIT;
0324     bool rtstatus = true;
0325 
0326     if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
0327         return 1;
0328 
0329     firmware = (struct rt_firmware *)rtlhal->pfirmware;
0330     firmware->fwstatus = FW_STATUS_INIT;
0331 
0332     puc_mappedfile = firmware->sz_fw_tmpbuffer;
0333 
0334     /* 1. Retrieve FW header. */
0335     firmware->pfwheader = (struct fw_hdr *) puc_mappedfile;
0336     pfwheader = firmware->pfwheader;
0337     firmware->firmwareversion =  byte(pfwheader->version, 0);
0338     firmware->pfwheader->fwpriv.hci_sel = 1;/* pcie */
0339 
0340     rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
0341         "signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n",
0342         pfwheader->signature,
0343         pfwheader->version, pfwheader->dmem_size,
0344         pfwheader->img_imem_size, pfwheader->img_sram_size);
0345 
0346     /* 2. Retrieve IMEM image. */
0347     if ((pfwheader->img_imem_size == 0) || (pfwheader->img_imem_size >
0348         sizeof(firmware->fw_imem))) {
0349         pr_err("memory for data image is less than IMEM required\n");
0350         goto fail;
0351     } else {
0352         puc_mappedfile += fwhdr_size;
0353 
0354         memcpy(firmware->fw_imem, puc_mappedfile,
0355                pfwheader->img_imem_size);
0356         firmware->fw_imem_len = pfwheader->img_imem_size;
0357     }
0358 
0359     /* 3. Retriecve EMEM image. */
0360     if (pfwheader->img_sram_size > sizeof(firmware->fw_emem)) {
0361         pr_err("memory for data image is less than EMEM required\n");
0362         goto fail;
0363     } else {
0364         puc_mappedfile += firmware->fw_imem_len;
0365 
0366         memcpy(firmware->fw_emem, puc_mappedfile,
0367                pfwheader->img_sram_size);
0368         firmware->fw_emem_len = pfwheader->img_sram_size;
0369     }
0370 
0371     /* 4. download fw now */
0372     fwstatus = _rtl92s_firmware_get_nextstatus(firmware->fwstatus);
0373     while (fwstatus != FW_STATUS_READY) {
0374         /* Image buffer redirection. */
0375         switch (fwstatus) {
0376         case FW_STATUS_LOAD_IMEM:
0377             puc_mappedfile = firmware->fw_imem;
0378             ul_filelength = firmware->fw_imem_len;
0379             break;
0380         case FW_STATUS_LOAD_EMEM:
0381             puc_mappedfile = firmware->fw_emem;
0382             ul_filelength = firmware->fw_emem_len;
0383             break;
0384         case FW_STATUS_LOAD_DMEM:
0385             /* Partial update the content of header private. */
0386             pfwheader = firmware->pfwheader;
0387             pfw_priv = &pfwheader->fwpriv;
0388             _rtl92s_firmwareheader_priveupdate(hw, pfw_priv);
0389             puc_mappedfile = (u8 *)(firmware->pfwheader) +
0390                     RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE;
0391             ul_filelength = fwhdr_size -
0392                     RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE;
0393             break;
0394         default:
0395             pr_err("Unexpected Download step!!\n");
0396             goto fail;
0397         }
0398 
0399         /* <2> Download image file */
0400         rtstatus = _rtl92s_firmware_downloadcode(hw, puc_mappedfile,
0401                 ul_filelength);
0402 
0403         if (!rtstatus) {
0404             pr_err("fail!\n");
0405             goto fail;
0406         }
0407 
0408         /* <3> Check whether load FW process is ready */
0409         rtstatus = _rtl92s_firmware_checkready(hw, fwstatus);
0410         if (!rtstatus) {
0411             pr_err("rtl8192se: firmware fail!\n");
0412             goto fail;
0413         }
0414 
0415         fwstatus = _rtl92s_firmware_get_nextstatus(firmware->fwstatus);
0416     }
0417 
0418     return rtstatus;
0419 fail:
0420     return 0;
0421 }
0422 
0423 static u32 _rtl92s_fill_h2c_cmd(struct sk_buff *skb, u32 h2cbufferlen,
0424                 u32 cmd_num, u32 *pelement_id, u32 *pcmd_len,
0425                 u8 **pcmb_buffer, u8 *cmd_start_seq)
0426 {
0427     u32 totallen = 0, len = 0, tx_desclen = 0;
0428     u32 pre_continueoffset = 0;
0429     u8 *ph2c_buffer;
0430     u8 i = 0;
0431 
0432     do {
0433         /* 8 - Byte alignment */
0434         len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8);
0435 
0436         /* Buffer length is not enough */
0437         if (h2cbufferlen < totallen + len + tx_desclen)
0438             break;
0439 
0440         /* Clear content */
0441         ph2c_buffer = skb_put(skb, (u32)len);
0442         memset((ph2c_buffer + totallen + tx_desclen), 0, len);
0443 
0444         /* CMD len */
0445         le32p_replace_bits((__le32 *)(ph2c_buffer + totallen +
0446                           tx_desclen), pcmd_len[i],
0447                    GENMASK(15, 0));
0448 
0449         /* CMD ID */
0450         le32p_replace_bits((__le32 *)(ph2c_buffer + totallen +
0451                           tx_desclen), pelement_id[i],
0452                    GENMASK(23, 16));
0453 
0454         /* CMD Sequence */
0455         *cmd_start_seq = *cmd_start_seq % 0x80;
0456         le32p_replace_bits((__le32 *)(ph2c_buffer + totallen +
0457                           tx_desclen), *cmd_start_seq,
0458                    GENMASK(30, 24));
0459         ++*cmd_start_seq;
0460 
0461         /* Copy memory */
0462         memcpy((ph2c_buffer + totallen + tx_desclen +
0463             H2C_TX_CMD_HDR_LEN), pcmb_buffer[i], pcmd_len[i]);
0464 
0465         /* CMD continue */
0466         /* set the continue in prevoius cmd. */
0467         if (i < cmd_num - 1)
0468             le32p_replace_bits((__le32 *)(ph2c_buffer +
0469                               pre_continueoffset),
0470                        1, BIT(31));
0471 
0472         pre_continueoffset = totallen;
0473 
0474         totallen += len;
0475     } while (++i < cmd_num);
0476 
0477     return totallen;
0478 }
0479 
0480 static u32 _rtl92s_get_h2c_cmdlen(u32 h2cbufferlen, u32 cmd_num, u32 *pcmd_len)
0481 {
0482     u32 totallen = 0, len = 0, tx_desclen = 0;
0483     u8 i = 0;
0484 
0485     do {
0486         /* 8 - Byte alignment */
0487         len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8);
0488 
0489         /* Buffer length is not enough */
0490         if (h2cbufferlen < totallen + len + tx_desclen)
0491             break;
0492 
0493         totallen += len;
0494     } while (++i < cmd_num);
0495 
0496     return totallen + tx_desclen;
0497 }
0498 
0499 static bool _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw *hw, u8 h2c_cmd,
0500                      u8 *pcmd_buffer)
0501 {
0502     struct rtl_priv *rtlpriv = rtl_priv(hw);
0503     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0504     struct rtl_tcb_desc *cb_desc;
0505     struct sk_buff *skb;
0506     u32 element_id = 0;
0507     u32 cmd_len = 0;
0508     u32 len;
0509 
0510     switch (h2c_cmd) {
0511     case FW_H2C_SETPWRMODE:
0512         element_id = H2C_SETPWRMODE_CMD ;
0513         cmd_len = sizeof(struct h2c_set_pwrmode_parm);
0514         break;
0515     case FW_H2C_JOINBSSRPT:
0516         element_id = H2C_JOINBSSRPT_CMD;
0517         cmd_len = sizeof(struct h2c_joinbss_rpt_parm);
0518         break;
0519     case FW_H2C_WOWLAN_UPDATE_GTK:
0520         element_id = H2C_WOWLAN_UPDATE_GTK_CMD;
0521         cmd_len = sizeof(struct h2c_wpa_two_way_parm);
0522         break;
0523     case FW_H2C_WOWLAN_UPDATE_IV:
0524         element_id = H2C_WOWLAN_UPDATE_IV_CMD;
0525         cmd_len = sizeof(unsigned long long);
0526         break;
0527     case FW_H2C_WOWLAN_OFFLOAD:
0528         element_id = H2C_WOWLAN_FW_OFFLOAD;
0529         cmd_len = sizeof(u8);
0530         break;
0531     default:
0532         break;
0533     }
0534 
0535     len = _rtl92s_get_h2c_cmdlen(MAX_TRANSMIT_BUFFER_SIZE, 1, &cmd_len);
0536     skb = dev_alloc_skb(len);
0537     if (!skb)
0538         return false;
0539     cb_desc = (struct rtl_tcb_desc *)(skb->cb);
0540     cb_desc->queue_index = TXCMD_QUEUE;
0541     cb_desc->cmd_or_init = DESC_PACKET_TYPE_NORMAL;
0542     cb_desc->last_inipkt = false;
0543 
0544     _rtl92s_fill_h2c_cmd(skb, MAX_TRANSMIT_BUFFER_SIZE, 1, &element_id,
0545             &cmd_len, &pcmd_buffer, &rtlhal->h2c_txcmd_seq);
0546     _rtl92s_cmd_send_packet(hw, skb, false);
0547     rtlpriv->cfg->ops->tx_polling(hw, TXCMD_QUEUE);
0548 
0549     return true;
0550 }
0551 
0552 void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
0553 {
0554     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0555     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
0556     struct h2c_set_pwrmode_parm pwrmode;
0557     u16 max_wakeup_period = 0;
0558 
0559     pwrmode.mode = mode;
0560     pwrmode.flag_low_traffic_en = 0;
0561     pwrmode.flag_lpnav_en = 0;
0562     pwrmode.flag_rf_low_snr_en = 0;
0563     pwrmode.flag_dps_en = 0;
0564     pwrmode.bcn_rx_en = 0;
0565     pwrmode.bcn_to = 0;
0566     le16p_replace_bits((__le16 *)(((u8 *)(&pwrmode) + 8)),
0567                mac->vif->bss_conf.beacon_int, GENMASK(15, 0));
0568     pwrmode.app_itv = 0;
0569     pwrmode.awake_bcn_itvl = ppsc->reg_max_lps_awakeintvl;
0570     pwrmode.smart_ps = 1;
0571     pwrmode.bcn_pass_period = 10;
0572 
0573     /* Set beacon pass count */
0574     if (pwrmode.mode == FW_PS_MIN_MODE)
0575         max_wakeup_period = mac->vif->bss_conf.beacon_int;
0576     else if (pwrmode.mode == FW_PS_MAX_MODE)
0577         max_wakeup_period = mac->vif->bss_conf.beacon_int *
0578             mac->vif->bss_conf.dtim_period;
0579 
0580     if (max_wakeup_period >= 500)
0581         pwrmode.bcn_pass_cnt = 1;
0582     else if ((max_wakeup_period >= 300) && (max_wakeup_period < 500))
0583         pwrmode.bcn_pass_cnt = 2;
0584     else if ((max_wakeup_period >= 200) && (max_wakeup_period < 300))
0585         pwrmode.bcn_pass_cnt = 3;
0586     else if ((max_wakeup_period >= 20) && (max_wakeup_period < 200))
0587         pwrmode.bcn_pass_cnt = 5;
0588     else
0589         pwrmode.bcn_pass_cnt = 1;
0590 
0591     _rtl92s_firmware_set_h2c_cmd(hw, FW_H2C_SETPWRMODE, (u8 *)&pwrmode);
0592 
0593 }
0594 
0595 void rtl92s_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw,
0596         u8 mstatus, u8 ps_qosinfo)
0597 {
0598     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0599     struct h2c_joinbss_rpt_parm joinbss_rpt;
0600 
0601     joinbss_rpt.opmode = mstatus;
0602     joinbss_rpt.ps_qos_info = ps_qosinfo;
0603     joinbss_rpt.bssid[0] = mac->bssid[0];
0604     joinbss_rpt.bssid[1] = mac->bssid[1];
0605     joinbss_rpt.bssid[2] = mac->bssid[2];
0606     joinbss_rpt.bssid[3] = mac->bssid[3];
0607     joinbss_rpt.bssid[4] = mac->bssid[4];
0608     joinbss_rpt.bssid[5] = mac->bssid[5];
0609     le16p_replace_bits((__le16 *)(((u8 *)(&joinbss_rpt) + 8)),
0610                mac->vif->bss_conf.beacon_int, GENMASK(15, 0));
0611     le16p_replace_bits((__le16 *)(((u8 *)(&joinbss_rpt) + 10)),
0612                mac->assoc_id, GENMASK(15, 0));
0613 
0614     _rtl92s_firmware_set_h2c_cmd(hw, FW_H2C_JOINBSSRPT, (u8 *)&joinbss_rpt);
0615 }
0616