1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /* Copyright(c) 2013 - 2018 Intel Corporation. */
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun #include "fm10k.h"
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <linux/debugfs.h>
7*4882a593Smuzhiyun #include <linux/seq_file.h>
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun static struct dentry *dbg_root;
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun /* Descriptor Seq Functions */
12*4882a593Smuzhiyun
fm10k_dbg_desc_seq_start(struct seq_file * s,loff_t * pos)13*4882a593Smuzhiyun static void *fm10k_dbg_desc_seq_start(struct seq_file *s, loff_t *pos)
14*4882a593Smuzhiyun {
15*4882a593Smuzhiyun struct fm10k_ring *ring = s->private;
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun return (*pos < ring->count) ? pos : NULL;
18*4882a593Smuzhiyun }
19*4882a593Smuzhiyun
fm10k_dbg_desc_seq_next(struct seq_file * s,void __always_unused * v,loff_t * pos)20*4882a593Smuzhiyun static void *fm10k_dbg_desc_seq_next(struct seq_file *s,
21*4882a593Smuzhiyun void __always_unused *v,
22*4882a593Smuzhiyun loff_t *pos)
23*4882a593Smuzhiyun {
24*4882a593Smuzhiyun struct fm10k_ring *ring = s->private;
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun return (++(*pos) < ring->count) ? pos : NULL;
27*4882a593Smuzhiyun }
28*4882a593Smuzhiyun
fm10k_dbg_desc_seq_stop(struct seq_file __always_unused * s,void __always_unused * v)29*4882a593Smuzhiyun static void fm10k_dbg_desc_seq_stop(struct seq_file __always_unused *s,
30*4882a593Smuzhiyun void __always_unused *v)
31*4882a593Smuzhiyun {
32*4882a593Smuzhiyun /* Do nothing. */
33*4882a593Smuzhiyun }
34*4882a593Smuzhiyun
fm10k_dbg_desc_break(struct seq_file * s,int i)35*4882a593Smuzhiyun static void fm10k_dbg_desc_break(struct seq_file *s, int i)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun while (i--)
38*4882a593Smuzhiyun seq_putc(s, '-');
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun seq_putc(s, '\n');
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun
fm10k_dbg_tx_desc_seq_show(struct seq_file * s,void * v)43*4882a593Smuzhiyun static int fm10k_dbg_tx_desc_seq_show(struct seq_file *s, void *v)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun struct fm10k_ring *ring = s->private;
46*4882a593Smuzhiyun int i = *(loff_t *)v;
47*4882a593Smuzhiyun static const char tx_desc_hdr[] =
48*4882a593Smuzhiyun "DES BUFFER_ADDRESS LENGTH VLAN MSS HDRLEN FLAGS\n";
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun /* Generate header */
51*4882a593Smuzhiyun if (!i) {
52*4882a593Smuzhiyun seq_printf(s, tx_desc_hdr);
53*4882a593Smuzhiyun fm10k_dbg_desc_break(s, sizeof(tx_desc_hdr) - 1);
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /* Validate descriptor allocation */
57*4882a593Smuzhiyun if (!ring->desc) {
58*4882a593Smuzhiyun seq_printf(s, "%03X Descriptor ring not allocated.\n", i);
59*4882a593Smuzhiyun } else {
60*4882a593Smuzhiyun struct fm10k_tx_desc *txd = FM10K_TX_DESC(ring, i);
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun seq_printf(s, "%03X %#018llx %#06x %#06x %#06x %#06x %#04x\n",
63*4882a593Smuzhiyun i, txd->buffer_addr, txd->buflen, txd->vlan,
64*4882a593Smuzhiyun txd->mss, txd->hdrlen, txd->flags);
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun return 0;
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun
fm10k_dbg_rx_desc_seq_show(struct seq_file * s,void * v)70*4882a593Smuzhiyun static int fm10k_dbg_rx_desc_seq_show(struct seq_file *s, void *v)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun struct fm10k_ring *ring = s->private;
73*4882a593Smuzhiyun int i = *(loff_t *)v;
74*4882a593Smuzhiyun static const char rx_desc_hdr[] =
75*4882a593Smuzhiyun "DES DATA RSS STATERR LENGTH VLAN DGLORT SGLORT TIMESTAMP\n";
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun /* Generate header */
78*4882a593Smuzhiyun if (!i) {
79*4882a593Smuzhiyun seq_printf(s, rx_desc_hdr);
80*4882a593Smuzhiyun fm10k_dbg_desc_break(s, sizeof(rx_desc_hdr) - 1);
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun /* Validate descriptor allocation */
84*4882a593Smuzhiyun if (!ring->desc) {
85*4882a593Smuzhiyun seq_printf(s, "%03X Descriptor ring not allocated.\n", i);
86*4882a593Smuzhiyun } else {
87*4882a593Smuzhiyun union fm10k_rx_desc *rxd = FM10K_RX_DESC(ring, i);
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun seq_printf(s,
90*4882a593Smuzhiyun "%03X %#010x %#010x %#010x %#06x %#06x %#06x %#06x %#018llx\n",
91*4882a593Smuzhiyun i, rxd->d.data, rxd->d.rss, rxd->d.staterr,
92*4882a593Smuzhiyun rxd->w.length, rxd->w.vlan, rxd->w.dglort,
93*4882a593Smuzhiyun rxd->w.sglort, rxd->q.timestamp);
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun return 0;
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun static const struct seq_operations fm10k_dbg_tx_desc_seq_ops = {
100*4882a593Smuzhiyun .start = fm10k_dbg_desc_seq_start,
101*4882a593Smuzhiyun .next = fm10k_dbg_desc_seq_next,
102*4882a593Smuzhiyun .stop = fm10k_dbg_desc_seq_stop,
103*4882a593Smuzhiyun .show = fm10k_dbg_tx_desc_seq_show,
104*4882a593Smuzhiyun };
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun static const struct seq_operations fm10k_dbg_rx_desc_seq_ops = {
107*4882a593Smuzhiyun .start = fm10k_dbg_desc_seq_start,
108*4882a593Smuzhiyun .next = fm10k_dbg_desc_seq_next,
109*4882a593Smuzhiyun .stop = fm10k_dbg_desc_seq_stop,
110*4882a593Smuzhiyun .show = fm10k_dbg_rx_desc_seq_show,
111*4882a593Smuzhiyun };
112*4882a593Smuzhiyun
fm10k_dbg_desc_open(struct inode * inode,struct file * filep)113*4882a593Smuzhiyun static int fm10k_dbg_desc_open(struct inode *inode, struct file *filep)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun struct fm10k_ring *ring = inode->i_private;
116*4882a593Smuzhiyun struct fm10k_q_vector *q_vector = ring->q_vector;
117*4882a593Smuzhiyun const struct seq_operations *desc_seq_ops;
118*4882a593Smuzhiyun int err;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun if (ring < q_vector->rx.ring)
121*4882a593Smuzhiyun desc_seq_ops = &fm10k_dbg_tx_desc_seq_ops;
122*4882a593Smuzhiyun else
123*4882a593Smuzhiyun desc_seq_ops = &fm10k_dbg_rx_desc_seq_ops;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun err = seq_open(filep, desc_seq_ops);
126*4882a593Smuzhiyun if (err)
127*4882a593Smuzhiyun return err;
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun ((struct seq_file *)filep->private_data)->private = ring;
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun return 0;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun static const struct file_operations fm10k_dbg_desc_fops = {
135*4882a593Smuzhiyun .owner = THIS_MODULE,
136*4882a593Smuzhiyun .open = fm10k_dbg_desc_open,
137*4882a593Smuzhiyun .read = seq_read,
138*4882a593Smuzhiyun .llseek = seq_lseek,
139*4882a593Smuzhiyun .release = seq_release,
140*4882a593Smuzhiyun };
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun /**
143*4882a593Smuzhiyun * fm10k_dbg_q_vector_init - setup debugfs for the q_vectors
144*4882a593Smuzhiyun * @q_vector: q_vector to allocate directories for
145*4882a593Smuzhiyun *
146*4882a593Smuzhiyun * A folder is created for each q_vector found. In each q_vector
147*4882a593Smuzhiyun * folder, a debugfs file is created for each tx and rx ring
148*4882a593Smuzhiyun * allocated to the q_vector.
149*4882a593Smuzhiyun **/
fm10k_dbg_q_vector_init(struct fm10k_q_vector * q_vector)150*4882a593Smuzhiyun void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector)
151*4882a593Smuzhiyun {
152*4882a593Smuzhiyun struct fm10k_intfc *interface = q_vector->interface;
153*4882a593Smuzhiyun char name[16];
154*4882a593Smuzhiyun int i;
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun if (!interface->dbg_intfc)
157*4882a593Smuzhiyun return;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun /* Generate a folder for each q_vector */
160*4882a593Smuzhiyun snprintf(name, sizeof(name), "q_vector.%03d", q_vector->v_idx);
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun q_vector->dbg_q_vector = debugfs_create_dir(name, interface->dbg_intfc);
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun /* Generate a file for each rx ring in the q_vector */
165*4882a593Smuzhiyun for (i = 0; i < q_vector->tx.count; i++) {
166*4882a593Smuzhiyun struct fm10k_ring *ring = &q_vector->tx.ring[i];
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun snprintf(name, sizeof(name), "tx_ring.%03d", ring->queue_index);
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun debugfs_create_file(name, 0600,
171*4882a593Smuzhiyun q_vector->dbg_q_vector, ring,
172*4882a593Smuzhiyun &fm10k_dbg_desc_fops);
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun /* Generate a file for each rx ring in the q_vector */
176*4882a593Smuzhiyun for (i = 0; i < q_vector->rx.count; i++) {
177*4882a593Smuzhiyun struct fm10k_ring *ring = &q_vector->rx.ring[i];
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun snprintf(name, sizeof(name), "rx_ring.%03d", ring->queue_index);
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun debugfs_create_file(name, 0600,
182*4882a593Smuzhiyun q_vector->dbg_q_vector, ring,
183*4882a593Smuzhiyun &fm10k_dbg_desc_fops);
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun /**
188*4882a593Smuzhiyun * fm10k_dbg_free_q_vector_dir - setup debugfs for the q_vectors
189*4882a593Smuzhiyun * @q_vector: q_vector to allocate directories for
190*4882a593Smuzhiyun **/
fm10k_dbg_q_vector_exit(struct fm10k_q_vector * q_vector)191*4882a593Smuzhiyun void fm10k_dbg_q_vector_exit(struct fm10k_q_vector *q_vector)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun struct fm10k_intfc *interface = q_vector->interface;
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun if (interface->dbg_intfc)
196*4882a593Smuzhiyun debugfs_remove_recursive(q_vector->dbg_q_vector);
197*4882a593Smuzhiyun q_vector->dbg_q_vector = NULL;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun /**
201*4882a593Smuzhiyun * fm10k_dbg_intfc_init - setup the debugfs directory for the intferface
202*4882a593Smuzhiyun * @interface: the interface that is starting up
203*4882a593Smuzhiyun **/
204*4882a593Smuzhiyun
fm10k_dbg_intfc_init(struct fm10k_intfc * interface)205*4882a593Smuzhiyun void fm10k_dbg_intfc_init(struct fm10k_intfc *interface)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun const char *name = pci_name(interface->pdev);
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun if (dbg_root)
210*4882a593Smuzhiyun interface->dbg_intfc = debugfs_create_dir(name, dbg_root);
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun /**
214*4882a593Smuzhiyun * fm10k_dbg_intfc_exit - clean out the interface's debugfs entries
215*4882a593Smuzhiyun * @interface: the interface that is stopping
216*4882a593Smuzhiyun **/
fm10k_dbg_intfc_exit(struct fm10k_intfc * interface)217*4882a593Smuzhiyun void fm10k_dbg_intfc_exit(struct fm10k_intfc *interface)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun if (dbg_root)
220*4882a593Smuzhiyun debugfs_remove_recursive(interface->dbg_intfc);
221*4882a593Smuzhiyun interface->dbg_intfc = NULL;
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun /**
225*4882a593Smuzhiyun * fm10k_dbg_init - start up debugfs for the driver
226*4882a593Smuzhiyun **/
fm10k_dbg_init(void)227*4882a593Smuzhiyun void fm10k_dbg_init(void)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun dbg_root = debugfs_create_dir(fm10k_driver_name, NULL);
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun /**
233*4882a593Smuzhiyun * fm10k_dbg_exit - clean out the driver's debugfs entries
234*4882a593Smuzhiyun **/
fm10k_dbg_exit(void)235*4882a593Smuzhiyun void fm10k_dbg_exit(void)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun debugfs_remove_recursive(dbg_root);
238*4882a593Smuzhiyun dbg_root = NULL;
239*4882a593Smuzhiyun }
240