linux/drivers/net/ethernet/pensando/ionic/ionic_stats.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 2017 - 2019 Pensando Systems, Inc */
   3
   4#include <linux/kernel.h>
   5#include <linux/mutex.h>
   6#include <linux/netdevice.h>
   7
   8#include "ionic.h"
   9#include "ionic_lif.h"
  10#include "ionic_stats.h"
  11
  12static const struct ionic_stat_desc ionic_lif_stats_desc[] = {
  13        IONIC_LIF_STAT_DESC(tx_packets),
  14        IONIC_LIF_STAT_DESC(tx_bytes),
  15        IONIC_LIF_STAT_DESC(rx_packets),
  16        IONIC_LIF_STAT_DESC(rx_bytes),
  17        IONIC_LIF_STAT_DESC(tx_tso),
  18        IONIC_LIF_STAT_DESC(tx_tso_bytes),
  19        IONIC_LIF_STAT_DESC(tx_csum_none),
  20        IONIC_LIF_STAT_DESC(tx_csum),
  21        IONIC_LIF_STAT_DESC(rx_csum_none),
  22        IONIC_LIF_STAT_DESC(rx_csum_complete),
  23        IONIC_LIF_STAT_DESC(rx_csum_error),
  24        IONIC_LIF_STAT_DESC(hw_tx_dropped),
  25        IONIC_LIF_STAT_DESC(hw_rx_dropped),
  26        IONIC_LIF_STAT_DESC(hw_rx_over_errors),
  27        IONIC_LIF_STAT_DESC(hw_rx_missed_errors),
  28        IONIC_LIF_STAT_DESC(hw_tx_aborted_errors),
  29};
  30
  31static const struct ionic_stat_desc ionic_port_stats_desc[] = {
  32        IONIC_PORT_STAT_DESC(frames_rx_ok),
  33        IONIC_PORT_STAT_DESC(frames_rx_all),
  34        IONIC_PORT_STAT_DESC(frames_rx_bad_fcs),
  35        IONIC_PORT_STAT_DESC(frames_rx_bad_all),
  36        IONIC_PORT_STAT_DESC(octets_rx_ok),
  37        IONIC_PORT_STAT_DESC(octets_rx_all),
  38        IONIC_PORT_STAT_DESC(frames_rx_unicast),
  39        IONIC_PORT_STAT_DESC(frames_rx_multicast),
  40        IONIC_PORT_STAT_DESC(frames_rx_broadcast),
  41        IONIC_PORT_STAT_DESC(frames_rx_pause),
  42        IONIC_PORT_STAT_DESC(frames_rx_bad_length),
  43        IONIC_PORT_STAT_DESC(frames_rx_undersized),
  44        IONIC_PORT_STAT_DESC(frames_rx_oversized),
  45        IONIC_PORT_STAT_DESC(frames_rx_fragments),
  46        IONIC_PORT_STAT_DESC(frames_rx_jabber),
  47        IONIC_PORT_STAT_DESC(frames_rx_pripause),
  48        IONIC_PORT_STAT_DESC(frames_rx_stomped_crc),
  49        IONIC_PORT_STAT_DESC(frames_rx_too_long),
  50        IONIC_PORT_STAT_DESC(frames_rx_vlan_good),
  51        IONIC_PORT_STAT_DESC(frames_rx_dropped),
  52        IONIC_PORT_STAT_DESC(frames_rx_less_than_64b),
  53        IONIC_PORT_STAT_DESC(frames_rx_64b),
  54        IONIC_PORT_STAT_DESC(frames_rx_65b_127b),
  55        IONIC_PORT_STAT_DESC(frames_rx_128b_255b),
  56        IONIC_PORT_STAT_DESC(frames_rx_256b_511b),
  57        IONIC_PORT_STAT_DESC(frames_rx_512b_1023b),
  58        IONIC_PORT_STAT_DESC(frames_rx_1024b_1518b),
  59        IONIC_PORT_STAT_DESC(frames_rx_1519b_2047b),
  60        IONIC_PORT_STAT_DESC(frames_rx_2048b_4095b),
  61        IONIC_PORT_STAT_DESC(frames_rx_4096b_8191b),
  62        IONIC_PORT_STAT_DESC(frames_rx_8192b_9215b),
  63        IONIC_PORT_STAT_DESC(frames_rx_other),
  64        IONIC_PORT_STAT_DESC(frames_tx_ok),
  65        IONIC_PORT_STAT_DESC(frames_tx_all),
  66        IONIC_PORT_STAT_DESC(frames_tx_bad),
  67        IONIC_PORT_STAT_DESC(octets_tx_ok),
  68        IONIC_PORT_STAT_DESC(octets_tx_total),
  69        IONIC_PORT_STAT_DESC(frames_tx_unicast),
  70        IONIC_PORT_STAT_DESC(frames_tx_multicast),
  71        IONIC_PORT_STAT_DESC(frames_tx_broadcast),
  72        IONIC_PORT_STAT_DESC(frames_tx_pause),
  73        IONIC_PORT_STAT_DESC(frames_tx_pripause),
  74        IONIC_PORT_STAT_DESC(frames_tx_vlan),
  75        IONIC_PORT_STAT_DESC(frames_tx_less_than_64b),
  76        IONIC_PORT_STAT_DESC(frames_tx_64b),
  77        IONIC_PORT_STAT_DESC(frames_tx_65b_127b),
  78        IONIC_PORT_STAT_DESC(frames_tx_128b_255b),
  79        IONIC_PORT_STAT_DESC(frames_tx_256b_511b),
  80        IONIC_PORT_STAT_DESC(frames_tx_512b_1023b),
  81        IONIC_PORT_STAT_DESC(frames_tx_1024b_1518b),
  82        IONIC_PORT_STAT_DESC(frames_tx_1519b_2047b),
  83        IONIC_PORT_STAT_DESC(frames_tx_2048b_4095b),
  84        IONIC_PORT_STAT_DESC(frames_tx_4096b_8191b),
  85        IONIC_PORT_STAT_DESC(frames_tx_8192b_9215b),
  86        IONIC_PORT_STAT_DESC(frames_tx_other),
  87        IONIC_PORT_STAT_DESC(frames_tx_pri_0),
  88        IONIC_PORT_STAT_DESC(frames_tx_pri_1),
  89        IONIC_PORT_STAT_DESC(frames_tx_pri_2),
  90        IONIC_PORT_STAT_DESC(frames_tx_pri_3),
  91        IONIC_PORT_STAT_DESC(frames_tx_pri_4),
  92        IONIC_PORT_STAT_DESC(frames_tx_pri_5),
  93        IONIC_PORT_STAT_DESC(frames_tx_pri_6),
  94        IONIC_PORT_STAT_DESC(frames_tx_pri_7),
  95        IONIC_PORT_STAT_DESC(frames_rx_pri_0),
  96        IONIC_PORT_STAT_DESC(frames_rx_pri_1),
  97        IONIC_PORT_STAT_DESC(frames_rx_pri_2),
  98        IONIC_PORT_STAT_DESC(frames_rx_pri_3),
  99        IONIC_PORT_STAT_DESC(frames_rx_pri_4),
 100        IONIC_PORT_STAT_DESC(frames_rx_pri_5),
 101        IONIC_PORT_STAT_DESC(frames_rx_pri_6),
 102        IONIC_PORT_STAT_DESC(frames_rx_pri_7),
 103        IONIC_PORT_STAT_DESC(tx_pripause_0_1us_count),
 104        IONIC_PORT_STAT_DESC(tx_pripause_1_1us_count),
 105        IONIC_PORT_STAT_DESC(tx_pripause_2_1us_count),
 106        IONIC_PORT_STAT_DESC(tx_pripause_3_1us_count),
 107        IONIC_PORT_STAT_DESC(tx_pripause_4_1us_count),
 108        IONIC_PORT_STAT_DESC(tx_pripause_5_1us_count),
 109        IONIC_PORT_STAT_DESC(tx_pripause_6_1us_count),
 110        IONIC_PORT_STAT_DESC(tx_pripause_7_1us_count),
 111        IONIC_PORT_STAT_DESC(rx_pripause_0_1us_count),
 112        IONIC_PORT_STAT_DESC(rx_pripause_1_1us_count),
 113        IONIC_PORT_STAT_DESC(rx_pripause_2_1us_count),
 114        IONIC_PORT_STAT_DESC(rx_pripause_3_1us_count),
 115        IONIC_PORT_STAT_DESC(rx_pripause_4_1us_count),
 116        IONIC_PORT_STAT_DESC(rx_pripause_5_1us_count),
 117        IONIC_PORT_STAT_DESC(rx_pripause_6_1us_count),
 118        IONIC_PORT_STAT_DESC(rx_pripause_7_1us_count),
 119        IONIC_PORT_STAT_DESC(rx_pause_1us_count),
 120        IONIC_PORT_STAT_DESC(frames_tx_truncated),
 121};
 122
 123static const struct ionic_stat_desc ionic_tx_stats_desc[] = {
 124        IONIC_TX_STAT_DESC(pkts),
 125        IONIC_TX_STAT_DESC(bytes),
 126        IONIC_TX_STAT_DESC(clean),
 127        IONIC_TX_STAT_DESC(dma_map_err),
 128        IONIC_TX_STAT_DESC(linearize),
 129        IONIC_TX_STAT_DESC(frags),
 130        IONIC_TX_STAT_DESC(tso),
 131        IONIC_TX_STAT_DESC(tso_bytes),
 132        IONIC_TX_STAT_DESC(csum_none),
 133        IONIC_TX_STAT_DESC(csum),
 134        IONIC_TX_STAT_DESC(vlan_inserted),
 135};
 136
 137static const struct ionic_stat_desc ionic_rx_stats_desc[] = {
 138        IONIC_RX_STAT_DESC(pkts),
 139        IONIC_RX_STAT_DESC(bytes),
 140        IONIC_RX_STAT_DESC(dma_map_err),
 141        IONIC_RX_STAT_DESC(alloc_err),
 142        IONIC_RX_STAT_DESC(csum_none),
 143        IONIC_RX_STAT_DESC(csum_complete),
 144        IONIC_RX_STAT_DESC(csum_error),
 145        IONIC_RX_STAT_DESC(dropped),
 146        IONIC_RX_STAT_DESC(vlan_stripped),
 147};
 148
 149static const struct ionic_stat_desc ionic_txq_stats_desc[] = {
 150        IONIC_TX_Q_STAT_DESC(stop),
 151        IONIC_TX_Q_STAT_DESC(wake),
 152        IONIC_TX_Q_STAT_DESC(drop),
 153        IONIC_TX_Q_STAT_DESC(dbell_count),
 154};
 155
 156static const struct ionic_stat_desc ionic_dbg_cq_stats_desc[] = {
 157        IONIC_CQ_STAT_DESC(compl_count),
 158};
 159
 160static const struct ionic_stat_desc ionic_dbg_intr_stats_desc[] = {
 161        IONIC_INTR_STAT_DESC(rearm_count),
 162};
 163
 164static const struct ionic_stat_desc ionic_dbg_napi_stats_desc[] = {
 165        IONIC_NAPI_STAT_DESC(poll_count),
 166};
 167
 168#define IONIC_NUM_LIF_STATS ARRAY_SIZE(ionic_lif_stats_desc)
 169#define IONIC_NUM_PORT_STATS ARRAY_SIZE(ionic_port_stats_desc)
 170#define IONIC_NUM_TX_STATS ARRAY_SIZE(ionic_tx_stats_desc)
 171#define IONIC_NUM_RX_STATS ARRAY_SIZE(ionic_rx_stats_desc)
 172#define IONIC_NUM_TX_Q_STATS ARRAY_SIZE(ionic_txq_stats_desc)
 173#define IONIC_NUM_DBG_CQ_STATS ARRAY_SIZE(ionic_dbg_cq_stats_desc)
 174#define IONIC_NUM_DBG_INTR_STATS ARRAY_SIZE(ionic_dbg_intr_stats_desc)
 175#define IONIC_NUM_DBG_NAPI_STATS ARRAY_SIZE(ionic_dbg_napi_stats_desc)
 176
 177#define MAX_Q(lif)   ((lif)->netdev->real_num_tx_queues)
 178
 179static void ionic_get_lif_stats(struct ionic_lif *lif,
 180                                struct ionic_lif_sw_stats *stats)
 181{
 182        struct ionic_tx_stats *tstats;
 183        struct ionic_rx_stats *rstats;
 184        struct rtnl_link_stats64 ns;
 185        struct ionic_qcq *txqcq;
 186        struct ionic_qcq *rxqcq;
 187        int q_num;
 188
 189        memset(stats, 0, sizeof(*stats));
 190
 191        for (q_num = 0; q_num < MAX_Q(lif); q_num++) {
 192                txqcq = lif_to_txqcq(lif, q_num);
 193                if (txqcq && txqcq->stats) {
 194                        tstats = &txqcq->stats->tx;
 195                        stats->tx_packets += tstats->pkts;
 196                        stats->tx_bytes += tstats->bytes;
 197                        stats->tx_tso += tstats->tso;
 198                        stats->tx_tso_bytes += tstats->tso_bytes;
 199                        stats->tx_csum_none += tstats->csum_none;
 200                        stats->tx_csum += tstats->csum;
 201                }
 202
 203                rxqcq = lif_to_rxqcq(lif, q_num);
 204                if (rxqcq && rxqcq->stats) {
 205                        rstats = &rxqcq->stats->rx;
 206                        stats->rx_packets += rstats->pkts;
 207                        stats->rx_bytes += rstats->bytes;
 208                        stats->rx_csum_none += rstats->csum_none;
 209                        stats->rx_csum_complete += rstats->csum_complete;
 210                        stats->rx_csum_error += rstats->csum_error;
 211                }
 212        }
 213
 214        ionic_get_stats64(lif->netdev, &ns);
 215        stats->hw_tx_dropped = ns.tx_dropped;
 216        stats->hw_rx_dropped = ns.rx_dropped;
 217        stats->hw_rx_over_errors = ns.rx_over_errors;
 218        stats->hw_rx_missed_errors = ns.rx_missed_errors;
 219        stats->hw_tx_aborted_errors = ns.tx_aborted_errors;
 220}
 221
 222static u64 ionic_sw_stats_get_count(struct ionic_lif *lif)
 223{
 224        u64 total = 0;
 225
 226        /* lif stats */
 227        total += IONIC_NUM_LIF_STATS;
 228
 229        /* tx stats */
 230        total += MAX_Q(lif) * IONIC_NUM_TX_STATS;
 231
 232        /* rx stats */
 233        total += MAX_Q(lif) * IONIC_NUM_RX_STATS;
 234
 235        /* port stats */
 236        total += IONIC_NUM_PORT_STATS;
 237
 238        if (test_bit(IONIC_LIF_F_UP, lif->state) &&
 239            test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state)) {
 240                /* tx debug stats */
 241                total += MAX_Q(lif) * (IONIC_NUM_DBG_CQ_STATS +
 242                                      IONIC_NUM_TX_Q_STATS +
 243                                      IONIC_NUM_DBG_INTR_STATS +
 244                                      IONIC_MAX_NUM_SG_CNTR);
 245
 246                /* rx debug stats */
 247                total += MAX_Q(lif) * (IONIC_NUM_DBG_CQ_STATS +
 248                                      IONIC_NUM_DBG_INTR_STATS +
 249                                      IONIC_NUM_DBG_NAPI_STATS +
 250                                      IONIC_MAX_NUM_NAPI_CNTR);
 251        }
 252
 253        return total;
 254}
 255
 256static void ionic_sw_stats_get_strings(struct ionic_lif *lif, u8 **buf)
 257{
 258        int i, q_num;
 259
 260        for (i = 0; i < IONIC_NUM_LIF_STATS; i++) {
 261                snprintf(*buf, ETH_GSTRING_LEN, ionic_lif_stats_desc[i].name);
 262                *buf += ETH_GSTRING_LEN;
 263        }
 264
 265        for (i = 0; i < IONIC_NUM_PORT_STATS; i++) {
 266                snprintf(*buf, ETH_GSTRING_LEN,
 267                         ionic_port_stats_desc[i].name);
 268                *buf += ETH_GSTRING_LEN;
 269        }
 270
 271        for (q_num = 0; q_num < MAX_Q(lif); q_num++) {
 272                for (i = 0; i < IONIC_NUM_TX_STATS; i++) {
 273                        snprintf(*buf, ETH_GSTRING_LEN, "tx_%d_%s",
 274                                 q_num, ionic_tx_stats_desc[i].name);
 275                        *buf += ETH_GSTRING_LEN;
 276                }
 277
 278                if (test_bit(IONIC_LIF_F_UP, lif->state) &&
 279                    test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state)) {
 280                        for (i = 0; i < IONIC_NUM_TX_Q_STATS; i++) {
 281                                snprintf(*buf, ETH_GSTRING_LEN,
 282                                         "txq_%d_%s",
 283                                         q_num,
 284                                         ionic_txq_stats_desc[i].name);
 285                                *buf += ETH_GSTRING_LEN;
 286                        }
 287                        for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) {
 288                                snprintf(*buf, ETH_GSTRING_LEN,
 289                                         "txq_%d_cq_%s",
 290                                         q_num,
 291                                         ionic_dbg_cq_stats_desc[i].name);
 292                                *buf += ETH_GSTRING_LEN;
 293                        }
 294                        for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) {
 295                                snprintf(*buf, ETH_GSTRING_LEN,
 296                                         "txq_%d_intr_%s",
 297                                         q_num,
 298                                         ionic_dbg_intr_stats_desc[i].name);
 299                                *buf += ETH_GSTRING_LEN;
 300                        }
 301                        for (i = 0; i < IONIC_MAX_NUM_SG_CNTR; i++) {
 302                                snprintf(*buf, ETH_GSTRING_LEN,
 303                                         "txq_%d_sg_cntr_%d",
 304                                         q_num, i);
 305                                *buf += ETH_GSTRING_LEN;
 306                        }
 307                }
 308        }
 309        for (q_num = 0; q_num < MAX_Q(lif); q_num++) {
 310                for (i = 0; i < IONIC_NUM_RX_STATS; i++) {
 311                        snprintf(*buf, ETH_GSTRING_LEN,
 312                                 "rx_%d_%s",
 313                                 q_num, ionic_rx_stats_desc[i].name);
 314                        *buf += ETH_GSTRING_LEN;
 315                }
 316
 317                if (test_bit(IONIC_LIF_F_UP, lif->state) &&
 318                    test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state)) {
 319                        for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) {
 320                                snprintf(*buf, ETH_GSTRING_LEN,
 321                                         "rxq_%d_cq_%s",
 322                                         q_num,
 323                                         ionic_dbg_cq_stats_desc[i].name);
 324                                *buf += ETH_GSTRING_LEN;
 325                        }
 326                        for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) {
 327                                snprintf(*buf, ETH_GSTRING_LEN,
 328                                         "rxq_%d_intr_%s",
 329                                         q_num,
 330                                         ionic_dbg_intr_stats_desc[i].name);
 331                                *buf += ETH_GSTRING_LEN;
 332                        }
 333                        for (i = 0; i < IONIC_NUM_DBG_NAPI_STATS; i++) {
 334                                snprintf(*buf, ETH_GSTRING_LEN,
 335                                         "rxq_%d_napi_%s",
 336                                         q_num,
 337                                         ionic_dbg_napi_stats_desc[i].name);
 338                                *buf += ETH_GSTRING_LEN;
 339                        }
 340                        for (i = 0; i < IONIC_MAX_NUM_NAPI_CNTR; i++) {
 341                                snprintf(*buf, ETH_GSTRING_LEN,
 342                                         "rxq_%d_napi_work_done_%d",
 343                                         q_num, i);
 344                                *buf += ETH_GSTRING_LEN;
 345                        }
 346                }
 347        }
 348}
 349
 350static void ionic_sw_stats_get_values(struct ionic_lif *lif, u64 **buf)
 351{
 352        struct ionic_port_stats *port_stats;
 353        struct ionic_lif_sw_stats lif_stats;
 354        struct ionic_qcq *txqcq, *rxqcq;
 355        struct ionic_tx_stats *txstats;
 356        struct ionic_rx_stats *rxstats;
 357        int i, q_num;
 358
 359        ionic_get_lif_stats(lif, &lif_stats);
 360
 361        for (i = 0; i < IONIC_NUM_LIF_STATS; i++) {
 362                **buf = IONIC_READ_STAT64(&lif_stats, &ionic_lif_stats_desc[i]);
 363                (*buf)++;
 364        }
 365
 366        port_stats = &lif->ionic->idev.port_info->stats;
 367        for (i = 0; i < IONIC_NUM_PORT_STATS; i++) {
 368                **buf = IONIC_READ_STAT_LE64(port_stats,
 369                                             &ionic_port_stats_desc[i]);
 370                (*buf)++;
 371        }
 372
 373        for (q_num = 0; q_num < MAX_Q(lif); q_num++) {
 374                txstats = &lif_to_txstats(lif, q_num);
 375
 376                for (i = 0; i < IONIC_NUM_TX_STATS; i++) {
 377                        **buf = IONIC_READ_STAT64(txstats,
 378                                                  &ionic_tx_stats_desc[i]);
 379                        (*buf)++;
 380                }
 381
 382                if (test_bit(IONIC_LIF_F_UP, lif->state) &&
 383                    test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state)) {
 384                        txqcq = lif_to_txqcq(lif, q_num);
 385                        for (i = 0; i < IONIC_NUM_TX_Q_STATS; i++) {
 386                                **buf = IONIC_READ_STAT64(&txqcq->q,
 387                                                      &ionic_txq_stats_desc[i]);
 388                                (*buf)++;
 389                        }
 390                        for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) {
 391                                **buf = IONIC_READ_STAT64(&txqcq->cq,
 392                                                   &ionic_dbg_cq_stats_desc[i]);
 393                                (*buf)++;
 394                        }
 395                        for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) {
 396                                **buf = IONIC_READ_STAT64(&txqcq->intr,
 397                                                 &ionic_dbg_intr_stats_desc[i]);
 398                                (*buf)++;
 399                        }
 400                        for (i = 0; i < IONIC_MAX_NUM_SG_CNTR; i++) {
 401                                **buf = txstats->sg_cntr[i];
 402                                (*buf)++;
 403                        }
 404                }
 405        }
 406
 407        for (q_num = 0; q_num < MAX_Q(lif); q_num++) {
 408                rxstats = &lif_to_rxstats(lif, q_num);
 409
 410                for (i = 0; i < IONIC_NUM_RX_STATS; i++) {
 411                        **buf = IONIC_READ_STAT64(rxstats,
 412                                                  &ionic_rx_stats_desc[i]);
 413                        (*buf)++;
 414                }
 415
 416                if (test_bit(IONIC_LIF_F_UP, lif->state) &&
 417                    test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state)) {
 418                        rxqcq = lif_to_rxqcq(lif, q_num);
 419                        for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) {
 420                                **buf = IONIC_READ_STAT64(&rxqcq->cq,
 421                                                   &ionic_dbg_cq_stats_desc[i]);
 422                                (*buf)++;
 423                        }
 424                        for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) {
 425                                **buf = IONIC_READ_STAT64(&rxqcq->intr,
 426                                                 &ionic_dbg_intr_stats_desc[i]);
 427                                (*buf)++;
 428                        }
 429                        for (i = 0; i < IONIC_NUM_DBG_NAPI_STATS; i++) {
 430                                **buf = IONIC_READ_STAT64(&rxqcq->napi_stats,
 431                                                 &ionic_dbg_napi_stats_desc[i]);
 432                                (*buf)++;
 433                        }
 434                        for (i = 0; i < IONIC_MAX_NUM_NAPI_CNTR; i++) {
 435                                **buf = rxqcq->napi_stats.work_done_cntr[i];
 436                                (*buf)++;
 437                        }
 438                }
 439        }
 440}
 441
 442const struct ionic_stats_group_intf ionic_stats_groups[] = {
 443        /* SW Stats group */
 444        {
 445                .get_strings = ionic_sw_stats_get_strings,
 446                .get_values = ionic_sw_stats_get_values,
 447                .get_count = ionic_sw_stats_get_count,
 448        },
 449        /* Add more stat groups here */
 450};
 451
 452const int ionic_num_stats_grps = ARRAY_SIZE(ionic_stats_groups);
 453