diff options
Diffstat (limited to 'drivers/net/wireless/realtek/rtw88/rx.c')
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/rx.c | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/drivers/net/wireless/realtek/rtw88/rx.c b/drivers/net/wireless/realtek/rtw88/rx.c new file mode 100644 index 000000000000..4d837f0c6d5f --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/rx.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include "main.h" +#include "rx.h" +#include "ps.h" + +void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr; + struct rtw_vif *rtwvif; + + hdr = (struct ieee80211_hdr *)skb->data; + + if (!ieee80211_is_data(hdr->frame_control)) + return; + + if (!is_broadcast_ether_addr(hdr->addr1) && + !is_multicast_ether_addr(hdr->addr1)) { + rtwdev->stats.rx_unicast += skb->len; + rtwdev->stats.rx_cnt++; + if (vif) { + rtwvif = (struct rtw_vif *)vif->drv_priv; + rtwvif->stats.rx_unicast += skb->len; + rtwvif->stats.rx_cnt++; + if (rtwvif->stats.rx_cnt > RTW_LPS_THRESHOLD) + rtw_leave_lps_irqsafe(rtwdev, rtwvif); + } + } +} +EXPORT_SYMBOL(rtw_rx_stats); + +struct rtw_rx_addr_match_data { + struct rtw_dev *rtwdev; + struct ieee80211_hdr *hdr; + struct rtw_rx_pkt_stat *pkt_stat; + u8 *bssid; +}; + +static void rtw_rx_addr_match_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct rtw_rx_addr_match_data *iter_data = data; + struct ieee80211_sta *sta; + struct ieee80211_hdr *hdr = iter_data->hdr; + struct rtw_dev *rtwdev = iter_data->rtwdev; + struct rtw_sta_info *si; + struct rtw_rx_pkt_stat *pkt_stat = iter_data->pkt_stat; + u8 *bssid = iter_data->bssid; + + if (ether_addr_equal(vif->bss_conf.bssid, bssid) && + (ether_addr_equal(vif->addr, hdr->addr1) || + ieee80211_is_beacon(hdr->frame_control))) + sta = ieee80211_find_sta_by_ifaddr(rtwdev->hw, hdr->addr2, + vif->addr); + else + return; + + if (!sta) + return; + + si = (struct rtw_sta_info *)sta->drv_priv; + ewma_rssi_add(&si->avg_rssi, pkt_stat->rssi); +} + +static void rtw_rx_addr_match(struct rtw_dev *rtwdev, + struct rtw_rx_pkt_stat *pkt_stat, + struct ieee80211_hdr *hdr) +{ + struct rtw_rx_addr_match_data data = {}; + + if (pkt_stat->crc_err || pkt_stat->icv_err || !pkt_stat->phy_status || + ieee80211_is_ctl(hdr->frame_control)) + return; + + data.rtwdev = rtwdev; + data.hdr = hdr; + data.pkt_stat = pkt_stat; + data.bssid = get_hdr_bssid(hdr); + + rtw_iterate_vifs_atomic(rtwdev, rtw_rx_addr_match_iter, &data); +} + +void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, + struct rtw_rx_pkt_stat *pkt_stat, + struct ieee80211_hdr *hdr, + struct ieee80211_rx_status *rx_status, + u8 *phy_status) +{ + struct ieee80211_hw *hw = rtwdev->hw; + + memset(rx_status, 0, sizeof(*rx_status)); + rx_status->freq = hw->conf.chandef.chan->center_freq; + rx_status->band = hw->conf.chandef.chan->band; + if (pkt_stat->crc_err) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + if (pkt_stat->decrypted) + rx_status->flag |= RX_FLAG_DECRYPTED; + + if (pkt_stat->rate >= DESC_RATEVHT1SS_MCS0) + rx_status->encoding = RX_ENC_VHT; + else if (pkt_stat->rate >= DESC_RATEMCS0) + rx_status->encoding = RX_ENC_HT; + + if (pkt_stat->rate >= DESC_RATEVHT1SS_MCS0 && + pkt_stat->rate <= DESC_RATEVHT1SS_MCS9) { + rx_status->nss = 1; + rx_status->rate_idx = pkt_stat->rate - DESC_RATEVHT1SS_MCS0; + } else if (pkt_stat->rate >= DESC_RATEVHT2SS_MCS0 && + pkt_stat->rate <= DESC_RATEVHT2SS_MCS9) { + rx_status->nss = 2; + rx_status->rate_idx = pkt_stat->rate - DESC_RATEVHT2SS_MCS0; + } else if (pkt_stat->rate >= DESC_RATEVHT3SS_MCS0 && + pkt_stat->rate <= DESC_RATEVHT3SS_MCS9) { + rx_status->nss = 3; + rx_status->rate_idx = pkt_stat->rate - DESC_RATEVHT3SS_MCS0; + } else if (pkt_stat->rate >= DESC_RATEVHT4SS_MCS0 && + pkt_stat->rate <= DESC_RATEVHT4SS_MCS9) { + rx_status->nss = 4; + rx_status->rate_idx = pkt_stat->rate - DESC_RATEVHT4SS_MCS0; + } else if (pkt_stat->rate >= DESC_RATEMCS0 && + pkt_stat->rate <= DESC_RATEMCS15) { + rx_status->rate_idx = pkt_stat->rate - DESC_RATEMCS0; + } else if (rx_status->band == NL80211_BAND_5GHZ && + pkt_stat->rate >= DESC_RATE6M && + pkt_stat->rate <= DESC_RATE54M) { + rx_status->rate_idx = pkt_stat->rate - DESC_RATE6M; + } else if (rx_status->band == NL80211_BAND_2GHZ && + pkt_stat->rate >= DESC_RATE1M && + pkt_stat->rate <= DESC_RATE54M) { + rx_status->rate_idx = pkt_stat->rate - DESC_RATE1M; + } else { + rx_status->rate_idx = 0; + } + + rx_status->flag |= RX_FLAG_MACTIME_START; + rx_status->mactime = pkt_stat->tsf_low; + + if (pkt_stat->bw == RTW_CHANNEL_WIDTH_80) + rx_status->bw = RATE_INFO_BW_80; + else if (pkt_stat->bw == RTW_CHANNEL_WIDTH_40) + rx_status->bw = RATE_INFO_BW_40; + else + rx_status->bw = RATE_INFO_BW_20; + + rx_status->signal = pkt_stat->signal_power; + + rtw_rx_addr_match(rtwdev, pkt_stat, hdr); +} |