162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright(c) 2013 - 2018 Intel Corporation. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include "fm10k.h" 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/debugfs.h> 762306a36Sopenharmony_ci#include <linux/seq_file.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_cistatic struct dentry *dbg_root; 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/* Descriptor Seq Functions */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic void *fm10k_dbg_desc_seq_start(struct seq_file *s, loff_t *pos) 1462306a36Sopenharmony_ci{ 1562306a36Sopenharmony_ci struct fm10k_ring *ring = s->private; 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci return (*pos < ring->count) ? pos : NULL; 1862306a36Sopenharmony_ci} 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic void *fm10k_dbg_desc_seq_next(struct seq_file *s, 2162306a36Sopenharmony_ci void __always_unused *v, 2262306a36Sopenharmony_ci loff_t *pos) 2362306a36Sopenharmony_ci{ 2462306a36Sopenharmony_ci struct fm10k_ring *ring = s->private; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci return (++(*pos) < ring->count) ? pos : NULL; 2762306a36Sopenharmony_ci} 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistatic void fm10k_dbg_desc_seq_stop(struct seq_file __always_unused *s, 3062306a36Sopenharmony_ci void __always_unused *v) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci /* Do nothing. */ 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic void fm10k_dbg_desc_break(struct seq_file *s, int i) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci while (i--) 3862306a36Sopenharmony_ci seq_putc(s, '-'); 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci seq_putc(s, '\n'); 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic int fm10k_dbg_tx_desc_seq_show(struct seq_file *s, void *v) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci struct fm10k_ring *ring = s->private; 4662306a36Sopenharmony_ci int i = *(loff_t *)v; 4762306a36Sopenharmony_ci static const char tx_desc_hdr[] = 4862306a36Sopenharmony_ci "DES BUFFER_ADDRESS LENGTH VLAN MSS HDRLEN FLAGS\n"; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci /* Generate header */ 5162306a36Sopenharmony_ci if (!i) { 5262306a36Sopenharmony_ci seq_printf(s, tx_desc_hdr); 5362306a36Sopenharmony_ci fm10k_dbg_desc_break(s, sizeof(tx_desc_hdr) - 1); 5462306a36Sopenharmony_ci } 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci /* Validate descriptor allocation */ 5762306a36Sopenharmony_ci if (!ring->desc) { 5862306a36Sopenharmony_ci seq_printf(s, "%03X Descriptor ring not allocated.\n", i); 5962306a36Sopenharmony_ci } else { 6062306a36Sopenharmony_ci struct fm10k_tx_desc *txd = FM10K_TX_DESC(ring, i); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci seq_printf(s, "%03X %#018llx %#06x %#06x %#06x %#06x %#04x\n", 6362306a36Sopenharmony_ci i, txd->buffer_addr, txd->buflen, txd->vlan, 6462306a36Sopenharmony_ci txd->mss, txd->hdrlen, txd->flags); 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci return 0; 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic int fm10k_dbg_rx_desc_seq_show(struct seq_file *s, void *v) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci struct fm10k_ring *ring = s->private; 7362306a36Sopenharmony_ci int i = *(loff_t *)v; 7462306a36Sopenharmony_ci static const char rx_desc_hdr[] = 7562306a36Sopenharmony_ci "DES DATA RSS STATERR LENGTH VLAN DGLORT SGLORT TIMESTAMP\n"; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci /* Generate header */ 7862306a36Sopenharmony_ci if (!i) { 7962306a36Sopenharmony_ci seq_printf(s, rx_desc_hdr); 8062306a36Sopenharmony_ci fm10k_dbg_desc_break(s, sizeof(rx_desc_hdr) - 1); 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci /* Validate descriptor allocation */ 8462306a36Sopenharmony_ci if (!ring->desc) { 8562306a36Sopenharmony_ci seq_printf(s, "%03X Descriptor ring not allocated.\n", i); 8662306a36Sopenharmony_ci } else { 8762306a36Sopenharmony_ci union fm10k_rx_desc *rxd = FM10K_RX_DESC(ring, i); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci seq_printf(s, 9062306a36Sopenharmony_ci "%03X %#010x %#010x %#010x %#06x %#06x %#06x %#06x %#018llx\n", 9162306a36Sopenharmony_ci i, rxd->d.data, rxd->d.rss, rxd->d.staterr, 9262306a36Sopenharmony_ci rxd->w.length, rxd->w.vlan, rxd->w.dglort, 9362306a36Sopenharmony_ci rxd->w.sglort, rxd->q.timestamp); 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci return 0; 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic const struct seq_operations fm10k_dbg_tx_desc_seq_ops = { 10062306a36Sopenharmony_ci .start = fm10k_dbg_desc_seq_start, 10162306a36Sopenharmony_ci .next = fm10k_dbg_desc_seq_next, 10262306a36Sopenharmony_ci .stop = fm10k_dbg_desc_seq_stop, 10362306a36Sopenharmony_ci .show = fm10k_dbg_tx_desc_seq_show, 10462306a36Sopenharmony_ci}; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic const struct seq_operations fm10k_dbg_rx_desc_seq_ops = { 10762306a36Sopenharmony_ci .start = fm10k_dbg_desc_seq_start, 10862306a36Sopenharmony_ci .next = fm10k_dbg_desc_seq_next, 10962306a36Sopenharmony_ci .stop = fm10k_dbg_desc_seq_stop, 11062306a36Sopenharmony_ci .show = fm10k_dbg_rx_desc_seq_show, 11162306a36Sopenharmony_ci}; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cistatic int fm10k_dbg_desc_open(struct inode *inode, struct file *filep) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci struct fm10k_ring *ring = inode->i_private; 11662306a36Sopenharmony_ci struct fm10k_q_vector *q_vector = ring->q_vector; 11762306a36Sopenharmony_ci const struct seq_operations *desc_seq_ops; 11862306a36Sopenharmony_ci int err; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci if (ring < q_vector->rx.ring) 12162306a36Sopenharmony_ci desc_seq_ops = &fm10k_dbg_tx_desc_seq_ops; 12262306a36Sopenharmony_ci else 12362306a36Sopenharmony_ci desc_seq_ops = &fm10k_dbg_rx_desc_seq_ops; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci err = seq_open(filep, desc_seq_ops); 12662306a36Sopenharmony_ci if (err) 12762306a36Sopenharmony_ci return err; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci ((struct seq_file *)filep->private_data)->private = ring; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci return 0; 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic const struct file_operations fm10k_dbg_desc_fops = { 13562306a36Sopenharmony_ci .owner = THIS_MODULE, 13662306a36Sopenharmony_ci .open = fm10k_dbg_desc_open, 13762306a36Sopenharmony_ci .read = seq_read, 13862306a36Sopenharmony_ci .llseek = seq_lseek, 13962306a36Sopenharmony_ci .release = seq_release, 14062306a36Sopenharmony_ci}; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci/** 14362306a36Sopenharmony_ci * fm10k_dbg_q_vector_init - setup debugfs for the q_vectors 14462306a36Sopenharmony_ci * @q_vector: q_vector to allocate directories for 14562306a36Sopenharmony_ci * 14662306a36Sopenharmony_ci * A folder is created for each q_vector found. In each q_vector 14762306a36Sopenharmony_ci * folder, a debugfs file is created for each tx and rx ring 14862306a36Sopenharmony_ci * allocated to the q_vector. 14962306a36Sopenharmony_ci **/ 15062306a36Sopenharmony_civoid fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci struct fm10k_intfc *interface = q_vector->interface; 15362306a36Sopenharmony_ci char name[16]; 15462306a36Sopenharmony_ci int i; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci if (!interface->dbg_intfc) 15762306a36Sopenharmony_ci return; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci /* Generate a folder for each q_vector */ 16062306a36Sopenharmony_ci snprintf(name, sizeof(name), "q_vector.%03d", q_vector->v_idx); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci q_vector->dbg_q_vector = debugfs_create_dir(name, interface->dbg_intfc); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci /* Generate a file for each rx ring in the q_vector */ 16562306a36Sopenharmony_ci for (i = 0; i < q_vector->tx.count; i++) { 16662306a36Sopenharmony_ci struct fm10k_ring *ring = &q_vector->tx.ring[i]; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci snprintf(name, sizeof(name), "tx_ring.%03d", ring->queue_index); 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci debugfs_create_file(name, 0600, 17162306a36Sopenharmony_ci q_vector->dbg_q_vector, ring, 17262306a36Sopenharmony_ci &fm10k_dbg_desc_fops); 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci /* Generate a file for each rx ring in the q_vector */ 17662306a36Sopenharmony_ci for (i = 0; i < q_vector->rx.count; i++) { 17762306a36Sopenharmony_ci struct fm10k_ring *ring = &q_vector->rx.ring[i]; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci snprintf(name, sizeof(name), "rx_ring.%03d", ring->queue_index); 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci debugfs_create_file(name, 0600, 18262306a36Sopenharmony_ci q_vector->dbg_q_vector, ring, 18362306a36Sopenharmony_ci &fm10k_dbg_desc_fops); 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci/** 18862306a36Sopenharmony_ci * fm10k_dbg_q_vector_exit - setup debugfs for the q_vectors 18962306a36Sopenharmony_ci * @q_vector: q_vector to allocate directories for 19062306a36Sopenharmony_ci **/ 19162306a36Sopenharmony_civoid fm10k_dbg_q_vector_exit(struct fm10k_q_vector *q_vector) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci struct fm10k_intfc *interface = q_vector->interface; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci if (interface->dbg_intfc) 19662306a36Sopenharmony_ci debugfs_remove_recursive(q_vector->dbg_q_vector); 19762306a36Sopenharmony_ci q_vector->dbg_q_vector = NULL; 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci/** 20162306a36Sopenharmony_ci * fm10k_dbg_intfc_init - setup the debugfs directory for the intferface 20262306a36Sopenharmony_ci * @interface: the interface that is starting up 20362306a36Sopenharmony_ci **/ 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_civoid fm10k_dbg_intfc_init(struct fm10k_intfc *interface) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci const char *name = pci_name(interface->pdev); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci if (dbg_root) 21062306a36Sopenharmony_ci interface->dbg_intfc = debugfs_create_dir(name, dbg_root); 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci/** 21462306a36Sopenharmony_ci * fm10k_dbg_intfc_exit - clean out the interface's debugfs entries 21562306a36Sopenharmony_ci * @interface: the interface that is stopping 21662306a36Sopenharmony_ci **/ 21762306a36Sopenharmony_civoid fm10k_dbg_intfc_exit(struct fm10k_intfc *interface) 21862306a36Sopenharmony_ci{ 21962306a36Sopenharmony_ci if (dbg_root) 22062306a36Sopenharmony_ci debugfs_remove_recursive(interface->dbg_intfc); 22162306a36Sopenharmony_ci interface->dbg_intfc = NULL; 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci/** 22562306a36Sopenharmony_ci * fm10k_dbg_init - start up debugfs for the driver 22662306a36Sopenharmony_ci **/ 22762306a36Sopenharmony_civoid fm10k_dbg_init(void) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci dbg_root = debugfs_create_dir(fm10k_driver_name, NULL); 23062306a36Sopenharmony_ci} 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci/** 23362306a36Sopenharmony_ci * fm10k_dbg_exit - clean out the driver's debugfs entries 23462306a36Sopenharmony_ci **/ 23562306a36Sopenharmony_civoid fm10k_dbg_exit(void) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci debugfs_remove_recursive(dbg_root); 23862306a36Sopenharmony_ci dbg_root = NULL; 23962306a36Sopenharmony_ci} 240