Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  debugfs_sta.c   Sprache: C

 
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
 * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
 */


#include <linux/vmalloc.h>

#include "debugfs_sta.h"
#include "core.h"
#include "peer.h"
#include "debug.h"
#include "debugfs_htt_stats.h"
#include "debugfs.h"

static
u32 ath12k_dbg_sta_dump_rate_stats(u8 *buf, u32 offset, const int size,
       bool he_rates_avail,
       const struct ath12k_rx_peer_rate_stats *stats)
{
 static const char *legacy_rate_str[HAL_RX_MAX_NUM_LEGACY_RATES] = {
     "1 Mbps""2 Mbps""5.5 Mbps""6 Mbps",
     "9 Mbps""11 Mbps""12 Mbps""18 Mbps",
     "24 Mbps""36 Mbps""48 Mbps""54 Mbps"};
 u8 max_bw = HAL_RX_BW_MAX, max_gi = HAL_RX_GI_MAX, max_mcs = HAL_RX_MAX_NSS;
 int mcs = 0, bw = 0, nss = 0, gi = 0, bw_num = 0;
 u32 i, len = offset, max = max_bw * max_gi * max_mcs;
 bool found;

 len += scnprintf(buf + len, size - len, "\nEHT stats:\n");
 for (i = 0; i <= HAL_RX_MAX_MCS_BE; i++)
  len += scnprintf(buf + len, size - len,
       "MCS %d: %llu%s", i, stats->be_mcs_count[i],
       (i + 1) % 8 ? "\t" : "\n");

 len += scnprintf(buf + len, size - len, "\nHE stats:\n");
 for (i = 0; i <= HAL_RX_MAX_MCS_HE; i++)
  len += scnprintf(buf + len, size - len,
       "MCS %d: %llu%s", i, stats->he_mcs_count[i],
       (i + 1) % 6 ? "\t" : "\n");

 len += scnprintf(buf + len, size - len, "\nVHT stats:\n");
 for (i = 0; i <= HAL_RX_MAX_MCS_VHT; i++)
  len += scnprintf(buf + len, size - len,
       "MCS %d: %llu%s", i, stats->vht_mcs_count[i],
       (i + 1) % 5 ? "\t" : "\n");

 len += scnprintf(buf + len, size - len, "\nHT stats:\n");
 for (i = 0; i <= HAL_RX_MAX_MCS_HT; i++)
  len += scnprintf(buf + len, size - len,
       "MCS %d: %llu%s", i, stats->ht_mcs_count[i],
       (i + 1) % 8 ? "\t" : "\n");

 len += scnprintf(buf + len, size - len, "\nLegacy stats:\n");
 for (i = 0; i < HAL_RX_MAX_NUM_LEGACY_RATES; i++)
  len += scnprintf(buf + len, size - len,
       "%s: %llu%s", legacy_rate_str[i],
       stats->legacy_count[i],
       (i + 1) % 4 ? "\t" : "\n");

 len += scnprintf(buf + len, size - len, "\nNSS stats:\n");
 for (i = 0; i < HAL_RX_MAX_NSS; i++)
  len += scnprintf(buf + len, size - len,
       "%dx%d: %llu ", i + 1, i + 1,
       stats->nss_count[i]);

 len += scnprintf(buf + len, size - len,
     "\n\nGI: 0.8 us %llu 0.4 us %llu 1.6 us %llu 3.2 us %llu\n",
     stats->gi_count[0],
     stats->gi_count[1],
     stats->gi_count[2],
     stats->gi_count[3]);

 len += scnprintf(buf + len, size - len,
      "BW: 20 MHz %llu 40 MHz %llu 80 MHz %llu 160 MHz %llu 320 MHz %llu\n",
      stats->bw_count[0],
      stats->bw_count[1],
      stats->bw_count[2],
      stats->bw_count[3],
      stats->bw_count[4]);

 for (i = 0; i < max; i++) {
  found = false;

  for (mcs = 0; mcs <= HAL_RX_MAX_MCS_HT; mcs++) {
   if (stats->rx_rate[bw][gi][nss][mcs]) {
    found = true;
    break;
   }
  }

  if (!found)
   goto skip_report;

  switch (bw) {
  case HAL_RX_BW_20MHZ:
   bw_num = 20;
   break;
  case HAL_RX_BW_40MHZ:
   bw_num = 40;
   break;
  case HAL_RX_BW_80MHZ:
   bw_num = 80;
   break;
  case HAL_RX_BW_160MHZ:
   bw_num = 160;
   break;
  case HAL_RX_BW_320MHZ:
   bw_num = 320;
   break;
  }

  len += scnprintf(buf + len, size - len, "\n%d Mhz gi %d us %dx%d : ",
     bw_num, gi, nss + 1, nss + 1);

  for (mcs = 0; mcs <= HAL_RX_MAX_MCS_HT; mcs++) {
   if (stats->rx_rate[bw][gi][nss][mcs])
    len += scnprintf(buf + len, size - len,
       " %d:%llu", mcs,
       stats->rx_rate[bw][gi][nss][mcs]);
  }

skip_report:
  if (nss++ >= max_mcs - 1) {
   nss = 0;
   if (gi++ >= max_gi - 1) {
    gi = 0;
    if (bw < max_bw - 1)
     bw++;
   }
  }
 }

 len += scnprintf(buf + len, size - len, "\n");

 return len - offset;
}

static ssize_t ath12k_dbg_sta_dump_rx_stats(struct file *file,
         char __user *user_buf,
         size_t count, loff_t *ppos)
{
 struct ieee80211_link_sta *link_sta = file->private_data;
 struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(link_sta->sta);
 const int size = ATH12K_STA_RX_STATS_BUF_SIZE;
 struct ath12k_hw *ah = ahsta->ahvif->ah;
 struct ath12k_rx_peer_stats *rx_stats;
 struct ath12k_link_sta *arsta;
 u8 link_id = link_sta->link_id;
 int len = 0, i, ret = 0;
 bool he_rates_avail;
 struct ath12k *ar;

 wiphy_lock(ah->hw->wiphy);

 if (!(BIT(link_id) & ahsta->links_map)) {
  wiphy_unlock(ah->hw->wiphy);
  return -ENOENT;
 }

 arsta = wiphy_dereference(ah->hw->wiphy, ahsta->link[link_id]);
 if (!arsta || !arsta->arvif->ar) {
  wiphy_unlock(ah->hw->wiphy);
  return -ENOENT;
 }

 ar = arsta->arvif->ar;

 u8 *buf __free(kfree) = kzalloc(size, GFP_KERNEL);
 if (!buf) {
  ret = -ENOENT;
  goto out;
 }

 spin_lock_bh(&ar->ab->base_lock);

 rx_stats = arsta->rx_stats;
 if (!rx_stats) {
  ret = -ENOENT;
  goto unlock;
 }

 len += scnprintf(buf + len, size - len, "RX peer stats:\n\n");
 len += scnprintf(buf + len, size - len, "Num of MSDUs: %llu\n",
    rx_stats->num_msdu);
 len += scnprintf(buf + len, size - len, "Num of MSDUs with TCP L4: %llu\n",
    rx_stats->tcp_msdu_count);
 len += scnprintf(buf + len, size - len, "Num of MSDUs with UDP L4: %llu\n",
    rx_stats->udp_msdu_count);
 len += scnprintf(buf + len, size - len, "Num of other MSDUs: %llu\n",
    rx_stats->other_msdu_count);
 len += scnprintf(buf + len, size - len, "Num of MSDUs part of AMPDU: %llu\n",
    rx_stats->ampdu_msdu_count);
 len += scnprintf(buf + len, size - len, "Num of MSDUs not part of AMPDU: %llu\n",
    rx_stats->non_ampdu_msdu_count);
 len += scnprintf(buf + len, size - len, "Num of MSDUs using STBC: %llu\n",
    rx_stats->stbc_count);
 len += scnprintf(buf + len, size - len, "Num of MSDUs beamformed: %llu\n",
    rx_stats->beamformed_count);
 len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS ok: %llu\n",
    rx_stats->num_mpdu_fcs_ok);
 len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS error: %llu\n",
    rx_stats->num_mpdu_fcs_err);

 he_rates_avail = (rx_stats->pream_cnt[HAL_RX_PREAMBLE_11AX] > 1) ? true : false;

 len += scnprintf(buf + len, size - len,
    "preamble: 11A %llu 11B %llu 11N %llu 11AC %llu 11AX %llu 11BE %llu\n",
    rx_stats->pream_cnt[0], rx_stats->pream_cnt[1],
    rx_stats->pream_cnt[2], rx_stats->pream_cnt[3],
    rx_stats->pream_cnt[4], rx_stats->pream_cnt[6]);
 len += scnprintf(buf + len, size - len,
    "reception type: SU %llu MU_MIMO %llu MU_OFDMA %llu MU_OFDMA_MIMO %llu\n",
    rx_stats->reception_type[0], rx_stats->reception_type[1],
    rx_stats->reception_type[2], rx_stats->reception_type[3]);

 len += scnprintf(buf + len, size - len, "TID(0-15) Legacy TID(16):");
 for (i = 0; i <= IEEE80211_NUM_TIDS; i++)
  len += scnprintf(buf + len, size - len, "%llu ", rx_stats->tid_count[i]);

 len += scnprintf(buf + len, size - len, "\nRX Duration:%llu\n",
    rx_stats->rx_duration);

 len += scnprintf(buf + len, size - len,
    "\nDCM: %llu\nRU26: %llu\nRU52: %llu\nRU106: %llu\nRU242: %llu\nRU484: %llu\nRU996: %llu\nRU996x2: %llu\n",
    rx_stats->dcm_count, rx_stats->ru_alloc_cnt[0],
    rx_stats->ru_alloc_cnt[1], rx_stats->ru_alloc_cnt[2],
    rx_stats->ru_alloc_cnt[3], rx_stats->ru_alloc_cnt[4],
    rx_stats->ru_alloc_cnt[5], rx_stats->ru_alloc_cnt[6]);

 len += scnprintf(buf + len, size - len, "\nRX success packet stats:\n");
 len += ath12k_dbg_sta_dump_rate_stats(buf, len, size, he_rates_avail,
           &rx_stats->pkt_stats);

 len += scnprintf(buf + len, size - len, "\n");

 len += scnprintf(buf + len, size - len, "\nRX success byte stats:\n");
 len += ath12k_dbg_sta_dump_rate_stats(buf, len, size, he_rates_avail,
           &rx_stats->byte_stats);

unlock:
 spin_unlock_bh(&ar->ab->base_lock);

 if (len)
  ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
out:
 wiphy_unlock(ah->hw->wiphy);
 return ret;
}

static const struct file_operations fops_rx_stats = {
 .read = ath12k_dbg_sta_dump_rx_stats,
 .open = simple_open,
 .owner = THIS_MODULE,
 .llseek = default_llseek,
};

static ssize_t ath12k_dbg_sta_reset_rx_stats(struct file *file,
          const char __user *buf,
          size_t count, loff_t *ppos)
{
 struct ieee80211_link_sta *link_sta = file->private_data;
 struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(link_sta->sta);
 struct ath12k_hw *ah = ahsta->ahvif->ah;
 struct ath12k_rx_peer_stats *rx_stats;
 struct ath12k_link_sta *arsta;
 u8 link_id = link_sta->link_id;
 struct ath12k *ar;
 bool reset;
 int ret;

 ret = kstrtobool_from_user(buf, count, &reset);
 if (ret)
  return ret;

 if (!reset)
  return -EINVAL;

 wiphy_lock(ah->hw->wiphy);

 if (!(BIT(link_id) & ahsta->links_map)) {
  ret = -ENOENT;
  goto out;
 }

 arsta = wiphy_dereference(ah->hw->wiphy, ahsta->link[link_id]);
 if (!arsta || !arsta->arvif->ar) {
  ret = -ENOENT;
  goto out;
 }

 ar = arsta->arvif->ar;

 spin_lock_bh(&ar->ab->base_lock);

 rx_stats = arsta->rx_stats;
 if (!rx_stats) {
  spin_unlock_bh(&ar->ab->base_lock);
  ret = -ENOENT;
  goto out;
 }

 memset(rx_stats, 0, sizeof(*rx_stats));
 spin_unlock_bh(&ar->ab->base_lock);

 ret = count;
out:
 wiphy_unlock(ah->hw->wiphy);
 return ret;
}

static const struct file_operations fops_reset_rx_stats = {
 .write = ath12k_dbg_sta_reset_rx_stats,
 .open = simple_open,
 .owner = THIS_MODULE,
 .llseek = default_llseek,
};

void ath12k_debugfs_link_sta_op_add(struct ieee80211_hw *hw,
        struct ieee80211_vif *vif,
        struct ieee80211_link_sta *link_sta,
        struct dentry *dir)
{
 struct ath12k *ar;

 lockdep_assert_wiphy(hw->wiphy);

 ar = ath12k_get_ar_by_vif(hw, vif, link_sta->link_id);
 if (!ar)
  return;

 if (ath12k_debugfs_is_extd_rx_stats_enabled(ar)) {
  debugfs_create_file("rx_stats", 0400, dir, link_sta,
        &fops_rx_stats);
  debugfs_create_file("reset_rx_stats", 0200, dir, link_sta,
        &fops_reset_rx_stats);
 }
}

Messung V0.5
C=98 H=91 G=94

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge