Part of the split. Please, take a look at the cover letter for more details Reviewed-by: Viktor Barna <viktor.barna.rj@xxxxxxxxxxxxxx> Reviewed-by: Gal Gur <gal.gur.jx@xxxxxxxxxxx> Signed-off-by: Alexander Savchenko <oleksandr.savchenko.dn@xxxxxxxxxxxxxx> --- drivers/net/wireless/renesas/ra6w/stats.c | 94 +++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 drivers/net/wireless/renesas/ra6w/stats.c diff --git a/drivers/net/wireless/renesas/ra6w/stats.c b/drivers/net/wireless/renesas/ra6w/stats.c new file mode 100644 index 000000000000..59f431b3f158 --- /dev/null +++ b/drivers/net/wireless/renesas/ra6w/stats.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * This file contains statistics routine. + * + * Copyright (C) [2022-2025] Renesas Electronics Corporation and/or its affiliates. + */ + +#include "cfg80211.h" +#include "stats.h" + +void ra6w_stats_rx_update(struct ra6w_stats *stats, + const struct ra6w_cfg80211_sta_stats *sta_stats) +{ + struct ra6w_stats_rx *rx_stats = stats->rx_stats; + const struct ra6w_rx_ext_hdr *last_rx = &sta_stats->last_rx_data_ext; + + if (!stats->stats_enabled || !rx_stats) + return; + + rx_stats->format_mode = last_rx->format_mod; + + switch (last_rx->format_mod) { + case RA6W_CFG80211_FORMATMOD_NON_HT: + rx_stats->flags |= RA6W_STATS_RX_OFDM_BIT; + rx_stats->non_ht.ofdm++; + fallthrough; + case RA6W_CFG80211_FORMATMOD_NON_HT_DUP_OFDM: + rx_stats->flags |= RA6W_STATS_RX_CCK_BIT; + rx_stats->non_ht.cck++; + rx_stats->non_ht.bw = last_rx->ch_bw; + break; + case RA6W_CFG80211_FORMATMOD_HT_MF: + case RA6W_CFG80211_FORMATMOD_HT_GF: + rx_stats->flags |= RA6W_STATS_RX_HT_BIT; + rx_stats->ht.bw = last_rx->ch_bw & 0x1; + rx_stats->ht.nss = last_rx->ht.num_extn_ss & 0x3; + rx_stats->ht.mcs = last_rx->ht.mcs & 0x7; + rx_stats->ht.gi = last_rx->ht.short_gi & 0x1; + rx_stats->ht.ht[rx_stats->ht.gi][rx_stats->ht.mcs]++; + break; + case RA6W_CFG80211_FORMATMOD_VHT: + rx_stats->flags |= RA6W_STATS_RX_VHT_BIT; + rx_stats->vht.bw = last_rx->ch_bw; + rx_stats->vht.nss = last_rx->vht.nss; + rx_stats->vht.mcs = last_rx->vht.mcs; + rx_stats->vht.gi = last_rx->vht.short_gi & 0x1; + rx_stats->vht.vht[rx_stats->vht.gi][rx_stats->vht.mcs]++; + break; + case RA6W_CFG80211_FORMATMOD_HE_MU: + case RA6W_CFG80211_FORMATMOD_HE_SU: + case RA6W_CFG80211_FORMATMOD_HE_ER: + case RA6W_CFG80211_FORMATMOD_HE_TB: + rx_stats->flags |= RA6W_STATS_RX_HE_SU_BIT; + rx_stats->he_su.mcs = last_rx->he.mcs; + rx_stats->he_su.nss = last_rx->he.nss; + rx_stats->he_su.gi = last_rx->he.gi_type; + rx_stats->he_su.he[rx_stats->he_su.gi][rx_stats->he_su.mcs]++; + break; + default: + break; + } +} + +int ra6w_stats_init(struct ra6w_stats *stats) +{ + struct ra6w_stats_rx *rx_stats = NULL; + + if (stats->stats_enabled) + return 0; + + rx_stats = kzalloc(sizeof(*rx_stats), GFP_KERNEL); + if (!rx_stats) + return -ENOMEM; + + stats->rx_stats = rx_stats; + stats->stats_enabled = true; + + return 0; +} + +void ra6w_stats_deinit(struct ra6w_stats *stats) +{ + struct ra6w_cfg80211_vif *vif = container_of(stats, struct ra6w_cfg80211_vif, stats); + struct ra6w_cfg80211_priv *priv = vif->priv; + + if (!stats->stats_enabled) + return; + + ra6w_ctrl_stats_tx_start_req(&priv->core->ctrl, RA6W_STATS_TX_STOP_BIT); + + stats->stats_enabled = false; + kfree(stats->rx_stats); + stats->rx_stats = NULL; +} -- 2.17.1