162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright(c) 2009-2012 Realtek Corporation.*/ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include "../wifi.h" 562306a36Sopenharmony_ci#include "../usb.h" 662306a36Sopenharmony_ci#include "../ps.h" 762306a36Sopenharmony_ci#include "../base.h" 862306a36Sopenharmony_ci#include "reg.h" 962306a36Sopenharmony_ci#include "def.h" 1062306a36Sopenharmony_ci#include "phy.h" 1162306a36Sopenharmony_ci#include "rf.h" 1262306a36Sopenharmony_ci#include "dm.h" 1362306a36Sopenharmony_ci#include "mac.h" 1462306a36Sopenharmony_ci#include "trx.h" 1562306a36Sopenharmony_ci#include "../rtl8192c/fw_common.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistatic int configvertoutep(struct ieee80211_hw *hw) 1862306a36Sopenharmony_ci{ 1962306a36Sopenharmony_ci u8 ep_cfg, txqsele; 2062306a36Sopenharmony_ci u8 ep_nums = 0; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 2362306a36Sopenharmony_ci struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); 2462306a36Sopenharmony_ci struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci rtlusb->out_queue_sel = 0; 2762306a36Sopenharmony_ci ep_cfg = rtl_read_byte(rtlpriv, REG_TEST_SIE_OPTIONAL); 2862306a36Sopenharmony_ci ep_cfg = (ep_cfg & USB_TEST_EP_MASK) >> USB_TEST_EP_SHIFT; 2962306a36Sopenharmony_ci switch (ep_cfg) { 3062306a36Sopenharmony_ci case 0: /* 2 bulk OUT, 1 bulk IN */ 3162306a36Sopenharmony_ci case 3: 3262306a36Sopenharmony_ci rtlusb->out_queue_sel = TX_SELE_HQ | TX_SELE_LQ; 3362306a36Sopenharmony_ci ep_nums = 2; 3462306a36Sopenharmony_ci break; 3562306a36Sopenharmony_ci case 1: /* 1 bulk IN/OUT => map all endpoint to Low queue */ 3662306a36Sopenharmony_ci case 2: /* 1 bulk IN, 1 bulk OUT => map all endpoint to High queue */ 3762306a36Sopenharmony_ci txqsele = rtl_read_byte(rtlpriv, REG_TEST_USB_TXQS); 3862306a36Sopenharmony_ci if (txqsele & 0x0F) /* /map all endpoint to High queue */ 3962306a36Sopenharmony_ci rtlusb->out_queue_sel = TX_SELE_HQ; 4062306a36Sopenharmony_ci else if (txqsele&0xF0) /* map all endpoint to Low queue */ 4162306a36Sopenharmony_ci rtlusb->out_queue_sel = TX_SELE_LQ; 4262306a36Sopenharmony_ci ep_nums = 1; 4362306a36Sopenharmony_ci break; 4462306a36Sopenharmony_ci default: 4562306a36Sopenharmony_ci break; 4662306a36Sopenharmony_ci } 4762306a36Sopenharmony_ci return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL; 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic int configvernoutep(struct ieee80211_hw *hw) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci u8 ep_cfg; 5362306a36Sopenharmony_ci u8 ep_nums = 0; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 5662306a36Sopenharmony_ci struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); 5762306a36Sopenharmony_ci struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci rtlusb->out_queue_sel = 0; 6062306a36Sopenharmony_ci /* Normal and High queue */ 6162306a36Sopenharmony_ci ep_cfg = rtl_read_byte(rtlpriv, (REG_NORMAL_SIE_EP + 1)); 6262306a36Sopenharmony_ci if (ep_cfg & USB_NORMAL_SIE_EP_MASK) { 6362306a36Sopenharmony_ci rtlusb->out_queue_sel |= TX_SELE_HQ; 6462306a36Sopenharmony_ci ep_nums++; 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci if ((ep_cfg >> USB_NORMAL_SIE_EP_SHIFT) & USB_NORMAL_SIE_EP_MASK) { 6762306a36Sopenharmony_ci rtlusb->out_queue_sel |= TX_SELE_NQ; 6862306a36Sopenharmony_ci ep_nums++; 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci /* Low queue */ 7162306a36Sopenharmony_ci ep_cfg = rtl_read_byte(rtlpriv, (REG_NORMAL_SIE_EP + 2)); 7262306a36Sopenharmony_ci if (ep_cfg & USB_NORMAL_SIE_EP_MASK) { 7362306a36Sopenharmony_ci rtlusb->out_queue_sel |= TX_SELE_LQ; 7462306a36Sopenharmony_ci ep_nums++; 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL; 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic void twooutepmapping(struct ieee80211_hw *hw, bool is_chip8, 8062306a36Sopenharmony_ci bool bwificfg, struct rtl_ep_map *ep_map) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci if (bwificfg) { /* for WMM */ 8562306a36Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, 8662306a36Sopenharmony_ci "USB Chip-B & WMM Setting.....\n"); 8762306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_BE] = 2; 8862306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_BK] = 3; 8962306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_VI] = 3; 9062306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_VO] = 2; 9162306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_MGT] = 2; 9262306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_BCN] = 2; 9362306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_HI] = 2; 9462306a36Sopenharmony_ci } else { /* typical setting */ 9562306a36Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, 9662306a36Sopenharmony_ci "USB typical Setting.....\n"); 9762306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_BE] = 3; 9862306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_BK] = 3; 9962306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_VI] = 2; 10062306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_VO] = 2; 10162306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_MGT] = 2; 10262306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_BCN] = 2; 10362306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_HI] = 2; 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic void threeoutepmapping(struct ieee80211_hw *hw, bool bwificfg, 10862306a36Sopenharmony_ci struct rtl_ep_map *ep_map) 10962306a36Sopenharmony_ci{ 11062306a36Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci if (bwificfg) { /* for WMM */ 11362306a36Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, 11462306a36Sopenharmony_ci "USB 3EP Setting for WMM.....\n"); 11562306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_BE] = 5; 11662306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_BK] = 3; 11762306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_VI] = 3; 11862306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_VO] = 2; 11962306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_MGT] = 2; 12062306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_BCN] = 2; 12162306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_HI] = 2; 12262306a36Sopenharmony_ci } else { /* typical setting */ 12362306a36Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, 12462306a36Sopenharmony_ci "USB 3EP Setting for typical.....\n"); 12562306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_BE] = 5; 12662306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_BK] = 5; 12762306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_VI] = 3; 12862306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_VO] = 2; 12962306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_MGT] = 2; 13062306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_BCN] = 2; 13162306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_HI] = 2; 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic void oneoutepmapping(struct ieee80211_hw *hw, struct rtl_ep_map *ep_map) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_BE] = 2; 13862306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_BK] = 2; 13962306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_VI] = 2; 14062306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_VO] = 2; 14162306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_MGT] = 2; 14262306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_BCN] = 2; 14362306a36Sopenharmony_ci ep_map->ep_mapping[RTL_TXQ_HI] = 2; 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic int _out_ep_mapping(struct ieee80211_hw *hw) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci int err = 0; 14962306a36Sopenharmony_ci bool ischipn, bwificfg = false; 15062306a36Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 15162306a36Sopenharmony_ci struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); 15262306a36Sopenharmony_ci struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); 15362306a36Sopenharmony_ci struct rtl_ep_map *ep_map = &(rtlusb->ep_map); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci ischipn = IS_NORMAL_CHIP(rtlhal->version); 15662306a36Sopenharmony_ci switch (rtlusb->out_ep_nums) { 15762306a36Sopenharmony_ci case 2: 15862306a36Sopenharmony_ci twooutepmapping(hw, ischipn, bwificfg, ep_map); 15962306a36Sopenharmony_ci break; 16062306a36Sopenharmony_ci case 3: 16162306a36Sopenharmony_ci /* Test chip doesn't support three out EPs. */ 16262306a36Sopenharmony_ci if (!ischipn) { 16362306a36Sopenharmony_ci err = -EINVAL; 16462306a36Sopenharmony_ci goto err_out; 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci threeoutepmapping(hw, ischipn, ep_map); 16762306a36Sopenharmony_ci break; 16862306a36Sopenharmony_ci case 1: 16962306a36Sopenharmony_ci oneoutepmapping(hw, ep_map); 17062306a36Sopenharmony_ci break; 17162306a36Sopenharmony_ci default: 17262306a36Sopenharmony_ci err = -EINVAL; 17362306a36Sopenharmony_ci break; 17462306a36Sopenharmony_ci } 17562306a36Sopenharmony_cierr_out: 17662306a36Sopenharmony_ci return err; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci} 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci/* endpoint mapping */ 18162306a36Sopenharmony_ciint rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 18462306a36Sopenharmony_ci int error = 0; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci if (likely(IS_NORMAL_CHIP(rtlhal->version))) 18762306a36Sopenharmony_ci error = configvernoutep(hw); 18862306a36Sopenharmony_ci else 18962306a36Sopenharmony_ci error = configvertoutep(hw); 19062306a36Sopenharmony_ci if (error) 19162306a36Sopenharmony_ci goto err_out; 19262306a36Sopenharmony_ci error = _out_ep_mapping(hw); 19362306a36Sopenharmony_ci if (error) 19462306a36Sopenharmony_ci goto err_out; 19562306a36Sopenharmony_cierr_out: 19662306a36Sopenharmony_ci return error; 19762306a36Sopenharmony_ci} 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ciu16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci u16 hw_queue_index; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci if (unlikely(ieee80211_is_beacon(fc))) { 20462306a36Sopenharmony_ci hw_queue_index = RTL_TXQ_BCN; 20562306a36Sopenharmony_ci goto out; 20662306a36Sopenharmony_ci } 20762306a36Sopenharmony_ci if (ieee80211_is_mgmt(fc)) { 20862306a36Sopenharmony_ci hw_queue_index = RTL_TXQ_MGT; 20962306a36Sopenharmony_ci goto out; 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci switch (mac80211_queue_index) { 21262306a36Sopenharmony_ci case 0: 21362306a36Sopenharmony_ci hw_queue_index = RTL_TXQ_VO; 21462306a36Sopenharmony_ci break; 21562306a36Sopenharmony_ci case 1: 21662306a36Sopenharmony_ci hw_queue_index = RTL_TXQ_VI; 21762306a36Sopenharmony_ci break; 21862306a36Sopenharmony_ci case 2: 21962306a36Sopenharmony_ci hw_queue_index = RTL_TXQ_BE; 22062306a36Sopenharmony_ci break; 22162306a36Sopenharmony_ci case 3: 22262306a36Sopenharmony_ci hw_queue_index = RTL_TXQ_BK; 22362306a36Sopenharmony_ci break; 22462306a36Sopenharmony_ci default: 22562306a36Sopenharmony_ci hw_queue_index = RTL_TXQ_BE; 22662306a36Sopenharmony_ci WARN_ONCE(true, "rtl8192cu: QSLT_BE queue, skb_queue:%d\n", 22762306a36Sopenharmony_ci mac80211_queue_index); 22862306a36Sopenharmony_ci break; 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ciout: 23162306a36Sopenharmony_ci return hw_queue_index; 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cistatic enum rtl_desc_qsel _rtl8192cu_mq_to_descq(struct ieee80211_hw *hw, 23562306a36Sopenharmony_ci __le16 fc, u16 mac80211_queue_index) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci enum rtl_desc_qsel qsel; 23862306a36Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci if (unlikely(ieee80211_is_beacon(fc))) { 24162306a36Sopenharmony_ci qsel = QSLT_BEACON; 24262306a36Sopenharmony_ci goto out; 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci if (ieee80211_is_mgmt(fc)) { 24562306a36Sopenharmony_ci qsel = QSLT_MGNT; 24662306a36Sopenharmony_ci goto out; 24762306a36Sopenharmony_ci } 24862306a36Sopenharmony_ci switch (mac80211_queue_index) { 24962306a36Sopenharmony_ci case 0: /* VO */ 25062306a36Sopenharmony_ci qsel = QSLT_VO; 25162306a36Sopenharmony_ci rtl_dbg(rtlpriv, COMP_USB, DBG_DMESG, 25262306a36Sopenharmony_ci "VO queue, set qsel = 0x%x\n", QSLT_VO); 25362306a36Sopenharmony_ci break; 25462306a36Sopenharmony_ci case 1: /* VI */ 25562306a36Sopenharmony_ci qsel = QSLT_VI; 25662306a36Sopenharmony_ci rtl_dbg(rtlpriv, COMP_USB, DBG_DMESG, 25762306a36Sopenharmony_ci "VI queue, set qsel = 0x%x\n", QSLT_VI); 25862306a36Sopenharmony_ci break; 25962306a36Sopenharmony_ci case 3: /* BK */ 26062306a36Sopenharmony_ci qsel = QSLT_BK; 26162306a36Sopenharmony_ci rtl_dbg(rtlpriv, COMP_USB, DBG_DMESG, 26262306a36Sopenharmony_ci "BK queue, set qsel = 0x%x\n", QSLT_BK); 26362306a36Sopenharmony_ci break; 26462306a36Sopenharmony_ci case 2: /* BE */ 26562306a36Sopenharmony_ci default: 26662306a36Sopenharmony_ci qsel = QSLT_BE; 26762306a36Sopenharmony_ci rtl_dbg(rtlpriv, COMP_USB, DBG_DMESG, 26862306a36Sopenharmony_ci "BE queue, set qsel = 0x%x\n", QSLT_BE); 26962306a36Sopenharmony_ci break; 27062306a36Sopenharmony_ci } 27162306a36Sopenharmony_ciout: 27262306a36Sopenharmony_ci return qsel; 27362306a36Sopenharmony_ci} 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci/* =============================================================== */ 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci/*---------------------------------------------------------------------- 27862306a36Sopenharmony_ci * 27962306a36Sopenharmony_ci * Rx handler 28062306a36Sopenharmony_ci * 28162306a36Sopenharmony_ci *---------------------------------------------------------------------- */ 28262306a36Sopenharmony_cibool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, 28362306a36Sopenharmony_ci struct rtl_stats *stats, 28462306a36Sopenharmony_ci struct ieee80211_rx_status *rx_status, 28562306a36Sopenharmony_ci u8 *pdesc8, struct sk_buff *skb) 28662306a36Sopenharmony_ci{ 28762306a36Sopenharmony_ci struct rx_fwinfo_92c *p_drvinfo; 28862306a36Sopenharmony_ci struct rx_desc_92c *p_desc = (struct rx_desc_92c *)pdesc8; 28962306a36Sopenharmony_ci __le32 *pdesc = (__le32 *)pdesc8; 29062306a36Sopenharmony_ci u32 phystatus = get_rx_desc_phy_status(pdesc); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci stats->length = (u16)get_rx_desc_pkt_len(pdesc); 29362306a36Sopenharmony_ci stats->rx_drvinfo_size = (u8)get_rx_desc_drvinfo_size(pdesc) * 29462306a36Sopenharmony_ci RX_DRV_INFO_SIZE_UNIT; 29562306a36Sopenharmony_ci stats->rx_bufshift = (u8)(get_rx_desc_shift(pdesc) & 0x03); 29662306a36Sopenharmony_ci stats->icv = (u16)get_rx_desc_icv(pdesc); 29762306a36Sopenharmony_ci stats->crc = (u16)get_rx_desc_crc32(pdesc); 29862306a36Sopenharmony_ci stats->hwerror = (stats->crc | stats->icv); 29962306a36Sopenharmony_ci stats->decrypted = !get_rx_desc_swdec(pdesc); 30062306a36Sopenharmony_ci stats->rate = (u8)get_rx_desc_rx_mcs(pdesc); 30162306a36Sopenharmony_ci stats->shortpreamble = (u16)get_rx_desc_splcp(pdesc); 30262306a36Sopenharmony_ci stats->isampdu = (bool)(get_rx_desc_paggr(pdesc) == 1); 30362306a36Sopenharmony_ci stats->isfirst_ampdu = (bool)((get_rx_desc_paggr(pdesc) == 1) && 30462306a36Sopenharmony_ci (get_rx_desc_faggr(pdesc) == 1)); 30562306a36Sopenharmony_ci stats->timestamp_low = get_rx_desc_tsfl(pdesc); 30662306a36Sopenharmony_ci stats->rx_is40mhzpacket = (bool)get_rx_desc_bw(pdesc); 30762306a36Sopenharmony_ci stats->is_ht = (bool)get_rx_desc_rx_ht(pdesc); 30862306a36Sopenharmony_ci rx_status->freq = hw->conf.chandef.chan->center_freq; 30962306a36Sopenharmony_ci rx_status->band = hw->conf.chandef.chan->band; 31062306a36Sopenharmony_ci if (get_rx_desc_crc32(pdesc)) 31162306a36Sopenharmony_ci rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; 31262306a36Sopenharmony_ci if (!get_rx_desc_swdec(pdesc)) 31362306a36Sopenharmony_ci rx_status->flag |= RX_FLAG_DECRYPTED; 31462306a36Sopenharmony_ci if (get_rx_desc_bw(pdesc)) 31562306a36Sopenharmony_ci rx_status->bw = RATE_INFO_BW_40; 31662306a36Sopenharmony_ci if (get_rx_desc_rx_ht(pdesc)) 31762306a36Sopenharmony_ci rx_status->encoding = RX_ENC_HT; 31862306a36Sopenharmony_ci rx_status->flag |= RX_FLAG_MACTIME_START; 31962306a36Sopenharmony_ci if (stats->decrypted) 32062306a36Sopenharmony_ci rx_status->flag |= RX_FLAG_DECRYPTED; 32162306a36Sopenharmony_ci rx_status->rate_idx = rtlwifi_rate_mapping(hw, stats->is_ht, 32262306a36Sopenharmony_ci false, stats->rate); 32362306a36Sopenharmony_ci rx_status->mactime = get_rx_desc_tsfl(pdesc); 32462306a36Sopenharmony_ci if (phystatus) { 32562306a36Sopenharmony_ci p_drvinfo = (struct rx_fwinfo_92c *)(skb->data + 32662306a36Sopenharmony_ci stats->rx_bufshift); 32762306a36Sopenharmony_ci rtl92c_translate_rx_signal_stuff(hw, skb, stats, p_desc, 32862306a36Sopenharmony_ci p_drvinfo); 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci /*rx_status->qual = stats->signal; */ 33162306a36Sopenharmony_ci rx_status->signal = stats->recvsignalpower + 10; 33262306a36Sopenharmony_ci return true; 33362306a36Sopenharmony_ci} 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci#define RTL_RX_DRV_INFO_UNIT 8 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_cistatic void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb) 33862306a36Sopenharmony_ci{ 33962306a36Sopenharmony_ci struct ieee80211_rx_status *rx_status = 34062306a36Sopenharmony_ci (struct ieee80211_rx_status *)IEEE80211_SKB_RXCB(skb); 34162306a36Sopenharmony_ci u32 skb_len, pkt_len, drvinfo_len; 34262306a36Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 34362306a36Sopenharmony_ci __le32 *rxdesc; 34462306a36Sopenharmony_ci struct rtl_stats stats = { 34562306a36Sopenharmony_ci .signal = 0, 34662306a36Sopenharmony_ci .rate = 0, 34762306a36Sopenharmony_ci }; 34862306a36Sopenharmony_ci struct rx_fwinfo_92c *p_drvinfo; 34962306a36Sopenharmony_ci bool bv; 35062306a36Sopenharmony_ci __le16 fc; 35162306a36Sopenharmony_ci struct ieee80211_hdr *hdr; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci memset(rx_status, 0, sizeof(*rx_status)); 35462306a36Sopenharmony_ci rxdesc = (__le32 *)skb->data; 35562306a36Sopenharmony_ci skb_len = skb->len; 35662306a36Sopenharmony_ci drvinfo_len = (get_rx_desc_drvinfo_size(rxdesc) * RTL_RX_DRV_INFO_UNIT); 35762306a36Sopenharmony_ci pkt_len = get_rx_desc_pkt_len(rxdesc); 35862306a36Sopenharmony_ci /* TODO: Error recovery. drop this skb or something. */ 35962306a36Sopenharmony_ci WARN_ON(skb_len < (pkt_len + RTL_RX_DESC_SIZE + drvinfo_len)); 36062306a36Sopenharmony_ci stats.length = (u16)get_rx_desc_pkt_len(rxdesc); 36162306a36Sopenharmony_ci stats.rx_drvinfo_size = (u8)get_rx_desc_drvinfo_size(rxdesc) * 36262306a36Sopenharmony_ci RX_DRV_INFO_SIZE_UNIT; 36362306a36Sopenharmony_ci stats.rx_bufshift = (u8)(get_rx_desc_shift(rxdesc) & 0x03); 36462306a36Sopenharmony_ci stats.icv = (u16)get_rx_desc_icv(rxdesc); 36562306a36Sopenharmony_ci stats.crc = (u16)get_rx_desc_crc32(rxdesc); 36662306a36Sopenharmony_ci stats.hwerror = (stats.crc | stats.icv); 36762306a36Sopenharmony_ci stats.decrypted = !get_rx_desc_swdec(rxdesc); 36862306a36Sopenharmony_ci stats.rate = (u8)get_rx_desc_rx_mcs(rxdesc); 36962306a36Sopenharmony_ci stats.shortpreamble = (u16)get_rx_desc_splcp(rxdesc); 37062306a36Sopenharmony_ci stats.isampdu = (bool)((get_rx_desc_paggr(rxdesc) == 1) && 37162306a36Sopenharmony_ci (get_rx_desc_faggr(rxdesc) == 1)); 37262306a36Sopenharmony_ci stats.timestamp_low = get_rx_desc_tsfl(rxdesc); 37362306a36Sopenharmony_ci stats.rx_is40mhzpacket = (bool)get_rx_desc_bw(rxdesc); 37462306a36Sopenharmony_ci stats.is_ht = (bool)get_rx_desc_rx_ht(rxdesc); 37562306a36Sopenharmony_ci /* TODO: is center_freq changed when doing scan? */ 37662306a36Sopenharmony_ci /* TODO: Shall we add protection or just skip those two step? */ 37762306a36Sopenharmony_ci rx_status->freq = hw->conf.chandef.chan->center_freq; 37862306a36Sopenharmony_ci rx_status->band = hw->conf.chandef.chan->band; 37962306a36Sopenharmony_ci if (get_rx_desc_crc32(rxdesc)) 38062306a36Sopenharmony_ci rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; 38162306a36Sopenharmony_ci if (!get_rx_desc_swdec(rxdesc)) 38262306a36Sopenharmony_ci rx_status->flag |= RX_FLAG_DECRYPTED; 38362306a36Sopenharmony_ci if (get_rx_desc_bw(rxdesc)) 38462306a36Sopenharmony_ci rx_status->bw = RATE_INFO_BW_40; 38562306a36Sopenharmony_ci if (get_rx_desc_rx_ht(rxdesc)) 38662306a36Sopenharmony_ci rx_status->encoding = RX_ENC_HT; 38762306a36Sopenharmony_ci /* Data rate */ 38862306a36Sopenharmony_ci rx_status->rate_idx = rtlwifi_rate_mapping(hw, stats.is_ht, 38962306a36Sopenharmony_ci false, stats.rate); 39062306a36Sopenharmony_ci /* There is a phy status after this rx descriptor. */ 39162306a36Sopenharmony_ci if (get_rx_desc_phy_status(rxdesc)) { 39262306a36Sopenharmony_ci p_drvinfo = (struct rx_fwinfo_92c *)(rxdesc + RTL_RX_DESC_SIZE); 39362306a36Sopenharmony_ci rtl92c_translate_rx_signal_stuff(hw, skb, &stats, 39462306a36Sopenharmony_ci (struct rx_desc_92c *)rxdesc, p_drvinfo); 39562306a36Sopenharmony_ci } 39662306a36Sopenharmony_ci skb_pull(skb, (drvinfo_len + RTL_RX_DESC_SIZE)); 39762306a36Sopenharmony_ci hdr = rtl_get_hdr(skb); 39862306a36Sopenharmony_ci fc = hdr->frame_control; 39962306a36Sopenharmony_ci bv = ieee80211_is_probe_resp(fc); 40062306a36Sopenharmony_ci if (bv) 40162306a36Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, 40262306a36Sopenharmony_ci "Got probe response frame\n"); 40362306a36Sopenharmony_ci if (ieee80211_is_beacon(fc)) 40462306a36Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "Got beacon frame\n"); 40562306a36Sopenharmony_ci if (ieee80211_is_data(fc)) 40662306a36Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "Got data frame\n"); 40762306a36Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, 40862306a36Sopenharmony_ci "Fram: fc = 0x%X addr1 = 0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:0x%02X\n", 40962306a36Sopenharmony_ci fc, 41062306a36Sopenharmony_ci (u32)hdr->addr1[0], (u32)hdr->addr1[1], 41162306a36Sopenharmony_ci (u32)hdr->addr1[2], (u32)hdr->addr1[3], 41262306a36Sopenharmony_ci (u32)hdr->addr1[4], (u32)hdr->addr1[5]); 41362306a36Sopenharmony_ci ieee80211_rx(hw, skb); 41462306a36Sopenharmony_ci} 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_civoid rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb) 41762306a36Sopenharmony_ci{ 41862306a36Sopenharmony_ci _rtl_rx_process(hw, skb); 41962306a36Sopenharmony_ci} 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci/*---------------------------------------------------------------------- 42262306a36Sopenharmony_ci * 42362306a36Sopenharmony_ci * Tx handler 42462306a36Sopenharmony_ci * 42562306a36Sopenharmony_ci *---------------------------------------------------------------------- */ 42662306a36Sopenharmony_civoid rtl8192c_tx_cleanup(struct ieee80211_hw *hw, struct sk_buff *skb) 42762306a36Sopenharmony_ci{ 42862306a36Sopenharmony_ci} 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ciint rtl8192c_tx_post_hdl(struct ieee80211_hw *hw, struct urb *urb, 43162306a36Sopenharmony_ci struct sk_buff *skb) 43262306a36Sopenharmony_ci{ 43362306a36Sopenharmony_ci return 0; 43462306a36Sopenharmony_ci} 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_cistruct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *hw, 43762306a36Sopenharmony_ci struct sk_buff_head *list) 43862306a36Sopenharmony_ci{ 43962306a36Sopenharmony_ci return skb_dequeue(list); 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci/*======================================== trx ===============================*/ 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_cistatic void _rtl_fill_usb_tx_desc(__le32 *txdesc) 44562306a36Sopenharmony_ci{ 44662306a36Sopenharmony_ci set_tx_desc_own(txdesc, 1); 44762306a36Sopenharmony_ci set_tx_desc_last_seg(txdesc, 1); 44862306a36Sopenharmony_ci set_tx_desc_first_seg(txdesc, 1); 44962306a36Sopenharmony_ci} 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci/* 45262306a36Sopenharmony_ci * For HW recovery information 45362306a36Sopenharmony_ci */ 45462306a36Sopenharmony_cistatic void _rtl_tx_desc_checksum(__le32 *txdesc) 45562306a36Sopenharmony_ci{ 45662306a36Sopenharmony_ci __le16 *ptr = (__le16 *)txdesc; 45762306a36Sopenharmony_ci u16 checksum = 0; 45862306a36Sopenharmony_ci u32 index; 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci /* Clear first */ 46162306a36Sopenharmony_ci set_tx_desc_tx_desc_checksum(txdesc, 0); 46262306a36Sopenharmony_ci for (index = 0; index < 16; index++) 46362306a36Sopenharmony_ci checksum = checksum ^ le16_to_cpu(*(ptr + index)); 46462306a36Sopenharmony_ci set_tx_desc_tx_desc_checksum(txdesc, checksum); 46562306a36Sopenharmony_ci} 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_civoid rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, 46862306a36Sopenharmony_ci struct ieee80211_hdr *hdr, u8 *pdesc_tx, 46962306a36Sopenharmony_ci u8 *pbd_desc_tx, struct ieee80211_tx_info *info, 47062306a36Sopenharmony_ci struct ieee80211_sta *sta, 47162306a36Sopenharmony_ci struct sk_buff *skb, 47262306a36Sopenharmony_ci u8 queue_index, 47362306a36Sopenharmony_ci struct rtl_tcb_desc *tcb_desc) 47462306a36Sopenharmony_ci{ 47562306a36Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 47662306a36Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 47762306a36Sopenharmony_ci struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 47862306a36Sopenharmony_ci bool defaultadapter = true; 47962306a36Sopenharmony_ci u8 *qc = ieee80211_get_qos_ctl(hdr); 48062306a36Sopenharmony_ci u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; 48162306a36Sopenharmony_ci u16 seq_number; 48262306a36Sopenharmony_ci __le16 fc = hdr->frame_control; 48362306a36Sopenharmony_ci u8 rate_flag = info->control.rates[0].flags; 48462306a36Sopenharmony_ci u16 pktlen = skb->len; 48562306a36Sopenharmony_ci enum rtl_desc_qsel fw_qsel = _rtl8192cu_mq_to_descq(hw, fc, 48662306a36Sopenharmony_ci skb_get_queue_mapping(skb)); 48762306a36Sopenharmony_ci u8 *txdesc8; 48862306a36Sopenharmony_ci __le32 *txdesc; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; 49162306a36Sopenharmony_ci rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc); 49262306a36Sopenharmony_ci txdesc8 = skb_push(skb, RTL_TX_HEADER_SIZE); 49362306a36Sopenharmony_ci txdesc = (__le32 *)txdesc8; 49462306a36Sopenharmony_ci memset(txdesc, 0, RTL_TX_HEADER_SIZE); 49562306a36Sopenharmony_ci set_tx_desc_pkt_size(txdesc, pktlen); 49662306a36Sopenharmony_ci set_tx_desc_linip(txdesc, 0); 49762306a36Sopenharmony_ci set_tx_desc_pkt_offset(txdesc, RTL_DUMMY_OFFSET); 49862306a36Sopenharmony_ci set_tx_desc_offset(txdesc, RTL_TX_HEADER_SIZE); 49962306a36Sopenharmony_ci set_tx_desc_tx_rate(txdesc, tcb_desc->hw_rate); 50062306a36Sopenharmony_ci if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble) 50162306a36Sopenharmony_ci set_tx_desc_data_shortgi(txdesc, 1); 50262306a36Sopenharmony_ci if (mac->tids[tid].agg.agg_state == RTL_AGG_ON && 50362306a36Sopenharmony_ci info->flags & IEEE80211_TX_CTL_AMPDU) { 50462306a36Sopenharmony_ci set_tx_desc_agg_enable(txdesc, 1); 50562306a36Sopenharmony_ci set_tx_desc_max_agg_num(txdesc, 0x14); 50662306a36Sopenharmony_ci } else { 50762306a36Sopenharmony_ci set_tx_desc_agg_break(txdesc, 1); 50862306a36Sopenharmony_ci } 50962306a36Sopenharmony_ci set_tx_desc_seq(txdesc, seq_number); 51062306a36Sopenharmony_ci set_tx_desc_rts_enable(txdesc, 51162306a36Sopenharmony_ci ((tcb_desc->rts_enable && 51262306a36Sopenharmony_ci !tcb_desc->cts_enable) ? 1 : 0)); 51362306a36Sopenharmony_ci set_tx_desc_hw_rts_enable(txdesc, 51462306a36Sopenharmony_ci ((tcb_desc->rts_enable || 51562306a36Sopenharmony_ci tcb_desc->cts_enable) ? 1 : 0)); 51662306a36Sopenharmony_ci set_tx_desc_cts2self(txdesc, ((tcb_desc->cts_enable) ? 1 : 0)); 51762306a36Sopenharmony_ci set_tx_desc_rts_stbc(txdesc, ((tcb_desc->rts_stbc) ? 1 : 0)); 51862306a36Sopenharmony_ci set_tx_desc_rts_rate(txdesc, tcb_desc->rts_rate); 51962306a36Sopenharmony_ci set_tx_desc_rts_bw(txdesc, 0); 52062306a36Sopenharmony_ci set_tx_desc_rts_sc(txdesc, tcb_desc->rts_sc); 52162306a36Sopenharmony_ci set_tx_desc_rts_short(txdesc, 52262306a36Sopenharmony_ci ((tcb_desc->rts_rate <= DESC_RATE54M) ? 52362306a36Sopenharmony_ci (tcb_desc->rts_use_shortpreamble ? 1 : 0) 52462306a36Sopenharmony_ci : (tcb_desc->rts_use_shortgi ? 1 : 0))); 52562306a36Sopenharmony_ci if (mac->bw_40) { 52662306a36Sopenharmony_ci if (rate_flag & IEEE80211_TX_RC_DUP_DATA) { 52762306a36Sopenharmony_ci set_tx_desc_data_bw(txdesc, 1); 52862306a36Sopenharmony_ci set_tx_desc_data_sc(txdesc, 3); 52962306a36Sopenharmony_ci } else if(rate_flag & IEEE80211_TX_RC_40_MHZ_WIDTH){ 53062306a36Sopenharmony_ci set_tx_desc_data_bw(txdesc, 1); 53162306a36Sopenharmony_ci set_tx_desc_data_sc(txdesc, mac->cur_40_prime_sc); 53262306a36Sopenharmony_ci } else { 53362306a36Sopenharmony_ci set_tx_desc_data_bw(txdesc, 0); 53462306a36Sopenharmony_ci set_tx_desc_data_sc(txdesc, 0); 53562306a36Sopenharmony_ci } 53662306a36Sopenharmony_ci } else { 53762306a36Sopenharmony_ci set_tx_desc_data_bw(txdesc, 0); 53862306a36Sopenharmony_ci set_tx_desc_data_sc(txdesc, 0); 53962306a36Sopenharmony_ci } 54062306a36Sopenharmony_ci rcu_read_lock(); 54162306a36Sopenharmony_ci sta = ieee80211_find_sta(mac->vif, mac->bssid); 54262306a36Sopenharmony_ci if (sta) { 54362306a36Sopenharmony_ci u8 ampdu_density = sta->deflink.ht_cap.ampdu_density; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci set_tx_desc_ampdu_density(txdesc, ampdu_density); 54662306a36Sopenharmony_ci } 54762306a36Sopenharmony_ci rcu_read_unlock(); 54862306a36Sopenharmony_ci if (info->control.hw_key) { 54962306a36Sopenharmony_ci struct ieee80211_key_conf *keyconf = info->control.hw_key; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci switch (keyconf->cipher) { 55262306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_WEP40: 55362306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_WEP104: 55462306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_TKIP: 55562306a36Sopenharmony_ci set_tx_desc_sec_type(txdesc, 0x1); 55662306a36Sopenharmony_ci break; 55762306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_CCMP: 55862306a36Sopenharmony_ci set_tx_desc_sec_type(txdesc, 0x3); 55962306a36Sopenharmony_ci break; 56062306a36Sopenharmony_ci default: 56162306a36Sopenharmony_ci set_tx_desc_sec_type(txdesc, 0x0); 56262306a36Sopenharmony_ci break; 56362306a36Sopenharmony_ci } 56462306a36Sopenharmony_ci } 56562306a36Sopenharmony_ci set_tx_desc_pkt_id(txdesc, 0); 56662306a36Sopenharmony_ci set_tx_desc_queue_sel(txdesc, fw_qsel); 56762306a36Sopenharmony_ci set_tx_desc_data_rate_fb_limit(txdesc, 0x1F); 56862306a36Sopenharmony_ci set_tx_desc_rts_rate_fb_limit(txdesc, 0xF); 56962306a36Sopenharmony_ci set_tx_desc_disable_fb(txdesc, 0); 57062306a36Sopenharmony_ci set_tx_desc_use_rate(txdesc, tcb_desc->use_driver_rate ? 1 : 0); 57162306a36Sopenharmony_ci if (ieee80211_is_data_qos(fc)) { 57262306a36Sopenharmony_ci if (mac->rdg_en) { 57362306a36Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE, 57462306a36Sopenharmony_ci "Enable RDG function\n"); 57562306a36Sopenharmony_ci set_tx_desc_rdg_enable(txdesc, 1); 57662306a36Sopenharmony_ci set_tx_desc_htc(txdesc, 1); 57762306a36Sopenharmony_ci } 57862306a36Sopenharmony_ci } 57962306a36Sopenharmony_ci if (rtlpriv->dm.useramask) { 58062306a36Sopenharmony_ci set_tx_desc_rate_id(txdesc, tcb_desc->ratr_index); 58162306a36Sopenharmony_ci set_tx_desc_macid(txdesc, tcb_desc->mac_id); 58262306a36Sopenharmony_ci } else { 58362306a36Sopenharmony_ci set_tx_desc_rate_id(txdesc, 0xC + tcb_desc->ratr_index); 58462306a36Sopenharmony_ci set_tx_desc_macid(txdesc, tcb_desc->ratr_index); 58562306a36Sopenharmony_ci } 58662306a36Sopenharmony_ci if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps && 58762306a36Sopenharmony_ci ppsc->fwctrl_lps) { 58862306a36Sopenharmony_ci set_tx_desc_hwseq_en(txdesc, 1); 58962306a36Sopenharmony_ci set_tx_desc_pkt_id(txdesc, 8); 59062306a36Sopenharmony_ci if (!defaultadapter) 59162306a36Sopenharmony_ci set_tx_desc_qos(txdesc, 1); 59262306a36Sopenharmony_ci } 59362306a36Sopenharmony_ci if (ieee80211_has_morefrags(fc)) 59462306a36Sopenharmony_ci set_tx_desc_more_frag(txdesc, 1); 59562306a36Sopenharmony_ci if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || 59662306a36Sopenharmony_ci is_broadcast_ether_addr(ieee80211_get_DA(hdr))) 59762306a36Sopenharmony_ci set_tx_desc_bmc(txdesc, 1); 59862306a36Sopenharmony_ci _rtl_fill_usb_tx_desc(txdesc); 59962306a36Sopenharmony_ci _rtl_tx_desc_checksum(txdesc); 60062306a36Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE, "==>\n"); 60162306a36Sopenharmony_ci} 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_civoid rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 *pdesc8, 60462306a36Sopenharmony_ci u32 buffer_len, bool is_pspoll) 60562306a36Sopenharmony_ci{ 60662306a36Sopenharmony_ci __le32 *pdesc = (__le32 *)pdesc8; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci /* Clear all status */ 60962306a36Sopenharmony_ci memset(pdesc, 0, RTL_TX_HEADER_SIZE); 61062306a36Sopenharmony_ci set_tx_desc_first_seg(pdesc, 1); /* bFirstSeg; */ 61162306a36Sopenharmony_ci set_tx_desc_last_seg(pdesc, 1); /* bLastSeg; */ 61262306a36Sopenharmony_ci set_tx_desc_offset(pdesc, RTL_TX_HEADER_SIZE); /* Offset = 32 */ 61362306a36Sopenharmony_ci set_tx_desc_pkt_size(pdesc, buffer_len); /* Buffer size + command hdr */ 61462306a36Sopenharmony_ci set_tx_desc_queue_sel(pdesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */ 61562306a36Sopenharmony_ci /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error 61662306a36Sopenharmony_ci * vlaue by Hw. */ 61762306a36Sopenharmony_ci if (is_pspoll) { 61862306a36Sopenharmony_ci set_tx_desc_nav_use_hdr(pdesc, 1); 61962306a36Sopenharmony_ci } else { 62062306a36Sopenharmony_ci set_tx_desc_hwseq_en(pdesc, 1); /* Hw set sequence number */ 62162306a36Sopenharmony_ci set_tx_desc_pkt_id(pdesc, BIT(3)); /* set bit3 to 1. */ 62262306a36Sopenharmony_ci } 62362306a36Sopenharmony_ci set_tx_desc_use_rate(pdesc, 1); /* use data rate which is set by Sw */ 62462306a36Sopenharmony_ci set_tx_desc_own(pdesc, 1); 62562306a36Sopenharmony_ci set_tx_desc_tx_rate(pdesc, DESC_RATE1M); 62662306a36Sopenharmony_ci _rtl_tx_desc_checksum(pdesc); 62762306a36Sopenharmony_ci} 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_civoid rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, 63062306a36Sopenharmony_ci u8 *pdesc8, bool firstseg, 63162306a36Sopenharmony_ci bool lastseg, struct sk_buff *skb) 63262306a36Sopenharmony_ci{ 63362306a36Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 63462306a36Sopenharmony_ci u8 fw_queue = QSLT_BEACON; 63562306a36Sopenharmony_ci struct ieee80211_hdr *hdr = rtl_get_hdr(skb); 63662306a36Sopenharmony_ci __le16 fc = hdr->frame_control; 63762306a36Sopenharmony_ci __le32 *pdesc = (__le32 *)pdesc8; 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE); 64062306a36Sopenharmony_ci if (firstseg) 64162306a36Sopenharmony_ci set_tx_desc_offset(pdesc, RTL_TX_HEADER_SIZE); 64262306a36Sopenharmony_ci set_tx_desc_tx_rate(pdesc, DESC_RATE1M); 64362306a36Sopenharmony_ci set_tx_desc_seq(pdesc, 0); 64462306a36Sopenharmony_ci set_tx_desc_linip(pdesc, 0); 64562306a36Sopenharmony_ci set_tx_desc_queue_sel(pdesc, fw_queue); 64662306a36Sopenharmony_ci set_tx_desc_first_seg(pdesc, 1); 64762306a36Sopenharmony_ci set_tx_desc_last_seg(pdesc, 1); 64862306a36Sopenharmony_ci set_tx_desc_rate_id(pdesc, 7); 64962306a36Sopenharmony_ci set_tx_desc_macid(pdesc, 0); 65062306a36Sopenharmony_ci set_tx_desc_own(pdesc, 1); 65162306a36Sopenharmony_ci set_tx_desc_pkt_size(pdesc, (u16)skb->len); 65262306a36Sopenharmony_ci set_tx_desc_first_seg(pdesc, 1); 65362306a36Sopenharmony_ci set_tx_desc_last_seg(pdesc, 1); 65462306a36Sopenharmony_ci set_tx_desc_offset(pdesc, 0x20); 65562306a36Sopenharmony_ci set_tx_desc_use_rate(pdesc, 1); 65662306a36Sopenharmony_ci if (!ieee80211_is_data_qos(fc)) { 65762306a36Sopenharmony_ci set_tx_desc_hwseq_en(pdesc, 1); 65862306a36Sopenharmony_ci set_tx_desc_pkt_id(pdesc, 8); 65962306a36Sopenharmony_ci } 66062306a36Sopenharmony_ci RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C Tx Cmd Content", 66162306a36Sopenharmony_ci pdesc, RTL_TX_DESC_SIZE); 66262306a36Sopenharmony_ci} 663