diff mbox series

[RFC,v1,252/256] cl8k: add wrs/wrs_stats.c

Message ID 20210617160223.160998-253-viktor.barna@celeno.com (mailing list archive)
State RFC
Delegated to: Kalle Valo
Headers show
Series wireless: cl8k driver for Celeno IEEE 802.11ax devices | expand

Commit Message

Viktor Barna June 17, 2021, 4:02 p.m. UTC
From: Viktor Barna <viktor.barna@celeno.com>

(Part of the split. Please, take a look at the cover letter for more
details).

Signed-off-by: Viktor Barna <viktor.barna@celeno.com>
---
 .../net/wireless/celeno/cl8k/wrs/wrs_stats.c  | 242 ++++++++++++++++++
 1 file changed, 242 insertions(+)
 create mode 100644 drivers/net/wireless/celeno/cl8k/wrs/wrs_stats.c

--
2.30.0
diff mbox series

Patch

diff --git a/drivers/net/wireless/celeno/cl8k/wrs/wrs_stats.c b/drivers/net/wireless/celeno/cl8k/wrs/wrs_stats.c
new file mode 100644
index 000000000000..3e477e82a16a
--- /dev/null
+++ b/drivers/net/wireless/celeno/cl8k/wrs/wrs_stats.c
@@ -0,0 +1,242 @@ 
+// SPDX-License-Identifier: MIT
+/* Copyright(c) 2019-2021, Celeno Communications Ltd. */
+
+#include "wrs/wrs_stats.h"
+#include "wrs/wrs.h"
+#include "utils/utils.h"
+
+static struct cl_wrs_per_stats *cl_wrs_stats_per_entry(struct cl_wrs_params *wrs_params)
+{
+       struct cl_wrs_per_stats *per_stats = NULL, *per_stats_new = NULL;
+       struct cl_wrs_tx_params *tx_params = &wrs_params->tx_params;
+       struct list_head *list_rates = &wrs_params->list_rates;
+       u8 bw = tx_params->bw;
+       u8 nss = tx_params->nss;
+       u8 mcs = tx_params->mcs;
+       u8 gi = tx_params->gi;
+
+       list_for_each_entry(per_stats, list_rates, list) {
+               if (per_stats->bw != bw ||
+                   per_stats->nss != nss ||
+                   per_stats->mcs != mcs ||
+                   per_stats->gi != gi)
+                       continue;
+
+               /*
+                * Move the entry to the beginning of the list, so that it
+                * will be faster to find next time.
+                */
+               if (per_stats != list_entry(list_rates->next, struct cl_wrs_per_stats, list)) {
+                       list_del(&per_stats->list);
+                       list_add(&per_stats->list, list_rates);
+               }
+
+               return per_stats;
+       }
+
+       /* Entry not found - allocate new entry and add to list */
+       per_stats_new = kzalloc(sizeof(*per_stats_new), GFP_ATOMIC);
+
+       if (!per_stats_new)
+               return NULL;
+
+       per_stats_new->bw = bw;
+       per_stats_new->nss = nss;
+       per_stats_new->mcs = mcs;
+       per_stats_new->gi = gi;
+
+       list_add(&per_stats_new->list, &wrs_params->list_rates);
+
+       return per_stats_new;
+}
+
+void cl_wrs_stats_per_update(struct cl_wrs_db *wrs_db,
+                            struct cl_wrs_sta *wrs_sta,
+                            struct cl_wrs_params *wrs_params,
+                            struct cl_wrs_tx_cntrs *tx_cntrs)
+{
+       u16 curr_rate_idx = wrs_params->rate_idx;
+       struct cl_wrs_table *table_node = &wrs_params->table[curr_rate_idx];
+       struct cl_wrs_per_stats *per_stats = cl_wrs_stats_per_entry(wrs_params);
+
+       if (!per_stats)
+               return;
+
+       wrs_params->frames_total += tx_cntrs->total;
+       wrs_params->fail_total += tx_cntrs->fail;
+       wrs_params->ba_not_rcv_total += tx_cntrs->ba_not_rcv;
+       wrs_params->epr_acc += tx_cntrs->epr_acc;
+
+       per_stats->frames_total += tx_cntrs->total;
+       per_stats->frames_failed += tx_cntrs->fail;
+       per_stats->epr_acc += tx_cntrs->epr_acc;
+
+       if (wrs_params->calc_ba_not_rcv) {
+               per_stats->frames_total += tx_cntrs->ba_not_rcv;
+               per_stats->frames_failed += tx_cntrs->ba_not_rcv;
+       }
+
+       table_node->frames_total = wrs_params->frames_total;
+       table_node->ba_not_rcv_total = wrs_params->ba_not_rcv_total;
+       table_node->epr_acc = wrs_params->epr_acc;
+}
+
+struct per_info {
+       u32 frames_failed;
+       u32 frames_total;
+       u64 epr_acc;
+};
+
+static void _cl_wrs_stats_per_print(char **buf, int *len, ssize_t *buf_size,
+                                   struct cl_wrs_rate *curr_rate,
+                                   struct per_info *per_info,
+                                   u64 total_all_rates,
+                                   u8 bw, u8 nss, u8 mcs, u8 gi)
+{
+       u64 frames_total = per_info->frames_total;
+       u64 frames_failed = per_info->frames_failed;
+       u64 epr_acc = per_info->epr_acc;
+       u32 per_high = 0, per_low = 0, usage_high = 0, usage_low = 0, epr_high = 0, epr_low = 0;
+
+       if (frames_total == 0)
+               return;
+
+       cl_div64_decimal(100 * frames_failed, frames_total, &per_high, &per_low);
+       cl_div64_decimal(100 * frames_total, total_all_rates, &usage_high, &usage_low);
+       cl_div64_decimal(epr_acc, frames_total * WRS_DATA_RATE_FACTOR, &epr_high, &epr_low);
+
+       cl_snprintf(buf, len, buf_size,
+                   "|%3s|%3u|%3u|%-9s|%4u.%02u|%10llu|%10llu|%3u.%02u|%4u.%02u|",
+                   WRS_BW_STR(bw), nss, mcs, WRS_GI_STR(gi),
+                   usage_high, usage_low, frames_failed,
+                   frames_total, per_high, per_low, epr_high,
+                   epr_low);
+
+       /* Add an arrow to the current rate */
+       if (curr_rate->bw == bw &&
+           curr_rate->nss == nss &&
+           curr_rate->mcs == mcs &&
+           curr_rate->gi == gi)
+               cl_snprintf(buf, len, buf_size, "<==\n");
+       else
+               cl_snprintf(buf, len, buf_size, "\n");
+
+       cl_snprintf(buf, len, buf_size,
+                   "|------------------------------------------------------------------|\n");
+}
+
+void cl_wrs_stats_per_print(struct cl_hw *cl_hw,
+                           struct cl_wrs_sta *wrs_sta,
+                           struct cl_wrs_params *wrs_params)
+{
+       struct cl_wrs_rate *curr_rate = &wrs_params->table[wrs_params->rate_idx].rate;
+       struct cl_wrs_per_stats *per_stats = NULL;
+       u8 bw = 0, nss = 0, mcs = 0, gi = 0;
+       u16 alloc_size = CHNL_BW_MAX * WRS_SS_MAX * WRS_MCS_MAX * WRS_GI_MAX;
+       u32 total_epr_high = 0, total_epr_low = 0;
+       u64 total_epr_acc = 0, total_all_rates = 0;
+       char *buf = NULL;
+       ssize_t buf_size;
+       int len = 0;
+       struct per_info (*per_info_arr)[WRS_SS_MAX][WRS_MCS_MAX][WRS_GI_MAX] =
+               kzalloc(alloc_size * sizeof(struct per_info), GFP_ATOMIC);
+
+       if (!per_info_arr)
+               return;
+
+       list_for_each_entry(per_stats, &wrs_params->list_rates, list) {
+               bw = per_stats->bw;
+               nss = per_stats->nss;
+               mcs = per_stats->mcs;
+               gi = per_stats->gi;
+
+               total_all_rates += per_stats->frames_total;
+               total_epr_acc += per_stats->epr_acc;
+
+               per_info_arr[bw][nss][mcs][gi].frames_failed = per_stats->frames_failed;
+               per_info_arr[bw][nss][mcs][gi].frames_total = per_stats->frames_total;
+               per_info_arr[bw][nss][mcs][gi].epr_acc = per_stats->epr_acc;
+       }
+
+       if (total_all_rates == 0) {
+               cl_snprintf(&buf, &len, &buf_size, "Table rate empty\n");
+               goto out;
+       }
+
+       cl_snprintf(&buf, &len, &buf_size,
+                   "|------------------------------------------------------------------|\n"
+                   "|BW |NSS|MCS|GI       |Usage  |Fail      |Total     |PER   |EPR    |\n"
+                   "|---+---+---+---------+-------+----------+----------+------+-------|\n");
+
+       for (bw = 0; bw <= wrs_sta->max_rate_cap.bw; bw++)
+               for (nss = 0; nss <= wrs_sta->max_rate_cap.nss; nss++)
+                       for (mcs = 0; mcs <= wrs_sta->max_rate_cap.mcs; mcs++)
+                               for (gi = 0; gi <= wrs_sta->max_rate_cap.gi; gi++)
+                                       _cl_wrs_stats_per_print(&buf, &len, &buf_size,
+                                                               curr_rate,
+                                                               &per_info_arr[bw][nss][mcs][gi],
+                                                               total_all_rates,
+                                                               bw, nss, mcs, gi);
+
+       cl_div64_decimal(total_epr_acc, total_all_rates * WRS_DATA_RATE_FACTOR,
+                        &total_epr_high, &total_epr_low);
+       cl_snprintf(&buf, &len, &buf_size,
+                   "###  Effective PHY Rate = %u.%u Mbps  ###\n",
+                   total_epr_high, total_epr_low);
+
+out:
+       kfree(per_info_arr);
+       cl_vendor_reply(cl_hw, buf, len);
+       kfree(buf);
+}
+
+void cl_wrs_stats_per_reset(struct cl_wrs_params *wrs_params)
+{
+       cl_wrs_stats_per_remove(wrs_params);
+}
+
+void cl_wrs_stats_per_init(struct cl_wrs_params *wrs_params)
+{
+       INIT_LIST_HEAD(&wrs_params->list_rates);
+}
+
+void cl_wrs_stats_per_remove(struct cl_wrs_params *wrs_params)
+{
+       struct cl_wrs_per_stats *per_stats = NULL, *per_stats_next = NULL;
+
+       list_for_each_entry_safe(per_stats, per_stats_next, &wrs_params->list_rates, list) {
+               list_del(&per_stats->list);
+               kfree(per_stats);
+       }
+}
+
+void cl_wrs_stats_decision_print(struct cl_wrs_params *wrs_params)
+{
+       u32 *decision_cnt = wrs_params->decision_cnt;
+
+       pr_debug("\n");
+       pr_debug("----------------------------\n");
+       pr_debug("|Decision       |Count     |\n");
+       pr_debug("|--------------------------|\n");
+       pr_debug("|NONE           |%10u|\n", decision_cnt[WRS_DECISION_NONE]);
+       pr_debug("|SAME           |%10u|\n", decision_cnt[WRS_DECISION_SAME]);
+       pr_debug("|UP             |%10u|\n", decision_cnt[WRS_DECISION_UP]);
+       pr_debug("|UP QUICK       |%10u|\n", decision_cnt[WRS_DECISION_UP_QUICK]);
+       pr_debug("|UP RSSI        |%10u|\n", decision_cnt[WRS_DECISION_UP_RSSI]);
+       pr_debug("|UP MCS1        |%10u|\n", decision_cnt[WRS_DECISION_UP_MCS1]);
+       pr_debug("|DOWN           |%10u|\n", decision_cnt[WRS_DECISION_DOWN]);
+       pr_debug("|DOWN RSSI      |%10u|\n", decision_cnt[WRS_DECISION_DOWN_RSSI]);
+       pr_debug("|DOWN IMMEDIATE |%10u|\n", decision_cnt[WRS_DECISION_DOWN_IMMEDIATE]);
+       pr_debug("|DOWN QUICK     |%10u|\n", decision_cnt[WRS_DECISION_DOWN_QUICK]);
+       pr_debug("|DOWN NO SYNC   |%10u|\n", decision_cnt[WRS_DECISION_DOWN_NO_SYNC]);
+       pr_debug("|RSSI MGMT      |%10u|\n", decision_cnt[WRS_DECISION_RSSI_MGMT]);
+       pr_debug("----------------------------\n");
+       pr_debug("\n");
+       pr_debug("Immediate drop ignore = [%u]\n", wrs_params->immediate_drop_ignore);
+}
+
+void cl_wrs_stats_decision_reset(struct cl_wrs_params *wrs_params)
+{
+       memset(&wrs_params->decision_cnt, 0, sizeof(wrs_params->decision_cnt));
+       wrs_params->immediate_drop_ignore = 0;
+}