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