wifi: mt76: mt7915: rework tx packets counting when WED is active
authorPeter Chiu <chui-hao.chiu@mediatek.com>
Wed, 10 May 2023 04:53:17 +0000 (12:53 +0800)
committerFelix Fietkau <nbd@nbd.name>
Tue, 25 Jul 2023 19:59:40 +0000 (21:59 +0200)
PPDU TxS can only report MPDU count whereas mac80211 requires MSDU scale
(NL80211_STA_INFO_TX_PACKETS), so switch to get MSDU counts from WA
statistic.

Note that mt7915 WA firmware only counts tx_packet for WED path, so driver
needs to take care of host path additionally.

Fixes: 43eaa3689507 ("wifi: mt76: add PPDU based TxS support for WED device")
Co-developed-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt76.h
drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
drivers/net/wireless/mediatek/mt76/mt7915/main.c
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h

index 6b07b8f..0e9f419 100644 (file)
@@ -277,7 +277,7 @@ struct mt76_sta_stats {
        u64 tx_mcs[16];         /* mcs idx */
        u64 tx_bytes;
        /* WED TX */
-       u32 tx_packets;
+       u32 tx_packets;         /* unit: MSDU */
        u32 tx_retries;
        u32 tx_failed;
        /* WED RX */
index 3686684..f6346a4 100644 (file)
@@ -523,7 +523,9 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
 
                /* counting non-offloading skbs */
                wcid->stats.tx_bytes += skb->len;
-               wcid->stats.tx_packets++;
+               /* mt7915 WA only counts WED path */
+               if (is_mt7915(dev) && mtk_wed_device_active(&dev->mmio.wed))
+                       wcid->stats.tx_packets++;
        }
 
        val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |
@@ -606,12 +608,11 @@ bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid,
        txs = le32_to_cpu(txs_data[0]);
 
        /* PPDU based reporting */
-       if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) {
+       if (mtk_wed_device_active(&dev->mmio.wed) &&
+           FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) {
                stats->tx_bytes +=
                        le32_get_bits(txs_data[5], MT_TXS5_MPDU_TX_BYTE) -
                        le32_get_bits(txs_data[7], MT_TXS7_MPDU_RETRY_BYTE);
-               stats->tx_packets +=
-                       le32_get_bits(txs_data[5], MT_TXS5_MPDU_TX_CNT);
                stats->tx_failed +=
                        le32_get_bits(txs_data[6], MT_TXS6_MPDU_FAIL_CNT);
                stats->tx_retries +=
index ca1ce97..7a52b68 100644 (file)
@@ -998,6 +998,7 @@ enum {
        MCU_EXT_EVENT_ASSERT_DUMP = 0x23,
        MCU_EXT_EVENT_RDD_REPORT = 0x3a,
        MCU_EXT_EVENT_CSA_NOTIFY = 0x4f,
+       MCU_EXT_EVENT_WA_TX_STAT = 0x74,
        MCU_EXT_EVENT_BCC_NOTIFY = 0x75,
        MCU_EXT_EVENT_MURU_CTRL = 0x9f,
 };
index 706aca3..6512fdf 100644 (file)
@@ -1042,8 +1042,10 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw,
                sinfo->tx_bytes = msta->wcid.stats.tx_bytes;
                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);
 
-               sinfo->tx_packets = msta->wcid.stats.tx_packets;
-               sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
+               if (!mt7915_mcu_wed_wa_tx_stats(phy->dev, msta->wcid.idx)) {
+                       sinfo->tx_packets = msta->wcid.stats.tx_packets;
+                       sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
+               }
 
                if (mtk_wed_get_rx_capa(&phy->dev->mt76.mmio.wed)) {
                        sinfo->rx_bytes = msta->wcid.stats.rx_bytes;
index 088a065..8da9c87 100644 (file)
@@ -164,7 +164,9 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
        }
 
        rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
-       if (seq != rxd->seq)
+       if (seq != rxd->seq &&
+           !(rxd->eid == MCU_CMD_EXT_CID &&
+             rxd->ext_eid == MCU_EXT_EVENT_WA_TX_STAT))
                return -EAGAIN;
 
        if (cmd == MCU_CMD(PATCH_SEM_CONTROL)) {
@@ -395,12 +397,14 @@ void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb)
        struct mt76_connac2_mcu_rxd *rxd;
 
        rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
-       if (rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT ||
-           rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST ||
-           rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP ||
-           rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC ||
-           rxd->ext_eid == MCU_EXT_EVENT_BCC_NOTIFY ||
-           !rxd->seq)
+       if ((rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT ||
+            rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST ||
+            rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP ||
+            rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC ||
+            rxd->ext_eid == MCU_EXT_EVENT_BCC_NOTIFY ||
+            !rxd->seq) &&
+            !(rxd->eid == MCU_CMD_EXT_CID &&
+              rxd->ext_eid == MCU_EXT_EVENT_WA_TX_STAT))
                mt7915_mcu_rx_unsolicited_event(dev, skb);
        else
                mt76_mcu_rx_event(&dev->mt76, skb);
@@ -3733,6 +3737,62 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
                                 &req, sizeof(req), true);
 }
 
+int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wlan_idx)
+{
+       struct {
+               __le32 cmd;
+               __le32 num;
+               __le32 __rsv;
+               __le16 wlan_idx;
+       } req = {
+               .cmd = cpu_to_le32(0x15),
+               .num = cpu_to_le32(1),
+               .wlan_idx = cpu_to_le16(wlan_idx),
+       };
+       struct mt7915_mcu_wa_tx_stat {
+               __le16 wlan_idx;
+               u8 __rsv[2];
+
+               /* tx_bytes is deprecated since WA byte counter uses u32,
+                * which easily leads to overflow.
+                */
+               __le32 tx_bytes;
+               __le32 tx_packets;
+       } *res;
+       struct mt76_wcid *wcid;
+       struct sk_buff *skb;
+       int ret;
+
+       ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WA_PARAM_CMD(QUERY),
+                                       &req, sizeof(req), true, &skb);
+       if (ret)
+               return ret;
+
+       if (!is_mt7915(&dev->mt76))
+               skb_pull(skb, 4);
+
+       res = (struct mt7915_mcu_wa_tx_stat *)skb->data;
+
+       if (le16_to_cpu(res->wlan_idx) != wlan_idx) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       rcu_read_lock();
+
+       wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
+       if (wcid)
+               wcid->stats.tx_packets += le32_to_cpu(res->tx_packets);
+       else
+               ret = -EINVAL;
+
+       rcu_read_unlock();
+out:
+       dev_kfree_skb(skb);
+
+       return ret;
+}
+
 int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set)
 {
        struct {
index b3ead35..3053f4a 100644 (file)
@@ -539,6 +539,7 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
                           struct ieee80211_sta *sta, struct rate_info *rate);
 int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy,
                                     struct cfg80211_chan_def *chandef);
+int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wcid);
 int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set);
 int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
 int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);