linux/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
   2/* Copyright 2015 Freescale Semiconductor Inc.
   3 * Copyright 2018-2019 NXP
   4 */
   5#include <linux/module.h>
   6#include <linux/debugfs.h>
   7#include "dpaa2-eth.h"
   8#include "dpaa2-eth-debugfs.h"
   9
  10#define DPAA2_ETH_DBG_ROOT "dpaa2-eth"
  11
  12static struct dentry *dpaa2_dbg_root;
  13
  14static int dpaa2_dbg_cpu_show(struct seq_file *file, void *offset)
  15{
  16        struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)file->private;
  17        struct rtnl_link_stats64 *stats;
  18        struct dpaa2_eth_drv_stats *extras;
  19        int i;
  20
  21        seq_printf(file, "Per-CPU stats for %s\n", priv->net_dev->name);
  22        seq_printf(file, "%s%16s%16s%16s%16s%16s%16s%16s%16s%16s\n",
  23                   "CPU", "Rx", "Rx Err", "Rx SG", "Tx", "Tx Err", "Tx conf",
  24                   "Tx SG", "Tx realloc", "Enq busy");
  25
  26        for_each_online_cpu(i) {
  27                stats = per_cpu_ptr(priv->percpu_stats, i);
  28                extras = per_cpu_ptr(priv->percpu_extras, i);
  29                seq_printf(file, "%3d%16llu%16llu%16llu%16llu%16llu%16llu%16llu%16llu%16llu\n",
  30                           i,
  31                           stats->rx_packets,
  32                           stats->rx_errors,
  33                           extras->rx_sg_frames,
  34                           stats->tx_packets,
  35                           stats->tx_errors,
  36                           extras->tx_conf_frames,
  37                           extras->tx_sg_frames,
  38                           extras->tx_reallocs,
  39                           extras->tx_portal_busy);
  40        }
  41
  42        return 0;
  43}
  44
  45static int dpaa2_dbg_cpu_open(struct inode *inode, struct file *file)
  46{
  47        int err;
  48        struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)inode->i_private;
  49
  50        err = single_open(file, dpaa2_dbg_cpu_show, priv);
  51        if (err < 0)
  52                netdev_err(priv->net_dev, "single_open() failed\n");
  53
  54        return err;
  55}
  56
  57static const struct file_operations dpaa2_dbg_cpu_ops = {
  58        .open = dpaa2_dbg_cpu_open,
  59        .read = seq_read,
  60        .llseek = seq_lseek,
  61        .release = single_release,
  62};
  63
  64static char *fq_type_to_str(struct dpaa2_eth_fq *fq)
  65{
  66        switch (fq->type) {
  67        case DPAA2_RX_FQ:
  68                return "Rx";
  69        case DPAA2_TX_CONF_FQ:
  70                return "Tx conf";
  71        default:
  72                return "N/A";
  73        }
  74}
  75
  76static int dpaa2_dbg_fqs_show(struct seq_file *file, void *offset)
  77{
  78        struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)file->private;
  79        struct dpaa2_eth_fq *fq;
  80        u32 fcnt, bcnt;
  81        int i, err;
  82
  83        seq_printf(file, "FQ stats for %s:\n", priv->net_dev->name);
  84        seq_printf(file, "%s%16s%16s%16s%16s\n",
  85                   "VFQID", "CPU", "Type", "Frames", "Pending frames");
  86
  87        for (i = 0; i <  priv->num_fqs; i++) {
  88                fq = &priv->fq[i];
  89                err = dpaa2_io_query_fq_count(NULL, fq->fqid, &fcnt, &bcnt);
  90                if (err)
  91                        fcnt = 0;
  92
  93                seq_printf(file, "%5d%16d%16s%16llu%16u\n",
  94                           fq->fqid,
  95                           fq->target_cpu,
  96                           fq_type_to_str(fq),
  97                           fq->stats.frames,
  98                           fcnt);
  99        }
 100
 101        return 0;
 102}
 103
 104static int dpaa2_dbg_fqs_open(struct inode *inode, struct file *file)
 105{
 106        int err;
 107        struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)inode->i_private;
 108
 109        err = single_open(file, dpaa2_dbg_fqs_show, priv);
 110        if (err < 0)
 111                netdev_err(priv->net_dev, "single_open() failed\n");
 112
 113        return err;
 114}
 115
 116static const struct file_operations dpaa2_dbg_fq_ops = {
 117        .open = dpaa2_dbg_fqs_open,
 118        .read = seq_read,
 119        .llseek = seq_lseek,
 120        .release = single_release,
 121};
 122
 123static int dpaa2_dbg_ch_show(struct seq_file *file, void *offset)
 124{
 125        struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)file->private;
 126        struct dpaa2_eth_channel *ch;
 127        int i;
 128
 129        seq_printf(file, "Channel stats for %s:\n", priv->net_dev->name);
 130        seq_printf(file, "%s%16s%16s%16s%16s\n",
 131                   "CHID", "CPU", "Deq busy", "CDANs", "Buf count");
 132
 133        for (i = 0; i < priv->num_channels; i++) {
 134                ch = priv->channel[i];
 135                seq_printf(file, "%4d%16d%16llu%16llu%16d\n",
 136                           ch->ch_id,
 137                           ch->nctx.desired_cpu,
 138                           ch->stats.dequeue_portal_busy,
 139                           ch->stats.cdan,
 140                           ch->buf_count);
 141        }
 142
 143        return 0;
 144}
 145
 146static int dpaa2_dbg_ch_open(struct inode *inode, struct file *file)
 147{
 148        int err;
 149        struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)inode->i_private;
 150
 151        err = single_open(file, dpaa2_dbg_ch_show, priv);
 152        if (err < 0)
 153                netdev_err(priv->net_dev, "single_open() failed\n");
 154
 155        return err;
 156}
 157
 158static const struct file_operations dpaa2_dbg_ch_ops = {
 159        .open = dpaa2_dbg_ch_open,
 160        .read = seq_read,
 161        .llseek = seq_lseek,
 162        .release = single_release,
 163};
 164
 165void dpaa2_dbg_add(struct dpaa2_eth_priv *priv)
 166{
 167        if (!dpaa2_dbg_root)
 168                return;
 169
 170        /* Create a directory for the interface */
 171        priv->dbg.dir = debugfs_create_dir(priv->net_dev->name,
 172                                           dpaa2_dbg_root);
 173        if (!priv->dbg.dir) {
 174                netdev_err(priv->net_dev, "debugfs_create_dir() failed\n");
 175                return;
 176        }
 177
 178        /* per-cpu stats file */
 179        priv->dbg.cpu_stats = debugfs_create_file("cpu_stats", 0444,
 180                                                  priv->dbg.dir, priv,
 181                                                  &dpaa2_dbg_cpu_ops);
 182        if (!priv->dbg.cpu_stats) {
 183                netdev_err(priv->net_dev, "debugfs_create_file() failed\n");
 184                goto err_cpu_stats;
 185        }
 186
 187        /* per-fq stats file */
 188        priv->dbg.fq_stats = debugfs_create_file("fq_stats", 0444,
 189                                                 priv->dbg.dir, priv,
 190                                                 &dpaa2_dbg_fq_ops);
 191        if (!priv->dbg.fq_stats) {
 192                netdev_err(priv->net_dev, "debugfs_create_file() failed\n");
 193                goto err_fq_stats;
 194        }
 195
 196        /* per-fq stats file */
 197        priv->dbg.ch_stats = debugfs_create_file("ch_stats", 0444,
 198                                                 priv->dbg.dir, priv,
 199                                                 &dpaa2_dbg_ch_ops);
 200        if (!priv->dbg.fq_stats) {
 201                netdev_err(priv->net_dev, "debugfs_create_file() failed\n");
 202                goto err_ch_stats;
 203        }
 204
 205        return;
 206
 207err_ch_stats:
 208        debugfs_remove(priv->dbg.fq_stats);
 209err_fq_stats:
 210        debugfs_remove(priv->dbg.cpu_stats);
 211err_cpu_stats:
 212        debugfs_remove(priv->dbg.dir);
 213}
 214
 215void dpaa2_dbg_remove(struct dpaa2_eth_priv *priv)
 216{
 217        debugfs_remove(priv->dbg.fq_stats);
 218        debugfs_remove(priv->dbg.ch_stats);
 219        debugfs_remove(priv->dbg.cpu_stats);
 220        debugfs_remove(priv->dbg.dir);
 221}
 222
 223void dpaa2_eth_dbg_init(void)
 224{
 225        dpaa2_dbg_root = debugfs_create_dir(DPAA2_ETH_DBG_ROOT, NULL);
 226        if (!dpaa2_dbg_root) {
 227                pr_err("DPAA2-ETH: debugfs create failed\n");
 228                return;
 229        }
 230
 231        pr_debug("DPAA2-ETH: debugfs created\n");
 232}
 233
 234void dpaa2_eth_dbg_exit(void)
 235{
 236        debugfs_remove(dpaa2_dbg_root);
 237}
 238