Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / net / ethernet / freescale / dpaa2 / dpaa2-eth-debugfs.c
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
12 static struct dentry *dpaa2_dbg_root;
13
14 static 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
45 static 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
57 static 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
64 static 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
76 static 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
104 static 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
116 static 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
123 static 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
146 static 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
158 static 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
165 void 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
207 err_ch_stats:
208         debugfs_remove(priv->dbg.fq_stats);
209 err_fq_stats:
210         debugfs_remove(priv->dbg.cpu_stats);
211 err_cpu_stats:
212         debugfs_remove(priv->dbg.dir);
213 }
214
215 void 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
223 void 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
234 void dpaa2_eth_dbg_exit(void)
235 {
236         debugfs_remove(dpaa2_dbg_root);
237 }