| From 97f4660009bcee136694bc1fdf376d0ffd8dc103 Mon Sep 17 00:00:00 2001 |
| From: Peter Chiu <chui-hao.chiu@mediatek.com> |
| Date: Fri, 28 Apr 2023 10:39:58 +0800 |
| Subject: [PATCH 1029/1044] mtk: wifi: mt76: mt7996: add debugfs knob for |
| rx_counters |
| |
| Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com> |
| --- |
| agg-rx.c | 8 ++++++++ |
| mac80211.c | 16 ++++++++++++++-- |
| mt76.h | 15 +++++++++++++++ |
| mt7996/mac.c | 18 +++++++++++++++--- |
| mt7996/mtk_debugfs.c | 42 ++++++++++++++++++++++++++++++++++++++++++ |
| 5 files changed, 94 insertions(+), 5 deletions(-) |
| |
| diff --git a/agg-rx.c b/agg-rx.c |
| index 10cbd9e5..adb5a7d7 100644 |
| --- a/agg-rx.c |
| +++ b/agg-rx.c |
| @@ -33,10 +33,13 @@ mt76_rx_aggr_release_frames(struct mt76_rx_tid *tid, |
| struct sk_buff_head *frames, |
| u16 head) |
| { |
| + struct mt76_phy *phy = mt76_dev_phy(tid->dev, tid->band_idx); |
| int idx; |
| |
| while (ieee80211_sn_less(tid->head, head)) { |
| idx = tid->head % tid->size; |
| + if (!tid->reorder_buf[idx]) |
| + phy->rx_stats.rx_agg_miss++; |
| mt76_aggr_release(tid, frames, idx); |
| } |
| } |
| @@ -151,6 +154,7 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames) |
| struct mt76_wcid *wcid = status->wcid; |
| struct ieee80211_sta *sta; |
| struct mt76_rx_tid *tid; |
| + struct mt76_phy *phy; |
| bool sn_less; |
| u16 seqno, head, size, idx; |
| u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK; |
| @@ -186,6 +190,7 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames) |
| head = tid->head; |
| seqno = status->seqno; |
| size = tid->size; |
| + phy = mt76_dev_phy(tid->dev, tid->band_idx); |
| sn_less = ieee80211_sn_less(seqno, head); |
| |
| if (!tid->started) { |
| @@ -197,6 +202,7 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames) |
| |
| if (sn_less) { |
| __skb_unlink(skb, frames); |
| + phy->rx_stats.rx_dup_drop++; |
| dev_kfree_skb(skb); |
| goto out; |
| } |
| @@ -223,6 +229,7 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames) |
| |
| /* Discard if the current slot is already in use */ |
| if (tid->reorder_buf[idx]) { |
| + phy->rx_stats.rx_dup_drop++; |
| dev_kfree_skb(skb); |
| goto out; |
| } |
| @@ -254,6 +261,7 @@ int mt76_rx_aggr_start(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tidno, |
| tid->head = ssn; |
| tid->size = size; |
| tid->num = tidno; |
| + tid->band_idx = wcid->phy_idx; |
| INIT_DELAYED_WORK(&tid->reorder_work, mt76_rx_aggr_reorder_work); |
| spin_lock_init(&tid->lock); |
| |
| diff --git a/mac80211.c b/mac80211.c |
| index 87dcc8a3..45791f6e 100644 |
| --- a/mac80211.c |
| +++ b/mac80211.c |
| @@ -784,6 +784,7 @@ static void mt76_rx_release_amsdu(struct mt76_phy *phy, enum mt76_rxq_id q) |
| } |
| |
| if (ether_addr_equal(skb->data + offset, rfc1042_header)) { |
| + phy->rx_stats.rx_drop++; |
| dev_kfree_skb(skb); |
| return; |
| } |
| @@ -1100,10 +1101,16 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb, |
| |
| *sta = wcid_to_sta(mstat.wcid); |
| *hw = mt76_phy_hw(dev, mstat.phy_idx); |
| + |
| + if ((mstat.flag & RX_FLAG_8023) || ieee80211_is_data_qos(hdr->frame_control)) { |
| + struct mt76_phy *phy = mt76_dev_phy(dev, mstat.phy_idx); |
| + |
| + phy->rx_stats.rx_mac80211++; |
| + } |
| } |
| |
| static void |
| -mt76_check_ccmp_pn(struct sk_buff *skb) |
| +mt76_check_ccmp_pn(struct mt76_dev *dev, struct sk_buff *skb) |
| { |
| struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; |
| struct mt76_wcid *wcid = status->wcid; |
| @@ -1150,7 +1157,11 @@ skip_hdr_check: |
| ret = memcmp(status->iv, wcid->rx_key_pn[security_idx], |
| sizeof(status->iv)); |
| if (ret <= 0) { |
| + struct mt76_phy *phy = mt76_dev_phy(dev, status->phy_idx); |
| + |
| + phy->rx_stats.rx_pn_iv_error++; |
| status->flag |= RX_FLAG_ONLY_MONITOR; |
| + |
| return; |
| } |
| |
| @@ -1331,7 +1342,7 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, |
| while ((skb = __skb_dequeue(frames)) != NULL) { |
| struct sk_buff *nskb = skb_shinfo(skb)->frag_list; |
| |
| - mt76_check_ccmp_pn(skb); |
| + mt76_check_ccmp_pn(dev, skb); |
| skb_shinfo(skb)->frag_list = NULL; |
| mt76_rx_convert(dev, skb, &hw, &sta); |
| ieee80211_rx_list(hw, sta, skb, &list); |
| @@ -1354,6 +1365,7 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, |
| } |
| |
| list_for_each_entry_safe(skb, tmp, &list, list) { |
| + dev->rx_kernel++; |
| skb_list_del_init(skb); |
| napi_gro_receive(napi, skb); |
| } |
| diff --git a/mt76.h b/mt76.h |
| index 46fbc87e..9e8848f7 100644 |
| --- a/mt76.h |
| +++ b/mt76.h |
| @@ -422,6 +422,7 @@ struct mt76_rx_tid { |
| struct rcu_head rcu_head; |
| |
| struct mt76_dev *dev; |
| + u8 band_idx; |
| |
| spinlock_t lock; |
| struct delayed_work reorder_work; |
| @@ -853,6 +854,19 @@ struct mt76_phy { |
| bool al; |
| u8 pin; |
| } leds; |
| + |
| + struct { |
| + u32 rx_mac80211; |
| + |
| + u32 rx_drop; |
| + u32 rx_rxd_drop; |
| + u32 rx_dup_drop; |
| + u32 rx_agg_miss; |
| + u32 rx_icv_error; |
| + u32 rx_fcs_error; |
| + u32 rx_tkip_mic_error; |
| + u32 rx_pn_iv_error; |
| + } rx_stats; |
| }; |
| |
| struct mt76_dev { |
| @@ -958,6 +972,7 @@ struct mt76_dev { |
| }; |
| |
| const char *bin_file_name; |
| + u32 rx_kernel; |
| }; |
| |
| /* per-phy stats. */ |
| diff --git a/mt7996/mac.c b/mt7996/mac.c |
| index 22d7dc6d..73c66e57 100644 |
| --- a/mt7996/mac.c |
| +++ b/mt7996/mac.c |
| @@ -469,8 +469,10 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q, |
| return -EINVAL; |
| |
| /* ICV error or CCMP/BIP/WPI MIC error */ |
| - if (rxd1 & MT_RXD1_NORMAL_ICV_ERR) |
| + if (rxd1 & MT_RXD1_NORMAL_ICV_ERR) { |
| + mphy->rx_stats.rx_icv_error++; |
| status->flag |= RX_FLAG_ONLY_MONITOR; |
| + } |
| |
| unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M; |
| idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1); |
| @@ -501,11 +503,15 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q, |
| !(csum_status & (BIT(0) | BIT(2) | BIT(3)))) |
| skb->ip_summed = CHECKSUM_UNNECESSARY; |
| |
| - if (rxd1 & MT_RXD3_NORMAL_FCS_ERR) |
| + if (rxd1 & MT_RXD3_NORMAL_FCS_ERR) { |
| + mphy->rx_stats.rx_fcs_error++; |
| status->flag |= RX_FLAG_FAILED_FCS_CRC; |
| + } |
| |
| - if (rxd1 & MT_RXD1_NORMAL_TKIP_MIC_ERR) |
| + if (rxd1 & MT_RXD1_NORMAL_TKIP_MIC_ERR) { |
| + mphy->rx_stats.rx_tkip_mic_error++; |
| status->flag |= RX_FLAG_MMIC_ERROR; |
| + } |
| |
| if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 && |
| !(rxd1 & (MT_RXD1_NORMAL_CLM | MT_RXD1_NORMAL_CM))) { |
| @@ -1414,8 +1420,10 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, |
| struct sk_buff *skb, u32 *info) |
| { |
| struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); |
| + struct mt76_phy *phy; |
| __le32 *rxd = (__le32 *)skb->data; |
| __le32 *end = (__le32 *)&skb->data[skb->len]; |
| + u8 band_idx; |
| enum rx_pkt_type type; |
| |
| type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); |
| @@ -1457,6 +1465,10 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, |
| } |
| fallthrough; |
| default: |
| + band_idx = le32_get_bits(rxd[1], MT_RXD1_NORMAL_BAND_IDX); |
| + phy = mt76_dev_phy(mdev, band_idx); |
| + if (likely(phy)) |
| + phy->rx_stats.rx_rxd_drop++; |
| dev_kfree_skb(skb); |
| break; |
| } |
| diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c |
| index d1ca9ce7..17bbed65 100644 |
| --- a/mt7996/mtk_debugfs.c |
| +++ b/mt7996/mtk_debugfs.c |
| @@ -2854,6 +2854,46 @@ mt7996_sr_scene_cond_show(struct seq_file *file, void *data) |
| } |
| DEFINE_SHOW_ATTRIBUTE(mt7996_sr_scene_cond); |
| |
| +static int mt7996_rx_counters(struct seq_file *s, void *data) |
| +{ |
| + struct mt7996_dev *dev = dev_get_drvdata(s->private); |
| + u32 rx_mac80211 = 0; |
| + int i = 0; |
| + |
| + for (i = 0; i < __MT_MAX_BAND; i++) { |
| + struct mt76_phy *phy = mt76_dev_phy(&dev->mt76, i); |
| + |
| + if (!phy) |
| + continue; |
| + |
| + seq_printf(s, "\n==========PHY%d==========\n", i); |
| + |
| +#define SEQ_PRINT(_str, _rx_param) do { \ |
| + seq_printf(s, _str"\n", phy->rx_stats._rx_param); \ |
| + } while (0) |
| + |
| + SEQ_PRINT("Rx to mac80211: %u", rx_mac80211); |
| + SEQ_PRINT("Rx drop: %u", rx_drop); |
| + SEQ_PRINT("Rx drop due to RXD type error: %u", rx_rxd_drop); |
| + SEQ_PRINT("Rx duplicated drop: %u", rx_dup_drop); |
| + SEQ_PRINT("Rx agg miss: %u", rx_agg_miss); |
| + SEQ_PRINT("Rx ICV error: %u", rx_icv_error); |
| + SEQ_PRINT("Rx FCS error: %u", rx_fcs_error); |
| + SEQ_PRINT("Rx TKIP MIC error: %u", rx_tkip_mic_error); |
| + SEQ_PRINT("Rx PN/IV error: %u", rx_pn_iv_error); |
| +#undef SEQ_PRINT |
| + |
| + rx_mac80211 += phy->rx_stats.rx_mac80211; |
| + } |
| + |
| + seq_printf(s, "\n==========SUM==========\n"); |
| + seq_printf(s, "Rx to kernel: %u\n", dev->mt76.rx_kernel); |
| + seq_printf(s, "Rx to mac80211: %u\n", rx_mac80211); |
| + |
| + |
| + return 0; |
| +} |
| + |
| int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir) |
| { |
| struct mt7996_dev *dev = phy->dev; |
| @@ -2917,6 +2957,8 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir) |
| |
| debugfs_create_devm_seqfile(dev->mt76.dev, "tr_info", dir, |
| mt7996_trinfo_read); |
| + debugfs_create_devm_seqfile(dev->mt76.dev, "rx_counters", dir, |
| + mt7996_rx_counters); |
| debugfs_create_file("txpower_level", 0600, dir, phy, &fops_txpower_level); |
| debugfs_create_file("txpower_info", 0600, dir, phy, &mt7996_txpower_info_fops); |
| debugfs_create_file("txpower_sku", 0600, dir, phy, &mt7996_txpower_sku_fops); |
| -- |
| 2.18.0 |
| |