In the current design, various chip functions and tables are built into rtw88 core. That causes kernel to load its functionalities even if a chip isn't currently used. We plan to make each chip's functionalities a separate kernel module to reduce rtw88 core. And kernel will be able to load the necessary. Before extracting chip functionalities, we export symbols inside rtw88 core which will be used in chip modules. Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com> Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org> Link: https://lore.kernel.org/r/20200515052327.31874-2-yhchuang@realtek.com
195 lines
5.1 KiB
C
195 lines
5.1 KiB
C
// 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"
|
|
#include "debug.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++;
|
|
}
|
|
}
|
|
}
|
|
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_phy_stat(struct rtw_dev *rtwdev,
|
|
struct rtw_rx_pkt_stat *pkt_stat,
|
|
struct ieee80211_hdr *hdr)
|
|
{
|
|
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
|
struct rtw_pkt_count *cur_pkt_cnt = &dm_info->cur_pkt_count;
|
|
u8 rate_ss, rate_ss_evm, evm_id;
|
|
u8 i, idx;
|
|
|
|
dm_info->curr_rx_rate = pkt_stat->rate;
|
|
|
|
if (ieee80211_is_beacon(hdr->frame_control))
|
|
cur_pkt_cnt->num_bcn_pkt++;
|
|
|
|
switch (pkt_stat->rate) {
|
|
case DESC_RATE1M...DESC_RATE11M:
|
|
goto pkt_num;
|
|
case DESC_RATE6M...DESC_RATE54M:
|
|
rate_ss = 0;
|
|
rate_ss_evm = 1;
|
|
evm_id = RTW_EVM_OFDM;
|
|
break;
|
|
case DESC_RATEMCS0...DESC_RATEMCS7:
|
|
case DESC_RATEVHT1SS_MCS0...DESC_RATEVHT1SS_MCS9:
|
|
rate_ss = 1;
|
|
rate_ss_evm = 1;
|
|
evm_id = RTW_EVM_1SS;
|
|
break;
|
|
case DESC_RATEMCS8...DESC_RATEMCS15:
|
|
case DESC_RATEVHT2SS_MCS0...DESC_RATEVHT2SS_MCS9:
|
|
rate_ss = 2;
|
|
rate_ss_evm = 2;
|
|
evm_id = RTW_EVM_2SS_A;
|
|
break;
|
|
default:
|
|
rtw_warn(rtwdev, "unknown pkt rate = %d\n", pkt_stat->rate);
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < rate_ss_evm; i++) {
|
|
idx = evm_id + i;
|
|
ewma_evm_add(&dm_info->ewma_evm[idx],
|
|
dm_info->rx_evm_dbm[i]);
|
|
}
|
|
|
|
for (i = 0; i < rtwdev->hal.rf_path_num; i++) {
|
|
idx = RTW_SNR_OFDM_A + 4 * rate_ss + i;
|
|
ewma_snr_add(&dm_info->ewma_snr[idx],
|
|
dm_info->rx_snr[i]);
|
|
}
|
|
pkt_num:
|
|
cur_pkt_cnt->num_qry_pkt[pkt_stat->rate]++;
|
|
}
|
|
|
|
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))
|
|
return;
|
|
|
|
if (!(ether_addr_equal(vif->addr, hdr->addr1) ||
|
|
ieee80211_is_beacon(hdr->frame_control)))
|
|
return;
|
|
|
|
rtw_rx_phy_stat(rtwdev, pkt_stat, hdr);
|
|
sta = ieee80211_find_sta_by_ifaddr(rtwdev->hw, hdr->addr2,
|
|
vif->addr);
|
|
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;
|
|
u8 path;
|
|
|
|
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 (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 if (pkt_stat->rate >= DESC_RATEMCS0) {
|
|
rtw_desc_to_mcsrate(pkt_stat->rate, &rx_status->rate_idx,
|
|
&rx_status->nss);
|
|
}
|
|
|
|
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;
|
|
for (path = 0; path < rtwdev->hal.rf_path_num; path++) {
|
|
rx_status->chains |= BIT(path);
|
|
rx_status->chain_signal[path] = pkt_stat->rx_power[path];
|
|
}
|
|
|
|
rtw_rx_addr_match(rtwdev, pkt_stat, hdr);
|
|
}
|
|
EXPORT_SYMBOL(rtw_rx_fill_rx_status);
|