Commit 082a36dc authored by Tsang-Shian Lin's avatar Tsang-Shian Lin Committed by Kalle Valo

rtw88: add phy_info debugfs to show Tx/Rx physical status

This commit adds several Tx/Rx physical information to phy_info
debugfs for 8822B/8822C. By this debugfs, we can know physical
information, such as Tx/Rx rate, RSSI, EVM,SNR, etc. The
information is gotten from the packets of Tx/Rx path. It has
no impact for the performance of 8822B/8822C.

In the fields, we may meet different kinds of problems, but
we may have no professional instrument to check them. At
this moment, this debugfs is a good tool, and it may provide
useful information for debug.
Signed-off-by: default avatarTsang-Shian Lin <thlin@realtek.com>
Signed-off-by: default avatarYan-Hsuan Chuang <yhchuang@realtek.com>
Reviewed-by: default avatarChris Chiu <chiu@endlessm.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent f39e9bd4
......@@ -498,12 +498,32 @@ static void rtw_print_vht_rate_txt(struct seq_file *m, u8 rate)
seq_printf(m, " VHT%uSMCS%u", n_ss, mcs_n);
}
static void rtw_print_rate(struct seq_file *m, u8 rate)
{
switch (rate) {
case DESC_RATE1M...DESC_RATE11M:
rtw_print_cck_rate_txt(m, rate);
break;
case DESC_RATE6M...DESC_RATE54M:
rtw_print_ofdm_rate_txt(m, rate);
break;
case DESC_RATEMCS0...DESC_RATEMCS15:
rtw_print_ht_rate_txt(m, rate);
break;
case DESC_RATEVHT1SS_MCS0...DESC_RATEVHT2SS_MCS9:
rtw_print_vht_rate_txt(m, rate);
break;
default:
seq_printf(m, " Unknown rate=0x%x\n", rate);
break;
}
}
static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v)
{
struct rtw_debugfs_priv *debugfs_priv = m->private;
struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
struct rtw_hal *hal = &rtwdev->hal;
void (*print_rate)(struct seq_file *, u8) = NULL;
u8 path, rate;
struct rtw_power_params pwr_param = {0};
u8 bw = hal->current_band_width;
......@@ -528,30 +548,11 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v)
rate < DESC_RATEVHT1SS_MCS0)
continue;
switch (rate) {
case DESC_RATE1M...DESC_RATE11M:
print_rate = rtw_print_cck_rate_txt;
break;
case DESC_RATE6M...DESC_RATE54M:
print_rate = rtw_print_ofdm_rate_txt;
break;
case DESC_RATEMCS0...DESC_RATEMCS15:
print_rate = rtw_print_ht_rate_txt;
break;
case DESC_RATEVHT1SS_MCS0...DESC_RATEVHT2SS_MCS9:
print_rate = rtw_print_vht_rate_txt;
break;
default:
print_rate = NULL;
break;
}
rtw_get_tx_power_params(rtwdev, path, rate, bw,
ch, regd, &pwr_param);
seq_printf(m, "%4c ", path + 'A');
if (print_rate)
print_rate(m, rate);
rtw_print_rate(m, rate);
seq_printf(m, " %3u(0x%02x) %4u %4d (%4d %4d)\n",
hal->tx_pwr_tbl[path][rate],
hal->tx_pwr_tbl[path][rate],
......@@ -567,6 +568,132 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v)
return 0;
}
static int rtw_debugfs_get_phy_info(struct seq_file *m, void *v)
{
struct rtw_debugfs_priv *debugfs_priv = m->private;
struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
struct rtw_traffic_stats *stats = &rtwdev->stats;
struct rtw_pkt_count *last_cnt = &dm_info->last_pkt_count;
struct rtw_efuse *efuse = &rtwdev->efuse;
struct ewma_evm *ewma_evm = dm_info->ewma_evm;
struct ewma_snr *ewma_snr = dm_info->ewma_snr;
u8 ss, rate_id;
seq_puts(m, "==========[Common Info]========\n");
seq_printf(m, "Is link = %c\n", rtw_is_assoc(rtwdev) ? 'Y' : 'N');
seq_printf(m, "Current CH(fc) = %u\n", rtwdev->hal.current_channel);
seq_printf(m, "Current BW = %u\n", rtwdev->hal.current_band_width);
seq_printf(m, "Current IGI = 0x%x\n", dm_info->igi_history[0]);
seq_printf(m, "TP {Tx, Rx} = {%u, %u}Mbps\n\n",
stats->tx_throughput, stats->rx_throughput);
seq_puts(m, "==========[Tx Phy Info]========\n");
seq_puts(m, "[Tx Rate] = ");
rtw_print_rate(m, dm_info->tx_rate);
seq_printf(m, "(0x%x)\n\n", dm_info->tx_rate);
seq_puts(m, "==========[Rx Phy Info]========\n");
seq_printf(m, "[Rx Beacon Count] = %u\n", last_cnt->num_bcn_pkt);
seq_puts(m, "[Rx Rate] = ");
rtw_print_rate(m, dm_info->curr_rx_rate);
seq_printf(m, "(0x%x)\n", dm_info->curr_rx_rate);
seq_puts(m, "[Rx Rate Count]:\n");
seq_printf(m, " * CCK = {%u, %u, %u, %u}\n",
last_cnt->num_qry_pkt[DESC_RATE1M],
last_cnt->num_qry_pkt[DESC_RATE2M],
last_cnt->num_qry_pkt[DESC_RATE5_5M],
last_cnt->num_qry_pkt[DESC_RATE11M]);
seq_printf(m, " * OFDM = {%u, %u, %u, %u, %u, %u, %u, %u}\n",
last_cnt->num_qry_pkt[DESC_RATE6M],
last_cnt->num_qry_pkt[DESC_RATE9M],
last_cnt->num_qry_pkt[DESC_RATE12M],
last_cnt->num_qry_pkt[DESC_RATE18M],
last_cnt->num_qry_pkt[DESC_RATE24M],
last_cnt->num_qry_pkt[DESC_RATE36M],
last_cnt->num_qry_pkt[DESC_RATE48M],
last_cnt->num_qry_pkt[DESC_RATE54M]);
for (ss = 0; ss < efuse->hw_cap.nss; ss++) {
rate_id = DESC_RATEMCS0 + ss * 8;
seq_printf(m, " * HT_MCS[%u:%u] = {%u, %u, %u, %u, %u, %u, %u, %u}\n",
ss * 8, ss * 8 + 7,
last_cnt->num_qry_pkt[rate_id],
last_cnt->num_qry_pkt[rate_id + 1],
last_cnt->num_qry_pkt[rate_id + 2],
last_cnt->num_qry_pkt[rate_id + 3],
last_cnt->num_qry_pkt[rate_id + 4],
last_cnt->num_qry_pkt[rate_id + 5],
last_cnt->num_qry_pkt[rate_id + 6],
last_cnt->num_qry_pkt[rate_id + 7]);
}
for (ss = 0; ss < efuse->hw_cap.nss; ss++) {
rate_id = DESC_RATEVHT1SS_MCS0 + ss * 10;
seq_printf(m, " * VHT_MCS-%uss MCS[0:9] = {%u, %u, %u, %u, %u, %u, %u, %u, %u, %u}\n",
ss + 1,
last_cnt->num_qry_pkt[rate_id],
last_cnt->num_qry_pkt[rate_id + 1],
last_cnt->num_qry_pkt[rate_id + 2],
last_cnt->num_qry_pkt[rate_id + 3],
last_cnt->num_qry_pkt[rate_id + 4],
last_cnt->num_qry_pkt[rate_id + 5],
last_cnt->num_qry_pkt[rate_id + 6],
last_cnt->num_qry_pkt[rate_id + 7],
last_cnt->num_qry_pkt[rate_id + 8],
last_cnt->num_qry_pkt[rate_id + 9]);
}
seq_printf(m, "[RSSI(dBm)] = {%d, %d}\n",
dm_info->rssi[RF_PATH_A] - 100,
dm_info->rssi[RF_PATH_B] - 100);
seq_printf(m, "[Rx EVM(dB)] = {-%d, -%d}\n",
dm_info->rx_evm_dbm[RF_PATH_A],
dm_info->rx_evm_dbm[RF_PATH_B]);
seq_printf(m, "[Rx SNR] = {%d, %d}\n",
dm_info->rx_snr[RF_PATH_A],
dm_info->rx_snr[RF_PATH_B]);
seq_printf(m, "[CFO_tail(KHz)] = {%d, %d}\n",
dm_info->cfo_tail[RF_PATH_A],
dm_info->cfo_tail[RF_PATH_B]);
if (dm_info->curr_rx_rate >= DESC_RATE11M) {
seq_puts(m, "[Rx Average Status]:\n");
seq_printf(m, " * OFDM, EVM: {-%d}, SNR: {%d}\n",
(u8)ewma_evm_read(&ewma_evm[RTW_EVM_OFDM]),
(u8)ewma_snr_read(&ewma_snr[RTW_SNR_OFDM_A]));
seq_printf(m, " * 1SS, EVM: {-%d}, SNR: {%d}\n",
(u8)ewma_evm_read(&ewma_evm[RTW_EVM_1SS]),
(u8)ewma_snr_read(&ewma_snr[RTW_SNR_1SS_A]));
seq_printf(m, " * 2SS, EVM: {-%d, -%d}, SNR: {%d, %d}\n",
(u8)ewma_evm_read(&ewma_evm[RTW_EVM_2SS_A]),
(u8)ewma_evm_read(&ewma_evm[RTW_EVM_2SS_B]),
(u8)ewma_snr_read(&ewma_snr[RTW_SNR_2SS_A]),
(u8)ewma_snr_read(&ewma_snr[RTW_SNR_2SS_B]));
}
seq_puts(m, "[Rx Counter]:\n");
seq_printf(m, " * CCA (CCK, OFDM, Total) = (%u, %u, %u)\n",
dm_info->cck_cca_cnt,
dm_info->ofdm_cca_cnt,
dm_info->total_cca_cnt);
seq_printf(m, " * False Alarm (CCK, OFDM, Total) = (%u, %u, %u)\n",
dm_info->cck_fa_cnt,
dm_info->ofdm_fa_cnt,
dm_info->total_fa_cnt);
seq_printf(m, " * CCK cnt (ok, err) = (%u, %u)\n",
dm_info->cck_ok_cnt, dm_info->cck_err_cnt);
seq_printf(m, " * OFDM cnt (ok, err) = (%u, %u)\n",
dm_info->ofdm_ok_cnt, dm_info->ofdm_err_cnt);
seq_printf(m, " * HT cnt (ok, err) = (%u, %u)\n",
dm_info->ht_ok_cnt, dm_info->ht_err_cnt);
seq_printf(m, " * VHT cnt (ok, err) = (%u, %u)\n",
dm_info->vht_ok_cnt, dm_info->vht_err_cnt);
return 0;
}
#define rtw_debug_impl_mac(page, addr) \
static struct rtw_debugfs_priv rtw_debug_priv_mac_ ##page = { \
.cb_read = rtw_debug_get_mac_page, \
......@@ -653,6 +780,10 @@ static struct rtw_debugfs_priv rtw_debug_priv_rsvd_page = {
.cb_read = rtw_debugfs_get_rsvd_page,
};
static struct rtw_debugfs_priv rtw_debug_priv_phy_info = {
.cb_read = rtw_debugfs_get_phy_info,
};
#define rtw_debugfs_add_core(name, mode, fopname, parent) \
do { \
rtw_debug_priv_ ##name.rtwdev = rtwdev; \
......@@ -682,6 +813,7 @@ void rtw_debugfs_init(struct rtw_dev *rtwdev)
rtw_debugfs_add_rw(rf_read);
rtw_debugfs_add_rw(dump_cam);
rtw_debugfs_add_rw(rsvd_page);
rtw_debugfs_add_r(phy_info);
rtw_debugfs_add_r(mac_0);
rtw_debugfs_add_r(mac_1);
rtw_debugfs_add_r(mac_2);
......
......@@ -178,6 +178,7 @@ static void rtw_watch_dog_work(struct work_struct *work)
{
struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
watch_dog_work.work);
struct rtw_traffic_stats *stats = &rtwdev->stats;
struct rtw_watch_dog_iter_data data = {};
bool busy_traffic = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
bool ps_active;
......@@ -198,17 +199,24 @@ static void rtw_watch_dog_work(struct work_struct *work)
if (busy_traffic != test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags))
rtw_coex_wl_status_change_notify(rtwdev);
if (rtwdev->stats.tx_cnt > RTW_LPS_THRESHOLD ||
rtwdev->stats.rx_cnt > RTW_LPS_THRESHOLD)
if (stats->tx_cnt > RTW_LPS_THRESHOLD ||
stats->rx_cnt > RTW_LPS_THRESHOLD)
ps_active = true;
else
ps_active = false;
ewma_tp_add(&stats->tx_ewma_tp,
(u32)(stats->tx_unicast >> RTW_TP_SHIFT));
ewma_tp_add(&stats->rx_ewma_tp,
(u32)(stats->rx_unicast >> RTW_TP_SHIFT));
stats->tx_throughput = ewma_tp_read(&stats->tx_ewma_tp);
stats->rx_throughput = ewma_tp_read(&stats->rx_ewma_tp);
/* reset tx/rx statictics */
rtwdev->stats.tx_unicast = 0;
rtwdev->stats.rx_unicast = 0;
rtwdev->stats.tx_cnt = 0;
rtwdev->stats.rx_cnt = 0;
stats->tx_unicast = 0;
stats->rx_unicast = 0;
stats->tx_cnt = 0;
stats->rx_cnt = 0;
if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
goto unlock;
......@@ -1281,6 +1289,21 @@ int rtw_chip_info_setup(struct rtw_dev *rtwdev)
}
EXPORT_SYMBOL(rtw_chip_info_setup);
static void rtw_stats_init(struct rtw_dev *rtwdev)
{
struct rtw_traffic_stats *stats = &rtwdev->stats;
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
int i;
ewma_tp_init(&stats->tx_ewma_tp);
ewma_tp_init(&stats->rx_ewma_tp);
for (i = 0; i < RTW_EVM_NUM; i++)
ewma_evm_init(&dm_info->ewma_evm[i]);
for (i = 0; i < RTW_SNR_NUM; i++)
ewma_snr_init(&dm_info->ewma_snr[i]);
}
int rtw_core_init(struct rtw_dev *rtwdev)
{
struct rtw_chip_info *chip = rtwdev->chip;
......@@ -1329,6 +1352,8 @@ int rtw_core_init(struct rtw_dev *rtwdev)
rtw_add_rsvd_page(rtwdev, RSVD_BEACON, false);
mutex_unlock(&rtwdev->mutex);
rtw_stats_init(rtwdev);
/* default rx filter setting */
rtwdev->hal.rcr = BIT_APP_FCS | BIT_APP_MIC | BIT_APP_ICV |
BIT_HTC_LOC_CTRL | BIT_APP_PHYSTS |
......
......@@ -29,6 +29,8 @@
#define RTW_RF_PATH_MAX 4
#define HW_FEATURE_LEN 13
#define RTW_TP_SHIFT 18 /* bytes/2s --> Mbps */
extern bool rtw_bf_support;
extern unsigned int rtw_fw_lps_deep_mode;
extern unsigned int rtw_debug_mask;
......@@ -339,6 +341,32 @@ enum rtw_flags {
NUM_OF_RTW_FLAGS,
};
enum rtw_evm {
RTW_EVM_OFDM = 0,
RTW_EVM_1SS,
RTW_EVM_2SS_A,
RTW_EVM_2SS_B,
/* keep it last */
RTW_EVM_NUM
};
enum rtw_snr {
RTW_SNR_OFDM_A = 0,
RTW_SNR_OFDM_B,
RTW_SNR_OFDM_C,
RTW_SNR_OFDM_D,
RTW_SNR_1SS_A,
RTW_SNR_1SS_B,
RTW_SNR_1SS_C,
RTW_SNR_1SS_D,
RTW_SNR_2SS_A,
RTW_SNR_2SS_B,
RTW_SNR_2SS_C,
RTW_SNR_2SS_D,
/* keep it last */
RTW_SNR_NUM
};
/* the power index is represented by differences, which cck-1s & ht40-1s are
* the base values, so for 1s's differences, there are only ht20 & ofdm
*/
......@@ -527,10 +555,16 @@ struct rtw_rx_pkt_stat {
s8 rx_power[RTW_RF_PATH_MAX];
u8 rssi;
u8 rxsc;
s8 rx_snr[RTW_RF_PATH_MAX];
u8 rx_evm[RTW_RF_PATH_MAX];
s8 cfo_tail[RTW_RF_PATH_MAX];
struct rtw_sta_info *si;
struct ieee80211_vif *vif;
};
DECLARE_EWMA(tp, 10, 2);
struct rtw_traffic_stats {
/* units in bytes */
u64 tx_unicast;
......@@ -543,6 +577,8 @@ struct rtw_traffic_stats {
/* units in Mbps */
u32 tx_throughput;
u32 rx_throughput;
struct ewma_tp tx_ewma_tp;
struct ewma_tp rx_ewma_tp;
};
enum rtw_lps_mode {
......@@ -1251,10 +1287,21 @@ struct rtw_swing_table {
const u8 *n[RTW_RF_PATH_MAX];
};
struct rtw_pkt_count {
u16 num_bcn_pkt;
u16 num_qry_pkt[DESC_RATE_MAX];
};
DECLARE_EWMA(evm, 10, 4);
DECLARE_EWMA(snr, 10, 4);
struct rtw_dm_info {
u32 cck_fa_cnt;
u32 ofdm_fa_cnt;
u32 total_fa_cnt;
u32 cck_cca_cnt;
u32 ofdm_cca_cnt;
u32 total_cca_cnt;
u32 cck_ok_cnt;
u32 cck_err_cnt;
......@@ -1296,6 +1343,17 @@ struct rtw_dm_info {
/* [bandwidth 0:20M/1:40M][number of path] */
u8 cck_pd_lv[2][RTW_RF_PATH_MAX];
u32 cck_fa_avg;
/* save the last rx phy status for debug */
s8 rx_snr[RTW_RF_PATH_MAX];
u8 rx_evm_dbm[RTW_RF_PATH_MAX];
s16 cfo_tail[RTW_RF_PATH_MAX];
u8 rssi[RTW_RF_PATH_MAX];
u8 curr_rx_rate;
struct rtw_pkt_count cur_pkt_count;
struct rtw_pkt_count last_pkt_count;
struct ewma_evm ewma_evm[RTW_EVM_NUM];
struct ewma_snr ewma_snr[RTW_SNR_NUM];
};
struct rtw_efuse {
......
......@@ -222,10 +222,19 @@ static void rtw_phy_stat_rssi(struct rtw_dev *rtwdev)
dm_info->min_rssi = data.min_rssi;
}
static void rtw_phy_stat_rate_cnt(struct rtw_dev *rtwdev)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
dm_info->last_pkt_count = dm_info->cur_pkt_count;
memset(&dm_info->cur_pkt_count, 0, sizeof(dm_info->cur_pkt_count));
}
static void rtw_phy_statistics(struct rtw_dev *rtwdev)
{
rtw_phy_stat_rssi(rtwdev);
rtw_phy_stat_false_alarm(rtwdev);
rtw_phy_stat_rate_cnt(rtwdev);
}
#define DIG_PERF_FA_TH_LOW 250
......
......@@ -815,6 +815,7 @@ static void rtw8822b_config_trx_mode(struct rtw_dev *rtwdev, u8 tx_path,
static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status,
struct rtw_rx_pkt_stat *pkt_stat)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
s8 min_rx_power = -120;
u8 pwdb = GET_PHY_STAT_P0_PWDB(phy_status);
......@@ -824,13 +825,19 @@ static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status,
pkt_stat->bw = RTW_CHANNEL_WIDTH_20;
pkt_stat->signal_power = max(pkt_stat->rx_power[RF_PATH_A],
min_rx_power);
dm_info->rssi[RF_PATH_A] = pkt_stat->rssi;
}
static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status,
struct rtw_rx_pkt_stat *pkt_stat)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
u8 rxsc, bw;
s8 min_rx_power = -120;
s8 rx_evm;
u8 evm_dbm = 0;
u8 rssi;
int path;
if (pkt_stat->rate > DESC_RATE11M && pkt_stat->rate < DESC_RATEMCS0)
rxsc = GET_PHY_STAT_P1_L_RXSC(phy_status);
......@@ -853,6 +860,34 @@ static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status,
pkt_stat->signal_power = max3(pkt_stat->rx_power[RF_PATH_A],
pkt_stat->rx_power[RF_PATH_B],
min_rx_power);
dm_info->curr_rx_rate = pkt_stat->rate;
pkt_stat->rx_evm[RF_PATH_A] = GET_PHY_STAT_P1_RXEVM_A(phy_status);
pkt_stat->rx_evm[RF_PATH_B] = GET_PHY_STAT_P1_RXEVM_B(phy_status);
pkt_stat->rx_snr[RF_PATH_A] = GET_PHY_STAT_P1_RXSNR_A(phy_status);
pkt_stat->rx_snr[RF_PATH_B] = GET_PHY_STAT_P1_RXSNR_B(phy_status);
pkt_stat->cfo_tail[RF_PATH_A] = GET_PHY_STAT_P1_CFO_TAIL_A(phy_status);
pkt_stat->cfo_tail[RF_PATH_B] = GET_PHY_STAT_P1_CFO_TAIL_B(phy_status);
for (path = 0; path <= rtwdev->hal.rf_path_num; path++) {
rssi = rtw_phy_rf_power_2_rssi(&pkt_stat->rx_power[path], 1);
dm_info->rssi[path] = rssi;
dm_info->rx_snr[path] = pkt_stat->rx_snr[path] >> 1;
dm_info->cfo_tail[path] = (pkt_stat->cfo_tail[path] * 5) >> 1;
rx_evm = pkt_stat->rx_evm[path];
if (rx_evm < 0) {
if (rx_evm == S8_MIN)
evm_dbm = 0;
else
evm_dbm = ((u8)-rx_evm >> 1);
}
dm_info->rx_evm_dbm[path] = evm_dbm;
}
}
static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
......@@ -999,6 +1034,7 @@ static void rtw8822b_false_alarm_statistics(struct rtw_dev *rtwdev)
u32 cck_fa_cnt;
u32 ofdm_fa_cnt;
u32 crc32_cnt;
u32 cca32_cnt;
cck_enable = rtw_read32(rtwdev, 0x808) & BIT(28);
cck_fa_cnt = rtw_read16(rtwdev, 0xa5c);
......@@ -1022,6 +1058,15 @@ static void rtw8822b_false_alarm_statistics(struct rtw_dev *rtwdev)
dm_info->vht_ok_cnt = crc32_cnt & 0xffff;
dm_info->vht_err_cnt = (crc32_cnt & 0xffff0000) >> 16;
cca32_cnt = rtw_read32(rtwdev, 0xf08);
dm_info->ofdm_cca_cnt = ((cca32_cnt & 0xffff0000) >> 16);
dm_info->total_cca_cnt = dm_info->ofdm_cca_cnt;
if (cck_enable) {
cca32_cnt = rtw_read32(rtwdev, 0xfcc);
dm_info->cck_cca_cnt = cca32_cnt & 0xffff;
dm_info->total_cca_cnt += dm_info->cck_cca_cnt;
}
rtw_write32_set(rtwdev, 0x9a4, BIT(17));
rtw_write32_clr(rtwdev, 0x9a4, BIT(17));
rtw_write32_clr(rtwdev, 0xa2c, BIT(15));
......
......@@ -127,6 +127,18 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(11, 8))
#define GET_PHY_STAT_P1_HT_RXSC(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(15, 12))
#define GET_PHY_STAT_P1_RXEVM_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0))
#define GET_PHY_STAT_P1_RXEVM_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(15, 8))
#define GET_PHY_STAT_P1_CFO_TAIL_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(7, 0))
#define GET_PHY_STAT_P1_CFO_TAIL_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(15, 8))
#define GET_PHY_STAT_P1_RXSNR_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0))
#define GET_PHY_STAT_P1_RXSNR_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(15, 8))
#define REG_HTSTFWT 0x800
#define REG_RXPSEL 0x808
......
......@@ -1643,6 +1643,8 @@ static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status,
u8 gain_a, gain_b;
s8 rx_power[RTW_RF_PATH_MAX];
s8 min_rx_power = -120;
u8 rssi;
int path;
rx_power[RF_PATH_A] = GET_PHY_STAT_P0_PWDB_A(phy_status);
rx_power[RF_PATH_B] = GET_PHY_STAT_P0_PWDB_B(phy_status);
......@@ -1665,6 +1667,11 @@ static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status,
pkt_stat->rx_power[RF_PATH_A] = rx_power[RF_PATH_A];
pkt_stat->rx_power[RF_PATH_B] = rx_power[RF_PATH_B];
for (path = 0; path <= rtwdev->hal.rf_path_num; path++) {
rssi = rtw_phy_rf_power_2_rssi(&pkt_stat->rx_power[path], 1);
dm_info->rssi[path] = rssi;
}
pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 1);
pkt_stat->bw = RTW_CHANNEL_WIDTH_20;
pkt_stat->signal_power = max(pkt_stat->rx_power[RF_PATH_A],
......@@ -1674,8 +1681,13 @@ static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status,
static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status,
struct rtw_rx_pkt_stat *pkt_stat)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
u8 rxsc, bw;
s8 min_rx_power = -120;
s8 rx_evm;
u8 evm_dbm = 0;
u8 rssi;
int path;
if (pkt_stat->rate > DESC_RATE11M && pkt_stat->rate < DESC_RATEMCS0)
rxsc = GET_PHY_STAT_P1_L_RXSC(phy_status);
......@@ -1696,6 +1708,34 @@ static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status,
pkt_stat->signal_power = max3(pkt_stat->rx_power[RF_PATH_A],
pkt_stat->rx_power[RF_PATH_B],
min_rx_power);
dm_info->curr_rx_rate = pkt_stat->rate;
pkt_stat->rx_evm[RF_PATH_A] = GET_PHY_STAT_P1_RXEVM_A(phy_status);
pkt_stat->rx_evm[RF_PATH_B] = GET_PHY_STAT_P1_RXEVM_B(phy_status);
pkt_stat->rx_snr[RF_PATH_A] = GET_PHY_STAT_P1_RXSNR_A(phy_status);
pkt_stat->rx_snr[RF_PATH_B] = GET_PHY_STAT_P1_RXSNR_B(phy_status);
pkt_stat->cfo_tail[RF_PATH_A] = GET_PHY_STAT_P1_CFO_TAIL_A(phy_status);
pkt_stat->cfo_tail[RF_PATH_B] = GET_PHY_STAT_P1_CFO_TAIL_B(phy_status);
for (path = 0; path <= rtwdev->hal.rf_path_num; path++) {
rssi = rtw_phy_rf_power_2_rssi(&pkt_stat->rx_power[path], 1);
dm_info->rssi[path] = rssi;
dm_info->rx_snr[path] = pkt_stat->rx_snr[path] >> 1;
dm_info->cfo_tail[path] = (pkt_stat->cfo_tail[path] * 5) >> 1;
rx_evm = pkt_stat->rx_evm[path];
if (rx_evm < 0) {
if (rx_evm == S8_MIN)
evm_dbm = 0;
else
evm_dbm = ((u8)-rx_evm >> 1);
}
dm_info->rx_evm_dbm[path] = evm_dbm;
}
}
static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
......@@ -1850,6 +1890,7 @@ static void rtw8822c_false_alarm_statistics(struct rtw_dev *rtwdev)
u32 cck_enable;
u32 cck_fa_cnt;
u32 crc32_cnt;
u32 cca32_cnt;
u32 ofdm_fa_cnt;
u32 ofdm_fa_cnt1, ofdm_fa_cnt2, ofdm_fa_cnt3, ofdm_fa_cnt4, ofdm_fa_cnt5;
u16 parity_fail, rate_illegal, crc8_fail, mcs_fail, sb_search_fail,
......@@ -1894,6 +1935,13 @@ static void rtw8822c_false_alarm_statistics(struct rtw_dev *rtwdev)
dm_info->vht_ok_cnt = crc32_cnt & 0xffff;
dm_info->vht_err_cnt = (crc32_cnt & 0xffff0000) >> 16;
cca32_cnt = rtw_read32(rtwdev, 0x2c08);
dm_info->ofdm_cca_cnt = ((cca32_cnt & 0xffff0000) >> 16);
dm_info->cck_cca_cnt = cca32_cnt & 0xffff;
dm_info->total_cca_cnt = dm_info->ofdm_cca_cnt;
if (cck_enable)
dm_info->total_cca_cnt += dm_info->cck_cca_cnt;
rtw_write32_mask(rtwdev, REG_CCANRX, BIT_CCK_FA_RST, 0);
rtw_write32_mask(rtwdev, REG_CCANRX, BIT_CCK_FA_RST, 2);
rtw_write32_mask(rtwdev, REG_CCANRX, BIT_OFDM_FA_RST, 0);
......
......@@ -149,6 +149,18 @@ const struct rtw_table name ## _tbl = { \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(11, 8))
#define GET_PHY_STAT_P1_HT_RXSC(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(15, 12))
#define GET_PHY_STAT_P1_RXEVM_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0))
#define GET_PHY_STAT_P1_RXEVM_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(15, 8))
#define GET_PHY_STAT_P1_CFO_TAIL_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(7, 0))
#define GET_PHY_STAT_P1_CFO_TAIL_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(15, 8))
#define GET_PHY_STAT_P1_RXSNR_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0))
#define GET_PHY_STAT_P1_RXSNR_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(15, 8))
#define REG_ANAPARLDO_POW_MAC 0x0029
#define BIT_LDOE25_PON BIT(0)
......
......@@ -5,6 +5,7 @@
#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)
......@@ -37,6 +38,60 @@ struct rtw_rx_addr_match_data {
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)
{
......@@ -48,14 +103,16 @@ static void rtw_rx_addr_match_iter(void *data, u8 *mac,
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
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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment