diff options
Diffstat (limited to 'drivers/net/wireless/rtlwifi/rtl8192ce/trx.c')
| -rw-r--r-- | drivers/net/wireless/rtlwifi/rtl8192ce/trx.c | 763 |
1 files changed, 243 insertions, 520 deletions
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index bf5852f2d63..8f04817cb7e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2009-2010 Realtek Corporation. + * Copyright(c) 2009-2012 Realtek Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -30,146 +30,23 @@ #include "../wifi.h" #include "../pci.h" #include "../base.h" +#include "../stats.h" #include "reg.h" #include "def.h" #include "phy.h" #include "trx.h" #include "led.h" -static enum rtl_desc_qsel _rtl92ce_map_hwqueue_to_fwqueue(u16 fc, - unsigned int - skb_queue) +static u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) { - enum rtl_desc_qsel qsel; + __le16 fc = rtl_get_fc(skb); - if (unlikely(ieee80211_is_beacon(fc))) { - qsel = QSLT_BEACON; - return qsel; - } - - if (ieee80211_is_mgmt(fc)) { - qsel = QSLT_MGNT; - return qsel; - } + if (unlikely(ieee80211_is_beacon(fc))) + return QSLT_BEACON; + if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) + return QSLT_MGNT; - switch (skb_queue) { - case VO_QUEUE: - qsel = QSLT_VO; - break; - case VI_QUEUE: - qsel = QSLT_VI; - break; - case BE_QUEUE: - qsel = QSLT_BE; - break; - case BK_QUEUE: - qsel = QSLT_BK; - break; - default: - qsel = QSLT_BE; - RT_ASSERT(false, ("BE queue, skb_queue:%d," - " set qsel = 0x%X\n", skb_queue, QSLT_BE)); - break; - } - return qsel; -} - -static int _rtl92ce_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu) -{ - int rate_idx; - - if (first_ampdu) { - if (false == isht) { - switch (desc_rate) { - case DESC92C_RATE1M: - rate_idx = 0; - break; - case DESC92C_RATE2M: - rate_idx = 1; - break; - case DESC92C_RATE5_5M: - rate_idx = 2; - break; - case DESC92C_RATE11M: - rate_idx = 3; - break; - case DESC92C_RATE6M: - rate_idx = 4; - break; - case DESC92C_RATE9M: - rate_idx = 5; - break; - case DESC92C_RATE12M: - rate_idx = 6; - break; - case DESC92C_RATE18M: - rate_idx = 7; - break; - case DESC92C_RATE24M: - rate_idx = 8; - break; - case DESC92C_RATE36M: - rate_idx = 9; - break; - case DESC92C_RATE48M: - rate_idx = 10; - break; - case DESC92C_RATE54M: - rate_idx = 11; - break; - default: - rate_idx = 0; - break; - } - } else { - rate_idx = 11; - } - - return rate_idx; - } - - switch (desc_rate) { - case DESC92C_RATE1M: - rate_idx = 0; - break; - case DESC92C_RATE2M: - rate_idx = 1; - break; - case DESC92C_RATE5_5M: - rate_idx = 2; - break; - case DESC92C_RATE11M: - rate_idx = 3; - break; - case DESC92C_RATE6M: - rate_idx = 4; - break; - case DESC92C_RATE9M: - rate_idx = 5; - break; - case DESC92C_RATE12M: - rate_idx = 6; - break; - case DESC92C_RATE18M: - rate_idx = 7; - break; - case DESC92C_RATE24M: - rate_idx = 8; - break; - case DESC92C_RATE36M: - rate_idx = 9; - break; - case DESC92C_RATE48M: - rate_idx = 10; - break; - case DESC92C_RATE54M: - rate_idx = 11; - break; - default: - rate_idx = 11; - break; - } - return rate_idx; + return skb->priority; } static u8 _rtl92c_query_rxpwrpercentage(char antpower) @@ -202,16 +79,6 @@ static u8 _rtl92c_evm_db_to_percentage(char value) return ret_val; } -static long _rtl92ce_translate_todbm(struct ieee80211_hw *hw, - u8 signal_strength_index) -{ - long signal_power; - - signal_power = (long)((signal_strength_index + 1) >> 1); - signal_power -= 95; - return signal_power; -} - static long _rtl92ce_signal_scale_mapping(struct ieee80211_hw *hw, long currsig) { @@ -245,34 +112,38 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, struct rtl_stats *pstats, struct rx_desc_92c *pdesc, struct rx_fwinfo_92c *p_drvinfo, - bool bpacket_match_bssid, - bool bpacket_toself, - bool b_packet_beacon) + bool packet_match_bssid, + bool packet_toself, + bool packet_beacon) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct phy_sts_cck_8192s_t *cck_buf; - s8 rx_pwr_all, rx_pwr[4]; - u8 rf_rx_num, evm, pwdb_all; + struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); + s8 rx_pwr_all = 0, rx_pwr[4]; + u8 evm, pwdb_all, rf_rx_num = 0; u8 i, max_spatial_stream; - u32 rssi, total_rssi; + u32 rssi, total_rssi = 0; bool is_cck_rate; is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc); - pstats->b_packet_matchbssid = bpacket_match_bssid; - pstats->b_packet_toself = bpacket_toself; - pstats->b_is_cck = is_cck_rate; - pstats->b_packet_beacon = b_packet_beacon; - pstats->b_is_cck = is_cck_rate; - pstats->rx_mimo_signalquality[0] = -1; - pstats->rx_mimo_signalquality[1] = -1; + pstats->packet_matchbssid = packet_match_bssid; + pstats->packet_toself = packet_toself; + pstats->is_cck = is_cck_rate; + pstats->packet_beacon = packet_beacon; + pstats->rx_mimo_sig_qual[0] = -1; + pstats->rx_mimo_sig_qual[1] = -1; if (is_cck_rate) { u8 report, cck_highpwr; cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; - cck_highpwr = (u8) rtl_get_bbreg(hw, - RFPGA0_XA_HSSIPARAMETER2, - BIT(9)); + if (ppsc->rfpwr_state == ERFON) + cck_highpwr = (u8) rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER2, + BIT(9)); + else + cck_highpwr = false; + if (!cck_highpwr) { u8 cck_agc_rpt = cck_buf->cck_agc_rpt; report = cck_buf->cck_agc_rpt & 0xc0; @@ -311,11 +182,31 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, } } - pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all); + pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); + /* CCK gain is smaller than OFDM/MCS gain, + * so we add gain diff by experiences, + * the val is 6 + */ + pwdb_all += 6; + if (pwdb_all > 100) + pwdb_all = 100; + /* modify the offset to make the same + * gain index with OFDM. + */ + if (pwdb_all > 34 && pwdb_all <= 42) + pwdb_all -= 2; + else if (pwdb_all > 26 && pwdb_all <= 34) + pwdb_all -= 6; + else if (pwdb_all > 14 && pwdb_all <= 26) + pwdb_all -= 8; + else if (pwdb_all > 4 && pwdb_all <= 14) + pwdb_all -= 4; + pstats->rx_pwdb_all = pwdb_all; pstats->recvsignalpower = rx_pwr_all; - if (bpacket_match_bssid) { + /* (3) Get Signal Quality (EVM) */ + if (packet_match_bssid) { u8 sq; if (pstats->rx_pwdb_all > 40) sq = 100; @@ -330,35 +221,44 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, } pstats->signalquality = sq; - pstats->rx_mimo_signalquality[0] = sq; - pstats->rx_mimo_signalquality[1] = -1; + pstats->rx_mimo_sig_qual[0] = sq; + pstats->rx_mimo_sig_qual[1] = -1; } } else { - rtlpriv->dm.brfpath_rxenable[0] = - rtlpriv->dm.brfpath_rxenable[1] = true; + rtlpriv->dm.rfpath_rxenable[0] = + rtlpriv->dm.rfpath_rxenable[1] = true; + /* (1)Get RSSI for HT rate */ for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) { - if (rtlpriv->dm.brfpath_rxenable[i]) + /* we will judge RF RX path now. */ + if (rtlpriv->dm.rfpath_rxenable[i]) rf_rx_num++; rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110; + /* Translate DBM to percentage. */ rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]); total_rssi += rssi; + /* Get Rx snr value in DB */ rtlpriv->stats.rx_snr_db[i] = (long)(p_drvinfo->rxsnr[i] / 2); - if (bpacket_match_bssid) + /* Record Signal Strength for next packet */ + if (packet_match_bssid) pstats->rx_mimo_signalstrength[i] = (u8) rssi; } + /* (2)PWDB, Average PWDB cacluated by + * hardware (for rate adaptive) + */ rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all); pstats->rx_pwdb_all = pwdb_all; pstats->rxpower = rx_pwr_all; pstats->recvsignalpower = rx_pwr_all; - if (pdesc->rxht && pdesc->rxmcs >= DESC92C_RATEMCS8 && - pdesc->rxmcs <= DESC92C_RATEMCS15) + /* (3)EVM of HT rate */ + if (pstats->is_ht && pstats->rate >= DESC92_RATEMCS8 && + pstats->rate <= DESC92_RATEMCS15) max_spatial_stream = 2; else max_spatial_stream = 1; @@ -366,16 +266,21 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, for (i = 0; i < max_spatial_stream; i++) { evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]); - if (bpacket_match_bssid) { + if (packet_match_bssid) { + /* Fill value in RFD, Get the first + * spatial stream only + */ if (i == 0) pstats->signalquality = (u8) (evm & 0xff); - pstats->rx_mimo_signalquality[i] = - (u8) (evm & 0xff); + pstats->rx_mimo_sig_qual[i] = (u8) (evm & 0xff); } } } + /* UI BSS List signal strength(in percentage), + * make it good looking, from 0~100. + */ if (is_cck_rate) pstats->signalstrength = (u8) (_rtl92ce_signal_scale_mapping(hw, pwdb_all)); @@ -385,225 +290,6 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, (hw, total_rssi /= rf_rx_num)); } -static void _rtl92ce_process_ui_rssi(struct ieee80211_hw *hw, - struct rtl_stats *pstats) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u8 rfpath; - u32 last_rssi, tmpval; - - if (pstats->b_packet_toself || pstats->b_packet_beacon) { - rtlpriv->stats.rssi_calculate_cnt++; - - if (rtlpriv->stats.ui_rssi.total_num++ >= - PHY_RSSI_SLID_WIN_MAX) { - rtlpriv->stats.ui_rssi.total_num = - PHY_RSSI_SLID_WIN_MAX; - last_rssi = - rtlpriv->stats.ui_rssi.elements[rtlpriv-> - stats.ui_rssi.index]; - rtlpriv->stats.ui_rssi.total_val -= last_rssi; - } - - rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength; - rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi. - index++] = - pstats->signalstrength; - - if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX) - rtlpriv->stats.ui_rssi.index = 0; - - tmpval = rtlpriv->stats.ui_rssi.total_val / - rtlpriv->stats.ui_rssi.total_num; - rtlpriv->stats.signal_strength = - _rtl92ce_translate_todbm(hw, (u8) tmpval); - pstats->rssi = rtlpriv->stats.signal_strength; - } - - if (!pstats->b_is_cck && pstats->b_packet_toself) { - for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; - rfpath++) { - - if (!rtl8192_phy_check_is_legal_rfpath(hw, rfpath)) - continue; - - if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { - rtlpriv->stats.rx_rssi_percentage[rfpath] = - pstats->rx_mimo_signalstrength[rfpath]; - - } - - if (pstats->rx_mimo_signalstrength[rfpath] > - rtlpriv->stats.rx_rssi_percentage[rfpath]) { - rtlpriv->stats.rx_rssi_percentage[rfpath] = - ((rtlpriv->stats. - rx_rssi_percentage[rfpath] * - (RX_SMOOTH_FACTOR - 1)) + - (pstats->rx_mimo_signalstrength[rfpath])) / - (RX_SMOOTH_FACTOR); - - rtlpriv->stats.rx_rssi_percentage[rfpath] = - rtlpriv->stats.rx_rssi_percentage[rfpath] + - 1; - } else { - rtlpriv->stats.rx_rssi_percentage[rfpath] = - ((rtlpriv->stats. - rx_rssi_percentage[rfpath] * - (RX_SMOOTH_FACTOR - 1)) + - (pstats->rx_mimo_signalstrength[rfpath])) / - (RX_SMOOTH_FACTOR); - } - - } - } -} - -static void _rtl92ce_update_rxsignalstatistics(struct ieee80211_hw *hw, - struct rtl_stats *pstats) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int weighting; - - if (rtlpriv->stats.recv_signal_power == 0) - rtlpriv->stats.recv_signal_power = pstats->recvsignalpower; - - if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power) - weighting = 5; - - else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power) - weighting = (-5); - - rtlpriv->stats.recv_signal_power = - (rtlpriv->stats.recv_signal_power * 5 + - pstats->recvsignalpower + weighting) / 6; -} - -static void _rtl92ce_process_pwdb(struct ieee80211_hw *hw, - struct rtl_stats *pstats) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - long undecorated_smoothed_pwdb; - - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - return; - } else { - undecorated_smoothed_pwdb = - rtlpriv->dm.undecorated_smoothed_pwdb; - } - - if (pstats->b_packet_toself || pstats->b_packet_beacon) { - if (undecorated_smoothed_pwdb < 0) - undecorated_smoothed_pwdb = pstats->rx_pwdb_all; - - if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) { - undecorated_smoothed_pwdb = - (((undecorated_smoothed_pwdb) * - (RX_SMOOTH_FACTOR - 1)) + - (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); - - undecorated_smoothed_pwdb = undecorated_smoothed_pwdb - + 1; - } else { - undecorated_smoothed_pwdb = - (((undecorated_smoothed_pwdb) * - (RX_SMOOTH_FACTOR - 1)) + - (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); - } - - rtlpriv->dm.undecorated_smoothed_pwdb = - undecorated_smoothed_pwdb; - _rtl92ce_update_rxsignalstatistics(hw, pstats); - } -} - -static void _rtl92ce_process_ui_link_quality(struct ieee80211_hw *hw, - struct rtl_stats *pstats) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 last_evm, n_spatialstream, tmpval; - - if (pstats->signalquality != 0) { - if (pstats->b_packet_toself || pstats->b_packet_beacon) { - - if (rtlpriv->stats.ui_link_quality.total_num++ >= - PHY_LINKQUALITY_SLID_WIN_MAX) { - rtlpriv->stats.ui_link_quality.total_num = - PHY_LINKQUALITY_SLID_WIN_MAX; - last_evm = - rtlpriv->stats. - ui_link_quality.elements[rtlpriv-> - stats.ui_link_quality. - index]; - rtlpriv->stats.ui_link_quality.total_val -= - last_evm; - } - - rtlpriv->stats.ui_link_quality.total_val += - pstats->signalquality; - rtlpriv->stats.ui_link_quality.elements[rtlpriv->stats. - ui_link_quality. - index++] = - pstats->signalquality; - - if (rtlpriv->stats.ui_link_quality.index >= - PHY_LINKQUALITY_SLID_WIN_MAX) - rtlpriv->stats.ui_link_quality.index = 0; - - tmpval = rtlpriv->stats.ui_link_quality.total_val / - rtlpriv->stats.ui_link_quality.total_num; - rtlpriv->stats.signal_quality = tmpval; - - rtlpriv->stats.last_sigstrength_inpercent = tmpval; - - for (n_spatialstream = 0; n_spatialstream < 2; - n_spatialstream++) { - if (pstats-> - rx_mimo_signalquality[n_spatialstream] != - -1) { - if (rtlpriv->stats. - rx_evm_percentage[n_spatialstream] - == 0) { - rtlpriv->stats. - rx_evm_percentage - [n_spatialstream] = - pstats->rx_mimo_signalquality - [n_spatialstream]; - } - - rtlpriv->stats. - rx_evm_percentage[n_spatialstream] = - ((rtlpriv-> - stats.rx_evm_percentage - [n_spatialstream] * - (RX_SMOOTH_FACTOR - 1)) + - (pstats-> - rx_mimo_signalquality - [n_spatialstream] * 1)) / - (RX_SMOOTH_FACTOR); - } - } - } - } else { - ; - } -} - -static void _rtl92ce_process_phyinfo(struct ieee80211_hw *hw, - u8 *buffer, - struct rtl_stats *pcurrent_stats) -{ - - if (!pcurrent_stats->b_packet_matchbssid && - !pcurrent_stats->b_packet_beacon) - return; - - _rtl92ce_process_ui_rssi(hw, pcurrent_stats); - _rtl92ce_process_pwdb(hw, pcurrent_stats); - _rtl92ce_process_ui_link_quality(hw, pcurrent_stats); -} - static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw, struct sk_buff *skb, struct rtl_stats *pstats, @@ -616,37 +302,37 @@ static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr; u8 *tmp_buf; u8 *praddr; - u8 *psaddr; - u16 fc, type; - bool b_packet_matchbssid, b_packet_toself, b_packet_beacon; + __le16 fc; + u16 type, c_fc; + bool packet_matchbssid, packet_toself, packet_beacon = false; tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; hdr = (struct ieee80211_hdr *)tmp_buf; - fc = le16_to_cpu(hdr->frame_control); + fc = hdr->frame_control; + c_fc = le16_to_cpu(fc); type = WLAN_FC_GET_TYPE(fc); praddr = hdr->addr1; - psaddr = hdr->addr2; - b_packet_matchbssid = + packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) && - (!compare_ether_addr(mac->bssid, - (fc & IEEE80211_FCTL_TODS) ? - hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? - hdr->addr2 : hdr->addr3)) && - (!pstats->b_hwerror) && (!pstats->b_crc) && (!pstats->b_icv)); + ether_addr_equal(mac->bssid, + (c_fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : + (c_fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : + hdr->addr3) && + (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv)); - b_packet_toself = b_packet_matchbssid && - (!compare_ether_addr(praddr, rtlefuse->dev_addr)); + packet_toself = packet_matchbssid && + ether_addr_equal(praddr, rtlefuse->dev_addr); if (ieee80211_is_beacon(fc)) - b_packet_beacon = true; + packet_beacon = true; _rtl92ce_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, - b_packet_matchbssid, b_packet_toself, - b_packet_beacon); + packet_matchbssid, packet_toself, + packet_beacon); - _rtl92ce_process_phyinfo(hw, tmp_buf, pstats); + rtl_process_phyinfo(hw, tmp_buf, pstats); } bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, @@ -656,53 +342,74 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, { struct rx_fwinfo_92c *p_drvinfo; struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; - + struct ieee80211_hdr *hdr; u32 phystatus = GET_RX_DESC_PHYST(pdesc); stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) * RX_DRV_INFO_SIZE_UNIT; stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03); - stats->b_icv = (u16) GET_RX_DESC_ICV(pdesc); - stats->b_crc = (u16) GET_RX_DESC_CRC32(pdesc); - stats->b_hwerror = (stats->b_crc | stats->b_icv); + stats->icv = (u16) GET_RX_DESC_ICV(pdesc); + stats->crc = (u16) GET_RX_DESC_CRC32(pdesc); + stats->hwerror = (stats->crc | stats->icv); stats->decrypted = !GET_RX_DESC_SWDEC(pdesc); stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc); - stats->b_shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); - stats->b_isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); - stats->b_isampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) + stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); + stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); + stats->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) && (GET_RX_DESC_FAGGR(pdesc) == 1)); stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); + stats->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); - rx_status->freq = hw->conf.channel->center_freq; - rx_status->band = hw->conf.channel->band; + stats->is_cck = RX_HAL_IS_CCK_RATE(pdesc); - if (GET_RX_DESC_CRC32(pdesc)) - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + rx_status->freq = hw->conf.chandef.chan->center_freq; + rx_status->band = hw->conf.chandef.chan->band; - if (!GET_RX_DESC_SWDEC(pdesc)) - rx_status->flag |= RX_FLAG_DECRYPTED; + hdr = (struct ieee80211_hdr *)(skb->data + stats->rx_drvinfo_size + + stats->rx_bufshift); - if (GET_RX_DESC_BW(pdesc)) + if (stats->crc) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + + if (stats->rx_is40Mhzpacket) rx_status->flag |= RX_FLAG_40MHZ; - if (GET_RX_DESC_RXHT(pdesc)) + if (stats->is_ht) rx_status->flag |= RX_FLAG_HT; - rx_status->flag |= RX_FLAG_TSFT; - - if (stats->decrypted) - rx_status->flag |= RX_FLAG_DECRYPTED; - - rx_status->rate_idx = _rtl92ce_rate_mapping((bool) - GET_RX_DESC_RXHT(pdesc), - (u8) - GET_RX_DESC_RXMCS(pdesc), - (bool) - GET_RX_DESC_PAGGR(pdesc)); - - rx_status->mactime = GET_RX_DESC_TSFL(pdesc); - if (phystatus == true) { + rx_status->flag |= RX_FLAG_MACTIME_START; + + /* hw will set stats->decrypted true, if it finds the + * frame is open data frame or mgmt frame. + * So hw will not decryption robust managment frame + * for IEEE80211w but still set status->decrypted + * true, so here we should set it back to undecrypted + * for IEEE80211w frame, and mac80211 sw will help + * to decrypt it + */ + if (stats->decrypted) { + if (!hdr) { + /* In testing, hdr was NULL here */ + return false; + } + if ((_ieee80211_is_robust_mgmt_frame(hdr)) && + (ieee80211_has_protected(hdr->frame_control))) + rx_status->flag &= ~RX_FLAG_DECRYPTED; + else + rx_status->flag |= RX_FLAG_DECRYPTED; + } + /* rate_idx: index of data rate into band's + * supported rates or MCS index if HT rates + * are use (RX_FLAG_HT) + * Notice: this is diff with windows define + */ + rx_status->rate_idx = rtlwifi_rate_mapping(hw, + stats->is_ht, stats->rate, + stats->isfirst_ampdu); + + rx_status->mactime = stats->timestamp_low; + if (phystatus) { p_drvinfo = (struct rx_fwinfo_92c *)(skb->data + stats->rx_bufshift); @@ -712,96 +419,104 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, } /*rx_status->qual = stats->signal; */ - rx_status->signal = stats->rssi + 10; - /*rx_status->noise = -stats->noise; */ + rx_status->signal = stats->recvsignalpower + 10; return true; } void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, - struct ieee80211_tx_info *info, struct sk_buff *skb, - unsigned int queue_index) + u8 *pbd_desc_tx, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, + u8 hw_queue, struct rtl_tcb_desc *tcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool b_defaultadapter = true; - - struct ieee80211_sta *sta = ieee80211_find_sta(mac->vif, mac->bssid); - - u8 *pdesc = (u8 *) pdesc_tx; - struct rtl_tcb_desc tcb_desc; - u8 *qc = ieee80211_get_qos_ctl(hdr); - u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; + bool defaultadapter = true; + u8 *pdesc = pdesc_tx; u16 seq_number; - u16 fc = le16_to_cpu(hdr->frame_control); - u8 rate_flag = info->control.rates[0].flags; - - enum rtl_desc_qsel fw_qsel = - _rtl92ce_map_hwqueue_to_fwqueue(le16_to_cpu(hdr->frame_control), - queue_index); + __le16 fc = hdr->frame_control; + u8 fw_qsel = _rtl92ce_map_hwqueue_to_fwqueue(skb, hw_queue); + bool firstseg = ((hdr->seq_ctrl & + cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); - bool b_firstseg = ((hdr->seq_ctrl & - cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); - - bool b_lastseg = ((hdr->frame_control & - cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); + bool lastseg = ((hdr->frame_control & + cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + u8 bw_40 = 0; + + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "DMA mapping error"); + return; + } + rcu_read_lock(); + sta = get_sta(hw, mac->vif, mac->bssid); + if (mac->opmode == NL80211_IFTYPE_STATION) { + bw_40 = mac->bw_40; + } else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC || + mac->opmode == NL80211_IFTYPE_MESH_POINT) { + if (sta) + bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40; + } + seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - rtl_get_tcb_desc(hw, info, skb, &tcb_desc); + rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc); CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92c)); - if (b_firstseg) { + if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { + firstseg = true; + lastseg = true; + } + if (firstseg) { SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - SET_TX_DESC_TX_RATE(pdesc, tcb_desc.hw_rate); + SET_TX_DESC_TX_RATE(pdesc, tcb_desc->hw_rate); - if (tcb_desc.use_shortgi || tcb_desc.use_shortpreamble) + if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble) SET_TX_DESC_DATA_SHORTGI(pdesc, 1); - if (mac->tids[tid].agg.agg_state == RTL_AGG_ON && - info->flags & IEEE80211_TX_CTL_AMPDU) { + if (info->flags & IEEE80211_TX_CTL_AMPDU) { SET_TX_DESC_AGG_BREAK(pdesc, 1); SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); } SET_TX_DESC_SEQ(pdesc, seq_number); - SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc.b_rts_enable && - !tcb_desc. - b_cts_enable) ? 1 : 0)); + SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc->rts_enable && + !tcb_desc-> + cts_enable) ? 1 : 0)); SET_TX_DESC_HW_RTS_ENABLE(pdesc, - ((tcb_desc.b_rts_enable - || tcb_desc.b_cts_enable) ? 1 : 0)); - SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc.b_cts_enable) ? 1 : 0)); - SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc.b_rts_stbc) ? 1 : 0)); + ((tcb_desc->rts_enable + || tcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc->rts_stbc) ? 1 : 0)); - SET_TX_DESC_RTS_RATE(pdesc, tcb_desc.rts_rate); + SET_TX_DESC_RTS_RATE(pdesc, tcb_desc->rts_rate); SET_TX_DESC_RTS_BW(pdesc, 0); - SET_TX_DESC_RTS_SC(pdesc, tcb_desc.rts_sc); + SET_TX_DESC_RTS_SC(pdesc, tcb_desc->rts_sc); SET_TX_DESC_RTS_SHORT(pdesc, - ((tcb_desc.rts_rate <= DESC92C_RATE54M) ? - (tcb_desc.b_rts_use_shortpreamble ? 1 : 0) - : (tcb_desc.b_rts_use_shortgi ? 1 : 0))); + ((tcb_desc->rts_rate <= DESC92_RATE54M) ? + (tcb_desc->rts_use_shortpreamble ? 1 : 0) + : (tcb_desc->rts_use_shortgi ? 1 : 0))); - if (mac->bw_40) { - if (tcb_desc.b_packet_bw) { + if (bw_40) { + if (tcb_desc->packet_bw) { SET_TX_DESC_DATA_BW(pdesc, 1); SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); } else { SET_TX_DESC_DATA_BW(pdesc, 0); - - if (rate_flag & IEEE80211_TX_RC_DUP_DATA) { - SET_TX_DESC_TX_SUB_CARRIER(pdesc, - mac->cur_40_prime_sc); - } + SET_TX_DESC_TX_SUB_CARRIER(pdesc, + mac->cur_40_prime_sc); } } else { SET_TX_DESC_DATA_BW(pdesc, 0); @@ -842,55 +557,55 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); SET_TX_DESC_DISABLE_FB(pdesc, 0); - SET_TX_DESC_USE_RATE(pdesc, tcb_desc.use_driver_rate ? 1 : 0); + SET_TX_DESC_USE_RATE(pdesc, tcb_desc->use_driver_rate ? 1 : 0); if (ieee80211_is_data_qos(fc)) { if (mac->rdg_en) { RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - ("Enable RDG function.\n")); + "Enable RDG function\n"); SET_TX_DESC_RDG_ENABLE(pdesc, 1); SET_TX_DESC_HTC(pdesc, 1); } } } + rcu_read_unlock(); - SET_TX_DESC_FIRST_SEG(pdesc, (b_firstseg ? 1 : 0)); - SET_TX_DESC_LAST_SEG(pdesc, (b_lastseg ? 1 : 0)); + SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); + SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - if (rtlpriv->dm.b_useramask) { - SET_TX_DESC_RATE_ID(pdesc, tcb_desc.ratr_index); - SET_TX_DESC_MACID(pdesc, tcb_desc.mac_id); + if (rtlpriv->dm.useramask) { + SET_TX_DESC_RATE_ID(pdesc, tcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, tcb_desc->mac_id); } else { - SET_TX_DESC_RATE_ID(pdesc, 0xC + tcb_desc.ratr_index); - SET_TX_DESC_MACID(pdesc, tcb_desc.ratr_index); + SET_TX_DESC_RATE_ID(pdesc, 0xC + tcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, tcb_desc->ratr_index); } - if ((!ieee80211_is_data_qos(fc)) && ppsc->b_leisure_ps && - ppsc->b_fwctrl_lps) { + if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) { SET_TX_DESC_HWSEQ_EN(pdesc, 1); SET_TX_DESC_PKT_ID(pdesc, 8); - if (!b_defaultadapter) + if (!defaultadapter) SET_TX_DESC_QOS(pdesc, 1); } - SET_TX_DESC_MORE_FRAG(pdesc, (b_lastseg ? 0 : 1)); + SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || is_broadcast_ether_addr(ieee80211_get_DA(hdr))) { SET_TX_DESC_BMC(pdesc, 1); } - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, ("\n")); + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); } void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc, bool b_firstseg, - bool b_lastseg, struct sk_buff *skb) + u8 *pdesc, bool firstseg, + bool lastseg, struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); @@ -901,14 +616,19 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, PCI_DMA_TODEVICE); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); - u16 fc = le16_to_cpu(hdr->frame_control); + __le16 fc = hdr->frame_control; + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "DMA mapping error"); + return; + } CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); - if (b_firstseg) + if (firstseg) SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); + SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE1M); SET_TX_DESC_SEQ(pdesc, 0); @@ -921,14 +641,14 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len)); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); SET_TX_DESC_RATE_ID(pdesc, 7); SET_TX_DESC_MACID(pdesc, 0); SET_TX_DESC_OWN(pdesc, 1); - SET_TX_DESC_PKT_SIZE((u8 *) pdesc, (u16) (skb->len)); + SET_TX_DESC_PKT_SIZE(pdesc, (u16) (skb->len)); SET_TX_DESC_FIRST_SEG(pdesc, 1); SET_TX_DESC_LAST_SEG(pdesc, 1); @@ -943,28 +663,30 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, } RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, - "H2C Tx Cmd Content\n", - pdesc, TX_DESC_SIZE); + "H2C Tx Cmd Content", pdesc, TX_DESC_SIZE); } -void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val) +void rtl92ce_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, + u8 desc_name, u8 *val) { - if (istx == true) { + if (istx) { switch (desc_name) { case HW_DESC_OWN: + wmb(); SET_TX_DESC_OWN(pdesc, 1); break; case HW_DESC_TX_NEXTDESC_ADDR: SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val); break; default: - RT_ASSERT(false, ("ERR txdesc :%d" - " not process\n", desc_name)); + RT_ASSERT(false, "ERR txdesc :%d not process\n", + desc_name); break; } } else { switch (desc_name) { case HW_DESC_RXOWN: + wmb(); SET_RX_DESC_OWN(pdesc, 1); break; case HW_DESC_RXBUFF_ADDR: @@ -977,8 +699,8 @@ void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val) SET_RX_DESC_EOR(pdesc, 1); break; default: - RT_ASSERT(false, ("ERR rxdesc :%d " - "not process\n", desc_name)); + RT_ASSERT(false, "ERR rxdesc :%d not process\n", + desc_name); break; } } @@ -988,7 +710,7 @@ u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name) { u32 ret = 0; - if (istx == true) { + if (istx) { switch (desc_name) { case HW_DESC_OWN: ret = GET_TX_DESC_OWN(p_desc); @@ -997,8 +719,8 @@ u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name) ret = GET_TX_DESC_TX_BUFFER_ADDRESS(p_desc); break; default: - RT_ASSERT(false, ("ERR txdesc :%d " - "not process\n", desc_name)); + RT_ASSERT(false, "ERR txdesc :%d not process\n", + desc_name); break; } } else { @@ -1011,15 +733,15 @@ u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name) ret = GET_RX_DESC_PKT_LEN(pdesc); break; default: - RT_ASSERT(false, ("ERR rxdesc :%d " - "not process\n", desc_name)); + RT_ASSERT(false, "ERR rxdesc :%d not process\n", + desc_name); break; } } return ret; } -void rtl92ce_tx_polling(struct ieee80211_hw *hw, unsigned int hw_queue) +void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) { struct rtl_priv *rtlpriv = rtl_priv(hw); if (hw_queue == BEACON_QUEUE) { @@ -1029,3 +751,4 @@ void rtl92ce_tx_polling(struct ieee80211_hw *hw, unsigned int hw_queue) BIT(0) << (hw_queue)); } } + |
