18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
28c2ecf20Sopenharmony_ci/* Copyright 2015 Freescale Semiconductor Inc.
38c2ecf20Sopenharmony_ci * Copyright 2018-2019 NXP
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci#include <linux/module.h>
68c2ecf20Sopenharmony_ci#include <linux/debugfs.h>
78c2ecf20Sopenharmony_ci#include "dpaa2-eth.h"
88c2ecf20Sopenharmony_ci#include "dpaa2-eth-debugfs.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#define DPAA2_ETH_DBG_ROOT "dpaa2-eth"
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_cistatic struct dentry *dpaa2_dbg_root;
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_cistatic int dpaa2_dbg_cpu_show(struct seq_file *file, void *offset)
158c2ecf20Sopenharmony_ci{
168c2ecf20Sopenharmony_ci	struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)file->private;
178c2ecf20Sopenharmony_ci	struct rtnl_link_stats64 *stats;
188c2ecf20Sopenharmony_ci	struct dpaa2_eth_drv_stats *extras;
198c2ecf20Sopenharmony_ci	int i;
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci	seq_printf(file, "Per-CPU stats for %s\n", priv->net_dev->name);
228c2ecf20Sopenharmony_ci	seq_printf(file, "%s%16s%16s%16s%16s%16s%16s%16s%16s%16s\n",
238c2ecf20Sopenharmony_ci		   "CPU", "Rx", "Rx Err", "Rx SG", "Tx", "Tx Err", "Tx conf",
248c2ecf20Sopenharmony_ci		   "Tx SG", "Tx converted to SG", "Enq busy");
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	for_each_online_cpu(i) {
278c2ecf20Sopenharmony_ci		stats = per_cpu_ptr(priv->percpu_stats, i);
288c2ecf20Sopenharmony_ci		extras = per_cpu_ptr(priv->percpu_extras, i);
298c2ecf20Sopenharmony_ci		seq_printf(file, "%3d%16llu%16llu%16llu%16llu%16llu%16llu%16llu%16llu%16llu\n",
308c2ecf20Sopenharmony_ci			   i,
318c2ecf20Sopenharmony_ci			   stats->rx_packets,
328c2ecf20Sopenharmony_ci			   stats->rx_errors,
338c2ecf20Sopenharmony_ci			   extras->rx_sg_frames,
348c2ecf20Sopenharmony_ci			   stats->tx_packets,
358c2ecf20Sopenharmony_ci			   stats->tx_errors,
368c2ecf20Sopenharmony_ci			   extras->tx_conf_frames,
378c2ecf20Sopenharmony_ci			   extras->tx_sg_frames,
388c2ecf20Sopenharmony_ci			   extras->tx_converted_sg_frames,
398c2ecf20Sopenharmony_ci			   extras->tx_portal_busy);
408c2ecf20Sopenharmony_ci	}
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	return 0;
438c2ecf20Sopenharmony_ci}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(dpaa2_dbg_cpu);
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistatic char *fq_type_to_str(struct dpaa2_eth_fq *fq)
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	switch (fq->type) {
508c2ecf20Sopenharmony_ci	case DPAA2_RX_FQ:
518c2ecf20Sopenharmony_ci		return "Rx";
528c2ecf20Sopenharmony_ci	case DPAA2_TX_CONF_FQ:
538c2ecf20Sopenharmony_ci		return "Tx conf";
548c2ecf20Sopenharmony_ci	default:
558c2ecf20Sopenharmony_ci		return "N/A";
568c2ecf20Sopenharmony_ci	}
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic int dpaa2_dbg_fqs_show(struct seq_file *file, void *offset)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)file->private;
628c2ecf20Sopenharmony_ci	struct dpaa2_eth_fq *fq;
638c2ecf20Sopenharmony_ci	u32 fcnt, bcnt;
648c2ecf20Sopenharmony_ci	int i, err;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	seq_printf(file, "FQ stats for %s:\n", priv->net_dev->name);
678c2ecf20Sopenharmony_ci	seq_printf(file, "%s%16s%16s%16s%16s%16s\n",
688c2ecf20Sopenharmony_ci		   "VFQID", "CPU", "TC", "Type", "Frames", "Pending frames");
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	for (i = 0; i <  priv->num_fqs; i++) {
718c2ecf20Sopenharmony_ci		fq = &priv->fq[i];
728c2ecf20Sopenharmony_ci		err = dpaa2_io_query_fq_count(NULL, fq->fqid, &fcnt, &bcnt);
738c2ecf20Sopenharmony_ci		if (err)
748c2ecf20Sopenharmony_ci			fcnt = 0;
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci		/* Skip FQs with no traffic */
778c2ecf20Sopenharmony_ci		if (!fq->stats.frames && !fcnt)
788c2ecf20Sopenharmony_ci			continue;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci		seq_printf(file, "%5d%16d%16d%16s%16llu%16u\n",
818c2ecf20Sopenharmony_ci			   fq->fqid,
828c2ecf20Sopenharmony_ci			   fq->target_cpu,
838c2ecf20Sopenharmony_ci			   fq->tc,
848c2ecf20Sopenharmony_ci			   fq_type_to_str(fq),
858c2ecf20Sopenharmony_ci			   fq->stats.frames,
868c2ecf20Sopenharmony_ci			   fcnt);
878c2ecf20Sopenharmony_ci	}
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	return 0;
908c2ecf20Sopenharmony_ci}
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(dpaa2_dbg_fqs);
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cistatic int dpaa2_dbg_ch_show(struct seq_file *file, void *offset)
958c2ecf20Sopenharmony_ci{
968c2ecf20Sopenharmony_ci	struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)file->private;
978c2ecf20Sopenharmony_ci	struct dpaa2_eth_channel *ch;
988c2ecf20Sopenharmony_ci	int i;
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	seq_printf(file, "Channel stats for %s:\n", priv->net_dev->name);
1018c2ecf20Sopenharmony_ci	seq_printf(file, "%s%16s%16s%16s%16s%16s%16s\n",
1028c2ecf20Sopenharmony_ci		   "CHID", "CPU", "Deq busy", "Frames", "CDANs",
1038c2ecf20Sopenharmony_ci		   "Avg Frm/CDAN", "Buf count");
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	for (i = 0; i < priv->num_channels; i++) {
1068c2ecf20Sopenharmony_ci		ch = priv->channel[i];
1078c2ecf20Sopenharmony_ci		seq_printf(file, "%4d%16d%16llu%16llu%16llu%16llu%16d\n",
1088c2ecf20Sopenharmony_ci			   ch->ch_id,
1098c2ecf20Sopenharmony_ci			   ch->nctx.desired_cpu,
1108c2ecf20Sopenharmony_ci			   ch->stats.dequeue_portal_busy,
1118c2ecf20Sopenharmony_ci			   ch->stats.frames,
1128c2ecf20Sopenharmony_ci			   ch->stats.cdan,
1138c2ecf20Sopenharmony_ci			   div64_u64(ch->stats.frames, ch->stats.cdan),
1148c2ecf20Sopenharmony_ci			   ch->buf_count);
1158c2ecf20Sopenharmony_ci	}
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	return 0;
1188c2ecf20Sopenharmony_ci}
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(dpaa2_dbg_ch);
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_civoid dpaa2_dbg_add(struct dpaa2_eth_priv *priv)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	struct dentry *dir;
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	/* Create a directory for the interface */
1278c2ecf20Sopenharmony_ci	dir = debugfs_create_dir(priv->net_dev->name, dpaa2_dbg_root);
1288c2ecf20Sopenharmony_ci	priv->dbg.dir = dir;
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	/* per-cpu stats file */
1318c2ecf20Sopenharmony_ci	debugfs_create_file("cpu_stats", 0444, dir, priv, &dpaa2_dbg_cpu_fops);
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	/* per-fq stats file */
1348c2ecf20Sopenharmony_ci	debugfs_create_file("fq_stats", 0444, dir, priv, &dpaa2_dbg_fqs_fops);
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	/* per-fq stats file */
1378c2ecf20Sopenharmony_ci	debugfs_create_file("ch_stats", 0444, dir, priv, &dpaa2_dbg_ch_fops);
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_civoid dpaa2_dbg_remove(struct dpaa2_eth_priv *priv)
1418c2ecf20Sopenharmony_ci{
1428c2ecf20Sopenharmony_ci	debugfs_remove_recursive(priv->dbg.dir);
1438c2ecf20Sopenharmony_ci}
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_civoid dpaa2_eth_dbg_init(void)
1468c2ecf20Sopenharmony_ci{
1478c2ecf20Sopenharmony_ci	dpaa2_dbg_root = debugfs_create_dir(DPAA2_ETH_DBG_ROOT, NULL);
1488c2ecf20Sopenharmony_ci	pr_debug("DPAA2-ETH: debugfs created\n");
1498c2ecf20Sopenharmony_ci}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_civoid dpaa2_eth_dbg_exit(void)
1528c2ecf20Sopenharmony_ci{
1538c2ecf20Sopenharmony_ci	debugfs_remove(dpaa2_dbg_root);
1548c2ecf20Sopenharmony_ci}
155