12774f206SBjoern A. Zeeb // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 22774f206SBjoern A. Zeeb /* Copyright(c) 2018-2019 Realtek Corporation 32774f206SBjoern A. Zeeb */ 42774f206SBjoern A. Zeeb 52774f206SBjoern A. Zeeb #include "main.h" 62774f206SBjoern A. Zeeb #include "rx.h" 72774f206SBjoern A. Zeeb #include "ps.h" 82774f206SBjoern A. Zeeb #include "debug.h" 92774f206SBjoern A. Zeeb #include "fw.h" 102774f206SBjoern A. Zeeb 112774f206SBjoern A. Zeeb void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, 122774f206SBjoern A. Zeeb struct sk_buff *skb) 132774f206SBjoern A. Zeeb { 142774f206SBjoern A. Zeeb struct ieee80211_hdr *hdr; 152774f206SBjoern A. Zeeb struct rtw_vif *rtwvif; 162774f206SBjoern A. Zeeb 172774f206SBjoern A. Zeeb hdr = (struct ieee80211_hdr *)skb->data; 182774f206SBjoern A. Zeeb 192774f206SBjoern A. Zeeb if (!ieee80211_is_data(hdr->frame_control)) 202774f206SBjoern A. Zeeb return; 212774f206SBjoern A. Zeeb 222774f206SBjoern A. Zeeb if (!is_broadcast_ether_addr(hdr->addr1) && 232774f206SBjoern A. Zeeb !is_multicast_ether_addr(hdr->addr1)) { 242774f206SBjoern A. Zeeb rtwdev->stats.rx_unicast += skb->len; 252774f206SBjoern A. Zeeb rtwdev->stats.rx_cnt++; 262774f206SBjoern A. Zeeb if (vif) { 272774f206SBjoern A. Zeeb rtwvif = (struct rtw_vif *)vif->drv_priv; 282774f206SBjoern A. Zeeb rtwvif->stats.rx_unicast += skb->len; 292774f206SBjoern A. Zeeb rtwvif->stats.rx_cnt++; 302774f206SBjoern A. Zeeb } 312774f206SBjoern A. Zeeb } 322774f206SBjoern A. Zeeb } 332774f206SBjoern A. Zeeb EXPORT_SYMBOL(rtw_rx_stats); 342774f206SBjoern A. Zeeb 352774f206SBjoern A. Zeeb struct rtw_rx_addr_match_data { 362774f206SBjoern A. Zeeb struct rtw_dev *rtwdev; 372774f206SBjoern A. Zeeb struct ieee80211_hdr *hdr; 382774f206SBjoern A. Zeeb struct rtw_rx_pkt_stat *pkt_stat; 392774f206SBjoern A. Zeeb u8 *bssid; 402774f206SBjoern A. Zeeb }; 412774f206SBjoern A. Zeeb 422774f206SBjoern A. Zeeb static void rtw_rx_phy_stat(struct rtw_dev *rtwdev, 432774f206SBjoern A. Zeeb struct rtw_rx_pkt_stat *pkt_stat, 442774f206SBjoern A. Zeeb struct ieee80211_hdr *hdr) 452774f206SBjoern A. Zeeb { 462774f206SBjoern A. Zeeb struct rtw_dm_info *dm_info = &rtwdev->dm_info; 472774f206SBjoern A. Zeeb struct rtw_pkt_count *cur_pkt_cnt = &dm_info->cur_pkt_count; 482774f206SBjoern A. Zeeb u8 rate_ss, rate_ss_evm, evm_id; 492774f206SBjoern A. Zeeb u8 i, idx; 502774f206SBjoern A. Zeeb 512774f206SBjoern A. Zeeb dm_info->curr_rx_rate = pkt_stat->rate; 522774f206SBjoern A. Zeeb 532774f206SBjoern A. Zeeb if (ieee80211_is_beacon(hdr->frame_control)) 542774f206SBjoern A. Zeeb cur_pkt_cnt->num_bcn_pkt++; 552774f206SBjoern A. Zeeb 562774f206SBjoern A. Zeeb switch (pkt_stat->rate) { 572774f206SBjoern A. Zeeb case DESC_RATE1M...DESC_RATE11M: 582774f206SBjoern A. Zeeb goto pkt_num; 592774f206SBjoern A. Zeeb case DESC_RATE6M...DESC_RATE54M: 602774f206SBjoern A. Zeeb rate_ss = 0; 612774f206SBjoern A. Zeeb rate_ss_evm = 1; 622774f206SBjoern A. Zeeb evm_id = RTW_EVM_OFDM; 632774f206SBjoern A. Zeeb break; 642774f206SBjoern A. Zeeb case DESC_RATEMCS0...DESC_RATEMCS7: 652774f206SBjoern A. Zeeb case DESC_RATEVHT1SS_MCS0...DESC_RATEVHT1SS_MCS9: 662774f206SBjoern A. Zeeb rate_ss = 1; 672774f206SBjoern A. Zeeb rate_ss_evm = 1; 682774f206SBjoern A. Zeeb evm_id = RTW_EVM_1SS; 692774f206SBjoern A. Zeeb break; 702774f206SBjoern A. Zeeb case DESC_RATEMCS8...DESC_RATEMCS15: 712774f206SBjoern A. Zeeb case DESC_RATEVHT2SS_MCS0...DESC_RATEVHT2SS_MCS9: 722774f206SBjoern A. Zeeb rate_ss = 2; 732774f206SBjoern A. Zeeb rate_ss_evm = 2; 742774f206SBjoern A. Zeeb evm_id = RTW_EVM_2SS_A; 752774f206SBjoern A. Zeeb break; 762774f206SBjoern A. Zeeb default: 772774f206SBjoern A. Zeeb rtw_warn(rtwdev, "unknown pkt rate = %d\n", pkt_stat->rate); 782774f206SBjoern A. Zeeb return; 792774f206SBjoern A. Zeeb } 802774f206SBjoern A. Zeeb 812774f206SBjoern A. Zeeb for (i = 0; i < rate_ss_evm; i++) { 822774f206SBjoern A. Zeeb idx = evm_id + i; 832774f206SBjoern A. Zeeb ewma_evm_add(&dm_info->ewma_evm[idx], 842774f206SBjoern A. Zeeb dm_info->rx_evm_dbm[i]); 852774f206SBjoern A. Zeeb } 862774f206SBjoern A. Zeeb 872774f206SBjoern A. Zeeb for (i = 0; i < rtwdev->hal.rf_path_num; i++) { 882774f206SBjoern A. Zeeb idx = RTW_SNR_OFDM_A + 4 * rate_ss + i; 892774f206SBjoern A. Zeeb ewma_snr_add(&dm_info->ewma_snr[idx], 902774f206SBjoern A. Zeeb dm_info->rx_snr[i]); 912774f206SBjoern A. Zeeb } 922774f206SBjoern A. Zeeb pkt_num: 932774f206SBjoern A. Zeeb cur_pkt_cnt->num_qry_pkt[pkt_stat->rate]++; 942774f206SBjoern A. Zeeb } 952774f206SBjoern A. Zeeb 962774f206SBjoern A. Zeeb static void rtw_rx_addr_match_iter(void *data, u8 *mac, 972774f206SBjoern A. Zeeb struct ieee80211_vif *vif) 982774f206SBjoern A. Zeeb { 992774f206SBjoern A. Zeeb struct rtw_rx_addr_match_data *iter_data = data; 1002774f206SBjoern A. Zeeb struct ieee80211_sta *sta; 1012774f206SBjoern A. Zeeb struct ieee80211_hdr *hdr = iter_data->hdr; 1022774f206SBjoern A. Zeeb struct rtw_dev *rtwdev = iter_data->rtwdev; 1032774f206SBjoern A. Zeeb struct rtw_sta_info *si; 1042774f206SBjoern A. Zeeb struct rtw_rx_pkt_stat *pkt_stat = iter_data->pkt_stat; 1052774f206SBjoern A. Zeeb u8 *bssid = iter_data->bssid; 1062774f206SBjoern A. Zeeb 1072774f206SBjoern A. Zeeb if (!ether_addr_equal(vif->bss_conf.bssid, bssid)) 1082774f206SBjoern A. Zeeb return; 1092774f206SBjoern A. Zeeb 1102774f206SBjoern A. Zeeb if (!(ether_addr_equal(vif->addr, hdr->addr1) || 1112774f206SBjoern A. Zeeb ieee80211_is_beacon(hdr->frame_control))) 1122774f206SBjoern A. Zeeb return; 1132774f206SBjoern A. Zeeb 1142774f206SBjoern A. Zeeb rtw_rx_phy_stat(rtwdev, pkt_stat, hdr); 1152774f206SBjoern A. Zeeb sta = ieee80211_find_sta_by_ifaddr(rtwdev->hw, hdr->addr2, 1162774f206SBjoern A. Zeeb vif->addr); 1172774f206SBjoern A. Zeeb if (!sta) 1182774f206SBjoern A. Zeeb return; 1192774f206SBjoern A. Zeeb 1202774f206SBjoern A. Zeeb si = (struct rtw_sta_info *)sta->drv_priv; 1212774f206SBjoern A. Zeeb ewma_rssi_add(&si->avg_rssi, pkt_stat->rssi); 1222774f206SBjoern A. Zeeb } 1232774f206SBjoern A. Zeeb 1242774f206SBjoern A. Zeeb static void rtw_rx_addr_match(struct rtw_dev *rtwdev, 1252774f206SBjoern A. Zeeb struct rtw_rx_pkt_stat *pkt_stat, 1262774f206SBjoern A. Zeeb struct ieee80211_hdr *hdr) 1272774f206SBjoern A. Zeeb { 1282774f206SBjoern A. Zeeb struct rtw_rx_addr_match_data data = {}; 1292774f206SBjoern A. Zeeb 1302774f206SBjoern A. Zeeb if (pkt_stat->crc_err || pkt_stat->icv_err || !pkt_stat->phy_status || 1312774f206SBjoern A. Zeeb ieee80211_is_ctl(hdr->frame_control)) 1322774f206SBjoern A. Zeeb return; 1332774f206SBjoern A. Zeeb 1342774f206SBjoern A. Zeeb data.rtwdev = rtwdev; 1352774f206SBjoern A. Zeeb data.hdr = hdr; 1362774f206SBjoern A. Zeeb data.pkt_stat = pkt_stat; 1372774f206SBjoern A. Zeeb data.bssid = get_hdr_bssid(hdr); 1382774f206SBjoern A. Zeeb 1392774f206SBjoern A. Zeeb rtw_iterate_vifs_atomic(rtwdev, rtw_rx_addr_match_iter, &data); 1402774f206SBjoern A. Zeeb } 1412774f206SBjoern A. Zeeb 1422774f206SBjoern A. Zeeb static void rtw_set_rx_freq_by_pktstat(struct rtw_rx_pkt_stat *pkt_stat, 1432774f206SBjoern A. Zeeb struct ieee80211_rx_status *rx_status) 1442774f206SBjoern A. Zeeb { 1452774f206SBjoern A. Zeeb rx_status->freq = pkt_stat->freq; 1462774f206SBjoern A. Zeeb rx_status->band = pkt_stat->band; 1472774f206SBjoern A. Zeeb } 1482774f206SBjoern A. Zeeb 1492774f206SBjoern A. Zeeb void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, 1502774f206SBjoern A. Zeeb struct rtw_rx_pkt_stat *pkt_stat, 1512774f206SBjoern A. Zeeb struct ieee80211_hdr *hdr, 1522774f206SBjoern A. Zeeb struct ieee80211_rx_status *rx_status, 1532774f206SBjoern A. Zeeb u8 *phy_status) 1542774f206SBjoern A. Zeeb { 1552774f206SBjoern A. Zeeb struct ieee80211_hw *hw = rtwdev->hw; 1562774f206SBjoern A. Zeeb u8 path; 1572774f206SBjoern A. Zeeb 1582774f206SBjoern A. Zeeb memset(rx_status, 0, sizeof(*rx_status)); 1592774f206SBjoern A. Zeeb rx_status->freq = hw->conf.chandef.chan->center_freq; 1602774f206SBjoern A. Zeeb rx_status->band = hw->conf.chandef.chan->band; 161*9c951734SBjoern A. Zeeb if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_SCAN_OFFLOAD) && 162*9c951734SBjoern A. Zeeb test_bit(RTW_FLAG_SCANNING, rtwdev->flags)) 1632774f206SBjoern A. Zeeb rtw_set_rx_freq_by_pktstat(pkt_stat, rx_status); 1642774f206SBjoern A. Zeeb if (pkt_stat->crc_err) 1652774f206SBjoern A. Zeeb rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; 1662774f206SBjoern A. Zeeb if (pkt_stat->decrypted) 1672774f206SBjoern A. Zeeb rx_status->flag |= RX_FLAG_DECRYPTED; 1682774f206SBjoern A. Zeeb 1692774f206SBjoern A. Zeeb if (pkt_stat->rate >= DESC_RATEVHT1SS_MCS0) 1702774f206SBjoern A. Zeeb rx_status->encoding = RX_ENC_VHT; 1712774f206SBjoern A. Zeeb else if (pkt_stat->rate >= DESC_RATEMCS0) 1722774f206SBjoern A. Zeeb rx_status->encoding = RX_ENC_HT; 1732774f206SBjoern A. Zeeb 1742774f206SBjoern A. Zeeb if (rx_status->band == NL80211_BAND_5GHZ && 1752774f206SBjoern A. Zeeb pkt_stat->rate >= DESC_RATE6M && 1762774f206SBjoern A. Zeeb pkt_stat->rate <= DESC_RATE54M) { 1772774f206SBjoern A. Zeeb rx_status->rate_idx = pkt_stat->rate - DESC_RATE6M; 1782774f206SBjoern A. Zeeb } else if (rx_status->band == NL80211_BAND_2GHZ && 1792774f206SBjoern A. Zeeb pkt_stat->rate >= DESC_RATE1M && 1802774f206SBjoern A. Zeeb pkt_stat->rate <= DESC_RATE54M) { 1812774f206SBjoern A. Zeeb rx_status->rate_idx = pkt_stat->rate - DESC_RATE1M; 1822774f206SBjoern A. Zeeb } else if (pkt_stat->rate >= DESC_RATEMCS0) { 1832774f206SBjoern A. Zeeb rtw_desc_to_mcsrate(pkt_stat->rate, &rx_status->rate_idx, 1842774f206SBjoern A. Zeeb &rx_status->nss); 1852774f206SBjoern A. Zeeb } 1862774f206SBjoern A. Zeeb 1872774f206SBjoern A. Zeeb rx_status->flag |= RX_FLAG_MACTIME_START; 1882774f206SBjoern A. Zeeb rx_status->mactime = pkt_stat->tsf_low; 1892774f206SBjoern A. Zeeb 1902774f206SBjoern A. Zeeb if (pkt_stat->bw == RTW_CHANNEL_WIDTH_80) 1912774f206SBjoern A. Zeeb rx_status->bw = RATE_INFO_BW_80; 1922774f206SBjoern A. Zeeb else if (pkt_stat->bw == RTW_CHANNEL_WIDTH_40) 1932774f206SBjoern A. Zeeb rx_status->bw = RATE_INFO_BW_40; 1942774f206SBjoern A. Zeeb else 1952774f206SBjoern A. Zeeb rx_status->bw = RATE_INFO_BW_20; 1962774f206SBjoern A. Zeeb 1972774f206SBjoern A. Zeeb rx_status->signal = pkt_stat->signal_power; 1982774f206SBjoern A. Zeeb for (path = 0; path < rtwdev->hal.rf_path_num; path++) { 1992774f206SBjoern A. Zeeb rx_status->chains |= BIT(path); 2002774f206SBjoern A. Zeeb rx_status->chain_signal[path] = pkt_stat->rx_power[path]; 2012774f206SBjoern A. Zeeb } 2022774f206SBjoern A. Zeeb 2032774f206SBjoern A. Zeeb rtw_rx_addr_match(rtwdev, pkt_stat, hdr); 2042774f206SBjoern A. Zeeb } 2052774f206SBjoern A. Zeeb EXPORT_SYMBOL(rtw_rx_fill_rx_status); 206