xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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