xref: /openbmc/linux/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c (revision 8be98d2f2a0a262f8bf8a0bc1fdf522b3c7aab17)
1ae06c70bSJeff Kirsher // SPDX-License-Identifier: GPL-2.0
251dce24bSJeff Kirsher /* Copyright(c) 2013 - 2018 Intel Corporation. */
37461fd91SAlexander Duyck 
47461fd91SAlexander Duyck #include "fm10k.h"
57461fd91SAlexander Duyck 
67461fd91SAlexander Duyck #include <linux/debugfs.h>
77461fd91SAlexander Duyck #include <linux/seq_file.h>
87461fd91SAlexander Duyck 
97461fd91SAlexander Duyck static struct dentry *dbg_root;
107461fd91SAlexander Duyck 
117461fd91SAlexander Duyck /* Descriptor Seq Functions */
127461fd91SAlexander Duyck 
fm10k_dbg_desc_seq_start(struct seq_file * s,loff_t * pos)137461fd91SAlexander Duyck static void *fm10k_dbg_desc_seq_start(struct seq_file *s, loff_t *pos)
147461fd91SAlexander Duyck {
157461fd91SAlexander Duyck 	struct fm10k_ring *ring = s->private;
167461fd91SAlexander Duyck 
177461fd91SAlexander Duyck 	return (*pos < ring->count) ? pos : NULL;
187461fd91SAlexander Duyck }
197461fd91SAlexander Duyck 
fm10k_dbg_desc_seq_next(struct seq_file * s,void __always_unused * v,loff_t * pos)20de445199SJeff Kirsher static void *fm10k_dbg_desc_seq_next(struct seq_file *s,
216fbc6b35SJacob Keller 				     void __always_unused *v,
226fbc6b35SJacob Keller 				     loff_t *pos)
237461fd91SAlexander Duyck {
247461fd91SAlexander Duyck 	struct fm10k_ring *ring = s->private;
257461fd91SAlexander Duyck 
267461fd91SAlexander Duyck 	return (++(*pos) < ring->count) ? pos : NULL;
277461fd91SAlexander Duyck }
287461fd91SAlexander Duyck 
fm10k_dbg_desc_seq_stop(struct seq_file __always_unused * s,void __always_unused * v)29de445199SJeff Kirsher static void fm10k_dbg_desc_seq_stop(struct seq_file __always_unused *s,
306fbc6b35SJacob Keller 				    void __always_unused *v)
317461fd91SAlexander Duyck {
327461fd91SAlexander Duyck 	/* Do nothing. */
337461fd91SAlexander Duyck }
347461fd91SAlexander Duyck 
fm10k_dbg_desc_break(struct seq_file * s,int i)357461fd91SAlexander Duyck static void fm10k_dbg_desc_break(struct seq_file *s, int i)
367461fd91SAlexander Duyck {
377461fd91SAlexander Duyck 	while (i--)
3895f49d4bSMarkus Elfring 		seq_putc(s, '-');
397461fd91SAlexander Duyck 
4095f49d4bSMarkus Elfring 	seq_putc(s, '\n');
417461fd91SAlexander Duyck }
427461fd91SAlexander Duyck 
fm10k_dbg_tx_desc_seq_show(struct seq_file * s,void * v)437461fd91SAlexander Duyck static int fm10k_dbg_tx_desc_seq_show(struct seq_file *s, void *v)
447461fd91SAlexander Duyck {
457461fd91SAlexander Duyck 	struct fm10k_ring *ring = s->private;
467461fd91SAlexander Duyck 	int i = *(loff_t *)v;
477461fd91SAlexander Duyck 	static const char tx_desc_hdr[] =
487461fd91SAlexander Duyck 		"DES BUFFER_ADDRESS     LENGTH VLAN   MSS    HDRLEN FLAGS\n";
497461fd91SAlexander Duyck 
507461fd91SAlexander Duyck 	/* Generate header */
517461fd91SAlexander Duyck 	if (!i) {
527461fd91SAlexander Duyck 		seq_printf(s, tx_desc_hdr);
537461fd91SAlexander Duyck 		fm10k_dbg_desc_break(s, sizeof(tx_desc_hdr) - 1);
547461fd91SAlexander Duyck 	}
557461fd91SAlexander Duyck 
567461fd91SAlexander Duyck 	/* Validate descriptor allocation */
577461fd91SAlexander Duyck 	if (!ring->desc) {
587461fd91SAlexander Duyck 		seq_printf(s, "%03X Descriptor ring not allocated.\n", i);
597461fd91SAlexander Duyck 	} else {
607461fd91SAlexander Duyck 		struct fm10k_tx_desc *txd = FM10K_TX_DESC(ring, i);
617461fd91SAlexander Duyck 
627461fd91SAlexander Duyck 		seq_printf(s, "%03X %#018llx %#06x %#06x %#06x %#06x %#04x\n",
637461fd91SAlexander Duyck 			   i, txd->buffer_addr, txd->buflen, txd->vlan,
647461fd91SAlexander Duyck 			   txd->mss, txd->hdrlen, txd->flags);
657461fd91SAlexander Duyck 	}
667461fd91SAlexander Duyck 
677461fd91SAlexander Duyck 	return 0;
687461fd91SAlexander Duyck }
697461fd91SAlexander Duyck 
fm10k_dbg_rx_desc_seq_show(struct seq_file * s,void * v)707461fd91SAlexander Duyck static int fm10k_dbg_rx_desc_seq_show(struct seq_file *s, void *v)
717461fd91SAlexander Duyck {
727461fd91SAlexander Duyck 	struct fm10k_ring *ring = s->private;
737461fd91SAlexander Duyck 	int i = *(loff_t *)v;
747461fd91SAlexander Duyck 	static const char rx_desc_hdr[] =
757461fd91SAlexander Duyck 	"DES DATA       RSS        STATERR    LENGTH VLAN   DGLORT SGLORT TIMESTAMP\n";
767461fd91SAlexander Duyck 
777461fd91SAlexander Duyck 	/* Generate header */
787461fd91SAlexander Duyck 	if (!i) {
797461fd91SAlexander Duyck 		seq_printf(s, rx_desc_hdr);
807461fd91SAlexander Duyck 		fm10k_dbg_desc_break(s, sizeof(rx_desc_hdr) - 1);
817461fd91SAlexander Duyck 	}
827461fd91SAlexander Duyck 
837461fd91SAlexander Duyck 	/* Validate descriptor allocation */
847461fd91SAlexander Duyck 	if (!ring->desc) {
857461fd91SAlexander Duyck 		seq_printf(s, "%03X Descriptor ring not allocated.\n", i);
867461fd91SAlexander Duyck 	} else {
877461fd91SAlexander Duyck 		union fm10k_rx_desc *rxd = FM10K_RX_DESC(ring, i);
887461fd91SAlexander Duyck 
897461fd91SAlexander Duyck 		seq_printf(s,
907461fd91SAlexander Duyck 			   "%03X %#010x %#010x %#010x %#06x %#06x %#06x %#06x %#018llx\n",
917461fd91SAlexander Duyck 			   i, rxd->d.data, rxd->d.rss, rxd->d.staterr,
927461fd91SAlexander Duyck 			   rxd->w.length, rxd->w.vlan, rxd->w.dglort,
937461fd91SAlexander Duyck 			   rxd->w.sglort, rxd->q.timestamp);
947461fd91SAlexander Duyck 	}
957461fd91SAlexander Duyck 
967461fd91SAlexander Duyck 	return 0;
977461fd91SAlexander Duyck }
987461fd91SAlexander Duyck 
997461fd91SAlexander Duyck static const struct seq_operations fm10k_dbg_tx_desc_seq_ops = {
1007461fd91SAlexander Duyck 	.start = fm10k_dbg_desc_seq_start,
1017461fd91SAlexander Duyck 	.next  = fm10k_dbg_desc_seq_next,
1027461fd91SAlexander Duyck 	.stop  = fm10k_dbg_desc_seq_stop,
1037461fd91SAlexander Duyck 	.show  = fm10k_dbg_tx_desc_seq_show,
1047461fd91SAlexander Duyck };
1057461fd91SAlexander Duyck 
1067461fd91SAlexander Duyck static const struct seq_operations fm10k_dbg_rx_desc_seq_ops = {
1077461fd91SAlexander Duyck 	.start = fm10k_dbg_desc_seq_start,
1087461fd91SAlexander Duyck 	.next  = fm10k_dbg_desc_seq_next,
1097461fd91SAlexander Duyck 	.stop  = fm10k_dbg_desc_seq_stop,
1107461fd91SAlexander Duyck 	.show  = fm10k_dbg_rx_desc_seq_show,
1117461fd91SAlexander Duyck };
1127461fd91SAlexander Duyck 
fm10k_dbg_desc_open(struct inode * inode,struct file * filep)1137461fd91SAlexander Duyck static int fm10k_dbg_desc_open(struct inode *inode, struct file *filep)
1147461fd91SAlexander Duyck {
1157461fd91SAlexander Duyck 	struct fm10k_ring *ring = inode->i_private;
1167461fd91SAlexander Duyck 	struct fm10k_q_vector *q_vector = ring->q_vector;
1177461fd91SAlexander Duyck 	const struct seq_operations *desc_seq_ops;
1187461fd91SAlexander Duyck 	int err;
1197461fd91SAlexander Duyck 
1207461fd91SAlexander Duyck 	if (ring < q_vector->rx.ring)
1217461fd91SAlexander Duyck 		desc_seq_ops = &fm10k_dbg_tx_desc_seq_ops;
1227461fd91SAlexander Duyck 	else
1237461fd91SAlexander Duyck 		desc_seq_ops = &fm10k_dbg_rx_desc_seq_ops;
1247461fd91SAlexander Duyck 
1257461fd91SAlexander Duyck 	err = seq_open(filep, desc_seq_ops);
1267461fd91SAlexander Duyck 	if (err)
1277461fd91SAlexander Duyck 		return err;
1287461fd91SAlexander Duyck 
1297461fd91SAlexander Duyck 	((struct seq_file *)filep->private_data)->private = ring;
1307461fd91SAlexander Duyck 
1317461fd91SAlexander Duyck 	return 0;
1327461fd91SAlexander Duyck }
1337461fd91SAlexander Duyck 
1347461fd91SAlexander Duyck static const struct file_operations fm10k_dbg_desc_fops = {
1357461fd91SAlexander Duyck 	.owner   = THIS_MODULE,
1367461fd91SAlexander Duyck 	.open    = fm10k_dbg_desc_open,
1377461fd91SAlexander Duyck 	.read    = seq_read,
1387461fd91SAlexander Duyck 	.llseek  = seq_lseek,
1397461fd91SAlexander Duyck 	.release = seq_release,
1407461fd91SAlexander Duyck };
1417461fd91SAlexander Duyck 
1427461fd91SAlexander Duyck /**
1437461fd91SAlexander Duyck  * fm10k_dbg_q_vector_init - setup debugfs for the q_vectors
1447461fd91SAlexander Duyck  * @q_vector: q_vector to allocate directories for
1457461fd91SAlexander Duyck  *
1467461fd91SAlexander Duyck  * A folder is created for each q_vector found. In each q_vector
1477461fd91SAlexander Duyck  * folder, a debugfs file is created for each tx and rx ring
1487461fd91SAlexander Duyck  * allocated to the q_vector.
1497461fd91SAlexander Duyck  **/
fm10k_dbg_q_vector_init(struct fm10k_q_vector * q_vector)1507461fd91SAlexander Duyck void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector)
1517461fd91SAlexander Duyck {
1527461fd91SAlexander Duyck 	struct fm10k_intfc *interface = q_vector->interface;
1537461fd91SAlexander Duyck 	char name[16];
1547461fd91SAlexander Duyck 	int i;
1557461fd91SAlexander Duyck 
1567461fd91SAlexander Duyck 	if (!interface->dbg_intfc)
1577461fd91SAlexander Duyck 		return;
1587461fd91SAlexander Duyck 
1597461fd91SAlexander Duyck 	/* Generate a folder for each q_vector */
160f6f19f8bSJacob Keller 	snprintf(name, sizeof(name), "q_vector.%03d", q_vector->v_idx);
1617461fd91SAlexander Duyck 
1627461fd91SAlexander Duyck 	q_vector->dbg_q_vector = debugfs_create_dir(name, interface->dbg_intfc);
1637461fd91SAlexander Duyck 
1647461fd91SAlexander Duyck 	/* Generate a file for each rx ring in the q_vector */
1657461fd91SAlexander Duyck 	for (i = 0; i < q_vector->tx.count; i++) {
1667461fd91SAlexander Duyck 		struct fm10k_ring *ring = &q_vector->tx.ring[i];
1677461fd91SAlexander Duyck 
168f6f19f8bSJacob Keller 		snprintf(name, sizeof(name), "tx_ring.%03d", ring->queue_index);
1697461fd91SAlexander Duyck 
1707461fd91SAlexander Duyck 		debugfs_create_file(name, 0600,
1717461fd91SAlexander Duyck 				    q_vector->dbg_q_vector, ring,
1727461fd91SAlexander Duyck 				    &fm10k_dbg_desc_fops);
1737461fd91SAlexander Duyck 	}
1747461fd91SAlexander Duyck 
1757461fd91SAlexander Duyck 	/* Generate a file for each rx ring in the q_vector */
1767461fd91SAlexander Duyck 	for (i = 0; i < q_vector->rx.count; i++) {
1777461fd91SAlexander Duyck 		struct fm10k_ring *ring = &q_vector->rx.ring[i];
1787461fd91SAlexander Duyck 
179f6f19f8bSJacob Keller 		snprintf(name, sizeof(name), "rx_ring.%03d", ring->queue_index);
1807461fd91SAlexander Duyck 
1817461fd91SAlexander Duyck 		debugfs_create_file(name, 0600,
1827461fd91SAlexander Duyck 				    q_vector->dbg_q_vector, ring,
1837461fd91SAlexander Duyck 				    &fm10k_dbg_desc_fops);
1847461fd91SAlexander Duyck 	}
1857461fd91SAlexander Duyck }
1867461fd91SAlexander Duyck 
1877461fd91SAlexander Duyck /**
188*262de08fSJesse Brandeburg  * fm10k_dbg_q_vector_exit - setup debugfs for the q_vectors
1897461fd91SAlexander Duyck  * @q_vector: q_vector to allocate directories for
1907461fd91SAlexander Duyck  **/
fm10k_dbg_q_vector_exit(struct fm10k_q_vector * q_vector)1917461fd91SAlexander Duyck void fm10k_dbg_q_vector_exit(struct fm10k_q_vector *q_vector)
1927461fd91SAlexander Duyck {
1937461fd91SAlexander Duyck 	struct fm10k_intfc *interface = q_vector->interface;
1947461fd91SAlexander Duyck 
1957461fd91SAlexander Duyck 	if (interface->dbg_intfc)
1967461fd91SAlexander Duyck 		debugfs_remove_recursive(q_vector->dbg_q_vector);
1977461fd91SAlexander Duyck 	q_vector->dbg_q_vector = NULL;
1987461fd91SAlexander Duyck }
1997461fd91SAlexander Duyck 
2007461fd91SAlexander Duyck /**
2017461fd91SAlexander Duyck  * fm10k_dbg_intfc_init - setup the debugfs directory for the intferface
2027461fd91SAlexander Duyck  * @interface: the interface that is starting up
2037461fd91SAlexander Duyck  **/
2047461fd91SAlexander Duyck 
fm10k_dbg_intfc_init(struct fm10k_intfc * interface)2057461fd91SAlexander Duyck void fm10k_dbg_intfc_init(struct fm10k_intfc *interface)
2067461fd91SAlexander Duyck {
2077461fd91SAlexander Duyck 	const char *name = pci_name(interface->pdev);
2087461fd91SAlexander Duyck 
2097461fd91SAlexander Duyck 	if (dbg_root)
2107461fd91SAlexander Duyck 		interface->dbg_intfc = debugfs_create_dir(name, dbg_root);
2117461fd91SAlexander Duyck }
2127461fd91SAlexander Duyck 
2137461fd91SAlexander Duyck /**
2147461fd91SAlexander Duyck  * fm10k_dbg_intfc_exit - clean out the interface's debugfs entries
2157461fd91SAlexander Duyck  * @interface: the interface that is stopping
2167461fd91SAlexander Duyck  **/
fm10k_dbg_intfc_exit(struct fm10k_intfc * interface)2177461fd91SAlexander Duyck void fm10k_dbg_intfc_exit(struct fm10k_intfc *interface)
2187461fd91SAlexander Duyck {
2197461fd91SAlexander Duyck 	if (dbg_root)
2207461fd91SAlexander Duyck 		debugfs_remove_recursive(interface->dbg_intfc);
2217461fd91SAlexander Duyck 	interface->dbg_intfc = NULL;
2227461fd91SAlexander Duyck }
2237461fd91SAlexander Duyck 
2247461fd91SAlexander Duyck /**
2257461fd91SAlexander Duyck  * fm10k_dbg_init - start up debugfs for the driver
2267461fd91SAlexander Duyck  **/
fm10k_dbg_init(void)2277461fd91SAlexander Duyck void fm10k_dbg_init(void)
2287461fd91SAlexander Duyck {
2297461fd91SAlexander Duyck 	dbg_root = debugfs_create_dir(fm10k_driver_name, NULL);
2307461fd91SAlexander Duyck }
2317461fd91SAlexander Duyck 
2327461fd91SAlexander Duyck /**
2337461fd91SAlexander Duyck  * fm10k_dbg_exit - clean out the driver's debugfs entries
2347461fd91SAlexander Duyck  **/
fm10k_dbg_exit(void)2357461fd91SAlexander Duyck void fm10k_dbg_exit(void)
2367461fd91SAlexander Duyck {
2377461fd91SAlexander Duyck 	debugfs_remove_recursive(dbg_root);
2387461fd91SAlexander Duyck 	dbg_root = NULL;
2397461fd91SAlexander Duyck }
240