Commit adde3eed authored by Yi-Chia Hsieh's avatar Yi-Chia Hsieh Committed by Felix Fietkau

wifi: mt76: mt7996: Add mcu commands for getting sta tx statistic

Per peer Tx/Rx statistic can only be obtained by querying WM when WED is
on. This patch switches to periodic event reporting in the case of WED
being enabled.
Signed-off-by: default avatarYi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
Signed-off-by: default avatarMoney Wang <Money.Wang@mediatek.com>
Signed-off-by: default avatarPeter Chiu <chui-hao.chiu@mediatek.com>
Signed-off-by: default avatarEvelyn Tsai <evelyn.tsai@mediatek.com>
Signed-off-by: default avatarRyder Lee <ryder.lee@mediatek.com>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 2461599f
......@@ -1022,6 +1022,8 @@ enum {
MCU_UNI_EVENT_ROC = 0x27,
MCU_UNI_EVENT_TX_DONE = 0x2d,
MCU_UNI_EVENT_NIC_CAPAB = 0x43,
MCU_UNI_EVENT_PER_STA_INFO = 0x6d,
MCU_UNI_EVENT_ALL_STA_INFO = 0x6e,
};
#define MCU_UNI_CMD_EVENT BIT(1)
......@@ -1240,6 +1242,8 @@ enum {
MCU_UNI_CMD_VOW = 0x37,
MCU_UNI_CMD_RRO = 0x57,
MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
MCU_UNI_CMD_PER_STA_INFO = 0x6d,
MCU_UNI_CMD_ALL_STA_INFO = 0x6e,
MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
};
......@@ -1320,6 +1324,17 @@ enum {
UNI_OFFLOAD_OFFLOAD_BMC_RPY_DETECT,
};
enum UNI_ALL_STA_INFO_TAG {
UNI_ALL_STA_TX_RATE,
UNI_ALL_STA_TX_STAT,
UNI_ALL_STA_TXRX_ADM_STAT,
UNI_ALL_STA_TXRX_AIR_TIME,
UNI_ALL_STA_DATA_TX_RETRY_COUNT,
UNI_ALL_STA_GI_MODE,
UNI_ALL_STA_TXRX_MSDU_COUNT,
UNI_ALL_STA_MAX_NUM
};
enum {
MT_NIC_CAP_TX_RESOURCE,
MT_NIC_CAP_TX_EFUSE_ADDR,
......
......@@ -2202,6 +2202,11 @@ void mt7996_mac_work(struct work_struct *work)
mphy->mac_work_count = 0;
mt7996_mac_update_stats(phy);
if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_ADM_STAT);
mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_MSDU_COUNT);
}
}
mutex_unlock(&mphy->dev->mutex);
......
......@@ -969,6 +969,7 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
struct station_info *sinfo)
{
struct mt7996_phy *phy = mt7996_hw_phy(hw);
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
struct rate_info *txrate = &msta->wcid.rate;
......@@ -1000,6 +1001,20 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal);
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG);
if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
sinfo->tx_bytes = msta->wcid.stats.tx_bytes;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);
sinfo->rx_bytes = msta->wcid.stats.rx_bytes;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64);
sinfo->tx_packets = msta->wcid.stats.tx_packets;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
sinfo->rx_packets = msta->wcid.stats.rx_packets;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);
}
}
static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta)
......
......@@ -449,6 +449,54 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
}
}
static void
mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
{
struct mt7996_mcu_all_sta_info_event *res;
u16 i;
skb_pull(skb, sizeof(struct mt7996_mcu_rxd));
res = (struct mt7996_mcu_all_sta_info_event *)skb->data;
for (i = 0; i < le16_to_cpu(res->sta_num); i++) {
u8 ac;
u16 wlan_idx;
struct mt76_wcid *wcid;
switch (le16_to_cpu(res->tag)) {
case UNI_ALL_STA_TXRX_ADM_STAT:
wlan_idx = le16_to_cpu(res->adm_stat[i].wlan_idx);
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
if (!wcid)
break;
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
wcid->stats.tx_bytes +=
le32_to_cpu(res->adm_stat[i].tx_bytes[ac]);
wcid->stats.rx_bytes +=
le32_to_cpu(res->adm_stat[i].rx_bytes[ac]);
}
break;
case UNI_ALL_STA_TXRX_MSDU_COUNT:
wlan_idx = le16_to_cpu(res->msdu_cnt[i].wlan_idx);
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
if (!wcid)
break;
wcid->stats.tx_packets +=
le32_to_cpu(res->msdu_cnt[i].tx_msdu_cnt);
wcid->stats.rx_packets +=
le32_to_cpu(res->msdu_cnt[i].rx_msdu_cnt);
break;
default:
break;
}
}
}
static void
mt7996_mcu_rx_ext_event(struct mt7996_dev *dev, struct sk_buff *skb)
{
......@@ -493,6 +541,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
case MCU_UNI_EVENT_RDD_REPORT:
mt7996_mcu_rx_radar_detected(dev, skb);
break;
case MCU_UNI_EVENT_ALL_STA_INFO:
mt7996_mcu_rx_all_sta_info_event(dev, skb);
break;
default:
break;
}
......@@ -4013,3 +4064,20 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(RRO), &req,
sizeof(req), true);
}
int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag)
{
struct mt7996_dev *dev = phy->dev;
struct {
u8 _rsv[4];
__le16 tag;
__le16 len;
} __packed req = {
.tag = cpu_to_le16(tag),
.len = cpu_to_le16(sizeof(req) - 4),
};
return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(ALL_STA_INFO),
&req, sizeof(req), false);
}
......@@ -153,6 +153,32 @@ struct mt7996_mcu_mib {
__le64 data;
} __packed;
struct mt7996_mcu_all_sta_info_event {
u8 rsv[4];
__le16 tag;
__le16 len;
u8 more;
u8 rsv2;
__le16 sta_num;
u8 rsv3[2];
union {
struct {
__le16 wlan_idx;
u8 rsv[2];
__le32 tx_bytes[IEEE80211_NUM_ACS];
__le32 rx_bytes[IEEE80211_NUM_ACS];
} adm_stat[0];
struct {
__le16 wlan_idx;
u8 rsv[2];
__le32 tx_msdu_cnt;
__le32 rx_msdu_cnt;
} msdu_cnt[0];
};
} __packed;
enum mt7996_chan_mib_offs {
UNI_MIB_OBSS_AIRTIME = 26,
UNI_MIB_NON_WIFI_TIME = 27,
......
......@@ -402,6 +402,7 @@ int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
void mt7996_mcu_exit(struct mt7996_dev *dev);
int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
{
......
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