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